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
    • Register
    • Login

    How to Use GetConnectionValue/s() or GetConnection()?

    Cinema 4D SDK
    2023 python
    3
    11
    1.4k
    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.
    • B
      bentraje
      last edited by

      Hi,

      I'm trying to retrieve a data of the inport and outport connection between two nodes.

      For example:
      Texture Node (OutColor OutPort) > Standard Node (Opacity InPort)

      I tried the GetPredessor and GetSuccesor but it only spits the nodes. And if it spits connection, it only spits one sided connection but not both.

      Again, I want the actual connection data.

      So I'm trying the GetConnectionValues() and GetConnection()
      But I'm confused how to implement it.
      In the documention, it says:
      GraphNode.GetConnectionValues(target, receiver)
      target – The other end of the connection.

      What is a target?

      The forum also doesn't give any relevant result to the aforementioned methods.
      Is it possible to have a sample working illustration code on the methods?

      Regards,
      Ben

      1 Reply Last reply Reply Quote 0
      • B
        bentraje
        last edited by

        I already the following code.
        It does give me a True result which I guess it means there is a connection.
        But the receiver returns an empty list.

        CASE: A texture node (outColor Outport) is connected to the standard node (opacity Inport)

                result = []
                GraphModelHelper.GetSelectedNodes(graph, maxon.NODE_KIND.ALL_MASK, result)
                texture = result[1]
                standard = result[0]
        
                port = standard.GetInputs().FindChild("com.redshift3d.redshift4c4d.nodes.core.standardmaterial.opacity_color")
        
                receiver = []
                connection = port.GetConnectionValues(texture, receiver)
        
                print (connection) # Returns True
                print (receiver) # Returns an Empty List instead of the actual connection
        
        ferdinandF 1 Reply Last reply Reply Quote 0
        • B
          bentraje
          last edited by bentraje

          I also tried the GetValue method but it gives me none

          val = standard.GetValue(attr="com.redshift3d.redshift4c4d.nodes.core.standardmaterial.opacity_color")) # returns None instead of the texture node out color

          val = port.GetValue(attr="com.redshift3d.redshift4c4d.nodes.core.standardmaterial.opacity_color")) #returns None instead of the texture node out color
          `

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

            Hello @bentraje,

            Thank you for reaching out to us. Your question has not been overlooked, but I did not get to it yet.

            Cheers,
            Ferdinand

            MAXON SDK Specialist
            developers.maxon.net

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

              Hey @bentraje,

              Thank you for reaching out to us and please excuse the short delay. Your code likely does not work because the two entities for which you attempt to evaluate the connection with GraphNode.GetConnectionValues are what the Nodes API calls a True Node (texture) and a Port Node (port). Connections can however only exist between an out-port and an in-port.

              The methods GraphNode.GetConstantValue, .GetDefaultValue, .GetValue, and .GetValue are all not related to connections. In short, GetDefaultValue yields the value a port has when no wire is connected to it, while GetValue yields any node attribute. Attributes are a somewhat underlying concept of ports and many more things.

              I am not quite sure what you are trying to achieve when you say

              I'm trying to retrieve a data of the inport and outport connection between two nodes.

              First of all, there is a slight ambiguity in the connection finding part of your question because there can be more than one connection between two true nodes, and there can be more than one wire between two ports.

              • GraphModelHelper.IsConnected: Allows you to evaluate if a given true or port node is connected to a given port node in any shape or form.
              • GraphNode.GetConnections: Yields all connections that fan out from a port node. So, you must iterate over the ports of a true node to use it.
              • GraphNode.GetWires: Returns the wires that are spanned between two port nodes.
              • GraphModelHelper.GetAllPredecessors, .GetAllSuccessors, .GetDirectPredecessors, and .GetDirectSuccessors: The concept of sucessors and predecessors puts an abstraction on top of node connections and lets you retrieve the true nodes that are connected up- or downstream to a true node.

              What to do here, depends also a bit on what you would consider 'data' in your question. Do you want to get the metadata for a connection like the direction and the wire mode? Or do you want to get hold of the value which is transported with the connection from an out-port to an in-port?

              Cheers,
              Ferdinand

              MAXON SDK Specialist
              developers.maxon.net

              B 1 Reply Last reply Reply Quote 1
              • B
                bentraje @ferdinand
                last edited by

                @ferdinand
                Thanks for the response.

                RE: Do you want to get the metadata .. or .. ?
                Can I have both? I never really thought as a trivial.
                I just want the data of two nodes. and the ports they are connected it.
                So I can recreate them later.

                For example, like in the above.
                Texture Node (OutColor OutPort) > Standard Node (Opacity InPort)
                Inherently there is 4 data there. 2 node with their 2 ports that is connected.

                RE: GraphNode.GetConnections

                I'm trying this but I'm not sure how to use it.

                        port = standard.GetInputs().FindChild("com.redshift3d.redshift4c4d.nodes.core.standardmaterial.opacity_color")
                
                        receiver = []
                        port.GetConnections(maxon.PORT_DIR.INPUT, conns=receiver, mask=maxon.Wires.value, mode=maxon.WIRE_MODE.ALL)
                

                It gives me an error of TypeError: unable to convert builtins.property to @net.maxon.graph.wires

                What I'm expecting for the GetConnectionsto spit is this one:
                Texture Node (OutColor OutPort) in whatever form because that is what it is connected to.

                1 Reply Last reply Reply Quote 0
                • B
                  bentraje
                  last edited by

                  For reference,

                  Here it is a simple equivalent in Maya Python.

                  # List all connections to BALL
                  list = cmds.listConnections('BALL')
                  
                  # List only incoming connections from BALL.tx
                  cmds.listConnections( 'standard_node.opacityColor', destination=False, source=True )
                  # result textureNode.outColor
                  

                  I am not expecting it to be 1 to 1 of course but I'm not also expecting to this trivial and hard.
                  I just really need the connection.

                  1 Reply Last reply Reply Quote 0
                  • B
                    bentraje
                    last edited by

                    Here is also the corresponding documentation.

                    https://download.autodesk.com/us/maya/2009help/CommandsPython/listConnections.html

                    You can see it below how it is being used so there's no whatsoever confusion on its usage.

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

                      Hey @bentraje,

                      first of all, I understand your frustration, we just yesterday talked about the state of the Nodes API and are well aware of its hurdles for anything but super-experts. On the other hand, I must point out again, that fragments of code or error messages are pretty meaningless. As stated in the forum guidelines, you should post executable code.

                      With that being said, I can confirm that GraphNode.GetConnectionValues is behaving oddly. But that could be because Redshift really does not like laptop as a rendering device. Everything else works fine for me here but I still have no clue what you want to do effectively.

                      PS: The mistake in your GetConnections call lied in the incorrect mask value. The documentation for the method is a bit butchered, we will fix that. I would however always recommend using the VS Code bindings, as it would have told you this:

                      da78fb95-5281-413d-81be-3afc10bbf818-image.png

                      Cheers,
                      Ferdinand

                      Graph:
                      aac45e2b-1a88-49fe-9716-1cbc9d2cb816-image.png
                      Output:

                      maxon.GraphModelHelper.GetDirectPredecessors(endNode, maxon.NODE_KIND.NODE) = [standardmaterial@Hv6m0BuyCB4idfeZnssZYC]
                      maxon.GraphModelHelper.GetDirectPredecessors(endNode, maxon.NODE_KIND.OUTPORT) = [standardmaterial@Hv6m0BuyCB4idfeZnssZYC>com.redshift3d.redshift4c4d.nodes.core.standardmaterial.outcolor]
                      maxon.GraphModelHelper.GetAllPredecessors(endNode, maxon.NODE_KIND.NODE) = [standardmaterial@Hv6m0BuyCB4idfeZnssZYC, group@WVcBzy1WDR_kJrRviYwbmF, texturesampler@EddwvQ5ALJSnU5EcX99U$x, texturesampler@E1AoVUhQEBEn$4nuyz8irm, rsscalarramp@TEY3JetDLNkqz86IJahb_C, texturesampler@aKfJScQXKF0ugzuJyl27MG, texturesampler@F9gCNSUTGdMlqUsC69b$0A, bumpmap@HiKbvo1FLNCkb4DKLPKvjE, texturesampler@crysppSdAZvt5dCHd$$i1E]
                      
                       ----------------------------------------------------------------------------------------------------
                      
                      out-port: standardmaterial@Hv6m0BuyCB4idfeZnssZYC>com.redshift3d.redshift4c4d.nodes.core.standardmaterial.outcolor
                      wires: Wires - Value:16, Event:16, Dependency:16, Context:0, Hidden:0, Inhibit:0, Slink:0, Tlink:0
                      default: 0.0,0.0,0.0
                      in-port: output@TvFBXodvDtuu346T8ZukFG<com.redshift3d.redshift4c4d.node.output.surface
                      
                      out-port: group@WVcBzy1WDR_kJrRviYwbmF>outcolor@KbTuENK$GBdgV12yPDVlKA
                      wires: Wires - Value:16, Event:16, Dependency:16, Context:0, Hidden:0, Inhibit:0, Slink:0, Tlink:0
                      default: 0.21404114365577698,0.21404114365577698,0.21404114365577698
                      in-port: standardmaterial@Hv6m0BuyCB4idfeZnssZYC<com.redshift3d.redshift4c4d.nodes.core.standardmaterial.base_color
                      
                      out-port: texturesampler@EddwvQ5ALJSnU5EcX99U$x>com.redshift3d.redshift4c4d.nodes.core.texturesampler.outcolor
                      wires: Wires - Value:16, Event:16, Dependency:16, Context:0, Hidden:0, Inhibit:0, Slink:0, Tlink:0
                      default: 0.0,0.0,0.0,1.0
                      in-port: group@WVcBzy1WDR_kJrRviYwbmF<in@GrX6SuapEpQkoY6CBvFyAj
                      
                      out-port: texturesampler@E1AoVUhQEBEn$4nuyz8irm>com.redshift3d.redshift4c4d.nodes.core.texturesampler.outcolor
                      wires: Wires - Value:16, Event:16, Dependency:16, Context:0, Hidden:0, Inhibit:0, Slink:0, Tlink:0
                      default: 0.0,0.0,0.0,1.0
                      in-port: group@WVcBzy1WDR_kJrRviYwbmF<in@fd8$tVTfOhKtjHscJx8tPm
                      
                      out-port: rsscalarramp@TEY3JetDLNkqz86IJahb_C>com.redshift3d.redshift4c4d.nodes.core.rsscalarramp.out
                      wires: Wires - Value:16, Event:16, Dependency:16, Context:0, Hidden:0, Inhibit:0, Slink:0, Tlink:0
                      default: 0
                      in-port: standardmaterial@Hv6m0BuyCB4idfeZnssZYC<com.redshift3d.redshift4c4d.nodes.core.standardmaterial.refl_weight
                      
                      out-port: texturesampler@aKfJScQXKF0ugzuJyl27MG>com.redshift3d.redshift4c4d.nodes.core.texturesampler.outcolor
                      wires: Wires - Value:16, Event:16, Dependency:16, Context:0, Hidden:0, Inhibit:0, Slink:0, Tlink:0
                      default: 0.0,0.0,0.0,1.0
                      in-port: rsscalarramp@TEY3JetDLNkqz86IJahb_C<com.redshift3d.redshift4c4d.nodes.core.rsscalarramp.input
                      
                      out-port: texturesampler@F9gCNSUTGdMlqUsC69b$0A>com.redshift3d.redshift4c4d.nodes.core.texturesampler.outcolor
                      wires: Wires - Value:16, Event:16, Dependency:16, Context:0, Hidden:0, Inhibit:0, Slink:0, Tlink:0
                      default: 0.0,0.0,0.0,1.0
                      in-port: standardmaterial@Hv6m0BuyCB4idfeZnssZYC<com.redshift3d.redshift4c4d.nodes.core.standardmaterial.refl_roughness
                      
                      out-port: texturesampler@EddwvQ5ALJSnU5EcX99U$x>com.redshift3d.redshift4c4d.nodes.core.texturesampler.outcolor
                      wires: Wires - Value:16, Event:16, Dependency:16, Context:0, Hidden:0, Inhibit:0, Slink:0, Tlink:0
                      default: 0.0,0.0,0.0,1.0
                      in-port: standardmaterial@Hv6m0BuyCB4idfeZnssZYC<com.redshift3d.redshift4c4d.nodes.core.standardmaterial.sheen_color
                      
                      out-port: bumpmap@HiKbvo1FLNCkb4DKLPKvjE>com.redshift3d.redshift4c4d.nodes.core.bumpmap.out
                      wires: Wires - Value:16, Event:16, Dependency:16, Context:0, Hidden:0, Inhibit:0, Slink:0, Tlink:0
                      default: 0.0,0.0,0.0
                      in-port: standardmaterial@Hv6m0BuyCB4idfeZnssZYC<com.redshift3d.redshift4c4d.nodes.core.standardmaterial.bump_input
                      
                      out-port: texturesampler@crysppSdAZvt5dCHd$$i1E>com.redshift3d.redshift4c4d.nodes.core.texturesampler.outcolor
                      wires: Wires - Value:16, Event:16, Dependency:16, Context:0, Hidden:0, Inhibit:0, Slink:0, Tlink:0
                      default: 0.0,0.0,0.0,1.0
                      in-port: bumpmap@HiKbvo1FLNCkb4DKLPKvjE<com.redshift3d.redshift4c4d.nodes.core.bumpmap.input
                      

                      Code:

                      """Unwinds connection information in the active node space graph of the first material in the
                      active scene.
                      """
                      
                      import c4d
                      import maxon
                      
                      doc: c4d.documents.BaseDocument  # The active document
                      
                      def main() -> None:
                          """Unwinds connection information in the active node space graph of the first material in the
                          active scene.
                          """
                          # Attempt to get the node graph for the active node space for the first material in the document.
                          material: c4d.BaseMaterial = doc.GetFirstMaterial()
                          if not material:
                              return
                          
                          nodeMaterial: c4d.NodeMaterial = material.GetNodeMaterialReference()
                          currentSpace: maxon.Id = c4d.GetActiveNodeSpaceId()
                          graph: maxon.NodesGraphModelInterface = nodeMaterial.GetGraph(currentSpace)
                          if graph.IsNullValue():
                              return
                          
                          # Get the end node in the graph, so that we can unwind connection information.
                          endNode: maxon.GraphNode = graph.GetNode(nodeMaterial.GetMaterialNodePath(currentSpace))
                          if endNode.IsNullValue():
                              return
                          
                          # Get the direct true node predecessors of the end node, i.e., all true nodes that are connected
                          # directly to the end node.
                          print (f"{maxon.GraphModelHelper.GetDirectPredecessors(endNode, maxon.NODE_KIND.NODE) = }")
                          # Get the direct out-port node predecessors of the end node, i.e., all out-port nodes that are
                          # connected directly to the end node.
                          print (f"{maxon.GraphModelHelper.GetDirectPredecessors(endNode, maxon.NODE_KIND.OUTPORT) = }")
                      
                          # Get all true node predecessors of the end node, i.e., all true nodes that are connected
                          # directly or indirectly to the end node. In a well connected graph, i.e., a graph where every
                          # node does contribute to the end node, this will simply yield all true nodes.
                          print (f"{maxon.GraphModelHelper.GetAllPredecessors(endNode, maxon.NODE_KIND.NODE) = }")
                      
                          print ("\n", "-" * 100)
                      
                          def GetPredConnectionInfo(node: maxon.GraphNode) -> None:
                              """Prints predecessor connection information for #node in a recursive fashion.
                              """
                              # Bail when the passed node is not a true node.
                              if node.GetKind() != maxon.NODE_KIND.NODE:
                                  return
                              
                              # For every input port in #node.
                              for inPort in node.GetInputs().GetChildren():
                                  # Get the connected output ports and their wires.
                                  for outPort, wires in inPort.GetConnections(
                                      maxon.PORT_DIR.INPUT, None, maxon.Wires.All(), maxon.WIRE_MODE.ALL):
                                      # Get the true node which owns #outPort, i.e., the other true node which is 
                                      # connected to the true node #node.
                                      otherNode: maxon.GraphNode = outPort.GetAncestor(maxon.NODE_KIND.NODE)
                                      defaultValue: any = outPort.GetDefaultValue()
                                      print (f"\nout-port: {outPort}")
                                      print (f"wires: {wires}")
                                      print (f"default: {defaultValue}")
                                      print (f"in-port: {inPort}")
                                      # Start the recursion with #otherNode.
                                      GetPredConnectionInfo(otherNode)
                      
                          GetPredConnectionInfo(endNode)
                      
                      if __name__ == '__main__':
                          main()
                      

                      MAXON SDK Specialist
                      developers.maxon.net

                      indexofrefractionI 1 Reply Last reply Reply Quote 1
                      • B
                        bentraje
                        last edited by

                        @ferdinand

                        Slr. Can confirm. This works.
                        This screenshot is all I need (i.e. how to use the GetConnections method).
                        Thanks

                        https://developers.maxon.net/forum/assets/uploads/files/1683785107297-da78fb95-5281-413d-81be-3afc10bbf818-image-resized.png

                        @

                        1 Reply Last reply Reply Quote 0
                        • indexofrefractionI
                          indexofrefraction @ferdinand
                          last edited by indexofrefraction

                          @ferdinand
                          first of all, I understand your frustration, we just yesterday talked about the state of the Nodes API and are well aware of its hurdles for anything but super-experts.

                          you can say that aloud!
                          the whole system is very hard to understand. the only thing i got is all we know about traditional materials and even shaders is for the bin. node support evolved over time and most node examples do not work for people still using older c4d versions. also there are misc 3rd-party renderers that use different kinds of nodes / node systems. Drag & drop of attributes to the console doesn't work anymore, as well. the days of easy scripting are gone.. 😵

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