Cannot Connect Xpresso Nodes in Python
-
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:
What I'm wanting is this:
Can you please help me understand what I'm doing wrong in this code? Thank you. -
"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 thatnode1.AddPort()
has returnedNone
.Why
AddPort()
has returnedNone
, I don't know. I can only speculate that one has to construct a more complexDescID
handlingMG_GRID_RESOLUTION
. -
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.