Just a tip:
If you find your compute function not firing like it should. Double check that your output attributes are NOT set to keyable.
What a pain that was.
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.
Here is some information on creating a enum attribute in maya python api.
Let’s start on creating an enum attribute that will work like an optionMenu.
First we create our enum class:
eAttr = OpenMaya.MFnEnumAttribute()
Then we can add our attribute to the class:
testNode.optionMenu= eAttr.create('options', 'options', 0)
Next we can add some ‘fields’ to the attribute. This is where we add the options to our optionMenu:
eAttr.addField('option1', 0) eAttr.addField('option2', 1) eAttr.addField('option3', 2) eAttr.addField('option4', 3) eAttr.addField('option5', 4)
There, now we have 5 options available to choose from. When queried, we will get an int in return.
Next let’s set up some options in the MFnEnumAttribute class:
eAttr.setKeyable(1) eAttr.setStorable(1)
We want to be able to key the option we want, and we want to be able to have current option save to the file.
Last, we need to add our newly created attribute to the node we are working on:
testNode.addAttribute(testNode.optionMenu)
The whole code for this enum attribute:
eAttr = OpenMaya.MFnEnumAttribute() testNode.optionMenu= eAttr.create('options', 'options', 0) eAttr.addField('option1', 0) eAttr.addField('option2', 1) eAttr.addField('option3', 2) eAttr.addField('option4', 3) eAttr.addField('option5', 4) eAttr.setKeyable(1) eAttr.setStorable(1) testNode.addAttribute(testNode.optionMenu)
Next, lets look at how to get at our optionMenu when we need to:
When we want to get at the data, we need to create a dataBlock:
optionMenu_value = dataBlock.inputValue(testNode.optionMenu)
The variable ‘optionMenu_value’ now contains the data we want. We can use it like this:
if optionMenu_value.asInt() == 0: runThisCode() if optionMenu_value.asInt() == 1: runThisCode() if optionMenu_value.asInt() == 2: runThisCode() etc.
This is an easy way to add a little option box to our plugin.