-
Notifications
You must be signed in to change notification settings - Fork 408
Add Functional NodeDef Support #2401
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 18 commits
f8ceb63
a9cc157
b96d4cd
814e524
179a6d6
36a154f
cf7d0f2
8ef6904
c52561b
cad97bc
5ac34e5
4dc3ee1
7add695
df75cae
f3b5985
cb430ab
ece55fc
ad477ee
8caf533
4057ff9
7e12bf1
231bcce
6fc3a7b
d999875
aa3ca63
d24b4f1
fc97603
5f62af2
8905df3
f481f6f
0018a27
dd352e6
a3ed34d
3e70748
d6346f8
f9a5603
f235733
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| <?xml version="1.0"?> | ||
| <materialx version="1.39"> | ||
| <nodegraph name="NG_test_colorcorrect_reference"> | ||
| <multiply name="AlphaGain" type="float"> | ||
| <input name="in1" type="float" nodename="inputAlpha" /> | ||
| <input name="in2" type="float" interfacename="AlphaGain_in2" /> | ||
| </multiply> | ||
| <add name="AlphaOffset" type="float"> | ||
| <input name="in1" type="float" nodename="AlphaGain" /> | ||
| <input name="in2" type="float" interfacename="AlphaOffset_in2" /> | ||
| </add> | ||
| <multiply name="ColorGain" type="color3"> | ||
| <input name="in1" type="color3" nodename="inputColor" /> | ||
| <input name="in2" type="color3" interfacename="ColorGain_in2" /> | ||
| </multiply> | ||
| <add name="ColorOffset" type="color3"> | ||
| <input name="in1" type="color3" nodename="ColorGain" /> | ||
| <input name="in2" type="color3" interfacename="ColorOffset_in2" /> | ||
| </add> | ||
| <constant name="inputColor" type="color3"> | ||
| <input name="value" type="color3" interfacename="inputColor_value" /> | ||
| </constant> | ||
| <constant name="inputAlpha" type="float"> | ||
| <input name="value" type="float" interfacename="inputAlpha_value" /> | ||
| </constant> | ||
| <output name="out" type="color3" nodename="ColorOffset" /> | ||
| <output name="out1" type="float" nodename="AlphaOffset" /> | ||
| <input name="AlphaGain_in2" type="float" value="0.8" uiname="AlphaGain in2" uifolder="Common" /> | ||
| <input name="AlphaOffset_in2" type="float" value="1" uiname="AlphaOffset in2" uifolder="Common" /> | ||
| <input name="ColorGain_in2" type="color3" value="0.9, 0.9, 0.9" uiname="ColorGain in2" uifolder="Common" /> | ||
| <input name="ColorOffset_in2" type="color3" value="0.379147, 0.0341412, 0.0341412" uiname="ColorOffset in2" uifolder="Common" /> | ||
| <input name="inputColor_value" type="color3" value="0.5, 0.5, 0.5" uiname="inputColor value" uifolder="Common" /> | ||
| <input name="inputAlpha_value" type="float" value="1" uiname="inputAlpha value" uifolder="Common" /> | ||
| </nodegraph> | ||
| <nodedef name="ND_test_colorcorrect" node="test_colorcorrect" version="1.0" isdefaultversion="false" nodegroup="adjustment" uiname="test_colorcorrect Version: 1.0" doc="This is version 1 of the definition for the graph: NG_test_colorcorrect"> | ||
| <nodegraph name="NG_test_colorcorrect"> | ||
| <multiply name="AlphaGain" type="float"> | ||
| <input name="in1" type="float" nodename="inputAlpha" /> | ||
| <input name="in2" type="float" interfacename="AlphaGain_in2" /> | ||
| </multiply> | ||
| <add name="AlphaOffset" type="float"> | ||
| <input name="in1" type="float" nodename="AlphaGain" /> | ||
| <input name="in2" type="float" interfacename="AlphaOffset_in2" /> | ||
| </add> | ||
| <multiply name="ColorGain" type="color3"> | ||
| <input name="in1" type="color3" nodename="inputColor" /> | ||
| <input name="in2" type="color3" interfacename="ColorGain_in2" /> | ||
| </multiply> | ||
| <add name="ColorOffset" type="color3"> | ||
| <input name="in1" type="color3" nodename="ColorGain" /> | ||
| <input name="in2" type="color3" interfacename="ColorOffset_in2" /> | ||
| </add> | ||
| <constant name="inputColor" type="color3"> | ||
| <input name="value" type="color3" interfacename="inputColor_value" /> | ||
| </constant> | ||
| <constant name="inputAlpha" type="float"> | ||
| <input name="value" type="float" interfacename="inputAlpha_value" /> | ||
| </constant> | ||
| <output name="out" type="color3" nodename="ColorOffset" /> | ||
| <output name="out1" type="float" nodename="AlphaOffset" /> | ||
| </nodegraph> | ||
| <input name="AlphaGain_in2" type="float" value="0.8" uiname="AlphaGain in2" uifolder="Common" /> | ||
| <input name="AlphaOffset_in2" type="float" value="1" uiname="AlphaOffset in2" uifolder="Common" /> | ||
| <input name="ColorGain_in2" type="color3" value="0.9, 0.9, 0.9" uiname="ColorGain in2" uifolder="Common" /> | ||
| <input name="ColorOffset_in2" type="color3" value="0.379147, 0.0341412, 0.0341412" uiname="ColorOffset in2" uifolder="Common" /> | ||
| <input name="inputColor_value" type="color3" value="0.5, 0.5, 0.5" uiname="inputColor value" uifolder="Common" /> | ||
| <input name="inputAlpha_value" type="float" value="1" uiname="inputAlpha value" uifolder="Common" /> | ||
| <output name="out" type="color3" /> | ||
| <output name="out1" type="float" /> | ||
| </nodedef> | ||
| <test_colorcorrect name="test_colorcorrect_instance" version="1.0" type="multioutput"> | ||
| <input name="inputColor_value" type="color3" value="0.0, 0.0, 0.0" /> | ||
| <input name="ColorOffset_in2" type="color3" value="1.0, 0.0, 0.0" /> | ||
| <output name="out" type="color3" /> | ||
| </test_colorcorrect> | ||
| <surface_unlit name="surface_unlit" type="surfaceshader"> | ||
| <input name="emission_color" type="color3" output="out" nodename="test_colorcorrect_instance" /> | ||
| </surface_unlit> | ||
| </materialx> |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -741,7 +741,14 @@ void NodeGraph::modifyInterfaceName(const string& inputPath, const string& inter | |
|
|
||
| NodeDefPtr NodeGraph::getNodeDef() const | ||
| { | ||
| NodeDefPtr nodedef = resolveNameReference<NodeDef>(getNodeDefString()); | ||
| ElementPtr parent = getSelfNonConst()->getParent(); | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. "Backwards" search looks for parent definitions now. |
||
| NodeDefPtr nodedef = parent->asA<NodeDef>(); | ||
| if (nodedef) | ||
| { | ||
| return nodedef; | ||
| } | ||
|
|
||
| nodedef = resolveNameReference<NodeDef>(getNodeDefString()); | ||
| // If not directly defined look for an implementation which has a nodedef association | ||
| if (!nodedef) | ||
| { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,6 +12,8 @@ | |
| #include <MaterialXFormat/XmlIo.h> | ||
| #include <MaterialXFormat/Util.h> | ||
|
|
||
| #include <iostream> | ||
|
|
||
| namespace mx = MaterialX; | ||
|
|
||
| bool isTopologicalOrder(const std::vector<mx::ElementPtr>& elems) | ||
|
|
@@ -675,7 +677,64 @@ TEST_CASE("Organization", "[nodegraph]") | |
| CHECK(nodeGraph->getBackdrops().empty()); | ||
| } | ||
|
|
||
| TEST_CASE("Node Definition Creation", "[nodedef]") | ||
| void testFunctionalNodeDef() | ||
| { | ||
| mx::FileSearchPath searchPath = mx::getDefaultDataSearchPath(); | ||
| mx::DocumentPtr doc = mx::createDocument(); | ||
| mx::readFromXmlFile(doc, "resources/Materials/TestSuite/stdlib/definition/functional_nodedef.mtlx", searchPath); | ||
|
|
||
| std::vector<mx::NodeDefPtr> nodedefs = doc->getNodeDefs(); | ||
| for (mx::NodeDefPtr nodeDef : nodedefs) | ||
| { | ||
| std::string nodeDefName = nodeDef->getName(); | ||
| std::string nodeGraphName = "NG_" + nodeDefName.substr(3); // Remove the 'ND_' prefix | ||
|
|
||
| mx::InterfaceElementPtr implementation = nodeDef->getImplementation(); | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Basic child nodegraph implementation search test. |
||
| REQUIRE(implementation != nullptr); | ||
| std::string msg = "Testing NodeDef: " + nodeDefName + " with implementation: " + implementation->getName(); | ||
| INFO(msg); | ||
| mx::NodeGraphPtr functionalNodeGraph = implementation->asA<mx::NodeGraph>(); | ||
| REQUIRE(functionalNodeGraph != nullptr); | ||
| if (functionalNodeGraph) | ||
| { | ||
| // Test that the child nodegraph is found via implementation search | ||
| REQUIRE(functionalNodeGraph->getName() == nodeGraphName); | ||
|
|
||
| // Test that this is actually a child nodegraph of the NodeDef | ||
| std::vector<mx::NodeGraphPtr> childNodeGraphs = nodeDef->getChildrenOfType<mx::NodeGraph>(); | ||
| for (mx::NodeGraphPtr childNodeGraph : childNodeGraphs) | ||
| { | ||
| if (childNodeGraph->getName() == nodeGraphName) | ||
| { | ||
| // Test that the child nodegraph is the functional graph | ||
| REQUIRE(childNodeGraph == functionalNodeGraph); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| std::string referenceGraphName = nodeGraphName + "_reference"; | ||
| mx::NodeGraphPtr referenceNodeGraph = doc->getNodeGraph(referenceGraphName); | ||
| REQUIRE(referenceNodeGraph != nullptr); | ||
| if (referenceNodeGraph) | ||
| { | ||
| referenceNodeGraph->setNodeDefString(nodeDefName); | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Superscede the child nodegraph impl with one that is not a child. As all changes cause a nodedef->impl cache rebuild this allows for this dynamic behaviour. |
||
|
|
||
| mx::InterfaceElementPtr implementation = nodeDef->getImplementation(); | ||
| REQUIRE(implementation != nullptr); | ||
| std::string msg = "Testing NodeDef: " + nodeDefName + " with implementation: " + implementation->getName(); | ||
| INFO(msg); | ||
| mx::NodeGraphPtr functionalNodeGraph = implementation->asA<mx::NodeGraph>(); | ||
| REQUIRE(functionalNodeGraph != nullptr); | ||
| if (functionalNodeGraph) | ||
| { | ||
| // Test the functional node graph is the reference graph | ||
| REQUIRE(functionalNodeGraph->getName() == referenceGraphName); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void testNodeDefCreationFromGraph(mx::DefinitionOptions options) | ||
| { | ||
| mx::FileSearchPath searchPath = mx::getDefaultDataSearchPath(); | ||
| mx::DocumentPtr stdlib = mx::createDocument(); | ||
|
|
@@ -714,10 +773,12 @@ TEST_CASE("Node Definition Creation", "[nodedef]") | |
| bool isDefaultVersion = false; | ||
| const std::string NODENAME = graph->getName(); | ||
|
|
||
|
|
||
| // Create a new functional graph and definition from a compound graph | ||
| bool addAsChild = options.addImplementationAsChild; | ||
| std::string newNodeDefName = doc->createValidChildName("ND_" + graph->getName()); | ||
| std::string newGraphName = doc->createValidChildName("NG_" + graph->getName()); | ||
| mx::NodeDefPtr nodeDef = doc->addNodeDefFromGraph(graph, newNodeDefName, NODENAME, newGraphName); | ||
| mx::NodeDefPtr nodeDef = doc->addNodeDefFromGraph(graph, newNodeDefName, NODENAME, newGraphName, &options); | ||
| REQUIRE(nodeDef != nullptr); | ||
| nodeDef->setVersionString(VERSION1); | ||
| nodeDef->setDefaultVersion(isDefaultVersion); | ||
|
|
@@ -759,9 +820,16 @@ TEST_CASE("Node Definition Creation", "[nodedef]") | |
| } | ||
|
|
||
| // Check validity of new functional nodegraph | ||
| mx::NodeGraphPtr newGraph = doc->getNodeGraph(newGraphName); | ||
| mx::NodeGraphPtr newGraph = !addAsChild ? doc->getNodeGraph(newGraphName) : nodeDef->getChildOfType<mx::NodeGraph>(newGraphName); | ||
| REQUIRE(newGraph != nullptr); | ||
| REQUIRE(newGraph->getNodeDefString() == newNodeDefName); | ||
| if (!addAsChild) | ||
| { | ||
| REQUIRE(newGraph->getNodeDefString() == newNodeDefName); | ||
| } | ||
| else | ||
| { | ||
| REQUIRE(newGraph->getNodeDefString().empty()); | ||
| } | ||
| mx::ConstInterfaceElementPtr decl = newGraph->getDeclaration(); | ||
| REQUIRE(decl->getName() == nodeDef->getName()); | ||
| REQUIRE(doc->validate()); | ||
|
|
@@ -826,6 +894,28 @@ TEST_CASE("Node Definition Creation", "[nodedef]") | |
| REQUIRE(doc->validate()); | ||
| } | ||
|
|
||
| TEST_CASE("Node Definition Creation", "[nodedef_create]") | ||
| { | ||
| mx::DefinitionOptions defOptions; | ||
|
|
||
| SECTION("Without implementation as child") | ||
| { | ||
| defOptions.addImplementationAsChild = false; | ||
| testNodeDefCreationFromGraph(defOptions); | ||
| } | ||
|
|
||
| SECTION("With implementation as child") | ||
| { | ||
| defOptions.addImplementationAsChild = true; | ||
| testNodeDefCreationFromGraph(defOptions); | ||
| } | ||
|
|
||
| SECTION("Functional NodeDef test") | ||
| { | ||
| testFunctionalNodeDef(); | ||
| } | ||
| } | ||
|
|
||
| TEST_CASE("Set Name Global", "[node, nodegraph]") | ||
| { | ||
| mx::DocumentPtr doc = mx::createDocument(); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Backwards" search looks for parent definitions now.