diff --git a/source/MaterialXCore/Node.cpp b/source/MaterialXCore/Node.cpp index 09d7114098..a6f57e7be2 100644 --- a/source/MaterialXCore/Node.cpp +++ b/source/MaterialXCore/Node.cpp @@ -717,6 +717,38 @@ void NodeGraph::modifyInterfaceName(const string& inputPath, const string& inter } } +void NodeGraph::setInputOrdering(const StringVec& inputNames) +{ + StringSet childInputNames; + std::vector childInputIndicies; + + for (ElementPtr child : _childOrder) + { + InputPtr input = child->asA(); + if (!input) + continue; + + const string& inputName = input->getName(); + childInputNames.insert(inputName); + childInputIndicies.push_back(getChildIndex(inputName)); + } + + // Check that all names exist in the inputs + StringSet orderedInputNames(inputNames.begin(), inputNames.end()); + if (childInputNames != orderedInputNames) + { + throw Exception("The set of names provided does not match the existing set of input names"); + } + + // Use the existing input child indices to set the locations for the + // named list. Pre-sort to add from lowest index to highest + std::sort(childInputIndicies.begin(), childInputIndicies.end()); + for (size_t i = 0; i < childInputIndicies.size(); i++) + { + setChildIndex(inputNames[i], childInputIndicies[i]); + } +} + NodeDefPtr NodeGraph::getNodeDef() const { NodeDefPtr nodedef = resolveNameReference(getNodeDefString()); diff --git a/source/MaterialXCore/Node.h b/source/MaterialXCore/Node.h index 7d5f998ced..7bde5604cf 100644 --- a/source/MaterialXCore/Node.h +++ b/source/MaterialXCore/Node.h @@ -379,6 +379,10 @@ class MX_CORE_API NodeGraph : public GraphElement /// @param interfaceName The new interface name. void modifyInterfaceName(const string& inputPath, const string& interfaceName); + /// Set the ordering of inputs + /// @param inputNames List of names of all inputs in the desired order from start to end. + void setInputOrdering(const StringVec& inputNames); + /// @} /// @name Validation /// @{ diff --git a/source/MaterialXTest/MaterialXCore/Node.cpp b/source/MaterialXTest/MaterialXCore/Node.cpp index 5e31c4293b..fadbda1bca 100644 --- a/source/MaterialXTest/MaterialXCore/Node.cpp +++ b/source/MaterialXTest/MaterialXCore/Node.cpp @@ -825,3 +825,41 @@ TEST_CASE("Node Definition Creation", "[nodedef]") REQUIRE(doc->validate()); } + +TEST_CASE("Input Ordering", "[nodegraph]") +{ + mx::DocumentPtr doc = mx::createDocument(); + mx::NodeGraphPtr graph = doc->addNodeGraph("graph1"); + mx::StringVec childNames = { "one", "node_0", "two", "node_1", "three", "node_3", "four" }; + for (const std::string& childName : childNames) + { + if (childName.rfind("node", 0) == 0) + graph->addNode("constant", childName); + else + graph->addInput(childName, "color3"); + } + + mx::StringVec incorrectInputOrdering = { "two2", "one", "four", "three" }; + bool haveIncorrectNames = true; + try + { + graph->setInputOrdering(incorrectInputOrdering); + haveIncorrectNames = false; + } + catch (mx::Exception& e) + { + INFO(e.what()) + } + REQUIRE(haveIncorrectNames); + + mx::StringVec desiredInputOrdering = { "two", "one", "four", "three" }; + graph->setInputOrdering(desiredInputOrdering); + + mx::StringVec desiredChildOrdering = { "two", "node_0", "one", "node_1", "four", "node_3", "three" }; + mx::StringVec resultingChildOrdering; + for (auto child : graph->getChildren()) + { + resultingChildOrdering.push_back(child->getName()); + } + REQUIRE((resultingChildOrdering == desiredChildOrdering)); +}