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

    Cannot Connect Xpresso Nodes in Python

    General Talk
    3
    3
    728
    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.
    • J
      johntravolski
      last edited by

      I am using the Python script manager to try and automate a few things. I am creating a hierarchy and I want to create an xpresso tag where the z offset of one cloner is driven by the z size of another cloner. Here's my code:

      import c4d
      from c4d import gui
      import math
      
      def main():
          cloner = c4d.BaseObject(1018544) # cloner id
          
          cloner[c4d.MG_LINEAR_OBJECT_POSITION,c4d.VECTOR_Y] = 0
          cloner[c4d.MG_LINEAR_OBJECT_POSITION,c4d.VECTOR_Z] = 500
          cloner[c4d.MG_LINEAR_COUNT] = 10
          cloner[c4d.MGCLONER_VOLUMEINSTANCES] = True
          
          doc.InsertObject(cloner)
          newnull = c4d.BaseObject(c4d.Onull)
          newnull.InsertUnder(cloner)
          internal_cloner = c4d.BaseObject(1018544) # cloner id
          internal_cloner.InsertUnder(newnull)
          internal_cloner[c4d.ID_MG_MOTIONGENERATOR_MODE] = 3 # 3 is grid array
          internal_cloner[c4d.MG_GRID_SIZE] = c4d.Vector(300, 200, 100)
          
          cube = c4d.BaseObject(c4d.Ocube)
          cube.InsertUnder(internal_cloner)
          cube[c4d.PRIM_CUBE_LEN] = c4d.Vector(20, 10, 100)
          
          xtag = c4d.BaseTag(c4d.Texpresso) # create the xpresso tag
          cloner.InsertTag(xtag)
          
          # http://mograph.net/board/index.php?/topic/26338-creating-xpresso-nodes-with-python-script/
          nodemaster = xtag.GetNodeMaster()
          node1 = nodemaster.CreateNode(nodemaster.GetRoot(), c4d.ID_OPERATOR_OBJECT, None, 100, 100)
          node1[c4d.GV_OBJECT_OBJECT_ID] = internal_cloner
          node1out = node1.AddPort(c4d.GV_PORT_OUTPUT, (c4d.MG_GRID_RESOLUTION, c4d.VECTOR_Z))
          
          node2 = nodemaster.CreateNode(nodemaster.GetRoot(), c4d.ID_OPERATOR_OBJECT, None, 300, 100)
          node2[c4d.GV_OBJECT_OBJECT_ID] = cloner
          node2in = node2.AddPort(c4d.GV_PORT_INPUT, (c4d.MG_LINEAR_OBJECT_POSITION, c4d.VECTOR_Z))
          
          node1out.Connect(node2in)
          
          c4d.EventAdd() # refreshed viewport to see changes automatically
          # id = op.GetType()
      
      if __name__=='__main__':
          main()
      

      Unfortunately, this does not work and gives me an "AttributeError: 'NoneType' object has no attribute 'Connect'.
      When looking at the results, you can see that the first cloner never had its output port created:
      alt text
      What I'm wanting is this:
      alt text
      Can you please help me understand what I'm doing wrong in this code? Thank you.

      1 Reply Last reply Reply Quote 0
      • P
        PluginStudent
        last edited by PluginStudent

        "AttributeError: 'NoneType' object has no attribute 'Connect'

        means that the variable node1out is a NoneType; it is not what you think it is. That means that node1.AddPort() has returned None.

        Why AddPort() has returned None, I don't know. I can only speculate that one has to construct a more complex DescID handling MG_GRID_RESOLUTION.

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

          Hi, here in Cinema 4D S22 defining the type of the cloner I don't have anymore an issue

          import c4d
          from c4d import gui
          import math
          
          def main():
              # Build Parent Cloner
              cloner = c4d.BaseObject(1018544)
              cloner[c4d.ID_MG_MOTIONGENERATOR_MODE] = c4d.ID_MG_MOTIONGENERATOR_MODE_LINEAR
              doc.InsertObject(cloner)
          
              # Build Null
              newnull = c4d.BaseObject(c4d.Onull)
              newnull.InsertUnder(cloner)
          
              # Build Children Cloner
              internal_cloner = c4d.BaseObject(1018544)
              internal_cloner[c4d.ID_MG_MOTIONGENERATOR_MODE] = c4d.ID_MG_MOTIONGENERATOR_MODE_GRIDARRAY
              internal_cloner.InsertUnder(newnull)
              internal_cloner.Message(c4d.MSG_MENUPREPARE, doc)
          
              # Cube
              cube = c4d.BaseObject(c4d.Ocube)
              internal_cloner.Message(c4d.MSG_MENUPREPARE, doc)
              cube.InsertUnder(internal_cloner)
          
              # Xpresso Tag
              xtag = c4d.BaseTag(c4d.Texpresso)
              cloner.InsertTag(xtag)
          
              # Setup Parent Cloner
              cloner[c4d.MG_LINEAR_OBJECT_POSITION, c4d.VECTOR_Y] = 0.0
              cloner[c4d.MG_LINEAR_OBJECT_POSITION, c4d.VECTOR_Z] = 500.0
              cloner[c4d.MG_LINEAR_COUNT] = 10
              cloner[c4d.MGCLONER_VOLUMEINSTANCES_MODE] = c4d.MGCLONER_VOLUMEINSTANCES_MODE_RENDERINSTANCE
          
              # Setup Children Cloner
              internal_cloner[c4d.MG_GRID_SIZE] = c4d.Vector(300, 200, 100)
          
              # Setup Cube
              cube[c4d.PRIM_CUBE_LEN] = c4d.Vector(20, 10, 100)
          
              # Setup Xpresso
              # http://mograph.net/board/index.php?/topic/26338-creating-xpresso-nodes-with-python-script/
              nodemaster = xtag.GetNodeMaster()
              node1 = nodemaster.CreateNode(nodemaster.GetRoot(), c4d.ID_OPERATOR_OBJECT, None, 100, 100)
              node1[c4d.GV_OBJECT_OBJECT_ID] = internal_cloner
              gridResParam = c4d.DescID(c4d.DescLevel(c4d.MG_GRID_RESOLUTION, c4d.DTYPE_VECTOR,0), c4d.DescLevel(c4d.VECTOR_Z, c4d.DTYPE_REAL,0))
              node1out = node1.AddPort(c4d.GV_PORT_OUTPUT, gridResParam)
          
              node2 = nodemaster.CreateNode(nodemaster.GetRoot(), c4d.ID_OPERATOR_OBJECT, None, 300, 100)
              node2[c4d.GV_OBJECT_OBJECT_ID] = cloner
              posParam = c4d.DescID(c4d.DescLevel(c4d.MG_LINEAR_OBJECT_POSITION, c4d.DTYPE_VECTOR,0), c4d.DescLevel(c4d.VECTOR_Z, c4d.DTYPE_REAL,0))
              node2in = node2.AddPort(c4d.GV_PORT_INPUT, posParam)
          
              # Connect
              if node1out is not None and node2in is not None:
                  node1out.Connect(node2in)
          
              c4d.EventAdd() # refreshed viewport to see changes automatically
          
          if __name__=='__main__':
              main()
          

          And as pointed by @PluginStudent the problem was because the AddPort fails. And I guess it failed because at the time you ask for the port creation since no explicit mode was defined in the Cloner the XPresso description was not properly fed so this GvPort didn't exist.

          Cheers,
          Maxime.

          MAXON SDK Specialist

          Development Blog, MAXON Registered Developer

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