SOLVED Append string the node path in retrieving the port?


Does not work
color_space_port= node.GetInputs().FindChild("com.redshift3d.redshift4c4d.nodes.core.texturesampler.tex0.colorspace")

What works
tex_parent_port = node.GetInputs().FindChild("com.redshift3d.redshift4c4d.nodes.core.texturesampler.tex0")
color_space_port= tex_parent_port .FindChild("colorspace")

I initially thought that just appending and hard coding the string works. But apparently, it does not. I have to use the FindChild even though I already know the actual path of the parameter/port.

Is this how it really behaves or am I missing something?

P.S. I understand that its trivial. But I guess its more pythonic to just use the "." notation to retrive the parameters/attributes of a node.

For example,

easier to read rather than daisy chaining several FindChild methods.

Hello @bentraje,

Thank you for reaching out to us.

FindChild takes an Id or node kind as its argument, ...texturesampler.tex0 is a valid node ID for the Redshift Texture node, ...texturesampler.tex0.colorspace is not, there is simply no such node.

The Filename (com.redshift3d.redshift4c4d.nodes.core.texturesampler.tex0) in-port of the Redshift Texture node is a port bundle, i.e., is a port that has child-ports. Its child port Color Space for example, has simply the ID colorspace and its Path child port the ID path.

I guess you want to save some vertical script space, the things you can do are:

  1. Just write it into one chained instruction: colorSpaceOutPort = node.GetInputs().FindChild("com.redshift3d.redshift4c4d.nodes.core.texturesampler.tex0").FindChild("colorspace")
  2. Use maxon.GraphModelHelper.ListAllNodess to retrieve all nodes in a graph that are have the ID colorspace. This will indeed list all nodes that have that ID, and GraphModelHelper was not available in R25.
  3. Use node paths, node paths sort of do what you want to be done. A node path is represented by the type NodePathInterface. There are multiple methods in the Nodes API which operate on node paths, the relevant for your use case would be GraphModelInterface.GetNode. But Node paths are not easy to construct by hand, as they must uniquely identify anything in a graph, so, when you have two Texture>Filename>Color Space node-trees in your graph, a node path must disambiguate them. There is also GraphNode.FindInnerNode which takes a relative node path as an argument, so you can index ports from a (true) node with it.

I personally would not do any of this. The Nodes API can produce code that is longer than one is comfortable with, this is true. But if you start condensing your code to extreme levels of abstraction, you won't be able to read any of it six months later (the "when I wrote this, only God and I knew what it meant, now only God knows"-effect). Be verbose in your code, especially when an API is complex, this is the best thing you can do for readability and maintainability.

We are aware of the problems of the Nodes API, and that especially technical artist type users wish for easier interfaces, "to just plug things together". But the Nodes API effectively implements a modern graph database model which is inherently complex. So, it is at least not easy to do this, without nullifying everything the Nodes API want to achieve: A strong abstraction of a scene/material graph. As indicated by GraphModelHelper, we are already working on this, but the Nodes API will probably be never as straight forward as a classic API scene graph was, simply because it is much more abstract.

What also plays into this, is that maxon attributes for Redshift IDs have not been exposed. It makes a big difference if you have to write node.GetInputs().FindChild("com.redshift3d.redshift4c4d.nodes.core.texturesampler.tex0") or if you can write node.GetInputs().FindChild(maxon.redshift.texturesampler.filename), but the C++ maxon attributes which would be necessary for this to trickle down to Python do not yet exist. I am lobbying for this since R25, but the Redshift team never got to it, next time we will talk, I will bug them again about this 😉



Thanks for the clarification and offering some alternatives.
I guess it has something do with how it was designed.

There is a FindChild equivalent in other DCC API too like in maya there is a GetAttr or something.
But again, if you know the actual parameter/attribute path like
There's no need. It's straightforward. You use that instead.

Anyhow, will close this thread now.