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 connect new ports and node ports in the group?

    Cinema 4D SDK
    python 2024
    3
    7
    1.6k
    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.
    • ?
      A Former User
      last edited by

      Snipaste_2023-12-05_10-15-14.png
      I would appreciate it if you could demonstrate the correct way to connect the red lines in the chart.

      import c4d
      import maxon
      from redshift_api import redshift_id as rsID
      
      def create_psr():
      
          mat = doc.GetActiveMaterial()
          if mat is None:
              raise ValueError("There is no selected BaseMaterial")
      
          nodeMaterial = mat.GetNodeMaterialReference()
          if nodeMaterial is None:
              raise ValueError("Cannot retrieve node material reference")
      
          nodespaceId = c4d.GetActiveNodeSpaceId()
      
          nimbusRef = mat.GetNimbusRef(nodespaceId)
          if nimbusRef is None:
              raise ValueError("Cannot retrieve the nimbus ref for that node space")
      
          graph = nimbusRef.GetGraph()
          if graph is None:
              raise ValueError("Cannot retrieve the graph of this nimbus ref")
      
          root = graph.GetRoot()
      
          nodes = []
          root.GetChildren(nodes, maxon.NODE_KIND.NODE)
      
          with graph.BeginTransaction() as transaction:
      
              TexNodeID: maxon.Id = maxon.Id(rsID.StrNodeID("texturesampler")) 
              rsmathabsvectorID: maxon.Id = maxon.Id(rsID.StrNodeID("rsmathabsvector")) 
              rsmathabsID: maxon.Id = maxon.Id(rsID.StrNodeID("rsmathabs")) 
      
              TexNode: maxon.GraphNode = graph.AddChild(maxon.Id(), TexNodeID) 
              P_rsmathabsvector: maxon.GraphNode = graph.AddChild(maxon.Id(), rsmathabsvectorID)
              S_rsmathabsvector: maxon.GraphNode = graph.AddChild(maxon.Id(), rsmathabsvectorID) 
              R_rsmathabs: maxon.GraphNode = graph.AddChild(maxon.Id(), rsmathabsID) 
      
              TexNodeScaleInputPort: maxon.GraphNode = TexNode.GetInputs().FindChild(
                  rsID.StrPortID("texturesampler", "scale"))
              TexNodeOffsetInputPort: maxon.GraphNode = TexNode.GetInputs().FindChild(
                  rsID.StrPortID("texturesampler", "offset"))
              TexNodeRotateInputPort: maxon.GraphNode = TexNode.GetInputs().FindChild(
                  rsID.StrPortID("texturesampler", "rotate"))
      
              P_rsmathabsvectorOutPort: maxon.GraphNode = P_rsmathabsvector.GetOutputs().FindChild(
                  rsID.StrPortID("rsmathabsvector", "out"))
              S_rsmathabsvectorOutPort: maxon.GraphNode = S_rsmathabsvector.GetOutputs().FindChild(
                  rsID.StrPortID("rsmathabsvector", "out"))
              R_rsmathabOutPort: maxon.GraphNode = R_rsmathabs.GetOutputs().FindChild(
                  rsID.StrPortID("rsmathabs", "out"))
              
              P_rsmathabsvectorInputPort: maxon.GraphNode = P_rsmathabsvector.GetInputs().FindChild(
                  rsID.StrPortID("rsmathabsvector", "input"))
              S_rsmathabsvectorInputPort: maxon.GraphNode = S_rsmathabsvector.GetInputs().FindChild(
                  rsID.StrPortID("rsmathabsvector", "input"))
              R_rsmathabInputPort: maxon.GraphNode = R_rsmathabs.GetInputs().FindChild(
                  rsID.StrPortID("rsmathabs", "input"))  
              
              P_rsmathabsvectorOutPort.Connect(TexNodeScaleInputPort, modes=maxon.WIRE_MODE.NORMAL, reverse=False)
              S_rsmathabsvectorOutPort.Connect(TexNodeOffsetInputPort, modes=maxon.WIRE_MODE.NORMAL, reverse=False)
              R_rsmathabOutPort.Connect(TexNodeRotateInputPort, modes=maxon.WIRE_MODE.NORMAL, reverse=False)
      
              GroupNodes = []
              GroupNodes.append(TexNode)
              GroupNodes.append(P_rsmathabsvector)
              GroupNodes.append(S_rsmathabsvector)
              GroupNodes.append(R_rsmathabs)
      
              TexNodeScaleOutPort: maxon.GraphNode = TexNode.GetInputs().FindChild(
                  rsID.StrPortID("texturesampler", "scale"))
      
              groupRoot = maxon.GraphNode()
      
              groupRoot = graph.MoveToGroup(groupRoot, maxon.Id("PSRgroupID"), GroupNodes)
      
              P_InputPort =  maxon.GraphModelHelper.CreateInputPort(groupRoot, "scaleid", "缩放")
              S_InputPort =  maxon.GraphModelHelper.CreateInputPort(groupRoot, "offsetid", "偏移")
              R_InputPort = maxon.GraphModelHelper.CreateInputPort(groupRoot, "rotateid", "旋转")
              PSR_OutputPort = maxon.GraphModelHelper.CreateOutputPort(groupRoot, "psrid", "输出")
              
              transaction.Commit()
      
          c4d.EventAdd()
      
      i_mazlovI 1 Reply Last reply Reply Quote 0
      • i_mazlovI
        i_mazlov @A Former User
        last edited by

        Hello @君心Jay,

        Welcome to the Plugin Café forum and the Cinema 4D development 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 Guidelines, as they line out details about the Maxon SDK Group support procedures. Of special importance are:

        • Support Procedures: Scope of Support: Lines out the things we will do and what we will not do.
        • Support Procedures: Confidential Data: Most questions should be accompanied by code but code cannot always be shared publicly. This section explains how to share code confidentially with Maxon.
        • Forum Structure and Features: Lines out how the forum works.
        • Structure of a Question: Lines out how to ask a good technical question. It is not mandatory to follow this exactly, but you should follow the idea of keeping things short and mentioning your primary question in a clear manner.

        About your First Question

        First of all there is no "correct" way of doing that. The pattern you should use depend on the context of your goal.

        For example, looking at your code snippet it seems that the easiest way for you to make these connections would be to first connect the graph with the outside nodes and then use the MoveToGroup function, which would rewire the connections for you automatically.

        This is, however, not the general case. If you would really like to manually wire these ports, you would simply need to find them inside the group and connect them normally using Connect function. The pitfall here is that once you move your sub-graph to the group, it changes its path. This basically means that you'd need to find these nodes using FindNodesByAssetId or GetInnerNodes functions.

        Please refer to the draft sketch below that shows both approaches (you need to comment/uncomment corresponding function call in main()).

        Cheers,
        Ilia

        Draft sketch:

        import c4d
        import maxon
        
        doc: c4d.documents.BaseDocument
        mat: c4d.BaseMaterial
        nimbusRef: maxon.NimbusBaseInterface
        graph: maxon.GraphModelInterface
        
        def main():
            global doc, mat, nimbusRef, graph
            mat = doc.GetActiveMaterial()
            nimbusRef = mat.GetNimbusRef(c4d.GetActiveNodeSpaceId())
            graph = nimbusRef.GetGraph()
        
            easy_way()
            # manual_wiring()
        
        class rsID:
            def StrNodeID(id: str) -> str:
                return "com.redshift3d.redshift4c4d.nodes.core." + id
            def StrPortID(nodeId: str, portId: str) -> str:
                return "com.redshift3d.redshift4c4d.nodes.core." + nodeId + "." + portId
            
        def easy_way():
            with graph.BeginTransaction() as transaction:
                # The outside value node
                valNode: maxon.GraphNode = graph.AddChild(maxon.Id(), maxon.Id("net.maxon.node.type"))
                valPortOutput: maxon.GraphNode = valNode.GetOutputs().FindChild("out")
        
                # The inside ABS node
                absNode: maxon.GraphNode = graph.AddChild(maxon.Id(), maxon.Id(rsID.StrNodeID("rsmathabs")))
                absPortInput: maxon.GraphNode = absNode.GetInputs().FindChild(rsID.StrPortID("rsmathabs", "input"))
                absPortOutput: maxon.GraphNode = absNode.GetOutputs().FindChild(rsID.StrPortID("rsmathabs", "out"))
        
                # Existing Standard material node
                stdMatNodes: list[maxon.GraphNode] = []
                maxon.GraphModelHelper.FindNodesByAssetId(graph, maxon.Id(rsID.StrNodeID("standardmaterial")), True, stdMatNodes)
                matNode: maxon.GraphNode = stdMatNodes[0]
                matPortOpac: maxon.GraphNode = matNode.GetInputs().FindChild(rsID.StrPortID("standardmaterial", "opacity_color"))
        
                # Connect everything in place
                valPortOutput.Connect(absPortInput)
                absPortOutput.Connect(matPortOpac)
        
                # Move to group -> rewiring is handled automatically
                graph.MoveToGroup(maxon.GraphNode(), maxon.Id("PSRgroupID"), [absNode])
        
                transaction.Commit()
            c4d.EventAdd()
            
        def manual_wiring():
            with graph.BeginTransaction() as transaction:
                # The outside value node
                valNode: maxon.GraphNode = graph.AddChild(maxon.Id(), maxon.Id("net.maxon.node.type"))
                valPortOutput: maxon.GraphNode = valNode.GetOutputs().FindChild("out")
        
                # The inside ABS node
                absNode: maxon.GraphNode = graph.AddChild(maxon.Id(), maxon.Id(rsID.StrNodeID("rsmathabs")))
        
                # Existing Standard material node
                stdMatNodes: list[maxon.GraphNode] = []
                maxon.GraphModelHelper.FindNodesByAssetId(graph, maxon.Id(rsID.StrNodeID("standardmaterial")), True, stdMatNodes)
                matNode: maxon.GraphNode = stdMatNodes[0]
                matPortOpac: maxon.GraphNode = matNode.GetInputs().FindChild(rsID.StrPortID("standardmaterial", "opacity_color"))
        
                # Move to group straight away
                groupRoot = graph.MoveToGroup(maxon.GraphNode(), maxon.Id("PSRgroupID"), [absNode])
        
                # Create group ports
                groupPortInputOutside: maxon.GraphNode =  maxon.GraphModelHelper.CreateInputPort(groupRoot, "group_input_id", "grpInput")
                groupPortOutputOutside: maxon.GraphNode =  maxon.GraphModelHelper.CreateOutputPort(groupRoot, "group_output_id", "grpOutput")
        
                # Connect group to the outside nodes
                valPortOutput.Connect(groupPortInputOutside)
                groupPortOutputOutside.Connect(matPortOpac)
                
                # Find innder node
                innerNodes: list[maxon.GraphNode] = []
                maxon.GraphModelHelper.FindNodesByAssetId(graph, maxon.Id(rsID.StrNodeID("rsmathabs")), True, innerNodes)
                absNodeInner: maxon.GraphNode = innerNodes[0]
        
                # Find inner node ports
                absNodeInnerInput: maxon.GraphNode = absNodeInner.GetInputs().FindChild(rsID.StrPortID("rsmathabs", "input"))
                absNodeInnerOutput: maxon.GraphNode = absNodeInner.GetOutputs().FindChild(rsID.StrPortID("rsmathabs", "out"))
        
                # Connect inner node ports to group ports
                groupPortInputOutside.Connect(absNodeInnerInput)
                absNodeInnerOutput.Connect(groupPortOutputOutside)
                
                transaction.Commit()
            c4d.EventAdd()
        
        if __name__ == '__main__':
            main()
        

        MAXON SDK Specialist
        developers.maxon.net

        DunhouD 1 Reply Last reply Reply Quote 2
        • DunhouD
          Dunhou @i_mazlov
          last edited by

          Hi @i_mazlov , thanks for the great answer.

          I would like to further inquire about this issue:

          1. if there are more than one "same id" nodes, how to make sure that the child of innerNodes list is the node we want, I test GraphNode.GetParent() and didn't return the "Group node" but return a path "Root", and I didn't found a method to check if a GraphNode is a child of a Group, how do we do that?

          2. If we use GraphNode.GetInnerNodes(), is it a better choice for this case, and if there some hidden danger for this?

                  # Find innder node
                  innerNodes: list[maxon.GraphNode] = []
                  groupRoot.GetInnerNodes(maxon.NODE_KIND.NODE,False,innerNodes)
          

          Thanks for your time!

          Cheers~
          DunHou

          https://boghma.com
          https://github.com/DunHouGo

          DunhouD i_mazlovI 2 Replies Last reply Reply Quote 0
          • DunhouD
            Dunhou @Dunhou
            last edited by Dunhou

            Hi there,

            Taking inspiration from this topic, I added UniTransform to the my RenderFlow plugin and added AddUniTransform to my renderEngine library, those will be add on the next update.

            Here is a quick preview, have fun.

            Cheers~
            DunHou

            unitrans.gif

            https://boghma.com
            https://github.com/DunHouGo

            1 Reply Last reply Reply Quote 1
            • ?
              A Former User
              last edited by

              Hi @i_mazlov , thanks for the great answer.
              I've learned a lot

              Cheers~
              君心Jay

              1 Reply Last reply Reply Quote 0
              • i_mazlovI
                i_mazlov @Dunhou
                last edited by

                Hi, @Dunhou ,

                Regarding your questions.

                if there are more than one "same id" nodes, how to make sure that the child of innerNodes list is the node we want

                Nodes cannot have the same ID, so you can easily distinguish them by it (GetId() function) or search for it with FindNodesById() function. The way you determine if current node is what you're looking for depends on the criteria you apply to this node. For example, you can filter nodes by their AssetId (using FindNodesByAssetId() function call as I showed above) or you can filter them by name (FindNodesByName()), or you can list nodes by some arbitrary condition (or set of conditions) using ListAllNodes().

                I didn't found a method to check if a GraphNode is a child of a Group

                The GetParent() function should do this for you, for example:

                    with graph.BeginTransaction() as transaction:
                        absNode: maxon.GraphNode = graph.AddChild(maxon.Id(), maxon.Id("com.redshift3d.redshift4c4d.nodes.core.rsmathabs"))
                        groupRoot: maxon.GraphNode = graph.MoveToGroup(maxon.GraphNode(), maxon.Id("myFancyGroupId"), [absNode])
                        absNode = groupRoot.FindChild(absNode.GetId())
                        print(groupRoot.GetId())
                        print(absNode.GetParent().GetId())
                        transaction.Commit()
                

                If we use GraphNode.GetInnerNodes(), is it a better choice for this case, and if there some hidden danger for this?

                Yes, probably reducing the scope to node's children would be more efficient here. I assume in this particular case FindChild() function would have been the best choice. However, you wouldn't notice any performance difference on such a small graph.

                Cheers,
                Ilia

                MAXON SDK Specialist
                developers.maxon.net

                DunhouD 1 Reply Last reply Reply Quote 0
                • DunhouD
                  Dunhou @i_mazlov
                  last edited by

                  Hi @i_mazlov ,

                  Thanks for your time, sorry for my bad that I use a confusing word for "id", I should say "asset id", but as you said, I can use ID to check this, for some reason, I overlooked this for a moment.

                  And the GetParent(), I found out that the culprit is GetSelectedNodes(), I use this to get a selected node(abs bode) but the return is "group", so what ever I try the return is 'Root'.

                  Thanks for all your works!

                  Cheers~
                  DunHou

                  https://boghma.com
                  https://github.com/DunHouGo

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