uiname for inputs only seem to work on node def inputs.
Hi,
Not sure the title is the best, but I wasn't sure how to phrase it, so here is a better description:
I'm creating a simple material graph, and I'd like to customize the ui name of a few inputs. E.g. for instance I have an image node named diffuse. When loading into MaterialX view, in the property editor the filename of that node would then appear as diffuse:filename.
I'd like that to appear as Diffuse Filename for instance. So I tried using the uiname attribute, but unfortunately: https://github.com/AcademySoftwareFoundation/MaterialX/blob/7228592bedb75492db88018da230c1a852408eeb/source/MaterialXRender/Util.cpp#L110-L113
This will always use the input def, thus ignoring the uiname on the attribute itself.
Is this intentional? Would it be acceptable to consider both the input def and the input when extracting UI properties? For instance checking first the input, and if it doesn't have a property, checking the input def? (which would then act kind of a like a default)
Hi @ix-dcourtois,
According to the spec uiname is only defined when on a nodedef input.
https://materialx.org/assets/MaterialX.v1.38.Spec.pdf#page=51
But, if your encapsulating things into a nodegraph, I think the "best" you can do is to add an interface input connected to an internal node input and use a more "user friendly" name. But, AFAIK, you can't specify a uiname on an interface input for a nodegraph either (which seems useful).
Otherwise the only option, I think is to create a nodedef from your nodegraph.
Ah, too bad :(
It feels like an arbitrary limitation from the spec though... wouldn't it make sense to also allow uiname (and other customization attributes) on regular inputs? From the code's perspective, the changes required to handle this would be fairly localized and simple (in the function I mentioned, it would just be a matter of checking the input itself first, and fallback to its def in case the attribute is not defined) and from a user's perspective, it would also feel quite ok: the def would provide a default, and then we would still have the possibility to customize the ui without having to bring out the heavy machniery of nodedef, etc.
I agree.
I guess it depends on how complex this can get. For example, can you specify a uiname on a node input and its graph interface. I believe there is nothing new in terms of logic so not hard to understand or implement.
The second item is which ui "things" can you specify. Uiname seems a good first candidate but would need to discuss if others make any sense. For example, dont think you want to allow this at the node level, nor allow attributes like uimin, uimax on instances would you?
Giving a ping to @dbsmythe and @jstone-lucasfilm for thoughts.
I was thinking about all the attributes starting with ui. Basically things that are only "hints" for how to present things to users, not things that actually change the material behavior.
And generally speaking I tend to avoid trying to second guess what people would want: it's very hard to know which of those ui attributes will make sense in what DCC/workflow/etc. So yes, while in my case right now I only need uiname and uifolder, there's no guarantee that I or someone else won't ever have the need to override some other ui attribute for any reason. Basically I can't see any "cons" to allow overriding all ui attributes instead of just a few, while the "pros" are pretty obvious :)
(this above is my personal opinion for the sake of discussion :p)
Edit: I've patched the getUIProperties function in my clone of MaterialX to test this, and it works fine with very limited modifications. I can post the diff here, or open a PR if necessary.
Hmm. I just checked the stock marble example, and uiname is specified on the interface inputs for the nodegraph and seems to show up.
<input name="base_color_1" type="color3" value="0.8, 0.8, 0.8" uiname="Color 1" uifolder="Marble Color" />
<input name="base_color_2" type="color3" value="0.1, 0.1, 0.3" uiname="Color 2" uifolder="Marble Color" />
<input name="noise_scale_1" type="float" value="6.0" uisoftmin="1.0" uisoftmax="10.0" uiname="Scale 1" uifolder="Marble Noise" />
<input name="noise_scale_2" type="float" value="4.0" uisoftmin="1.0" uisoftmax="10.0" uiname="Scale 2" uifolder="Marble Noise" />
<input name="noise_power" type="float" value="3.0" uisoftmin="1.0" uisoftmax="10.0" uiname="Power" uifolder="Marble Noise" />
<input name="noise_octaves" type="integer" value="3" uisoftmin="1" uisoftmax="8" uiname="Octaves" uifolder="Marble Noise" />
It could be written incorrectly as it's been a while since I worked on this.
I guess you want this to work on nodes internal to a graph or just nodes in general ? If it's nodes internal to the graph, then creating the interface input seems to work...
In the case of the marble, the input is a node graph input. It doesn't have any corresponding input in a nodedef. And thus the getUIProperties will use the actual input, which works.
This is my (simplified) case:
<?xml version="1.0"?>
<materialx version="1.38">
<surface name="mx_surface" type="surfaceshader" nodedef="ND_surface">
<input name="edf" type="EDF" nodename="mx_uniform_edf" />
</surface>
<uniform_edf name="mx_uniform_edf" type="EDF" nodedef="ND_uniform_edf">
<input name="color" type="color3" nodename="diffuse" />
</uniform_edf>
<image name="diffuse" type="color3" nodedef="ND_image_color3">
<input name="file" type="filename" value="D:/Pictures/20180204_105455.jpg" uifolder="Interface" uiname="Diffuse Filename" />
</image>
<surfacematerial name="mx_material" type="material">
<input name="surfaceshader" type="surfaceshader" nodename="mx_surface" />
</surfacematerial>
</materialx>
Here I'm "overridding" the file input of an image node, which has a nodedef. So the getUIProperties function (which I linked above) will actually get and use the nodedef input, thus losing my uiname and uifolder.
Here's the logic for why things are the way they are now regarding uiname and other ui attributes:
- If it's a functional nodegraph, e.g. one that has a nodedef to define the interface, then it's presumed that you want this node definition to be reusable and have potentially multiple instantiations of that nodegraph-defined node. In this case, it doesn't make sense that the UI for one instance of that node has a different UI than another instance of the same node, hence the restriction to not allow
uinameetc on inputs of functional nodegraphs. - If it's a compound nodegraph, e.g. one with no corresponding nodedef, then this is the definition of the UI for the nodegraph (and the nodegraph can't be instantiated multiple times), so it makes sense to allow
uinameetc. definitions on the top-level inputs, as is done in the standard_surface_marble_solid.mtlx example. Note that inputs to nodes within the compound nodegraph may not specify a uiname: those are local to the scope inside the nodegraph and are not publicly-accessible: they must instead connect viainterfacenameto the top-level input interface.
Your simplified case above is neither of the above: the nodes are not contained within a nodegraph at all. In theory, it wouldn't hurt to make it allowable to add uinames on such free-floating non-nodegraph-wrapped inputs, but I fear this could make the coding rules to determine whether a uiname should be allowed on a particular input and which uiname should take precedence a bit tricky. The current proper thing to do if you want to create a named UI is to wrap your whole example within a (compound) nodegraph, put the UI interface parameter inputs there, and use interfacename connections from your node inputs to the interface inputs. However, I'm open to discussion about whether the community thinks we should allow uiname attributes on inputs of free-floating nodes.
@ix-dcourtois From the discussion above, it sounds like the current behavior is expected in MaterialX 1.38, so I'll close out this issue for now. Going forward, though, we're open to proposals for improved UI name rules in future versions of MaterialX.