コード例 #1
0
ファイル: plugs.py プロジェクト: kthulhu/zoocore_maya
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
コード例 #2
0
ファイル: generalIk.py プロジェクト: edart76/edPlugin
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)
コード例 #3
0
ファイル: generalIk.py プロジェクト: edart76/edPlugin
    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)
コード例 #4
0
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