def getTypedValue(plug): """Returns the maya type from the given typedAttributePlug :param plug: MPLug :return: maya type """ tAttr = om2.MFnTypedAttribute(plug.attribute()) dataType = tAttr.attrType() if dataType == om2.MFnData.kInvalid: return None, None elif dataType == om2.MFnData.kString: return attrtypes.kMFnDataString, plug.asString() elif dataType == om2.MFnData.kNumeric: return getNumericValue(plug) elif dataType == om2.MFnData.kMatrix: return attrtypes.kMFnDataMatrix, om2.MFnMatrixData( plug.asMObject()).matrix() elif dataType == om2.MFnData.kFloatArray: return attrtypes.kMFnDataFloatArray, om2.MFnFloatArrayData( plug.asMObject()).array() elif dataType == om2.MFnData.kDoubleArray: return attrtypes.kMFnDataDoubleArray, om2.MFnDoubleArrayData( plug.asMObject()).array() elif dataType == om2.MFnData.kIntArray: return attrtypes.kMFnDataIntArray, om2.MFnIntArrayData( plug.asMObject()).array() elif dataType == om2.MFnData.kPointArray: return attrtypes.kMFnDataPointArray, om2.MFnPointArrayData( plug.asMObject()).array() elif dataType == om2.MFnData.kVectorArray: return attrtypes.kMFnDataVectorArray, om2.MFnVectorArrayData( plug.asMObject()).array() elif dataType == om2.MFnData.kStringArray: return attrtypes.kMFnDataStringArray, om2.MFnStringArrayData( plug.asMObject()).array() elif dataType == om2.MFnData.kMatrixArray: return attrtypes.kMFnDataMatrixArray, om2.MFnMatrixArrayData( plug.asMObject()).array() return None, None
def nodeInitializer(): # create attributes # pick your pointy poison solverAttrFn = om.MFnEnumAttribute() generalIk.aSolver = solverAttrFn.create("solver", "sol", 0) solverAttrFn.addField("CCD", 0) solverAttrFn.addField("FABRIK (not yet implemented)", 1) solverAttrFn.storable = True solverAttrFn.keyable = True solverAttrFn.readable = False solverAttrFn.writable = True om.MPxNode.addAttribute(generalIk.aSolver) iterAttrFn = om.MFnNumericAttribute() generalIk.aMaxIter = iterAttrFn.create("maxIterations", "mi", om.MFnNumericData.kLong, 30) iterAttrFn.storable = True iterAttrFn.keyable = True iterAttrFn.readable = False iterAttrFn.writable = True iterAttrFn.setMin(0) om.MPxNode.addAttribute(generalIk.aMaxIter) # how far will you go for perfection toleranceAttrFn = om.MFnNumericAttribute() generalIk.aTolerance = toleranceAttrFn.create("tolerance", "tol", om.MFnNumericData.kDouble, 0.1) toleranceAttrFn.storable = True toleranceAttrFn.keyable = True toleranceAttrFn.readable = False toleranceAttrFn.writable = True toleranceAttrFn.setMin(0) om.MPxNode.addAttribute(generalIk.aTolerance) # weight of the world globalWeightAttrFn = om.MFnNumericAttribute() generalIk.aGlobalWeight = globalWeightAttrFn.create( "globalWeight", "globalWeight", om.MFnNumericData.kDouble, 0.8) globalWeightAttrFn.writable = True globalWeightAttrFn.keyable = True om.MPxNode.addAttribute(generalIk.aGlobalWeight) # let the past die? # cacheOnAttrFn = om.MFnNumericAttribute() # generalIk.aCacheOn = cacheOnAttrFn.create( # "cacheOn", "cacheOn", om.MFnNumericData.kBoolean, 1) # om.MPxNode.addAttribute(generalIk.aCacheOn) generalIk.aCacheOn = nodeio.makeBindAttr(generalIk, name="cache") om.MPxNode.addAttribute(generalIk.aCacheOn) # what are your goals in life targetMatAttrFn = om.MFnMatrixAttribute() generalIk.aTargetMat = targetMatAttrFn.create("targetMatrix", "targetMat", 1) targetMatAttrFn.storable = True targetMatAttrFn.readable = False targetMatAttrFn.keyable = False targetMatAttrFn.writable = True targetMatAttrFn.cached = True om.MPxNode.addAttribute(generalIk.aTargetMat) # compare and contrast endMatAttrFn = om.MFnMatrixAttribute() generalIk.aEndMat = endMatAttrFn.create("inputEndMatrix", "endMat", 1) endMatAttrFn.storable = True endMatAttrFn.readable = False endMatAttrFn.keyable = False endMatAttrFn.writable = True endMatAttrFn.cached = True om.MPxNode.addAttribute(generalIk.aEndMat) # once i built a tower jntMatAttrFn = om.MFnMatrixAttribute() generalIk.aJntMat = jntMatAttrFn.create("worldMatrix", "worldMatrix", 1) jntMatAttrFn.storable = False jntMatAttrFn.writable = True jntMatAttrFn.cached = False # prevent ghost influences from staying # are you local jntLocalMatAttrFn = om.MFnMatrixAttribute() generalIk.aJntLocalMat = jntLocalMatAttrFn.create("localMatrix", "localMatrix", 1) # joint orients orientRxAttrFn = om.MFnUnitAttribute() generalIk.aOrientRx = orientRxAttrFn.create("orientX", "orientX", 1, 0.0) orientRyAttrFn = om.MFnUnitAttribute() generalIk.aOrientRy = orientRyAttrFn.create("orientY", "orientY", 1, 0.0) orientRzAttrFn = om.MFnUnitAttribute() generalIk.aOrientRz = orientRzAttrFn.create("orientZ", "orientZ", 1, 0.0) orientRotAttrFn = om.MFnCompoundAttribute() generalIk.aOrientRot = orientRotAttrFn.create("orient", "orient") orientRotAttrFn.storable = False orientRotAttrFn.writable = True orientRotAttrFn.keyable = False orientRotAttrFn.addChild(generalIk.aOrientRx) orientRotAttrFn.addChild(generalIk.aOrientRy) orientRotAttrFn.addChild(generalIk.aOrientRz) # rotate order rotOrderAttrFn = om.MFnNumericAttribute() generalIk.aRotOrder = rotOrderAttrFn.create("rotateOrder", "rotateOrder", om.MFnNumericData.kLong, 0) # eye on the sky jntUpMatAttrFn = om.MFnMatrixAttribute() generalIk.aJntUpMat = jntUpMatAttrFn.create("upMatrix", "jntUpMat", 1) jntUpMatAttrFn.storable = True jntUpMatAttrFn.writable = True jntUpMatAttrFn.cached = True # om.MPxNode.addAttribute(generalIk.aJntUpMat) # but which way is up jntUpDirAttrFn = om.MFnNumericAttribute() generalIk.aJntUpDir = jntUpDirAttrFn.create("upDir", "upDir", om.MFnNumericData.k3Double) # who is the heftiest boi jntWeightAttrFn = om.MFnNumericAttribute() generalIk.aJntWeight = jntWeightAttrFn.create("weight", "jntWeight", om.MFnNumericData.kDouble, 1) jntWeightAttrFn.storable = True jntWeightAttrFn.keyable = True jntWeightAttrFn.writable = True jntWeightAttrFn.setMin(0) # om.MPxNode.addAttribute(generalIk.aJntWeight) limitAttrFn = om.MFnCompoundAttribute() generalIk.aLimits = limitAttrFn.create("limits", "limits") # like really know them rxMaxAttrFn = om.MFnNumericAttribute() generalIk.aRxMax = rxMaxAttrFn.create("maxRotateX", "maxRx", om.MFnNumericData.kDouble, 0) # how low can you go rxMinAttrFn = om.MFnNumericAttribute() generalIk.aRxMin = rxMinAttrFn.create("minRotateX", "minRx", om.MFnNumericData.kDouble, 0) limitAttrFn.addChild(generalIk.aRxMax) limitAttrFn.addChild(generalIk.aRxMin) ## there is more to be done here # you will never break the chain jntArrayAttrFn = om.MFnCompoundAttribute() generalIk.aJnts = jntArrayAttrFn.create("inputJoints", "inputJoints") jntArrayAttrFn.array = True jntArrayAttrFn.usesArrayDataBuilder = True jntArrayAttrFn.addChild(generalIk.aJntMat) jntArrayAttrFn.addChild(generalIk.aJntLocalMat) jntArrayAttrFn.addChild(generalIk.aJntUpMat) jntArrayAttrFn.addChild(generalIk.aJntUpDir) jntArrayAttrFn.addChild(generalIk.aJntWeight) jntArrayAttrFn.addChild(generalIk.aOrientRot) jntArrayAttrFn.addChild(generalIk.aRotOrder) jntArrayAttrFn.addChild(generalIk.aLimits) # add limits later om.MPxNode.addAttribute(generalIk.aJnts) # fruits of labour outRxAttrFn = om.MFnUnitAttribute() generalIk.aOutRx = outRxAttrFn.create("rotateX", "outRx", 1, 0.0) outRxAttrFn.writable = False outRxAttrFn.keyable = False # om.MPxNode.addAttribute(generalIk.aOutRx) outRyAttrFn = om.MFnUnitAttribute() generalIk.aOutRy = outRyAttrFn.create("rotateY", "outRy", 1, 0.0) outRyAttrFn.writable = False outRyAttrFn.keyable = False # om.MPxNode.addAttribute(generalIk.aOutRy) outRzAttrFn = om.MFnUnitAttribute() generalIk.aOutRz = outRzAttrFn.create("rotateZ", "outRz", 1, 0.0) outRzAttrFn.writable = False outRzAttrFn.keyable = False # om.MPxNode.addAttribute(generalIk.aOutRz) outRotAttrFn = om.MFnCompoundAttribute() # generalIk.aOutRot = outRotAttrFn.create("outputRotate", "outRot", # om.MFnNumericData.k3Double) generalIk.aOutRot = outRotAttrFn.create("rotate", "outRot") outRotAttrFn.storable = False outRotAttrFn.writable = False outRotAttrFn.keyable = False outRotAttrFn.addChild(generalIk.aOutRx) outRotAttrFn.addChild(generalIk.aOutRy) outRotAttrFn.addChild(generalIk.aOutRz) om.MPxNode.addAttribute(generalIk.aOutRot) # # add smooth jazz outTransAttrFn = om.MFnNumericAttribute() generalIk.aOutTrans = outTransAttrFn.create("translate", "outTrans", om.MFnNumericData.k3Double) outTransAttrFn.storable = False outTransAttrFn.writable = False outTransAttrFn.keyable = False om.MPxNode.addAttribute(generalIk.aOutTrans) # all that the sun touches outArrayAttrFn = om.MFnCompoundAttribute() generalIk.aOutArray = outArrayAttrFn.create("outputJoints", "out") outArrayAttrFn.array = True outArrayAttrFn.usesArrayDataBuilder = True outArrayAttrFn.storable = False outArrayAttrFn.writable = False outArrayAttrFn.keyable = False outArrayAttrFn.addChild(generalIk.aOutRot) outArrayAttrFn.addChild(generalIk.aOutTrans) om.MPxNode.addAttribute(generalIk.aOutArray) # investigate rolling this into the input hierarchy # convenience end attributes for babies outEndTransFn = om.MFnNumericAttribute() generalIk.aOutEndTrans = outEndTransFn.create("outputEndTranslate", "outputEndTranslate", om.MFnNumericData.k3Double) outEndTransFn.writable = False om.MPxNode.addAttribute(generalIk.aOutEndTrans) outEndRotFn = om.MFnCompoundAttribute() generalIk.aOutEndRot = outEndRotFn.create("outputEndRotate", "outputEndRotate") outEndRotFn.writable = False outEndRxAttrFn = om.MFnUnitAttribute() generalIk.aOutEndRx = outEndRxAttrFn.create("outputEndRotateX", "outEndRx", 1, 0.0) outEndRotFn.addChild(generalIk.aOutEndRx) outEndRyAttrFn = om.MFnUnitAttribute() generalIk.aOutEndRy = outEndRyAttrFn.create("outputEndRotateY", "outEndRy", 1, 0.0) outEndRotFn.addChild(generalIk.aOutEndRy) outEndRzAttrFn = om.MFnUnitAttribute() generalIk.aOutEndRz = outEndRzAttrFn.create("outputEndRotateZ", "outEndRz", 1, 0.0) outEndRotFn.addChild(generalIk.aOutEndRz) om.MPxNode.addAttribute(generalIk.aOutEndRot) # debug debugTargetFn = om.MFnMatrixAttribute() generalIk.aDebugTarget = debugTargetFn.create("debugTarget", "debugTarget", 1) om.MPxNode.addAttribute(generalIk.aDebugTarget) debugOffset = om.MFnNumericAttribute() generalIk.aDebugOffset = debugOffset.create("debugOffset", "debugOffset", om.MFnNumericData.kDouble, 0) om.MPxNode.addAttribute(generalIk.aDebugOffset) # caching results to persist across graph evaluations cacheMatricesFn = om.MFnTypedAttribute() matrixArrayData = om.MFnMatrixArrayData().create() generalIk.aCacheMatrices = cacheMatricesFn.create( "cacheMatrices", "cacheMatrices", 12, matrixArrayData) # matrix array cacheMatricesFn.writable = True cacheMatricesFn.readable = True cacheMatricesFn.cached = True cacheMatricesFn.keyable = True om.MPxNode.addAttribute(generalIk.aCacheMatrices) # everyone's counting on you drivers = [ generalIk.aTargetMat, generalIk.aEndMat, generalIk.aJnts, generalIk.aMaxIter, generalIk.aGlobalWeight, generalIk.aTolerance, generalIk.aJntWeight, generalIk.aCacheOn ] driven = [ generalIk.aOutArray, generalIk.aOutEndTrans, generalIk.aOutEndRot, generalIk.aDebugTarget, generalIk.aDebugOffset ] nodeio.setAttributeAffects(drivers, driven, generalIk)
def compute(self, pPlug, pData): # only compute if output is in out array if not pPlug.isChild: return if (pPlug.parent() == generalIk.aOutArray): # descend into coordinated cycles # inputs solver = pData.inputValue(generalIk.aSolver).asInt() maxIter = pData.inputValue(generalIk.aMaxIter).asInt() tolerance = pData.inputValue(generalIk.aTolerance).asDouble() globalWeight = pData.inputValue(generalIk.aGlobalWeight).asDouble() cacheOn = pData.inputValue(generalIk.aCacheOn).asShort() # target targetMat = pData.inputValue(generalIk.aTargetMat).asMatrix() # end endMat = pData.inputValue(generalIk.aEndMat).asMatrix() # extract input world matrices from array then leave it alone inJntArrayDH = pData.inputArrayValue(generalIk.aJnts) inLength = inJntArrayDH.__len__() worldInputs = [None] * inLength orients = [None] * inLength ups = [None] * inLength jointData = [None] * inLength # ARRAY OF STRUCTS REEEEEEEE for i in range(inLength): inJntArrayDH.jumpToPhysicalElement(i) childCompDH = inJntArrayDH.inputValue() worldInputs[i] = childCompDH.child( generalIk.aJntMat).asMatrix() ups[i] = childCompDH.child(generalIk.aJntUpMat).asMatrix() orients[i] = om.MEulerRotation( childCompDH.child(generalIk.aOrientRot).asDouble3()) # extra data weight = childCompDH.child(generalIk.aJntWeight).asDouble() upDir = childCompDH.child(generalIk.aJntUpDir).asDouble3() jointData[i] = { "weight": weight, "upDir": upDir, } # from world inputs, reconstruct localised chain chainData = buildChains(worldInputs, orients, ups, length=inLength) localMatrices = chainData["localMatrices"] localUpMatrices = chainData["localUpMatrices"] ikSpaceMatrices = chainData["ikSpaceMatrices"] ikSpaceUpMatrices = chainData["ikSpaceUpMatrices"] # ikSpace and local matrices are correct # CACHE STUFF -------------------------------- # extract cached matrices from previous graph evaluation cacheMatrices = pData.inputValue(generalIk.aCacheMatrices) cacheArray = om.MFnMatrixArrayData(cacheMatrices.data()).array() if len(cacheArray) != inLength: print("cache length different, rebuilding") cacheArray.clear() for n in localMatrices: cacheArray.append(n) for i in range(inLength): if positionFromMatrix(localMatrices[i]) != \ positionFromMatrix(cacheArray[i]): print("cache entry {} position has changed, substituting". format(i)) cacheArray[i] = localMatrices[i] if cacheOn == 1 or cacheOn == 2: # bind or bound # set local matrices to cached ------ for i in range(inLength): localMatrices[i] = cacheArray[i] if cacheOn == 1: pData.inputValue(generalIk.aCacheOn).setShort(2) """ I don't think there is any point in treating the end matrix separately - it only adds a special case at every turn refactor to include it in normal local matrices """ # main loop ---------------- n = 0 tol = 100 endIkSpace = endMat * worldInputs[0].inverse() # endIkSpace is correct targetMat = neutraliseRotations(targetMat) endLocalSpace = endMat * worldInputs[-1].inverse() """ localise target into ikSpace """ targetIkSpace = targetMat * worldInputs[0].inverse() # targetIkSpace is correct while n < maxIter and tol > tolerance: debug() debug("n", n) data = iterateChainCCD( worldMatrices=worldInputs, ikSpaceMatrices=ikSpaceMatrices, localMatrices=localMatrices, length=inLength, targetMat=targetIkSpace, endMat=endIkSpace, localEndMat=endLocalSpace, upMatrices=ups, jointData=jointData, globalWeight=globalWeight, ikSpaceUpMatrices=ikSpaceUpMatrices, tolerance=tolerance, ) localMatrices = data["results"] debug("results", localMatrices) tol = data["tolerance"] endIkSpace = data["end"] targetMat = data["target"] n += 1 if tol < tolerance: # process is complete break results = localMatrices worldSpaceTarget = worldInputs[0] * targetMat ikSpaceOutputs = [ multiplyMatrices(localMatrices[:i + 1]) for i in range(inLength) ] endLocalSpace = endIkSpace * ikSpaceOutputs[-1].inverse() # save cached matrices for next evaluation # BEFORE reapplying world space to base cacheArray.clear() for i in localMatrices: cacheArray.append(i) # restore world space root position results[0] = results[0] * worldInputs[0] # outputs --------------- spaceConstant = 1 outDebugDH = pData.outputValue(generalIk.aDebugTarget) outDebugDH.setMMatrix(worldSpaceTarget) outDebugOffsetDH = pData.outputValue(generalIk.aDebugOffset) outDebugOffsetDH.setDouble(tol) # end transform endTfMat = om.MTransformationMatrix(endLocalSpace) outEndTransDH = pData.outputValue(generalIk.aOutEndTrans) outEndTransDH.set3Double(*endTfMat.translation(spaceConstant)) # convert jntArray of matrices to useful rotation values outArrayDH = pData.outputArrayValue(generalIk.aOutArray) for i in range(inLength): outArrayDH.jumpToPhysicalElement(i) outCompDH = outArrayDH.outputValue() outRotDH = outCompDH.child(generalIk.aOutRot) outRxDH = outRotDH.child(generalIk.aOutRx) outRyDH = outRotDH.child(generalIk.aOutRy) outRzDH = outRotDH.child(generalIk.aOutRz) # apply jointOrient ----- outMat = om.MTransformationMatrix(results[i]).rotateBy( orients[i].inverse(), spaceConstant) # set output rotations ------- outRot = outMat.rotation() # unitConversions bring SHAME on family xAngle = om.MAngle(outRot[0]) yAngle = om.MAngle(outRot[1]) zAngle = om.MAngle(outRot[2]) outRxDH.setMAngle(xAngle) outRyDH.setMAngle(yAngle) outRzDH.setMAngle(zAngle) outTranslate = (results[i][12], results[i][13], results[i][14]) outTransDH = outCompDH.child(generalIk.aOutTrans) outTransDH.set3Double(*outTranslate) outArrayDH.setAllClean() pData.setClean(pPlug)
def addAttribute(node, longName, shortName, attrType=attrtypes.kMFnNumericDouble, isArray=False, apply=True): """This function uses the api to create attributes on the given node, currently WIP but currently works for string,int, float, bool, message, matrix. if the attribute exists a ValueError will be raised. :param node: MObject :param longName: str, the long name for the attribute :param shortName: str, the shortName for the attribute :param attrType: attribute Type, attrtypes constants :param apply: if False the attribute will be immediately created on the node else just return the attribute instance :rtype: om.MObject """ if hasAttribute(node, longName): raise ValueError("Node -> '%s' already has attribute -> '%s'" % (nameFromMObject(node), longName)) aobj = None attr = None if attrType == attrtypes.kMFnNumericDouble: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.kDouble) elif attrType == attrtypes.kMFnNumericFloat: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.kFloat) elif attrType == attrtypes.kMFnNumericBoolean: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.kBoolean) elif attrType == attrtypes.kMFnNumericInt: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.kInt) elif attrType == attrtypes.kMFnNumericShort: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.kShort) elif attrType == attrtypes.kMFnNumericLong: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.kLong) elif attrType == attrtypes.kMFnNumericByte: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.kByte) elif attrType == attrtypes.kMFnNumericChar: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.kChar) elif attrType == attrtypes.kMFnNumericAddr: attr = om2.MFnNumericAttribute() aobj = attr.createAddr(longName, shortName) elif attrType == attrtypes.kMFnkEnumAttribute: attr = om2.MFnEnumAttribute() aobj = attr.create(longName, shortName) elif attrType == attrtypes.kMFnCompoundAttribute: attr = om2.MFnCompoundAttribute() aobj = attr.create(longName, shortName) elif attrType == attrtypes.kMFnMessageAttribute: attr = om2.MFnMessageAttribute() aobj = attr.create(longName, shortName) elif attrType == attrtypes.kMFnDataString: attr = om2.MFnTypedAttribute() stringData = om2.MFnStringData().create("") aobj = attr.create(longName, shortName, om2.MFnData.kString, stringData) elif attrType == attrtypes.kMFnUnitAttributeDistance: attr = om2.MFnUnitAttribute() aobj = attr.create(longName, shortName, om2.MDistance()) elif attrType == attrtypes.kMFnUnitAttributeAngle: attr = om2.MFnUnitAttribute() aobj = attr.create(longName, shortName, om2.MAngle()) elif attrType == attrtypes.kMFnUnitAttributeTime: attr = om2.MFnUnitAttribute() aobj = attr.create(longName, shortName, om2.MTime()) elif attrType == attrtypes.kMFnDataMatrix: attr = om2.MFnMatrixAttribute() aobj = attr.create(longName, shortName) elif attrType == attrtypes.kMFnDataFloatArray: attr = om2.MFnFloatArray() aobj = attr.create(longName, shortName) elif attrType == attrtypes.kMFnDataDoubleArray: data = om2.MFnDoubleArrayData().create(om2.MDoubleArray()) attr = om2.MFnTypedAttribute() aobj = attr.create(longName, shortName, om2.MFnData.kDoubleArray, data) elif attrType == attrtypes.kMFnDataIntArray: data = om2.MFnIntArrayData().create(om2.MIntArray()) attr = om2.MFnTypedAttribute() aobj = attr.create(longName, shortName, om2.MFnData.kIntArray, data) elif attrType == attrtypes.kMFnDataPointArray: data = om2.MFnPointArrayData().create(om2.MPointArray()) attr = om2.MFnTypedAttribute() aobj = attr.create(longName, shortName, om2.MFnData.kPointArray, data) elif attrType == attrtypes.kMFnDataVectorArray: data = om2.MFnVectorArrayData().create(om2.MVectorArray()) attr = om2.MFnTypedAttribute() aobj = attr.create(longName, shortName, om2.MFnData.kVectorArray, data) elif attrType == attrtypes.kMFnDataStringArray: data = om2.MFnStringArrayData().create(om2.MStringArray()) attr = om2.MFnTypedAttribute() aobj = attr.create(longName, shortName, om2.MFnData.kStringArray, data) elif attrType == attrtypes.kMFnDataMatrixArray: data = om2.MFnMatrixArrayData().create(om2.MMatrixArray()) attr = om2.MFnTypedAttribute() aobj = attr.create(longName, shortName, om2.MFnData.kMatrixArray, data) elif attrType == attrtypes.kMFnNumericInt64: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.kInt64) elif attrType == attrtypes.kMFnNumericLast: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.kLast) elif attrType == attrtypes.kMFnNumeric2Double: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.k2Double) elif attrType == attrtypes.kMFnNumeric2Float: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.k2Float) elif attrType == attrtypes.kMFnNumeric2Int: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.k2Int) elif attrType == attrtypes.kMFnNumeric2Long: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.k2Long) elif attrType == attrtypes.kMFnNumeric2Short: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.k2Short) elif attrType == attrtypes.kMFnNumeric3Double: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.k3Double) elif attrType == attrtypes.kMFnNumeric3Float: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.k3Float) elif attrType == attrtypes.kMFnNumeric3Int: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.k3Int) elif attrType == attrtypes.kMFnNumeric3Long: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.k3Long) elif attrType == attrtypes.kMFnNumeric3Short: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.k3Short) elif attrType == attrtypes.kMFnNumeric4Double: attr = om2.MFnNumericAttribute() aobj = attr.create(longName, shortName, om2.MFnNumericData.k4Double) if aobj is not None and apply: attr.array = isArray mod = om2.MDGModifier() mod.addAttribute(node, aobj) mod.doIt() return attr