If you are anything like me, you can’t always find what you need in the Maya Python API documentation. Sometimes the information in the docs does not match what actually exists in the header files. Sometimes you cannot find sufficient examples of what you want to accomplish in Autodesk’s sample scripts. When you really hit the bottom and have to scour the dregs of the internet, you will typically find a dearth of information.
Because developing Maya Nodes using the Python API has consistently been an excruciating process for me, I want to save you the headache and post things here as I come across them. Most things turn out to be fairly simple, yet require a lot of hair-ripping to sort out. One issue I came across today was setting values for compound attributes.
Let’s say you have an output connection for your node that looks like this:
# Output nAttr = OpenMaya.MFnNumericAttribute() customNode.out = nAttr.create( "output", "out", OpenMaya.MFnNumericData.kDouble) nAttr.setStorable(1) nAttr.setWritable(1)
Using the examples that ship with the software, you can easily figure out how to set this attribute in your
compute function. It will look something like this:
def compute(self,plug,dataBlock): if ( plug == customNode.out ): # Get the incoming data here # Perform some computations here # Our result is defined here somewhere as dResult # Output the data outputHandle = dataBlock.outputValue( customNode.out ) outputHandle.setDouble( dResult ) dataBlock.setClean( plug )
This is all well and good for those of you who want to make nodes that output a sine function. There is a good chance, however, that you will need to do something more complicated, like output values to control the translation of something. In such a case, you need a compound attribute—something like
k3Int, etc. So you will set up your output like this:
# Output nAttr = OpenMaya.MFnNumericAttribute() customNode.out = nAttr.create( "output", "out", OpenMaya.MFnNumericData.k3Double) nAttr.setStorable(1) nAttr.setWritable(1)
compute function may look like this:
def compute(self,plug,dataBlock): if ( plug == customNode.out ): # Get the incoming data here # Perform some computations here # Our result is defined here somewhere as dResult # Output the data outputHandle = dataBlock.outputValue( customNode.out ) outputHandle.set3Double( dResult, dResult, dResult ) dataBlock.setClean( plug )
Now, this seems to make sense. Unfortunately, this will not always work. I did a little bit of troubleshooting and found that setting up the
compute function like this will only work if you have multiple compound attributes as outgoing connections. In fact, if you have a single compound attribute as an outgoing connection, a
compute function like this is not called at all. This is because, as far as I can tell, when there is a single outgoing compound attribute, it is not the plug. Rather, its children are plugs which will activate the
compute function. In short, when you have a single outgoing compound attribute, you need to perform a test to see if the plug you are testing is a child of the actual compound attribute you are wanting to output. The solution therefore looks something like this:
def compute(self,plug,dataBlock): if ( plug == customNode.out or plug.parent() == customNode.out ):
Hopefully this will save you some headaches and troubleshooting. I know I would have liked to have seen some examples in the docs, and certainly at least hoped some other people on the internet had run into this problem. Here’s to all of you Maya Python users out there—I know you’re out there!