Working with Maya’s python api – The compound attribute

Continuing my explanation of maya’s python api, we come to the compound attribute.

This is a handy way to organize our arrays.

First we create our MFnCompoundAttribute class:

cAttr = OpenMaya.MFnCompoundAttribute()

Then we create an input array(we are using matrix as input) so let’s create that class.

mAttr = OpenMaya.MFnMatrixAttribute()

Then create our matrix array attribute that will be a child of our compound attribute:

testNode.inputs = mAttr.create('inputs', 'inputs')
mAttr.setKeyable(1)
mAttr.setArray(1)
testNode.addAttribute(testNode.inputs)

Next, we can create our ‘parent’ compound attribute:

testNode.poseList = cAttr.create("inputList", "inputList")
cAttr.addChild(rbfAttrNode.inputs) #Here is where we state the child 
cAttr.setArray(1)
cAttr.setHidden(1)
testNode.addAttribute(testNode.inputList)

As you can see, we created a compound attribute with our inputs array set to be the child.

This creates a hierarchy that would make sense:

inputList - Our compound attribute
    -inputList[0] - The first entry in the compound attribute array
        -inputs -The first entry in out matrix array
            -inputs[0] - matrix input 1
            -inputs[1]- matrix input 2
    -inputList[1] - The second entry in the compound attribute array
         -inputs -The second entry in out matrix array
             -inputs[0] - matrix input 1
             -inputs[1] - matrix input 2

Next we will look at how to get the data from each plug when we need it:

-Note, I found this very confusing when I first tried to do this correctly. Explanations are in the code as comments:

#First we get our compound array dataBlock
inputListArrayDataHandle = dataBlock.inputArrayValue(testNode.inputList)
#Get the amount of children arrays - this returns an int
index = inputListArrayDataHandle.elementCount()
#This is how I got the data I wanted, this can change based on what you need

#Create empty list
inputData = []
#Loop through the children arrays of the compound attribute
for i in range(index):
    #Go to the first child in the array
    inputListArrayDataHandle.jumpToElement(i)

    #(This is the first entry array(inputList[0] in the example above))
    inputsDataHandle = inputListArrayDataHandle.inputValue()

    # Get the child array attribute(The first entry in the children of the child array)
    # (This is the inputs in the example above)
    inputDataHandle = OpenMaya.MArrayDataHandle(inputsDataHandle .child(testNode.inputs))

    #Get the number of children in the child array
    index2 = attributeDataHandle.elementCount()
    # Create an empty to list 
    data = []
    #Loop through the number of matrix in the inputs array
    #These are the inputs[0], inputs[1]....inputs[n] in the example above
    for j in range(index2):
        #I created another emtpy list to keep track of things
        #I made this list set at 3 entries as I only wanted the transform data
        out = [None, None, None]
        #Go to the first entry in the inputs array
        inputDataHandle .jumpToElement(j)
        #Get the data as an MMatrix class
        mMatrix = om.MMatrix(inputDataHandle .inputValue().asMatrix())
        #Create a MTransformationMatrix class with the MMatrix variable
        mTrans = om.MTransformationMatrix(mMatrix)
        #Grab the wold position data
        trs = mTrans.translation(1)
        #Optional data that can be pulled from the matrix is(Not used in this example)
        #quat = mTrans.rotation(1)
        #axis, angle = quat.asAxisAngle()

        # Set out array values (xyz, xyz, angle)
        out[0] = trs[0]
        out[1] = trs[1]
        out[2] = trs[2]
        if out: #Check that there is data to fill out list
            for o in out:
                data.append(o)
    #Fill the top level list with the list
    inputData.append(data)

With the above example we end up with a list of arrays:
inputData = [[0,0,0], [0,0,0], [0,0,0], [0,0,0], [0,0,0]]

I hope you find this helpful.

Leave a Reply

Your email address will not be published. Required fields are marked *