diff --git a/resources/Materials/TestSuite/stdlib/definition/definition_from_nodegraph.mtlx b/resources/Materials/TestSuite/stdlib/definition/definition_from_nodegraph.mtlx index f83ba2db2b..f1958c162e 100644 --- a/resources/Materials/TestSuite/stdlib/definition/definition_from_nodegraph.mtlx +++ b/resources/Materials/TestSuite/stdlib/definition/definition_from_nodegraph.mtlx @@ -1,76 +1,29 @@ - - - - - - + + + - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + diff --git a/source/JsMaterialX/JsMaterialXCore/JsDocument.cpp b/source/JsMaterialX/JsMaterialXCore/JsDocument.cpp index 23901ecc0f..ec4881732d 100644 --- a/source/JsMaterialX/JsMaterialXCore/JsDocument.cpp +++ b/source/JsMaterialX/JsMaterialXCore/JsDocument.cpp @@ -59,8 +59,8 @@ EMSCRIPTEN_BINDINGS(document) .function("getTypeDefs", &mx::Document::getTypeDefs) .function("removeTypeDef", &mx::Document::removeTypeDef) BIND_MEMBER_FUNC("addNodeDef", mx::Document, addNodeDef, 0, 3, stRef, stRef, stRef) - BIND_MEMBER_FUNC("addNodeDefFromGraph", mx::Document, addNodeDefFromGraph, 7, 7, const mx::NodeGraphPtr, - stRef, stRef, stRef, bool, stRef, std::string) + BIND_MEMBER_FUNC("addNodeDefFromGraph", mx::Document, addNodeDefFromGraph, 4, 4, mx::NodeGraphPtr, + const std::string&, const std::string&, const std::string&) .function("getNodeDef", &mx::Document::getNodeDef) .function("getNodeDefs", &mx::Document::getNodeDefs) .function("removeNodeDef", &mx::Document::removeNodeDef) diff --git a/source/MaterialXCore/Document.cpp b/source/MaterialXCore/Document.cpp index c665ff43ec..dd3d9b2602 100644 --- a/source/MaterialXCore/Document.cpp +++ b/source/MaterialXCore/Document.cpp @@ -147,47 +147,82 @@ void Document::initialize() setVersionIntegers(MATERIALX_MAJOR_VERSION, MATERIALX_MINOR_VERSION); } -NodeDefPtr Document::addNodeDefFromGraph(const NodeGraphPtr nodeGraph, const string& nodeDefName, const string& node, - const string& version, bool isDefaultVersion, const string& group, const string& newGraphName) +NodeDefPtr Document::addNodeDefFromGraph(NodeGraphPtr nodeGraph, const string& nodeDefName, + const string& category, const string& newGraphName) { - if (getNodeDef(nodeDefName)) + if (category.empty()) { - throw Exception("Cannot create duplicate nodedef: " + nodeDefName); + throw Exception("Cannot create a nodedef without a category identifier"); } - NodeGraphPtr graph = nodeGraph; - if (!newGraphName.empty()) + if (getNodeDef(nodeDefName)) { - if (getNodeGraph(newGraphName)) - { - throw Exception("Cannot create duplicate nodegraph: " + newGraphName); - } - graph = addNodeGraph(newGraphName); - graph->copyContentFrom(nodeGraph); + throw Exception("Cannot create duplicate nodedef: " + nodeDefName); } - graph->setNodeDefString(nodeDefName); - NodeDefPtr nodeDef = addChild(nodeDefName); - nodeDef->setNodeString(node); - if (!group.empty()) + if (getNodeGraph(newGraphName)) { - nodeDef->setNodeGroup(group); + throw Exception("Cannot create duplicate nodegraph: " + newGraphName); } + + // Create a new functional nodegraph, and copy over the + // contents from the compound nodegraph + NodeGraphPtr graph = addNodeGraph(newGraphName); + graph->copyContentFrom(nodeGraph); - if (!version.empty()) + for (auto graphChild : graph->getChildren()) { - nodeDef->setVersionString(version); + graphChild->removeAttribute(Element::XPOS_ATTRIBUTE); + graphChild->removeAttribute(Element::YPOS_ATTRIBUTE); + } + graph->setNodeDefString(nodeDefName); + + // Create a new nodedef and set its category + NodeDefPtr nodeDef = addNodeDef(nodeDefName, EMPTY_STRING); + nodeDef->setNodeString(category); + + // Expose any existing interfaces from the graph. + // Any connection attributes ("nodegraph", "nodename", "interfacename") on the + // existing interface should be removed from the definition as well as any source URI. + + // Attributes which should not be copied over + StringSet filterAttributes = { PortElement::NODE_GRAPH_ATTRIBUTE, PortElement::NODE_NAME_ATTRIBUTE, + PortElement::INTERFACE_NAME_ATTRIBUTE, Element::XPOS_ATTRIBUTE, Element::YPOS_ATTRIBUTE }; - // Can only be a default version if there is a version string - if (isDefaultVersion) + // Transfer input interface from the graph to the nodedef + for (InputPtr input : graph->getInputs()) + { + InputPtr nodeDefInput = nodeDef->addInput(input->getName(), input->getType()); + if (nodeDefInput) { - nodeDef->setDefaultVersion(true); - } + nodeDefInput->copyContentFrom(input); + for (const string& filterAttribute : filterAttributes ) + { + nodeDefInput->removeAttribute(filterAttribute); + } + nodeDefInput->setSourceUri(EMPTY_STRING); + input->setInterfaceName(nodeDefInput->getName()); + } + } + // Remove interfaces from the nodegraph + for (InputPtr input : graph->getInputs()) + { + graph->removeInput(input->getName()); } - for (auto output : graph->getOutputs()) + // Copy the output interface from the graph to the nodedef + for (OutputPtr output : graph->getOutputs()) { - nodeDef->addOutput(output->getName(), output->getType()); + OutputPtr nodeDefOutput = nodeDef->addOutput(output->getName(), output->getType()); + if (nodeDefOutput) + { + nodeDefOutput->copyContentFrom(output); + for (const string& filterAttribute : filterAttributes) + { + nodeDefOutput->removeAttribute(filterAttribute); + } + nodeDefOutput->setSourceUri(EMPTY_STRING); + } } return nodeDef; @@ -367,4 +402,15 @@ void Document::invalidateCache() _cache->valid = false; } +// +// Deprecated methods +// + +NodeDefPtr Document::addNodeDefFromGraph(NodeGraphPtr nodeGraph, const string& nodeDefName, const string& node, + const string&, bool, const string&, const string& newGraphName) +{ + return addNodeDefFromGraph(nodeGraph, nodeDefName, node, newGraphName); +} + + MATERIALX_NAMESPACE_END diff --git a/source/MaterialXCore/Document.h b/source/MaterialXCore/Document.h index 8f5abbf8fb..08b3e1d22e 100644 --- a/source/MaterialXCore/Document.h +++ b/source/MaterialXCore/Document.h @@ -333,18 +333,14 @@ class MX_CORE_API Document : public GraphElement return child; } - /// Create a NodeDef declaration which is based on a NodeGraph. - /// @param nodeGraph NodeGraph used to create NodeDef - /// @param nodeDefName Declaration name - /// @param node Node type for the new declaration - /// @param version Version for the new declaration - /// @param isDefaultVersion If a version is specified is thie definition the default version - /// @param newGraphName Make a copy of this NodeGraph with the given name if a non-empty name is provided. Otherwise - /// modify the existing NodeGraph. Default value is an empty string. - /// @param nodeGroup Optional node group for the new declaration. The Default value is an emptry string. + /// Create a NodeDef and Functional Graph based on a Compound NodeGraph + /// @param nodeGraph Compound NodeGraph. + /// @param newGraphName Name of new functional NodeGraph. + /// @param nodeDefName Name of new NodeDef + /// @param category Category of the new NodeDef /// @return New declaration if successful. - NodeDefPtr addNodeDefFromGraph(const NodeGraphPtr nodeGraph, const string& nodeDefName, const string& node, const string& version, - bool isDefaultVersion, const string& nodeGroup, const string& newGraphName); + NodeDefPtr addNodeDefFromGraph(NodeGraphPtr nodeGraph, const string& nodeDefName, + const string& category, const string& newGraphName); /// Return the NodeDef, if any, with the given name. NodeDefPtr getNodeDef(const string& name) const @@ -669,6 +665,13 @@ class MX_CORE_API Document : public GraphElement /// @} + // + // These are deprecated wrappers for older versions of the function interfaces in this module. + // Clients using these interfaces should update them to the latest API. + // + [[deprecated]] NodeDefPtr addNodeDefFromGraph(NodeGraphPtr nodeGraph, const string& nodeDefName, const string& node, const string& version, + bool isDefaultVersion, const string& nodeGroup, const string& newGraphName); + public: static const string CATEGORY; static const string CMS_ATTRIBUTE; diff --git a/source/MaterialXCore/Element.cpp b/source/MaterialXCore/Element.cpp index 0af27c952f..94836245a7 100644 --- a/source/MaterialXCore/Element.cpp +++ b/source/MaterialXCore/Element.cpp @@ -19,6 +19,8 @@ const string Element::COLOR_SPACE_ATTRIBUTE = "colorspace"; const string Element::INHERIT_ATTRIBUTE = "inherit"; const string Element::NAMESPACE_ATTRIBUTE = "namespace"; const string Element::DOC_ATTRIBUTE = "doc"; +const string Element::XPOS_ATTRIBUTE = "xpos"; +const string Element::YPOS_ATTRIBUTE = "ypos"; const string TypedElement::TYPE_ATTRIBUTE = "type"; const string ValueElement::VALUE_ATTRIBUTE = "value"; const string ValueElement::INTERFACE_NAME_ATTRIBUTE = "interfacename"; diff --git a/source/MaterialXCore/Element.h b/source/MaterialXCore/Element.h index a087d79b95..d1abcdfdca 100644 --- a/source/MaterialXCore/Element.h +++ b/source/MaterialXCore/Element.h @@ -807,6 +807,8 @@ class MX_CORE_API Element : public std::enable_shared_from_this static const string INHERIT_ATTRIBUTE; static const string NAMESPACE_ATTRIBUTE; static const string DOC_ATTRIBUTE; + static const string XPOS_ATTRIBUTE; + static const string YPOS_ATTRIBUTE; protected: virtual void registerChildElement(ElementPtr child); diff --git a/source/MaterialXCore/Node.cpp b/source/MaterialXCore/Node.cpp index 9596d905bc..17784c4a96 100644 --- a/source/MaterialXCore/Node.cpp +++ b/source/MaterialXCore/Node.cpp @@ -647,34 +647,33 @@ void Node::addInputsFromNodeDef() } } -void NodeGraph::addInterfaceName(const string& inputPath, const string& interfaceName) +InputPtr NodeGraph::addInterfaceName(const string& inputPath, const string& interfaceName) { NodeDefPtr nodeDef = getNodeDef(); - if (!nodeDef) + InterfaceElementPtr interfaceElement = nodeDef ? nodeDef->asA() : getSelf()->asA(); + if (interfaceElement->getChild(interfaceName)) { - throw Exception("Cannot declare an interface for a nodegraph which is not associated with a node definition: " + getName()); - } - if (nodeDef->getChild(interfaceName)) - { - throw Exception("Interface: " + interfaceName + " has already been declared on the node definition: " + nodeDef->getName()); + throw Exception("Interface: " + interfaceName + " has already been declared on the interface: " + interfaceElement->getNamePath()); } + InputPtr interfaceInput; ElementPtr elem = getDescendant(inputPath); InputPtr input = elem ? elem->asA() : nullptr; if (input && !input->getConnectedNode()) { input->setInterfaceName(interfaceName); - InputPtr nodeDefInput = nodeDef->getInput(interfaceName); - if (!nodeDefInput) + interfaceInput = interfaceElement->getInput(interfaceName); + if (!interfaceInput) { - nodeDefInput = nodeDef->addInput(interfaceName, input->getType()); + interfaceInput = interfaceElement->addInput(interfaceName, input->getType()); } if (input->hasValue()) { - nodeDefInput->setValueString(input->getValueString()); + interfaceInput->setValueString(input->getValueString()); input->removeAttribute(Input::VALUE_ATTRIBUTE); } } + return interfaceInput; } void NodeGraph::removeInterfaceName(const string& inputPath) @@ -684,24 +683,44 @@ void NodeGraph::removeInterfaceName(const string& inputPath) if (input) { const string& interfaceName = input->getInterfaceName(); - getNodeDef()->removeChild(interfaceName); - input->setInterfaceName(EMPTY_STRING); + if (!interfaceName.empty()) + { + NodeDefPtr nodeDef = getNodeDef(); + InterfaceElementPtr interface = nodeDef ? nodeDef->asA() : getSelf()->asA(); + ElementPtr interfacePort = interface->getChild(interfaceName); + if (interfacePort) + { + InputPtr interfaceInput = interfacePort ? interfacePort->asA() : nullptr; + if (interfaceInput && interfaceInput->hasValue()) + { + input->setValueString(interfaceInput->getValueString()); + } + interface->removeChild(interfaceName); + } + input->setInterfaceName(EMPTY_STRING); + } } } void NodeGraph::modifyInterfaceName(const string& inputPath, const string& interfaceName) { + NodeDefPtr nodeDef = getNodeDef(); + InterfaceElementPtr interfaceElement = nodeDef ? nodeDef->asA() : getSelf()->asA(); + ElementPtr desc = getDescendant(inputPath); InputPtr input = desc ? desc->asA() : nullptr; if (input) { const string& previousName = input->getInterfaceName(); - ElementPtr previousChild = getNodeDef()->getChild(previousName); - if (previousChild) + if (previousName != interfaceName) { - previousChild->setName(interfaceName); + ElementPtr previousChild = interfaceElement->getChild(previousName); + if (previousChild) + { + previousChild->setName(interfaceName); + } + input->setInterfaceName(interfaceName); } - input->setInterfaceName(interfaceName); } } diff --git a/source/MaterialXCore/Node.h b/source/MaterialXCore/Node.h index 55846cf2e3..b42d18074e 100644 --- a/source/MaterialXCore/Node.h +++ b/source/MaterialXCore/Node.h @@ -376,7 +376,8 @@ class MX_CORE_API NodeGraph : public GraphElement /// Add an interface name to an existing NodeDef associated with this NodeGraph. /// @param inputPath Path to an input descendant of this graph. /// @param interfaceName The new interface name. - void addInterfaceName(const string& inputPath, const string& interfaceName); + /// @return Interface input. + InputPtr addInterfaceName(const string& inputPath, const string& interfaceName); /// Remove an interface name from an existing NodeDef associated with this NodeGraph. /// @param inputPath Path to an input descendant of this graph. diff --git a/source/MaterialXGraphEditor/Graph.cpp b/source/MaterialXGraphEditor/Graph.cpp index 9b9426f9d7..64614a02cb 100644 --- a/source/MaterialXGraphEditor/Graph.cpp +++ b/source/MaterialXGraphEditor/Graph.cpp @@ -456,7 +456,7 @@ int Graph::findLinkPosition(int id) bool Graph::checkPosition(UiNodePtr node) { return node->getMxElement() && - !node->getMxElement()->getAttribute("xpos").empty(); + !node->getMxElement()->getAttribute(mx::Element::XPOS_ATTRIBUTE).empty(); } // Calculate the total vertical space the node level takes up @@ -549,12 +549,12 @@ ImVec2 Graph::layoutPosition(UiNodePtr layoutNode, ImVec2 startingPos, bool init // Don't set position of group nodes if (node->getMessage().empty()) { - if (node->getMxElement()->hasAttribute("xpos")) + if (node->getMxElement()->hasAttribute(mx::Element::XPOS_ATTRIBUTE)) { - float x = std::stof(node->getMxElement()->getAttribute("xpos")); - if (node->getMxElement()->hasAttribute("ypos")) + float x = std::stof(node->getMxElement()->getAttribute(mx::Element::XPOS_ATTRIBUTE)); + if (node->getMxElement()->hasAttribute(mx::Element::YPOS_ATTRIBUTE)) { - float y = std::stof(node->getMxElement()->getAttribute("ypos")); + float y = std::stof(node->getMxElement()->getAttribute(mx::Element::YPOS_ATTRIBUTE)); x *= DEFAULT_NODE_SIZE.x; y *= DEFAULT_NODE_SIZE.y; ed::SetNodePosition(node->getId(), ImVec2(x, y)); @@ -4385,8 +4385,8 @@ void Graph::savePosition() ImVec2 pos = ed::GetNodePosition(node->getId()); pos.x /= DEFAULT_NODE_SIZE.x; pos.y /= DEFAULT_NODE_SIZE.y; - node->getMxElement()->setAttribute("xpos", std::to_string(pos.x)); - node->getMxElement()->setAttribute("ypos", std::to_string(pos.y)); + node->getMxElement()->setAttribute(mx::Element::XPOS_ATTRIBUTE, std::to_string(pos.x)); + node->getMxElement()->setAttribute(mx::Element::YPOS_ATTRIBUTE, std::to_string(pos.y)); if (node->getMxElement()->hasAttribute("nodedef")) { node->getMxElement()->removeAttribute("nodedef"); @@ -4409,8 +4409,8 @@ void Graph::saveDocument(mx::FilePath filePath) writeDoc = _graphDoc->copy(); for (mx::ElementPtr elem : writeDoc->traverseTree()) { - elem->removeAttribute("xpos"); - elem->removeAttribute("ypos"); + elem->removeAttribute(mx::Element::XPOS_ATTRIBUTE); + elem->removeAttribute(mx::Element::YPOS_ATTRIBUTE); } } diff --git a/source/MaterialXTest/MaterialXCore/Node.cpp b/source/MaterialXTest/MaterialXCore/Node.cpp index 655ec5b7fb..57e1cb44cc 100644 --- a/source/MaterialXTest/MaterialXCore/Node.cpp +++ b/source/MaterialXTest/MaterialXCore/Node.cpp @@ -627,97 +627,116 @@ TEST_CASE("Node Definition Creation", "[nodedef]") REQUIRE(graph); if (graph) { + // Add some input interfaces to the graph + for (auto node : graph->getNodes()) + { + for (mx::InputPtr input : node->getInputs()) + { + if (!input->getConnectedNode()) + { + const std::string relativePath = node->getName() + "/" + input->getName(); + const std::string interfaceName = graph->createValidChildName(relativePath); + mx::InputPtr interfaceInput = graph->addInterfaceName(relativePath, interfaceName); + REQUIRE(interfaceInput); + if (interfaceInput) + { + interfaceInput->setAttribute(mx::PortElement::UI_NAME_ATTRIBUTE, node->getName() + " " + input->getName()); + interfaceInput->setAttribute(mx::PortElement::UI_FOLDER_ATTRIBUTE, "Common"); + } + } + } + } + const std::string VERSION1 = "1.0"; const std::string GROUP = "adjustment"; bool isDefaultVersion = false; const std::string NODENAME = graph->getName(); - // Duplicate the graph and then make the duplicate a nodedef nodegraph + // Create a new functional graph and definition from a compound graph std::string newNodeDefName = doc->createValidChildName("ND_" + graph->getName()); std::string newGraphName = doc->createValidChildName("NG_" + graph->getName()); - mx::NodeDefPtr nodeDef = doc->addNodeDefFromGraph(graph, newNodeDefName, NODENAME, VERSION1, isDefaultVersion, GROUP, newGraphName); + mx::NodeDefPtr nodeDef = doc->addNodeDefFromGraph(graph, newNodeDefName, NODENAME, newGraphName); REQUIRE(nodeDef != nullptr); + nodeDef->setVersionString(VERSION1); + nodeDef->setDefaultVersion(isDefaultVersion); + nodeDef->setNodeGroup(GROUP); + nodeDef->setAttribute(mx::PortElement::UI_NAME_ATTRIBUTE, NODENAME + " Version: " + VERSION1); + nodeDef->setDocString("This is version 1 of the definition for the graph: " + newGraphName); + + // Check validity of new definition REQUIRE(nodeDef->getNodeGroup() == "adjustment"); REQUIRE(nodeDef->getVersionString() == VERSION1); REQUIRE_FALSE(nodeDef->getDefaultVersion()); - - // Try and fail to create the same definition - mx::NodeDefPtr temp; - try + for (mx::InputPtr origInput : graph->getInputs()) { - temp = nullptr; - temp = doc->addNodeDefFromGraph(graph, newNodeDefName, NODENAME, VERSION1, isDefaultVersion, GROUP, newGraphName); + mx::InputPtr nodeDefInput = nodeDef->getInput(origInput->getName()); + REQUIRE(nodeDefInput); + REQUIRE(*origInput == *nodeDefInput); } - catch (mx::Exception&) + mx::StringSet connectionAttributes = { - REQUIRE(temp == nullptr); + mx::PortElement::NODE_GRAPH_ATTRIBUTE, + mx::PortElement::NODE_NAME_ATTRIBUTE, + mx::PortElement::INTERFACE_NAME_ATTRIBUTE, + mx::Element::XPOS_ATTRIBUTE, + mx::Element::YPOS_ATTRIBUTE + }; + for (mx::OutputPtr origOutput : graph->getOutputs()) + { + mx::OutputPtr nodeDefOutput = nodeDef->getOutput(origOutput->getName()); + REQUIRE(nodeDefOutput); + for (const std::string& attribName : origOutput->getAttributeNames()) + { + if (connectionAttributes.count(attribName)) + { + REQUIRE(!nodeDefOutput->hasAttribute(attribName)); + continue; + } + REQUIRE(origOutput->getAttribute(attribName) == nodeDefOutput->getAttribute(attribName)); + } } - // Check that the new nodegraph has the correct definition + // Check validity of new functional nodegraph mx::NodeGraphPtr newGraph = doc->getNodeGraph(newGraphName); REQUIRE(newGraph != nullptr); REQUIRE(newGraph->getNodeDefString() == newNodeDefName); - - // Check declaration was set up properly mx::ConstInterfaceElementPtr decl = newGraph->getDeclaration(); REQUIRE(decl->getName() == nodeDef->getName()); + REQUIRE(doc->validate()); - // Arbitrarily add all unconnected inputs as interfaces - mx::ValueElementPtr newInterface = nullptr; - for (auto node : newGraph->getNodes()) - { - mx::NodeDefPtr nodeNodeDef = node->getNodeDef(); - REQUIRE(nodeNodeDef); - for (auto nodeDefValueElem : nodeNodeDef->getActiveValueElements()) - { - const std::string& valueElemName = nodeDefValueElem->getName(); - mx::ValueElementPtr valueElem = node->getValueElement(valueElemName); - if (!valueElem) - { - valueElem = node->addInputFromNodeDef(valueElemName); - if (!valueElem) - { - continue; - } - REQUIRE(valueElem->getAttribute(mx::ValueElement::TYPE_ATTRIBUTE) == - nodeDefValueElem->getAttribute(mx::ValueElement::TYPE_ATTRIBUTE)); - REQUIRE(valueElem->getAttribute(mx::ValueElement::VALUE_ATTRIBUTE) == - nodeDefValueElem->getAttribute(mx::ValueElement::VALUE_ATTRIBUTE)); - } + // Create the new node + mx::NodePtr newInstance = doc->addNode(NODENAME, mx::EMPTY_STRING, mx::MULTI_OUTPUT_TYPE_STRING); + REQUIRE(newInstance); - mx::InputPtr input = valueElem->asA(); - if (input && !input->getConnectedNode()) - { - std::string interfaceName = input->getNamePath(); - interfaceName = nodeDef->createValidChildName(interfaceName); - newGraph->addInterfaceName(input->getNamePath(newGraph), interfaceName); - REQUIRE(nodeDef->getChild(interfaceName)); - try - { - // Check duplicate failure case - newGraph->addInterfaceName(input->getNamePath(newGraph), interfaceName); - } - catch (mx::Exception& e) - { - REQUIRE(e.what()); - newGraph->removeInterfaceName(input->getNamePath(newGraph)); - REQUIRE(nodeDef->getChild(interfaceName) == nullptr); - newGraph->addInterfaceName(input->getNamePath(newGraph), interfaceName); - - const std::string newInterfaceName = interfaceName + "_renamed"; - newGraph->modifyInterfaceName(input->getNamePath(newGraph), newInterfaceName); - REQUIRE(nodeDef->getChild(newInterfaceName)); - } - } - } + // Remove default version attribute from previous definitions + for (mx::NodeDefPtr prevNodeDef : doc->getMatchingNodeDefs(NODENAME)) + { + prevNodeDef->setDefaultVersion(false); } // Add new version const std::string VERSION2 = "2.0"; newGraphName = mx::EMPTY_STRING; - nodeDef = doc->addNodeDefFromGraph(graph, newNodeDefName + "2", NODENAME, VERSION2, isDefaultVersion, GROUP, newGraphName); + newNodeDefName = doc->createValidChildName("ND_" + graph->getName() + "_2"); + newGraphName = doc->createValidChildName("NG_" + graph->getName() + "_2"); + + // Create new default version + nodeDef = doc->addNodeDefFromGraph(graph, newNodeDefName + "2", NODENAME, newGraphName); + nodeDef->setVersionString(VERSION2); + nodeDef->setNodeGroup(GROUP); nodeDef->setDefaultVersion(true); REQUIRE(nodeDef != nullptr); + nodeDef->setAttribute(mx::PortElement::UI_NAME_ATTRIBUTE, NODENAME + " Version: " + VERSION2); + nodeDef->setDocString("This is version 2 of the definition for the graph: " + newGraphName); + + // Check that we create the version by default + mx::NodePtr newDefault = doc->addNode(NODENAME, mx::EMPTY_STRING, mx::MULTI_OUTPUT_TYPE_STRING); + if (newDefault) + { + nodeDef = newDefault->getNodeDef(); + if (nodeDef) + REQUIRE(nodeDef->getVersionString() == VERSION2); + } std::vector matchingNodeDefs; for (auto docNodeDef : doc->getNodeDefs()) @@ -738,6 +757,9 @@ TEST_CASE("Node Definition Creation", "[nodedef]") } } REQUIRE(findDefault); + + doc->removeChild(graph->getName()); } + REQUIRE(doc->validate()); } diff --git a/source/PyMaterialX/PyMaterialXCore/PyDocument.cpp b/source/PyMaterialX/PyMaterialXCore/PyDocument.cpp index 101e1bea64..3f4403c673 100644 --- a/source/PyMaterialX/PyMaterialXCore/PyDocument.cpp +++ b/source/PyMaterialX/PyMaterialXCore/PyDocument.cpp @@ -10,6 +10,18 @@ namespace py = pybind11; namespace mx = MaterialX; +class PyBindDocument : public mx::Document +{ + public: + mx::NodeDefPtr old_addNodeDefFromGraph(mx::NodeGraphPtr nodeGraph, const std::string& nodeDefName, const std::string& node, + const std::string&, bool, const std::string&, const std::string& newGraphName) + { + PyErr_WarnEx(PyExc_DeprecationWarning, + "This method is deprecated, use addNodeDefFromGraph(nodeGraph, nodeDefName, category, newGraphName) instead.", 1); + return addNodeDefFromGraph(nodeGraph, nodeDefName, node, newGraphName); + } +}; + void bindPyDocument(py::module& mod) { mod.def("createDocument", &mx::createDocument); @@ -59,7 +71,9 @@ void bindPyDocument(py::module& mod) .def("removeTypeDef", &mx::Document::removeTypeDef) .def("addNodeDef", &mx::Document::addNodeDef, py::arg("name") = mx::EMPTY_STRING, py::arg("type") = mx::DEFAULT_TYPE_STRING, py::arg("node") = mx::EMPTY_STRING) - .def("addNodeDefFromGraph", &mx::Document::addNodeDefFromGraph) + .def("addNodeDefFromGraph", (mx::NodeDefPtr (mx::Document::*)(mx::NodeGraphPtr, const std::string&, const std::string&, const std::string&)) & mx::Document::addNodeDefFromGraph) + .def("addNodeDefFromGraph", (mx::NodeDefPtr(mx::Document::*)(mx::NodeGraphPtr, const std::string&, const std::string&, const std::string&, + bool, const std::string&, const std::string& )) & PyBindDocument::old_addNodeDefFromGraph) .def("getNodeDef", &mx::Document::getNodeDef) .def("getNodeDefs", &mx::Document::getNodeDefs) .def("removeNodeDef", &mx::Document::removeNodeDef)