MaterialX icon indicating copy to clipboard operation
MaterialX copied to clipboard

Add Functional NodeDef Support

Open kwokcb opened this issue 9 months ago • 1 comments

Implementation

This are the basic changes to handle the current "functional nodedef" proposal: #2355 as an new way to form associations between a definition and it's nodegraph implementation. This new variant is purely additive for the data model and code logic and API interface and internal logic.

Modifications.

  • Update node definition dictionary in the document cache to consider nodedefs with child nodegraphs (implementations). Non-child implementations have higher precedence.
  • Update definition query for implementations / nodegraphs to check for parent nodedef first.
  • Add DefintionOptions options class to which contains the option to add as child or not. Default is false. Additional arguments can be added here vs a list of args in the previous interface.
  • Update C++ Document::addNodeDefFromGraph() interface to take DefinitionsOptions as a new optional argument.
  • Add in Python and Javascript wrappers.

Tests

  • Add a functional_nodedef.mtlx test used for unit and codegen / render tests.
  • Update unit tests to run definition creation test for both sibling (current) and child (new) options as defined by DefinitionOptions.
  • Update Javascript unit tests. Expected: ✔ Build document ✔ Create NodeDef from NodeGraph with child implementation ✔ Create NodeDef from NodeGraph with referencing implementation
  • Manual testing in graph editor.
    • Value modifications
    • Show definition

Unit Test Results

Definition Created with Sibling Reference

<?xml version="1.0"?>
<materialx version="1.39">
 <nodegraph name="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" />
   <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">
   <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>
 <nodegraph name="NG_test_colorcorrect" nodedef="ND_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>
</materialx>

Definition Created with Child

<?xml version="1.0"?>
<materialx version="1.39">
  <nodegraph name="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" />
    <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>
</materialx>

Graph Editor : Std Library Definition Using Child Nodegraph

https://github.com/user-attachments/assets/f0c70ea9-af13-4e7d-96d7-5fcf65fa34b8

Graph Editor: Created Definition Using Child Nodegraph

  • Instance image

  • Definition Expanded image

kwokcb avatar May 21 '25 20:05 kwokcb

I think this looks good to me.

+1 to reverting the data library change for now - until we have socialized this change and validated its not going to inconvenience anyone if we start to update the data library.

I left one outstanding question about order of precedence - but maybe Ive got the wrong end of the stick....

I will put in a unit test for precedence, remove the stdlib change and add a specific test file for codegen / render tests. Thx.

kwokcb avatar Oct 24 '25 21:10 kwokcb

FYI: @ashwinbhat, after talking with @ld-kerley, I've made it so the logic is easy to extend to handling non nodegraph implementation encapsulation as a future next step. A new spec proposal issue will cover what is required there.

kwokcb avatar Dec 13 '25 17:12 kwokcb