Change texture node colorspace
-
Hi
I'm trying to change the colorspace of the selected texture nodes in a existing node material.I came across these topics but am unable to get it to work.
https://developers.maxon.net/forum/topic/14331/editing-rs-nodes-with-python
https://developers.maxon.net/forum/topic/14236/change-the-colorspace-of-redshift-texture-node/4?_=1672651116634Since I'm not very experienced with python, and especially for cinema I took this scripts as a starting point;
https://github.com/PluginCafe/cinema4d_py_sdk_extended/blob/master/scripts/05_modules/node/access_graph_entities_2024_2.pyThis is what I have currently, but I'm getting the following error;
Traceback (most recent call last): File "scriptmanager", line 73, in <module> File "scriptmanager", line 63, in main TypeError: 'InternedId' object is not callable
Anyone able to help me out?
import c4d import maxon doc: c4d.documents.BaseDocument # The active document. def main(): # For the selected mateiral in the currently active document ... for material in doc.GetActiveMaterials(): # ... get its node material reference and step over all materials which do not have a # Redshift graph or where the graph is malformed. nodeMaterial = c4d.NodeMaterial = material.GetNodeMaterialReference() if not nodeMaterial.HasSpace("com.redshift3d.redshift4c4d.class.nodespace"): continue graph = maxon.GraphModelRef = nodeMaterial.GetGraph( "com.redshift3d.redshift4c4d.class.nodespace") if graph.IsNullValue(): raise RuntimeError("Found malformed empty graph associated with node space.") # Get the root of the graph, the node which contains all other nodes. root = maxon.GraphNode = graph.GetRoot() # Iterate over all nodes in the graph, i.e., unpack things like nodes nested in groups. # With the mask argument we could also include ports in this iteration. for node in root.GetInnerNodes(mask=maxon.NODE_KIND.NODE, includeThis=False): # There is a difference between the asset ID of a node and its ID. The asset ID is # the identifier of the node template asset from which a node has been instantiated. # It is more or less the node type identifier. When we have three RS Texture nodes # in a graph they will all have the same asset ID. But their node ID on the other hand # will always be unique to a node. assetId = maxon.Id = node.GetValue("net.maxon.node.attribute.assetid")[0] nodeId = maxon.Id = node.GetId() # Step over everything that is not a Texture node, we could also check here for a node # id, in case we want to target a specific node instance. if assetId != maxon.Id("com.redshift3d.redshift4c4d.nodes.core.texturesampler") and node.GetBit(c4d.BIT_ACTIVE): print("texture node found") port = node.GetInputs().FindChild("com.redshift3d.redshift4c4d.nodes.core.texturesampler.tspace_id") port.SetDefaultValue("RS_INPUT_COLORSPACE_RAW ") if __name__ == "__main__": main()
-
Welcome to the Maxon developers forum and its community, it is great to have you with us!
Getting Started
Before creating your next postings, we would recommend making yourself accustomed with our forum and support procedures. You did not do anything wrong, we point all new users to these rules.
- Forum Overview: Provides a broad overview of the fundamental structure and rules of this forum, such as the purpose of the different sub-forums or the fact that we will ban users who engage in hate speech or harassment.
- Support Procedures: Provides a more in detail overview of how we provide technical support for APIs here. This topic will tell you how to ask good questions and limits of our technical support.
- Forum Features: Provides an overview of the technical features of this forum, such as Markdown markup or file uploads.
It is strongly recommended to read the first two topics carefully, especially the section Support Procedures: Asking Questions.
About your First Question
Hey, could you please share your full source code, the code snippet you shared only has 48 lines, so your error traceback cannot apply. There is also no
InternedId
in your code, which adds to the fact that this traceback cannot stem from the code you show us.But I have nevertheless a good idea what is going wrong for you, stuff like this (there are many instances of this in your code) is wrong:
root = maxon.GraphNode = graph.GetRoot()
What you are probably trying to imitate here, is the type hinting I tend to use in the code I write. I.e., the correct way to write this would be:
root: maxon.GraphNode = graph.GetRoot() # A type hint is preceded by a colon, not the equal sign
This line means: "Get the return value of #graph.GetRoot() and assign it to #root". The type hinting part (
: maxon.GraphNode
) is optional and just means: "I am also claiming that the return type of GetRoot is of typemaxon.GraphNode
." Type hints do not have to hold true, I could have also written therebool
(which is not true) and the code would just run fine. Type hints can be used by static type checkers and then have an impact on the runtime behaviour of code, but I just use type hinting in examples as it tends to make code more verbose, it is easier to see what is going on. Type hints are fully optional and the following line is functionality wise 100% identical:root = graph.GetRoot()
When you do what you did, you will overwrite the type, e.g.:
foo = maxon.InternedId = 5 # This line will now raise "TypeError: 'InternedId' object is not callable" because we both set the # variable #foo and the type attribute InternedId of the maxon module to the (integer object) "5". # So, for Python this now reads like "myId = 5()" and it is politely telling us that it thinks that we # are a bit stupid by trying to call a number. myId = maxon.InternedId() # Just demonstrate the effect, this will print (5, 5, 5, 5) a = b = c = d = 5 print(a, b, c, d)
So, long story short, you must either not use type hints or use
:
instead of=
to use the correct syntax for them.Cheers,
Ferdinand -
Hey, thanks for the help!
I've changed type hinting, just to make sure that was not the source of the problem.
The weird thing is, this is the whole script, so I have no clue where the traceback error is coming from.
InternedId is indeed not in my code.Even this script is giving that error now and that one was working just fine earlier today
https://github.com/PluginCafe/cinema4d_py_sdk_extended/blob/master/scripts/05_modules/node/access_graph_entities_2024_2.pyimport c4d import maxon doc: c4d.documents.BaseDocument # The active document. def main(): # For the selected mateiral in the currently active document ... for material in doc.GetActiveMaterials(): # ... get its node material reference and step over all materials which do not have a # Redshift graph or where the graph is malformed. nodeMaterial: c4d.NodeMaterial = material.GetNodeMaterialReference() if not nodeMaterial.HasSpace("com.redshift3d.redshift4c4d.class.nodespace"): continue graph: maxon.GraphModelRef = nodeMaterial.GetGraph( "com.redshift3d.redshift4c4d.class.nodespace") if graph.IsNullValue(): raise RuntimeError("Found malformed empty graph associated with node space.") # Get the root of the graph, the node which contains all other nodes. root: maxon.GraphNode = graph.GetRoot() # Iterate over all nodes in the graph, i.e., unpack things like nodes nested in groups. # With the mask argument we could also include ports in this iteration. for node in root.GetInnerNodes(mask=maxon.NODE_KIND.NODE, includeThis=False): # There is a difference between the asset ID of a node and its ID. The asset ID is # the identifier of the node template asset from which a node has been instantiated. # It is more or less the node type identifier. When we have three RS Texture nodes # in a graph they will all have the same asset ID. But their node ID on the other hand # will always be unique to a node. assetId: maxon.Id = node.GetValue("net.maxon.node.attribute.assetid")[0] nodeId: maxon.Id = node.GetId() # Step over everything that is not a Texture node, we could also check here for a node # id, in case we want to target a specific node instance. if assetId != maxon.Id("com.redshift3d.redshift4c4d.nodes.core.texturesampler") and node.GetBit(c4d.BIT_ACTIVE): continue print("texture node found") port = node.GetInputs().FindChild("com.redshift3d.redshift4c4d.nodes.core.texturesampler.tspace_id") port.SetPortValue("RS_INPUT_COLORSPACE_RAW ") if __name__ == "__main__": main()
Traceback (most recent call last): File "scriptmanager", line 45, in <module> File "scriptmanager", line 37, in main TypeError: 'InternedId' object is not callable
-
I do not have a scene with which I could run this (creating a Redshift material won't be enough to get to line 45), but since you attempt there to instantiate an ID (
maxon.Id("com.redshift3d.redshift4c4d.nodes.core.texturesampler")
), I would say this is still the old issue. You have to restart your Cinema 4D when you bricked your types in this manner. You interpreter-runtime-persistently overwrote whatmaxon.InternedId
etc. means with your old script(s). -
Okay, I was able to get it to work, now I just need some kind of way to get the selected nodes, is there any way to do this?
node.GetBit(c4d.BIT_ACTIVE)
doesn't seem to work with the new nodes and I'm unable to find a solution so far.Cheers,
Daan -
Please open a new topic for new subjects. See our Support Procedures: Asking Questions.
GetBit
is aBaseList2D
method, yournode
is not aBaseList2D
.