Maxon Developers Maxon Developers
    • Documentation
      • Cinema 4D Python API
      • Cinema 4D C++ API
      • Cineware API
      • ZBrush GoZ API
      • Code Examples on Github
    • Forum
    • Downloads
    • Support
      • Support Procedures
      • Registered Developer Program
      • Plugin IDs
      • Contact Us
    • Categories
      • Overview
      • News & Information
      • Cinema 4D SDK Support
      • Cineware SDK Support
      • ZBrush 4D SDK Support
      • Bugs
      • General Talk
    • Unread
    • Recent
    • Tags
    • Users
    • Login

    SetPortValue for Texture node ColorSpace

    Cinema 4D SDK
    python 2024 windows
    2
    3
    604
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • M
      Matthew_H
      last edited by

      I checked the forum, and there are few posts that asked the same question yet I still can't get it to work.
      Here is my code:

             # Add a Texture node to the graph
              idTextureNode: maxon.Id = maxon.Id("com.redshift3d.redshift4c4d.nodes.core.texturesampler")
              textureNode: maxon.GraphNode = graph.AddChild(maxon.Id(), idTextureNode)
      
              # Ensure the Texture node was created successfully
              if textureNode.IsNullValue():
                  print("Error: Texture node creation failed.")
                  return
      
              # Set the Color Space port value to RAW
              colorSpacePort: maxon.GraphNode = textureNode.GetInputs().FindChild(
                  "com.redshift3d.redshift4c4d.nodes.core.texturesampler.colorspace")
              if colorSpacePort:
                  try:
                      colorSpacePort.SetPortValue("RS_INPUT_COLORSPACE_RAW ")
                  except Exception as e:
                      print(f"Failed to set color space value: {e}")
      
              # Commit the transaction
              transaction.Commit()
      

      I get this:
      Failed to set color space value: no target to copy for '<net.maxon.graph.interface.graphmodel>'
      All I'm trying to do is set the color space to RAW for incoming normal bitmaps later.
      I'm new to coding, so I am sure I'm doing something wrong here. Help is much appreciated.

      Thank you.

      ferdinandF 1 Reply Last reply Reply Quote 0
      • ferdinandF
        ferdinand @Matthew_H
        last edited by ferdinand

        Hello @Matthew_H,

        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: How to Ask Questions.

        About your First Question

        Please make sure to give us complete, i.e., executable code examples in the future. Any time we must spend on getting to a starting point for a user problem will be subtracted from the time we can spend on a problem. I took in this case one of our existing code examples, but in other cases we might even refuse to answer until the user posts executable code.

        Your code contains three problems:

        1. Validity testing of a node is currently not yet possible via truth testing.
        2. You do not correctly access the Color Space child port in the port bundle Filename.
        3. The value you are tyring to write is incorrect (there is an extra white space at the end of the string).

        When we add all ports to an RS Texture node, it becomes more obvious that the Color Space port is part of a Filename port bundle.
        909084f7-7da7-4e4b-a6ef-04e91e560a6e-image.png

        Find below a code example using one of our Redshift code examples.

        Cheers,
        Ferdinand

        Result

        678f3353-705c-41be-be41-79945d017d1f-image.png

        Code

        The relevant code is within the snip markers:

        #coding: utf-8
        """Demonstrates setting up a Redshift node material composed out of multiple nodes.
        
        Creates a new node material with a graph in the Redshift material space, containing two texture 
        nodes and a mix node, in addition to the default RS Standard Material and Output node of the 
        material.
        
        Topics:
            * Creating a node material and adding a graph.
            * Adding nodes to a graph.
            * Setting the value of ports without wires.
            * Connecting ports with a wires.
        """
        __author__ = "Ferdinand Hoppe"
        __copyright__ = "Copyright (C) 2023 MAXON Computer GmbH"
        __date__ = "04/06/2024"
        __license__ = "Apache-2.0 License"
        __version__ = "2024.0.0"
        
        
        import c4d
        import maxon
        
        doc: c4d.documents.BaseDocument # The active document.
        
        def main() -> None:
            """Runs the example.
            """
            # The asset URLs for the "RustPaint0291_M.jpg" and "Sketch (HR basic026).jpg" texture assets in 
            # "tex/Surfaces/Dirt Scratches & Smudges/". These could also be replaced with local texture URLs,
            # e.g., "file:///c:/textures/stone.jpg". These IDs can be discovered with the #-button in the info
            # area of the Asset Browser.
            urlTexRust: maxon.Url = maxon.Url(r"asset:///file_edb3eb584c0d905c")
            urlTexSketch: maxon.Url = maxon.Url(r"asset:///file_3b194acc5a745a2c")
        
            # The node asset IDs for the two node types to be added in the example; the texture node and the
            # mix node. These and all other node IDs can be discovered in the node info overlay in the 
            # bottom left corner of the Node Editor. Open the Cinema 4D preferences by pressing CTRL/CMD + E
            # and enable Node Editor -> Ids in order to see node and port IDs in the Node Editor.
            idOutputNode: maxon.Id = maxon.Id("com.redshift3d.redshift4c4d.node.output")
            idStandardMaterial: maxon.Id = maxon.Id("com.redshift3d.redshift4c4d.nodes.core.standardmaterial")
            idTextureNode: maxon.Id = maxon.Id("com.redshift3d.redshift4c4d.nodes.core.texturesampler")
            idMixNode: maxon.Id = maxon.Id("com.redshift3d.redshift4c4d.nodes.core.rscolormix")
        
            # Instantiate a material, get its node material, and add a graph for the RS material space.
            material: c4d.BaseMaterial = c4d.BaseMaterial(c4d.Mmaterial)
            if not material:
                raise MemoryError(f"{material = }")
        
            nodeMaterial: c4d.NodeMaterial = material.GetNodeMaterialReference()
            redshiftNodeSpaceId: maxon.Id =  maxon.Id("com.redshift3d.redshift4c4d.class.nodespace")
            graph: maxon.GraphModelRef = nodeMaterial.CreateEmptyGraph(redshiftNodeSpaceId)
            if graph.IsNullValue():
                raise RuntimeError("Could not add Redshift graph to material.")
        
            # Open an undo operation and insert the material into the document. We must do this before we 
            # modify the graph of the material, as otherwise the viewport material will not correctly display 
            # the textures of the material until the user manually refreshes the material. It is also 
            # important to insert the material after we added the default graph to it, as otherwise we will 
            # end up with two undo steps in the undo stack.
            if not doc.StartUndo():
                raise RuntimeError("Could not start undo stack.")
            
            doc.InsertMaterial(material)
            if not doc.AddUndo(c4d.UNDOTYPE_NEWOBJ, material):
                raise RuntimeError("Could not add undo item.")
        
            # Define the user data for the transaction. This is optional, but can be used to tell the Nodes
            # API to add the transaction to the current undo stack instead of creating a new one. This will
            # then have the result that adding the material, adding the graph, and adding the nodes will be
            # one undo step in the undo stack.
            userData: maxon.DataDictionary = maxon.DataDictionary()
            userData.Set(maxon.nodes.UndoMode, maxon.nodes.UNDO_MODE.ADD)
        
            # Start modifying the graph by opening a transaction. Node graphs follow a database like 
            # transaction model where all changes are only finally applied once a transaction is committed.
            with graph.BeginTransaction(userData) as transaction:
        
                # Add the output, i.e., the terminal end node of the graph, as well as a standard material
                # node to the graph.
                outNode: maxon.GraphNode = graph.AddChild(maxon.Id(), idOutputNode)
                materialNode: maxon.GraphNode = graph.AddChild(maxon.Id(), idStandardMaterial)
        
                # Add two texture nodes and a blend node to the graph.
                rustTexNode: maxon.GraphNode = graph.AddChild(maxon.Id(), idTextureNode)
                sketchTexNode: maxon.GraphNode = graph.AddChild(maxon.Id(), idTextureNode)
                mixNode: maxon.GraphNode = graph.AddChild(maxon.Id(), idMixNode)
        
                # Get the input 'Surface' port of the 'Output' node and the output 'Out Color' port of the
                # 'Standard Material' node and connect them.
                surfacePortOutNode: maxon.GraphNode = outNode.GetInputs().FindChild(
                    "com.redshift3d.redshift4c4d.node.output.surface")
                outcolorPortMaterialNode: maxon.GraphNode = materialNode.GetOutputs().FindChild(
                    "com.redshift3d.redshift4c4d.nodes.core.standardmaterial.outcolor")
                outcolorPortMaterialNode.Connect(surfacePortOutNode)
        
                # Set the default value of the 'Mix Amount' port, i.e., the value the port has when no 
                # wire is connected to it. This is equivalent to the user setting the value to "0.5" in 
                # the Attribute Manager.
                mixAmount: maxon.GraphNode = mixNode.GetInputs().FindChild(
                    "com.redshift3d.redshift4c4d.nodes.core.rscolormix.mixamount")
                mixAmount.SetPortValue(0.5)
        
                # Set the path sub ports of the 'File' ports of the two image nodes to the texture URLs 
                # established above. Other than for the standard node space image node, the texture is 
                # expressed as a port bundle, i.e., a port which holds other ports. The texture of a texture
                # node is expressed as the "File" port, of which "Path", the URL, is only one of the possible
                # sub-ports to set.
                pathRustPort: maxon.GraphNode = rustTexNode.GetInputs().FindChild(
                    "com.redshift3d.redshift4c4d.nodes.core.texturesampler.tex0").FindChild("path")
                pathSketchPort: maxon.GraphNode = sketchTexNode.GetInputs().FindChild(
                    "com.redshift3d.redshift4c4d.nodes.core.texturesampler.tex0").FindChild("path")
                pathRustPort.SetPortValue(urlTexRust)
                pathSketchPort.SetPortValue(urlTexSketch)
        
                # --- Snip ---------------------------------------------------------------------------------
        
                # This was not correct, the color space port is not a child of the texture node, but of its
                # Filename port bundle. So, it must be texturesampler.tex0 and not texturesampler. And since
                # it is a port within a port, you need two FindChild calls to get to it.
        
                # colorSpacePort: maxon.GraphNode = textureNode.GetInputs().FindChild(
                #     "com.redshift3d.redshift4c4d.nodes.core.texturesampler.colorspace")
        
                colorSpacePort: maxon.GraphNode = rustTexNode.GetInputs().FindChild(
                    "com.redshift3d.redshift4c4d.nodes.core.texturesampler.tex0").FindChild("colorspace")
                
                # When you want to check if a retrieved graph node is valid, simple truth testing does 
                # unfortunately not (yet) work (Maxime has it on his bucket list). Instead, you must call:
                if not colorSpacePort.IsValid():
                    raise RuntimeError("Could not find the color space port.")
                
                # Set the color space of the texture node to "RS_INPUT_COLORSPACE_RAW".
                colorSpacePort.SetPortValue("RS_INPUT_COLORSPACE_RAW")
        
                # --- Snip ---------------------------------------------------------------------------------
        
                # Get the color output ports of the two texture nodes and the color blend node.
                rustTexColorOutPort: maxon.GraphNode = rustTexNode.GetOutputs().FindChild(
                    "com.redshift3d.redshift4c4d.nodes.core.texturesampler.outcolor")
                sketchTexColorOutPort: maxon.GraphNode = sketchTexNode.GetOutputs().FindChild(
                    "com.redshift3d.redshift4c4d.nodes.core.texturesampler.outcolor")
                mixColorOutPort: maxon.GraphNode = mixNode.GetOutputs().FindChild(
                    "com.redshift3d.redshift4c4d.nodes.core.rscolormix.outcolor")
        
                # Get the fore- and background port of the blend node and the color port of the BSDF node.
                mixInput1Port: maxon.GraphNode = mixNode.GetInputs().FindChild(
                    "com.redshift3d.redshift4c4d.nodes.core.rscolormix.input1")
                mixInput2Port: maxon.GraphNode = mixNode.GetInputs().FindChild(
                    "com.redshift3d.redshift4c4d.nodes.core.rscolormix.input2")
                stdBaseColorInPort: maxon.GraphNode = materialNode.GetInputs().FindChild(
                    "com.redshift3d.redshift4c4d.nodes.core.standardmaterial.base_color")
        
                # Wire up the two texture nodes to the blend node and the blend node to the BSDF node.
                rustTexColorOutPort.Connect(mixInput1Port, modes=maxon.WIRE_MODE.NORMAL, reverse=False)
                sketchTexColorOutPort.Connect(mixInput2Port, modes=maxon.WIRE_MODE.NORMAL, reverse=False)
                mixColorOutPort.Connect(stdBaseColorInPort, modes=maxon.WIRE_MODE.NORMAL, reverse=False)
        
                # Finish the transaction to apply the changes to the graph.
                transaction.Commit()
        
            if not doc.EndUndo():
                raise RuntimeError("Could not end undo stack.")
        
            c4d.EventAdd()
            
        if __name__ == "__main__":
            main()
        

        MAXON SDK Specialist
        developers.maxon.net

        1 Reply Last reply Reply Quote 0
        • M
          Matthew_H
          last edited by

          Thank you so much, this was very helpful to learn.
          All the best.

          1 Reply Last reply Reply Quote 0
          • First post
            Last post