Skip to content
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

Update token support for filename resolve and code generation #1171

Merged
merged 9 commits into from
Apr 22, 2021

Conversation

bernardkwok
Copy link

@bernardkwok bernardkwok commented Apr 21, 2021

Update #1159

Generalize token addition to a string resolver based on Element type.

  • This allows for Interface elements such as <node> and <nodegraph> to add child tokens in the same manner as <geomInfo> elements can via a StringResolver.
  • This is transparent to the user if Element::getResolvedValue() is used consistently.
  • The base logic is to only traversing up to the parent to look for sibling <token> Elements. However if the Element is an <input> and it has an interface then check tokens against that input instead.
  • Potentially UDIM replacement could also be performed in the same manner as this would be Document level tokens. This is not added in this change.
  • Code generation has been updated to properly store resolved values versus the unresolved one.

Example:

The following is a test graph with two tokens "exposed" as part of a compound <nodegraph>
image

with corresponding MTLX:

<?xml version="1.0"?>
<materialx version="1.38">
   <nodegraph name="Tokenized_Image"  >
      <token name="Image_Resolution" type="string" uniform="true" value="2k" uiname="Image Resolution" />
      <token name="Image_Extension" type="string" uniform="true" value="png" uiname="Image Extension" />
      <input name="Image_Filename" type="filename" uniform="true" value="resources/images/cloth_[ImageResolution].[Image_Extension]" />
      <tiledimage name="tiledimage" type="color3" nodedef="ND_tiledimage_color3" >
         <input name="file" type="filename" uniform="true" interfacename="Image_Filename" value="cloth.[Image_Extension]"/>
      </tiledimage>
      <output name="out" type="color3" nodename="tiledimage" />
   </nodegraph>
</materialx>

The resolved name would be resources/images/cloth_2k.png

The GLSL / Vanilla OSL unit tests results look like this:
image

This allows for Interface elements such as nodes and nodegraphs to add any child tokens in the same manner as geominfo elements can.
Currently this is only traversing up to the parent. Potentially UDIM replacement could also be performed in the same manner as this would
be Document level tokens.
Add in nodegraph test with tokens.
@bernardkwok bernardkwok self-assigned this Apr 21, 2021
// Apply any interface tokens to the filename
for (auto token : getActiveTokens())
{
string key = "[" + token->getName() + "]";
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interface tokens use [] delmiters vs <>.

source/MaterialXGenShader/ShaderGraph.cpp Outdated Show resolved Hide resolved
/// Add tokens to string resolver. Derived classes can override this
/// method to add per-class type tokens as desired. The default is to not
/// add any tokens.
virtual void addTokens(StringResolverPtr& /*resolver*/) const;
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addTokens() is a new virtual to allow each class derived from Element to add tokens to a string resolve as desired.
I used Element since it's the only common base class for InterfaceElement (ports) and GeomInfo.

}
}

// Check for any parent tokens
ConstElementPtr parent = getParent();
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will look for elements which are siblings.

@feldstj
Copy link

feldstj commented Apr 21, 2021

Should you add a test case for this?

@bernardkwok bernardkwok requested a review from feldstj April 21, 2021 19:11
<materialx version="1.38">
<nodegraph name="Tokenized_Image" >
<token name="Image_Resolution" type="string" uniform="true" value="2k" uiname="Image Resolution" />
<token name="Image_Extension" type="string" uniform="true" value="png" uiname="Image Extension" />

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: I guess the uniform flag is not used for tokens.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will remove. It was actually done on save of this file.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah yes since the tokens are represented as inputs it writes all input attributes to the file. Not a big issue but we could fix it by adding an attribute ignore list for tokens.

doc->validate();

mx::NodeGraphPtr graph = doc->getNodeGraph("Tokenized_Image");
if (graph)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: Maybe call REQUIRE(graph) here instead, since the test can't run if the test graph cannot be found.


// Test file name substitution creation.
mx::StringResolverPtr resolver = input->createStringResolver();
mx::StringMap substitutions = resolver->getFilenameSubstitutions();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: Maybe use const ref to avoid copy the StringMap.

…okens(). Here interface Inputs have precendence.

Update test to check this confguration as well as non-interfacename inputs.
@@ -317,6 +317,27 @@ InputPtr Input::getInterfaceInput() const
return nullptr;
}

void Input::addTokens(StringResolverPtr& resolver) const
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to customize inputs so that interfaces are taken into consideration. If there is an interface than use tokens at that level.

if (parent)
{
parent->addTokens(resolver);
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: You could call the base class method instead of duplicating that code here, in case it changes in the future.

Copy link

@niklasharrysson niklasharrysson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, and I only had one remaining small comment above.

@bernardkwok bernardkwok merged commit 9bda0ba into adsk_contrib/dev Apr 22, 2021
@bernardkwok bernardkwok deleted the adsk_contrib/interace_tokens branch April 22, 2021 22:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants