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

    How to group nodes in a Scaffold using Python

    Cinema 4D SDK
    2024 python
    2
    3
    614
    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.
    • D
      danielsian
      last edited by

      Hi, I've been searching for examples on how to add nodes to a scaffold group in Python, but there is nothing available and the documentation is not helping too much as well....

      This is what I was trying to do, creating a material based on the example from github and adding a scaffold and then trying to move some nodes into it. But of course it is not working as this is just an attempt from a trial and error.
      Any help would be appreciated.

      Thanks

      import c4d
      import maxon
      
      doc: c4d.documents.BaseDocument
      
      def main():
      
        urlTexRust: maxon.Url = maxon.Url(r"asset:///file_edb3eb584c0d905c")
        urlTexSketch: maxon.Url = maxon.Url(r"asset:///file_3b194acc5a745a2c")
      
        # The node asset IDs
        idTextureNode: maxon.Id = maxon.Id("com.redshift3d.redshift4c4d.nodes.core.texturesampler")
        idMixNode: maxon.Id = maxon.Id("com.redshift3d.redshift4c4d.nodes.core.rscolormix")
        idRsStandardMaterial: maxon.Id = maxon.Id("com.redshift3d.redshift4c4d.nodes.core.standardmaterial")
      
        # Instantiate a material, get its node material and the 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()
        graph: maxon.GraphModelRef = nodeMaterial.CreateDefaultGraph(
          maxon.Id("com.redshift3d.redshift4c4d.class.nodespace"))
        if graph.IsNullValue():
          raise RuntimeError("Could not add RS graph to material.")
      
        # Get the Standard Material node
        result: list[maxon.GraphNode] = []
        maxon.GraphModelHelper.FindNodesByAssetId(graph, idRsStandardMaterial, True, result)
        if len(result) < 1:
          raise RuntimeError("Could not find RS Standard node in material.")
        standardNode: maxon.GraphNode = result[0]
      
        with graph.BeginTransaction() as transaction:
          # 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)
      
          mixAmount: maxon.GraphNode = mixNode.GetInputs().FindChild(
            "com.redshift3d.redshift4c4d.nodes.core.rscolormix.mixamount")
          mixAmount.SetDefaultValue(0.5)
      
          # Get the ports and set the values
          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.SetDefaultValue(urlTexRust)
          pathSketchPort.SetDefaultValue(urlTexSketch)
      
          # 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 ports
          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 = standardNode.GetInputs().FindChild(
            "com.redshift3d.redshift4c4d.nodes.core.standardmaterial.base_color")
      
          # Connect the nodes
          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)
      
          transaction.Commit()
      
        # Find all the texture nodes
        tex_nodes = []
        maxon.GraphModelHelper.FindNodesByAssetId(graph, idTextureNode, True, tex_nodes)
      
        ################################
        #  my attempt of grouping the texture nodes in a Scaffold
        #
        with graph.BeginTransaction() as transaction:
          scaffold = graph.AddChild(maxon.Id(), maxon.Id("net.maxon.node.scaffold"))
          graph.MoveToGroup(scaffold, maxon.Id("idOfMyGroup"), tex_nodes)
          transaction.Commit()
        #  
        ################################
        
        doc.InsertMaterial(material)
        doc.SetActiveMaterial(material)
        c4d.EventAdd()
      
      if __name__ == "__main__":
        main()
      
      1 Reply Last reply Reply Quote 0
      • M
        m_adam
        last edited by

        Hi @danielsian you need to define the scaffold ID.

          # Find all the texture nodes
          tex_nodes = []
          maxon.GraphModelHelper.FindNodesByAssetId(graph, idTextureNode, True, tex_nodes)
        
          with graph.BeginTransaction() as transaction:
            scaffold = graph.AddChild(maxon.Id(), maxon.Id("net.maxon.node.scaffold"))
            
            for node in tex_nodes:
                node.SetValue("net.maxon.node.attribute.scaffoldid", scaffold.GetId())
                
            transaction.Commit()
        

        Cheers,
        Maxime.

        MAXON SDK Specialist

        Development Blog, MAXON Registered Developer

        1 Reply Last reply Reply Quote 0
        • D
          danielsian
          last edited by

          Hey @m_adam ,

          Thanks for your help. It works now.

          However, I'm wondering how I would have known that I needed to set the scaffold ID to the node. The documentation doesn't seem to explicitly mention this step. I might be wrong, but for someone without strong knowledge of the API, I'd never thought that way. I would rather added the selected nodes to a group, as this is what a scaffol is. Does that make sense?

          As a side note, after adding the nodes to the scaffold group, they appear messy, actually the nodes are nicely arranged inside the group, but the scaffold is overlapping other nodes. This is likely related to the bug we discussed here: https://developers.maxon.net/forum/post/73446. Am I right?

          Cheers

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