예제 #1
0
class AngleToDouble(om2.MPxNode):
    """ Main class of gfUtilAngleToDouble node. """

    kNodeName = ""
    kNodeClassify = ""
    kNodeID = ""

    inAngle = om2.MObject()
    outDouble = om2.MObject()

    def __init__(self):
        """ Constructor. """
        om2.MPxNode.__init__(self)

    @staticmethod
    def creator():
        """ Maya creator function. """
        return AngleToDouble()

    @staticmethod
    def initialize():
        """
        Defines the set of attributes for this node. The attributes declared in this function are assigned
        as static members to AngleToDouble class. Instances of AngleToDouble will use these attributes to create plugs
        for use in the compute() method.
        """
        uAttr = om2.MFnUnitAttribute()
        nAttr = om2.MFnNumericAttribute()

        AngleToDouble.inAngle = uAttr.create("angle", "angle",
                                             om2.MFnUnitAttribute.kAngle, 0.0)
        INPUT_ATTR(uAttr)

        AngleToDouble.outDouble = nAttr.create("outDouble", "od",
                                               om2.MFnNumericData.kDouble, 0.0)
        OUTPUT_ATTR(nAttr)

        AngleToDouble.addAttribute(AngleToDouble.inAngle)
        AngleToDouble.addAttribute(AngleToDouble.outDouble)
        AngleToDouble.attributeAffects(AngleToDouble.inAngle,
                                       AngleToDouble.outDouble)

    def compute(self, plug, dataBlock):
        """
        Node computation method:
            * plug is a connection point related to one of our node attributes (either an input or an output).
            * dataBlock contains the data on which we will base our computations.
        """
        # pylint: disable=no-self-use
        if plug != AngleToDouble.outDouble:
            return om2.kUnknownParameter

        angle = dataBlock.inputValue(
            AngleToDouble.inAngle).asAngle().asDegrees()
        outDoubleHandle = dataBlock.outputValue(AngleToDouble.outDouble)

        outDoubleHandle.setDouble(angle)
        outDoubleHandle.setClean()
예제 #2
0
class TestNode(om2.MPxNode):
    """ Main class of gfTestNode node. """

    kNodeName = ""
    kNodeClassify = ""
    kNodeID = ""

    inAttr = om2.MObject()
    outAttr = om2.MObject()

    def __init__(self):
        """ Constructor. """
        om2.MPxNode.__init__(self)

    @staticmethod
    def creator():
        """ Maya creator function. """
        return TestNode()

    @staticmethod
    def initialize():
        """
        Defines the set of attributes for this node. The attributes declared in this function are assigned
        as static members to TestNode class. Instances of TestNode will use these attributes to create plugs
        for use in the compute() method.
        """
        nAttr = om2.MFnNumericAttribute()

        TestNode.inAttr = nAttr.createPoint("inAttr", "ina")
        INPUT_ATTR(nAttr)

        TestNode.outAttr = nAttr.createPoint("outAttr", "outa")
        OUTPUT_ATTR(nAttr)

        TestNode.addAttribute(TestNode.inAttr)
        TestNode.addAttribute(TestNode.outAttr)
        TestNode.attributeAffects(TestNode.inAttr, TestNode.outAttr)

    def compute(self, plug, dataBlock):
        """
        Node computation method:
            * plug is a connection point related to one of our node attributes (either an input or an output).
            * dataBlock contains the data on which we will base our computations.
        """
        # pylint: disable=no-self-use
        if plug != TestNode.outAttr:
            return om2.kUnknownParameter

        inAttrValue = dataBlock.inputValue(TestNode.inAttr).asVector()

        outAttrHandle = dataBlock.outputValue(TestNode.outAttr)
        outAttrHandle.set3Float(inAttrValue.x, inAttrValue.y, inAttrValue.z)
        outAttrHandle.setClean()
예제 #3
0
class MeshController(omui2.MPxLocatorNode):
    """ Main class of gfMeshController node. """

    kNodeName = ""
    kNodeClassify = ""
    kNodeRegistrantID = ""
    kNodeID = ""

    inIndexList = om2.MObject()
    inOffset = om2.MObject()
    inMesh = om2.MObject()
    inColor = om2.MObject()

    ctrlVertices = []
    bBox = om2.MBoundingBox()

    def __init__(self):
        """ Constructor. """
        omui2.MPxLocatorNode.__init__(self)

    def postConstructor(self):
        """ Post Constructor. """
        thisMob = self.thisMObject()
        om2.MFnDependencyNode(thisMob).setName("%sShape#" %
                                               MeshController.kNodeName)

    @staticmethod
    def creator():
        """ Maya creator function. """
        return MeshController()

    @staticmethod
    def initialize():
        """
        Defines the set of attributes for this node. The attributes declared in this function are assigned
        as static members to MeshController class. Instances of MeshController will use these attributes to create plugs
        for use in the compute() method.
        """
        tAttr = om2.MFnTypedAttribute()
        nAttr = om2.MFnNumericAttribute()

        MeshController.inIndexList = tAttr.create("indexList", "index",
                                                  om2.MFnData.kString)
        INPUT_ATTR(tAttr)

        MeshController.inOffset = nAttr.create("offset", "offset",
                                               om2.MFnNumericData.kFloat, 0.0)
        INPUT_ATTR(nAttr)

        MeshController.inMesh = tAttr.create("controlMesh", "controlMesh",
                                             om2.MFnData.kMesh)
        INPUT_ATTR(tAttr)

        MeshController.inColor = nAttr.createColor("color", "color")
        nAttr.default = (1.0, 0.455, 0.086)
        INPUT_ATTR(nAttr)

        MeshController.addAttribute(MeshController.inIndexList)
        MeshController.addAttribute(MeshController.inOffset)
        MeshController.addAttribute(MeshController.inMesh)
        MeshController.addAttribute(MeshController.inColor)

    @staticmethod
    def listToMIntArray(strList):
        """ Convert a list of int to a MIntArray instance. """
        # pylint: disable=undefined-variable
        instance = om2.MIntArray()
        for i in strList:
            try:
                instance.append(int(i))
            except ValueError:
                pass
        return instance

    @staticmethod
    def getGeometryPoints(meshMob, indexStr, offset, transform):
        """ Find the info of the geometry who will be drawed. """
        # vtxNormals = []
        # vtxPositions = []

        # if not meshMob.isNull():
        #     polyIndexList = MeshController.listToMIntArray(indexStr.split(","))
        #     itPoly = om2.MItMeshPolygon(meshMob)
        #     while not itPoly.isDone():
        #         if itPoly.index() in polyIndexList:
        #             vtxNormals.append(itPoly.getNormals())
        #             vtxPositions.append(itPoly.getPoints(om2.MSpace.kWorld))
        #         itPoly.next(None)

        # return [vtxNormals, vtxPositions]

        #==============================================================================
        # # 47 FPS AVERAGE WITH NO EDGES | 27 FPS AVERAGE WITH EDGES
        # vtxNormals = []
        # vtxPositions = []

        # if not meshMob.isNull():
        #     polyIndexList = MeshController.listToMIntArray(indexStr.split(","))
        #     itPoly = om2.MItMeshPolygon(meshMob)
        #     for index in polyIndexList:
        #         itPoly.setIndex(index)
        #         vtxNormals.append(itPoly.getNormals())
        #         vtxPositions.append(itPoly.getPoints(om2.MSpace.kWorld))

        # return [vtxNormals, vtxPositions]

        #==============================================================================
        # # 45 FPS AVERAGE WITH NO EDGES | 25 FPS AVERAGE WITH EDGES
        # meshVtxPos = om2.MPointArray()
        # vtxIndexList = []
        # vtxPositions = []

        # if not meshMob.isNull():
        #     polyIndexList = MeshController.listToMIntArray(indexStr.split(","))
        #     meshFn = om2.MFnMesh(meshMob)
        #     meshVtxPos = meshFn.getPoints(om2.MSpace.kWorld)
        #     for index in polyIndexList:
        #         vtxIndexList.append(meshFn.getPolygonVertices(index))
        #     for poly in vtxIndexList:
        #         pntArray = om2.MPointArray()
        #         for pnt in poly:
        #             pntArray.append(meshVtxPos[pnt])
        #         vtxPositions.append(pntArray)

        # return [[], vtxPositions]

        #==============================================================================
        # 47 FPS AVERAGE WITH NO EDGES | 27 FPS AVERAGE WITH EDGES
        outPnts = []

        pntOffTolerance = 0.01
        tolerance = offset + pntOffTolerance
        bBox = om2.MBoundingBox()

        if not meshMob.isNull():
            polyIndexList = MeshController.listToMIntArray(indexStr.split(","))
            itPoly = om2.MItMeshPolygon(meshMob)
            for index in polyIndexList:
                itPoly.setIndex(index)
                polyVtxNormals = itPoly.getNormals()
                polyVtxPos = itPoly.getPoints(om2.MSpace.kWorld)
                outPolyVtxPos = om2.MPointArray()
                for i, pnt in enumerate(polyVtxPos):
                    curPnt = pnt
                    curNormal = polyVtxNormals[i]
                    outPnt = (curPnt + (curNormal * tolerance)) * transform
                    bBox.expand(outPnt)
                    outPolyVtxPos.append(outPnt)
                outPnts.append(outPolyVtxPos)

        MeshController.ctrlVertices = outPnts
        MeshController.bBox = bBox

    def compute(self, plug, dataBlock):
        """
        Node computation method:
            * plug is a connection point related to one of our node attributes (either an input or an output).
            * dataBlock contains the data on which we will base our computations.
        """
        # pylint: disable=unused-argument
        return

    def draw(self, view, path, style, status):
        """
        Draw custom geometry in the viewport using OpenGL calls.
            * view [M3dView] is a 3D view that is being drawn into.
            * path [MDagPath] to the parent (transform node) of this locator in the DAG.  To obtain the locator shape node,
                use MDagPath::extendToShape() if there is only one shape node under the transform or
                MDagPath::extendToShapeDirectlyBelow(unsigned int index) with the shape index if there are multiple
                shapes under the transform.
            * style [M3dView.DisplayStyle] is the style to draw object in.
            * status [M3dView.DisplayStatus] is the selection status of the object.
        """
        # pylint: disable=unused-argument
        # thisMob = self.thisMObject()
        # mWorldInv = path.inclusiveMatrixInverse()
        # indexStr = om2.MPlug(thisMob, MeshController.inIndexList).asString()
        # offset = om2.MPlug(thisMob, MeshController.inOffset).asFloat()
        # mesh = om2.MPlug(thisMob, MeshController.inMesh).asMDataHandle().asMesh()
        # color = om2.MPlug(thisMob, MeshController.inColor).asMDataHandle().asFloatVector()

        # # If plugs are dirty calculate the geometry points
        # MeshController.getGeometryPoints(mesh, indexStr, offset, mWorldInv)

        # view.beginGL()

        # glRenderer = omr1.MHardwareRenderer.theRenderer()
        # glFT = glRenderer.glFunctionTable()

        # glFT.glPushAttrib(omr1.MGL_CURRENT_BIT)
        # glFT.glDisable(omr1.MGL_CULL_FACE)
        # glFT.glEnable(omr1.MGL_BLEND)
        # glFT.glBlendFunc(omr1.MGL_SRC_ALPHA, omr1.MGL_ONE_MINUS_SRC_ALPHA)

        # color = om2.MFloatVector(color.x, color.y, color.z)
        # if status == view.kDormant:
        #     # Not selected
        #     alpha = 0.25
        # elif status == view.kActive:
        #     # Multiselection
        #     alpha = 0.65
        # elif status == view.kLead:
        #     # Selected
        #     alpha = 0.5

        # if style == view.kFlatShaded or style == view.kGouraudShaded:
        #     glFT.glColor4f(color.x, color.y, color.z, alpha)
        #     for poly in MeshController.ctrlVertices:
        #         glFT.glBegin(omr1.MGL_POLYGON)
        #         for pnt in poly:
        #             glFT.glVertex3f(pnt.x, pnt.y, pnt.z)
        #         glFT.glEnd()

        # if style == view.kWireFrame:
        #     glFT.glColor4f(color.x, color.y, color.z, 1.0)
        #     glFT.glBegin(omr1.MGL_LINES)
        #     for poly in MeshController.ctrlVertices:
        #         for i, pnt in enumerate(poly):
        #             glFT.glVertex3f(pnt.x, pnt.y, pnt.z)
        #             if i == len(poly) - 1:
        #                 glFT.glVertex3f(poly[0].x, poly[0].y, poly[0].z)
        #             else:
        #                 glFT.glVertex3f(poly[i+1].x, poly[i+1].y, poly[i+1].z)
        #     glFT.glEnd()

        # glFT.glPopAttrib()

        # view.endGL()
        return

    def isBounded(self):
        """isBounded?"""
        return True

    def isTransparent(self):
        """isTransparent?"""
        return True

    def boundingBox(self):
        """Return the boundingBox"""
        if not MeshController.ctrlVertices:
            thisMob = self.thisMObject()
            thisPath = om2.MDagPath.getAPathTo(thisMob)
            transformPath = om2.MDagPath.getAPathTo(
                om2.MFnDagNode(thisPath).parent(0))
            mWorldInv = transformPath.inclusiveMatrixInverse()
            indexStr = om2.MPlug(thisMob,
                                 MeshController.inIndexList).asString()
            offset = om2.MPlug(thisMob, MeshController.inOffset).asFloat()
            mesh = om2.MPlug(thisMob,
                             MeshController.inMesh).asMDataHandle().asMesh()
            MeshController.getGeometryPoints(mesh, indexStr, offset, mWorldInv)
        return MeshController.bBox

    def preEvaluation(self, context, evaluationNode):
        """ Called before this node is evaluated by Evaluation Manager.
            * context [MDGContext] is the context which the evaluation is happening.
            * evaluationNode [MEvaluationNode] the evaluation node which contains information
                about the dirty plugs that are about to be evaluated for the context.
                Should be only used to query information.
        """
        if context.isNormal():
            if evaluationNode.dirtyPlugExists(MeshController.inOffset):
                omr2.MRenderer.setGeometryDrawDirty(self.thisMObject())
            elif evaluationNode.dirtyPlugExists(MeshController.inIndexList):
                omr2.MRenderer.setGeometryDrawDirty(self.thisMObject())
            elif evaluationNode.dirtyPlugExists(MeshController.inMesh):
                omr2.MRenderer.setGeometryDrawDirty(self.thisMObject())
예제 #4
0
class SpaceConstraint(om2.MPxNode):
    """ Main class of gfUtilSpaceConstraint node. """

    kNodeName = ""
    kNodeClassify = ""
    kNodeID = ""
    kCallbackIDs = om2.MCallbackIdArray()
    kCallbackNodes = om2.MObjectArray()

    inSpace = om2.MObject()
    inOffset = om2.MObject()
    inOffsetMatches = om2.MObject()
    inTarget = om2.MObject()
    inAutoFillOff = om2.MObject()
    inSpaceMatch = om2.MObject()
    outConstTrans = om2.MObject()
    outConstRot = om2.MObject()
    outConstSca = om2.MObject()

    def __init__(self):
        """ Constructor. """
        om2.MPxNode.__init__(self)
        self.lastSpace = 0
        self.constraintObject = None

    @staticmethod
    def creator():
        """ Maya creator function. """
        return SpaceConstraint()

    @staticmethod
    def initialize():
        """
        Defines the set of attributes for this node. The attributes declared in this function are assigned
        as static members to SpaceConstraint class. Instances of SpaceConstraint will use these attributes to create plugs
        for use in the compute() method.
        """
        mAttr = om2.MFnMatrixAttribute()
        nAttr = om2.MFnNumericAttribute()
        uAttr = om2.MFnUnitAttribute()

        SpaceConstraint.inSpace = nAttr.create("space", "space",
                                               om2.MFnNumericData.kShort, 0)
        nAttr.setMin(0)
        INPUT_ATTR(nAttr)

        SpaceConstraint.inOffset = mAttr.create("offset", "offset",
                                                om2.MFnMatrixAttribute.kDouble)
        mAttr.array = True
        INPUT_ATTR(mAttr)

        SpaceConstraint.inOffsetMatches = mAttr.create(
            "offsetMatch", "offm", om2.MFnMatrixAttribute.kDouble)
        mAttr.array = True
        INPUT_ATTR(mAttr)

        SpaceConstraint.inTarget = mAttr.create("target", "target",
                                                om2.MFnMatrixAttribute.kDouble)
        mAttr.array = True
        INPUT_ATTR(mAttr)

        SpaceConstraint.inAutoFillOff = nAttr.create(
            "autoFillOffsets", "afoff", om2.MFnNumericData.kBoolean, True)
        INPUT_ATTR(nAttr)

        SpaceConstraint.inSpaceMatch = nAttr.create(
            "spaceMatch", "spaceMatch", om2.MFnNumericData.kBoolean, True)
        INPUT_ATTR(nAttr)

        SpaceConstraint.outConstTrans = nAttr.createPoint(
            "constraintTranslate", "ctrans")
        OUTPUT_ATTR(nAttr)

        rotX = uAttr.create("constraintRotateX", "crotx",
                            om2.MFnUnitAttribute.kAngle, 0.0)
        rotY = uAttr.create("constraintRotateY", "croty",
                            om2.MFnUnitAttribute.kAngle, 0.0)
        rotZ = uAttr.create("constraintRotateZ", "crotz",
                            om2.MFnUnitAttribute.kAngle, 0.0)
        SpaceConstraint.outConstRot = nAttr.create("constraintRotate", "crot",
                                                   rotX, rotY, rotZ)
        OUTPUT_ATTR(nAttr)

        SpaceConstraint.outConstSca = nAttr.createPoint(
            "constraintScale", "csca")
        nAttr.default = (1.0, 1.0, 1.0)
        OUTPUT_ATTR(nAttr)

        SpaceConstraint.addAttribute(SpaceConstraint.inSpace)
        SpaceConstraint.addAttribute(SpaceConstraint.inAutoFillOff)
        SpaceConstraint.addAttribute(SpaceConstraint.inSpaceMatch)
        SpaceConstraint.addAttribute(SpaceConstraint.inOffset)
        SpaceConstraint.addAttribute(SpaceConstraint.inOffsetMatches)
        SpaceConstraint.addAttribute(SpaceConstraint.inTarget)
        SpaceConstraint.addAttribute(SpaceConstraint.outConstTrans)
        SpaceConstraint.addAttribute(SpaceConstraint.outConstRot)
        SpaceConstraint.addAttribute(SpaceConstraint.outConstSca)
        SpaceConstraint.attributeAffects(SpaceConstraint.inSpace,
                                         SpaceConstraint.outConstTrans)
        SpaceConstraint.attributeAffects(SpaceConstraint.inOffset,
                                         SpaceConstraint.outConstTrans)
        SpaceConstraint.attributeAffects(SpaceConstraint.inOffsetMatches,
                                         SpaceConstraint.outConstTrans)
        SpaceConstraint.attributeAffects(SpaceConstraint.inTarget,
                                         SpaceConstraint.outConstTrans)
        SpaceConstraint.attributeAffects(SpaceConstraint.inSpace,
                                         SpaceConstraint.outConstRot)
        SpaceConstraint.attributeAffects(SpaceConstraint.inOffset,
                                         SpaceConstraint.outConstRot)
        SpaceConstraint.attributeAffects(SpaceConstraint.inOffsetMatches,
                                         SpaceConstraint.outConstRot)
        SpaceConstraint.attributeAffects(SpaceConstraint.inTarget,
                                         SpaceConstraint.outConstRot)
        SpaceConstraint.attributeAffects(SpaceConstraint.inSpace, rotX)
        SpaceConstraint.attributeAffects(SpaceConstraint.inOffset, rotX)
        SpaceConstraint.attributeAffects(SpaceConstraint.inOffsetMatches, rotX)
        SpaceConstraint.attributeAffects(SpaceConstraint.inTarget, rotX)
        SpaceConstraint.attributeAffects(SpaceConstraint.inSpace, rotY)
        SpaceConstraint.attributeAffects(SpaceConstraint.inOffset, rotY)
        SpaceConstraint.attributeAffects(SpaceConstraint.inOffsetMatches, rotY)
        SpaceConstraint.attributeAffects(SpaceConstraint.inTarget, rotY)
        SpaceConstraint.attributeAffects(SpaceConstraint.inSpace, rotZ)
        SpaceConstraint.attributeAffects(SpaceConstraint.inOffset, rotZ)
        SpaceConstraint.attributeAffects(SpaceConstraint.inOffsetMatches, rotZ)
        SpaceConstraint.attributeAffects(SpaceConstraint.inTarget, rotZ)
        SpaceConstraint.attributeAffects(SpaceConstraint.inSpace,
                                         SpaceConstraint.outConstSca)
        SpaceConstraint.attributeAffects(SpaceConstraint.inOffset,
                                         SpaceConstraint.outConstSca)
        SpaceConstraint.attributeAffects(SpaceConstraint.inOffsetMatches,
                                         SpaceConstraint.outConstSca)
        SpaceConstraint.attributeAffects(SpaceConstraint.inTarget,
                                         SpaceConstraint.outConstSca)

    def postConstructor(self):
        """ Post Constructor. """
        thisMob = self.thisMObject()

        # # Add space match callback
        # callback = om2.MNodeMessage.addAttributeChangedCallback(thisMob, SpaceConstraint.spaceMatchCallback, self)
        # SpaceConstraint.kCallbackIDs.append(callback)
        # SpaceConstraint.kCallbackNodes.append(thisMob)

        # spacePlug = om2.MPlug(thisMob, SpaceConstraint.inSpace)
        # callback = om2.MNodeMessage.addKeyableChangeOverride(spacePlug, SpaceConstraint.spaceMatchCallback2, self)
        # SpaceConstraint.kCallbackIDs.append(callback)
        # SpaceConstraint.kCallbackNodes.append(thisMob)
        # om2.MGlobal.displayInfo("Node callback: %s" % str(callback))
        # om2.MGlobal.displayInfo("All callbacks: %s" % str(SpaceConstraint.kCallbackIDs))

        # callback = om2.MNodeMessage.addNodeDirtyPlugCallback(thisMob, SpaceConstraint.spaceMatchCallback2, self)
        # SpaceConstraint.kCallbackIDs.append(callback)
        # SpaceConstraint.kCallbackNodes.append(thisMob)
        # om2.MGlobal.displayInfo("Node callback: %s" % str(callback))
        # om2.MGlobal.displayInfo("All callbacks: %s" % str(SpaceConstraint.kCallbackIDs))

        # om2.MUserEventMessage.registerUserEvent("preCompute")
        # callback1 = om2.MUserEventMessage.addUserEventCallback("preCompute", SpaceConstraint.spaceMatchCallback3, self)
        # callback1 = om2.MDGMessage.addTimeChangeCallback(SpaceConstraint.spaceMatchCallback3, self)
        # callback2 = om2.MNodeMessage.addAttributeChangedCallback(thisMob, SpaceConstraint.spaceMatchCallback4, self)
        # SpaceConstraint.kCallbackIDs.append(callback1)
        # SpaceConstraint.kCallbackIDs.append(callback2)
        # SpaceConstraint.kCallbackNodes.append(thisMob)
        # om2.MGlobal.displayInfo("All callbacks: %s" % str(SpaceConstraint.kCallbackIDs))
        callback1 = oma2.MAnimMessage.addAnimKeyframeEditedCallback(
            SpaceConstraint.spaceMatchCallback5, self)
        callback2 = om2.MDGMessage.addTimeChangeCallback(
            SpaceConstraint.spaceMatchCallback3, self)
        SpaceConstraint.kCallbackIDs.append(callback1)
        SpaceConstraint.kCallbackIDs.append(callback2)
        SpaceConstraint.kCallbackNodes.append(thisMob)
        om2.MGlobal.displayInfo("All callbacks: %s" %
                                str(SpaceConstraint.kCallbackIDs))

        # TODO: Using MDGMessage.timeChanged won't work because of jump in time. Instead use MAnimMessage to track keyframes.
        # TODO: If the time in a animation curve change, and the plug is animated, read the anim curve and set the space match.

    @staticmethod
    def spaceMatchCallback3(time, clientData):
        """Test"""
        om2.MGlobal.displayInfo("Updating animation...")
        oma2.MAnimMessage.flushAnimKeyframeEditedCallbacks()
        # thisMob = clientData.thisMObject()
        # spacePlug = om2.MPlug(thisMob, SpaceConstraint.inSpace)
        # oldSpaceValue = str(spacePlug.asShort())
        # clientData.setDependentsDirty()
        # spacePlug = om2.MPlug(thisMob, SpaceConstraint.inSpace)
        # newSpaceValue = str(spacePlug.asShort())
        # om2.MGlobal.displayInfo("[timeChanged] Old space value: %s | Current space value: %s" % (oldSpaceValue, newSpaceValue))

    @staticmethod
    def spaceMatchCallback5(editedKeys, clientData):
        """Test"""
        om2.MGlobal.displayInfo("Hello ma friend!")
        return True

    @staticmethod
    def spaceMatchCallback4(msg, plug, otherPlug, clientData):
        """Test"""
        thisMob = clientData.thisMObject()
        if msg == 2056:
            if plug == SpaceConstraint.inSpace:
                spacePlug = om2.MPlug(thisMob, SpaceConstraint.inSpace)
                om2.MGlobal.displayInfo(
                    "[attributeChanged] Current space value: %s" %
                    str(spacePlug.asShort()))

    @staticmethod
    def spaceMatchCallback2(node, plug, clientData):
        """Node dirty callback. Works, but not quite. """
        # 1- Check if space plug is dirty.
        if plug == SpaceConstraint.inSpace:
            # 2- Check if clientData is valid.
            thisMob = clientData.thisMObject()
            if not isinstance(clientData, SpaceConstraint):
                om2.MGlobal.displayError(
                    "[gfTools] gfSpaceConstraint don't recognize the clientData for space matching. Callback functionality skipped."
                )
                return
            # 3- Check if automatic space matching is enable.
            match = om2.MPlug(thisMob, SpaceConstraint.inSpaceMatch).asBool()
            if not match:
                return
            # 4- Check if space attribute changed.
            lastValue = clientData.lastSpace
            curValue = plug.asShort()
            spacePlug = om2.MPlug(thisMob, SpaceConstraint.inSpace)
            om2.MGlobal.displayInfo("Current space value: %s" %
                                    str(spacePlug.asShort()))
            if curValue == lastValue:
                return
            # 5- Check if any output is been used and get the output object.
            allClear = clientData.checkOutputConnections(thisMob)
            # 6- Check the inputs.
            targetPlug = om2.MPlug(thisMob, SpaceConstraint.inTarget)
            offsetPlug = om2.MPlug(thisMob, SpaceConstraint.inOffset)
            offsetMatchPlug = om2.MPlug(thisMob,
                                        SpaceConstraint.inOffsetMatches)
            numTarget = targetPlug.numElements() - 1
            if curValue > numTarget:
                curValue = numTarget
            # 7- If the node have necessary connections...
            if not allClear and (numTarget + 1) > 0:
                outObj = clientData.constraintObject
                if outObj.hasFn(om2.MFn.kDagNode):
                    # 8- Get the last world matrix of the target.
                    lastOffsetMatchPlug = offsetMatchPlug.elementByLogicalIndex(
                        lastValue)
                    lastOffsetMatchObj = lastOffsetMatchPlug.asMObject()
                    mtxDataFn = om2.MFnMatrixData(lastOffsetMatchObj)
                    mOffsetMatch = mtxDataFn.matrix()
                    lastOffsetPlug = offsetPlug.elementByLogicalIndex(
                        lastValue)
                    lastOffsetObj = lastOffsetPlug.asMObject()
                    mtxDataFn = om2.MFnMatrixData(lastOffsetObj)
                    mOffset = mtxDataFn.matrix()
                    lastTargetPlug = targetPlug.elementByLogicalIndex(
                        lastValue)
                    lastTargetObj = lastTargetPlug.asMObject()
                    mtxDataFn = om2.MFnMatrixData(lastTargetObj)
                    mTarget = mtxDataFn.matrix()
                    mLastOutputW = mOffsetMatch * mOffset * mTarget
                    # 9- Get the current world matrix of the target.
                    curTargetPlug = targetPlug.elementByLogicalIndex(curValue)
                    curTargetObj = curTargetPlug.asMObject()
                    mtxDataFn = om2.MFnMatrixData(curTargetObj)
                    mTarget = mtxDataFn.matrix()
                    curOffsetPlug = offsetPlug.elementByLogicalIndex(curValue)
                    curOffsetObj = curOffsetPlug.asMObject()
                    mtxDataFn = om2.MFnMatrixData(curOffsetObj)
                    mOffset = mtxDataFn.matrix()
                    mCurOutputW = mOffset * mTarget
                    # 10- Get the result of the match and set it into the plug.
                    mResult = mLastOutputW * mCurOutputW.inverse()
                    curOffsetMatchPlug = offsetMatchPlug.elementByLogicalIndex(
                        curValue)
                    curOffsetMatchHdle = curOffsetMatchPlug.asMDataHandle()
                    curOffsetMatchHdle.setMMatrix(mResult)
                    curOffsetMatchPlug.setMDataHandle(curOffsetMatchHdle)
                    # 11- Clean the offset match plug from last value.
                    lastOffsetMatchHdle = lastOffsetMatchPlug.asMDataHandle()
                    lastOffsetMatchHdle.setMMatrix(om2.MMatrix())
                    lastOffsetMatchPlug.setMDataHandle(lastOffsetMatchHdle)
                    om2.MGlobal.displayInfo("Performing space matching...")
            # 12- Store the current space value in class to be accessed later on.
            clientData.lastSpace = curValue

    @staticmethod
    def spaceMatchCallback(msg, plug, otherPlug, clientData):
        """
        The callback function.
        Note: Attribute Changed messages will not be generated while Maya is either in playback or scrubbing modes.
        If you need to do something during playback or scrubbing you will have to register a callback for the
        timeChanged message which is the only message that is sent during those modes.
            * msg [MNodeMessage::AttributeMessage] is the kind of attribute change triggering the callback.
            * plug [MPlug] is the node's plug where the connection changed.
            * otherPlug [MPlug] is the plug opposite the node's plug where the connection changed.
            * clientData [void*] is the user defined data passed to this callback function.
        """
        # pylint: disable=unused-argument
        # 6144 = create input array element.
        # 16385 = connecting output.
        # 16386 = disconnecting output.
        # 2052 = change output in compute method.
        # 2056 = set attribute.
        # 10240 = delete element plug from array attribute.
        # 18434 = disconnect input plug.
        # 18433 = connect input plug.

        thisMob = clientData.thisMObject()
        if not isinstance(clientData, SpaceConstraint):
            # SpaceConstraint *pMesh = static_cast<SpaceConstraint *>(clientData);
            om2.MGlobal.displayError(
                "[gfTools] gfSpaceConstraint don't recognize the clientData for space match callback. Callback functionality skiped."
            )
            return
        match = om2.MPlug(thisMob, SpaceConstraint.inSpaceMatch).asBool()
        if not match:
            return
        if msg == 2056:
            if plug == SpaceConstraint.inSpace:
                lastValue = clientData.lastSpace
                curValue = plug.asShort()
                # 1- Get the output plug
                allClear = clientData.checkOutputConnections(thisMob)
                # 2- Check if the curValue is valid. If it is not, get the last valid.
                targetPlug = om2.MPlug(thisMob, SpaceConstraint.inTarget)
                offsetPlug = om2.MPlug(thisMob, SpaceConstraint.inOffset)
                offsetMatchPlug = om2.MPlug(thisMob,
                                            SpaceConstraint.inOffsetMatches)
                numTarget = targetPlug.numElements() - 1
                if curValue > numTarget:
                    curValue = numTarget
                # 3- If the node have necessary connections...
                if not allClear and (numTarget + 1) > 0:
                    outObj = clientData.constraintObject
                    if outObj.hasFn(om2.MFn.kDagNode):
                        # 4- Get the last world matrix of the target
                        lastOffsetMatchPlug = offsetMatchPlug.elementByLogicalIndex(
                            lastValue)
                        lastOffsetMatchObj = lastOffsetMatchPlug.asMObject()
                        mtxDataFn = om2.MFnMatrixData(lastOffsetMatchObj)
                        mOffsetMatch = mtxDataFn.matrix()
                        lastOffsetPlug = offsetPlug.elementByLogicalIndex(
                            lastValue)
                        lastOffsetObj = lastOffsetPlug.asMObject()
                        mtxDataFn = om2.MFnMatrixData(lastOffsetObj)
                        mOffset = mtxDataFn.matrix()
                        lastTargetPlug = targetPlug.elementByLogicalIndex(
                            lastValue)
                        lastTargetObj = lastTargetPlug.asMObject()
                        mtxDataFn = om2.MFnMatrixData(lastTargetObj)
                        mTarget = mtxDataFn.matrix()
                        mLastOutputW = mOffsetMatch * mOffset * mTarget
                        # 5- Get the current world matrix of the target
                        curTargetPlug = targetPlug.elementByLogicalIndex(
                            curValue)
                        curTargetObj = curTargetPlug.asMObject()
                        mtxDataFn = om2.MFnMatrixData(curTargetObj)
                        mTarget = mtxDataFn.matrix()
                        curOffsetPlug = offsetPlug.elementByLogicalIndex(
                            curValue)
                        curOffsetObj = curOffsetPlug.asMObject()
                        mtxDataFn = om2.MFnMatrixData(curOffsetObj)
                        mOffset = mtxDataFn.matrix()
                        mCurOutputW = mOffset * mTarget
                        # 6- Get the result of the match and set it into the plug
                        mResult = mLastOutputW * mCurOutputW.inverse()
                        curOffsetMatchPlug = offsetMatchPlug.elementByLogicalIndex(
                            curValue)
                        curOffsetMatchHdle = curOffsetMatchPlug.asMDataHandle()
                        curOffsetMatchHdle.setMMatrix(mResult)
                        curOffsetMatchPlug.setMDataHandle(curOffsetMatchHdle)
                        # 7- Clean the offset match plug from last value
                        lastOffsetMatchHdle = lastOffsetMatchPlug.asMDataHandle(
                        )
                        lastOffsetMatchHdle.setMMatrix(om2.MMatrix())
                        lastOffsetMatchPlug.setMDataHandle(lastOffsetMatchHdle)
                clientData.lastSpace = curValue

    def checkOutputConnections(self, thisMob):
        """
        Check if any output plug is connected.
        If it have connections, return False and the object connected.
        """
        outPlugArray = om2.MPlugArray([
            om2.MPlug(thisMob, SpaceConstraint.outConstTrans),
            om2.MPlug(thisMob, SpaceConstraint.outConstRot),
            om2.MPlug(thisMob, SpaceConstraint.outConstSca)
        ])
        allClear = True
        for plug in outPlugArray:
            if plug.isConnected:
                allClear = False
                objPlugs = plug.connectedTo(False, True)
                obj = objPlugs[0].node()
                for outPlug in objPlugs:
                    outNode = outPlug.node()
                    if self.constraintObject is not None:
                        if outNode == self.constraintObject:
                            obj = self.constraintObject
                            break
                break
        self.constraintObject = None if allClear else obj
        return allClear

    def autoFillOffset(self, thisMob, index):
        """Auto fill offsets attributes."""
        allClear = self.checkOutputConnections(thisMob)
        obj = self.constraintObject
        if not allClear:
            if obj.hasFn(om2.MFn.kDagNode):
                objPath = om2.MFnDagNode(obj).getPath()
                mOut = objPath.inclusiveMatrix()
                targetPlug = om2.MPlug(thisMob, SpaceConstraint.inTarget)
                curTargetPlug = targetPlug.elementByLogicalIndex(index)
                curTargetObj = curTargetPlug.asMObject()
                mtxDataFn = om2.MFnMatrixData(curTargetObj)
                mTarget = mtxDataFn.matrix()
                mOffset = mOut * mTarget.inverse()
                offsetPlug = om2.MPlug(thisMob, SpaceConstraint.inOffset)
                curOffsetPlug = offsetPlug.elementByLogicalIndex(index)
                curOffsetHdle = curOffsetPlug.asMDataHandle()
                mCurOffset = curOffsetHdle.asMatrix()
                if mCurOffset == om2.MMatrix():
                    curOffsetHdle.setMMatrix(mOffset)
                    curOffsetPlug.setMDataHandle(curOffsetHdle)

    def connectionMade(self, plug, otherPlug, asSrc):
        """This method gets called when connections are made to attributes of this node.
            * plug (MPlug) is the attribute on this node.
            * otherPlug (MPlug) is the attribute on the other node.
            * asSrc (bool) is this plug a source of the connection.
        """
        thisMob = self.thisMObject()
        autoFill = om2.MPlug(thisMob, SpaceConstraint.inAutoFillOff).asBool()
        self.checkOutputConnections(thisMob)
        if plug == SpaceConstraint.inTarget:
            # Create empty slots in offset and offset match attributes if they don't exists.
            targetIndex = plug.logicalIndex()
            offsetPlug = om2.MPlug(thisMob, SpaceConstraint.inOffset)
            curOffPlug = offsetPlug.elementByLogicalIndex(targetIndex)
            curOffPlug.asMDataHandle()
            offsetMatchPlug = om2.MPlug(thisMob,
                                        SpaceConstraint.inOffsetMatches)
            curOffMatchPlug = offsetMatchPlug.elementByLogicalIndex(
                targetIndex)
            curOffMatchPlug.asMDataHandle()
            # Auto fill offset if it has a connected output
            if autoFill:
                self.autoFillOffset(thisMob, targetIndex)
        elif (plug == SpaceConstraint.outConstTrans
              or plug == SpaceConstraint.outConstRot
              or plug == SpaceConstraint.outConstSca):
            # Check if it has a target input connection. If true autoFill the offsets.
            targetPlug = om2.MPlug(thisMob, SpaceConstraint.inTarget)
            numTarget = targetPlug.numElements()
            if numTarget > 0 and autoFill:
                for targetIndex in range(numTarget):
                    self.autoFillOffset(thisMob, targetIndex)
        return om2.MPxNode.connectionMade(self, plug, otherPlug, asSrc)

    def connectionBroken(self, plug, otherPlug, asSrc):
        """This method gets called when connections of this node are broken.
            * plug (MPlug) is the attribute on this node.
            * otherPlug (MPlug) is the attribute on the other node.
            * asSrc (bool) is this plug a source of the connection.
        """
        thisMob = self.thisMObject()
        self.checkOutputConnections(thisMob)
        if plug == SpaceConstraint.outConstTrans:
            pass
        elif plug == SpaceConstraint.outConstRot:
            pass
        elif plug == SpaceConstraint.outConstSca:
            pass
        return om2.MPxNode.connectionBroken(self, plug, otherPlug, asSrc)

    def compute(self, plug, dataBlock):
        """
        Node computation method:
            * plug is a connection point related to one of our node attributes (either an input or an output).
            * dataBlock contains the data on which we will base our computations.
        """
        # pylint: disable=no-self-use
        # if not dataBlock.isClean(SpaceConstraint.inSpace):
        #     om2.MGlobal.displayInfo("\tSpace attribute is dirty.")
        #     om2.MUserEventMessage.postUserEvent("preCompute", self)

        curSpace = dataBlock.inputValue(SpaceConstraint.inSpace).asShort()

        offsetMatchHdle = dataBlock.inputArrayValue(
            SpaceConstraint.inOffsetMatches)
        offsetHdle = dataBlock.inputArrayValue(SpaceConstraint.inOffset)
        targetHdle = dataBlock.inputArrayValue(SpaceConstraint.inTarget)
        offsetMatchList = []
        offsetList = []
        targetList = []

        for i in range(len(offsetMatchHdle)):
            offsetMatchHdle.jumpToLogicalElement(i)
            mOffMatch = offsetMatchHdle.inputValue().asMatrix()
            offsetMatchList.append(mOffMatch)

        for i in range(len(offsetHdle)):
            offsetHdle.jumpToLogicalElement(i)
            mOff = offsetHdle.inputValue().asMatrix()
            offsetList.append(mOff)

        for i in range(len(targetHdle)):
            targetHdle.jumpToLogicalElement(i)
            mTgt = targetHdle.inputValue().asMatrix()
            targetList.append(mTgt)

        if len(offsetList) == 0 or len(targetList) == 0:
            mResult = om2.MMatrix()
        else:
            minRequired = min(len(offsetList), len(targetList)) - 1
            if curSpace > minRequired:
                curSpace = minRequired
            mResult = offsetMatchList[curSpace] * offsetList[
                curSpace] * targetList[curSpace]

        mtxFn = om2.MTransformationMatrix(mResult)

        if plug == SpaceConstraint.outConstTrans:
            vTransD = om2.MVector(mResult[12], mResult[13], mResult[14])
            vTrans = om2.MFloatVector(vTransD)
            outTransHdle = dataBlock.outputValue(SpaceConstraint.outConstTrans)
            outTransHdle.setMFloatVector(vTrans)
            outTransHdle.setClean()

        if plug == SpaceConstraint.outConstRot:
            eRot = mtxFn.rotation(asQuaternion=False)
            outRotHdle = dataBlock.outputValue(SpaceConstraint.outConstRot)
            outRotHdle.setMVector(eRot.asVector())
            outRotHdle.setClean()

        if plug == SpaceConstraint.outConstSca:
            outSca = mtxFn.scale(om2.MSpace.kWorld)
            outScaHdle = dataBlock.outputValue(SpaceConstraint.outConstSca)
            outScaHdle.set3Float(outSca[0], outSca[1], outSca[2])
            outScaHdle.setClean()
class DecomposeRowMatrix(om2.MPxNode):
    """ Main class of gfUtilDecompRowMtx node. """

    kNodeName = ""
    kNodeClassify = ""
    kNodeID = ""

    inMatrix = om2.MObject()
    inNormalizeOutput = om2.MObject()
    outRow1 = om2.MObject()
    outRow2 = om2.MObject()
    outRow3 = om2.MObject()
    outRow4 = om2.MObject()

    def __init__(self):
        """ Constructor. """
        om2.MPxNode.__init__(self)

    @staticmethod
    def creator():
        """ Maya creator function. """
        return DecomposeRowMatrix()

    @staticmethod
    def initialize():
        """
        Defines the set of attributes for this node. The attributes declared in this function are assigned
        as static members to DecomposeRowMatrix class. Instances of DecomposeRowMatrix will use these attributes to create plugs
        for use in the compute() method.
        """
        nAttr = om2.MFnNumericAttribute()
        mAttr = om2.MFnMatrixAttribute()

        DecomposeRowMatrix.inMatrix = mAttr.create(
            "inputMatrix", "im", om2.MFnMatrixAttribute.kFloat)
        INPUT_ATTR(mAttr)

        DecomposeRowMatrix.inNormalizeOutput = nAttr.create(
            "normalizeOutput", "no", om2.MFnNumericData.kBoolean, False)
        INPUT_ATTR(nAttr)

        DecomposeRowMatrix.outRow1 = nAttr.createPoint("row1", "r1")
        OUTPUT_ATTR(nAttr)

        DecomposeRowMatrix.outRow2 = nAttr.createPoint("row2", "r2")
        OUTPUT_ATTR(nAttr)

        DecomposeRowMatrix.outRow3 = nAttr.createPoint("row3", "r3")
        OUTPUT_ATTR(nAttr)

        DecomposeRowMatrix.outRow4 = nAttr.createPoint("row4", "r4")
        OUTPUT_ATTR(nAttr)

        DecomposeRowMatrix.addAttribute(DecomposeRowMatrix.inMatrix)
        DecomposeRowMatrix.addAttribute(DecomposeRowMatrix.inNormalizeOutput)
        DecomposeRowMatrix.addAttribute(DecomposeRowMatrix.outRow1)
        DecomposeRowMatrix.addAttribute(DecomposeRowMatrix.outRow2)
        DecomposeRowMatrix.addAttribute(DecomposeRowMatrix.outRow3)
        DecomposeRowMatrix.addAttribute(DecomposeRowMatrix.outRow4)
        DecomposeRowMatrix.attributeAffects(DecomposeRowMatrix.inMatrix,
                                            DecomposeRowMatrix.outRow1)
        DecomposeRowMatrix.attributeAffects(
            DecomposeRowMatrix.inNormalizeOutput, DecomposeRowMatrix.outRow1)
        DecomposeRowMatrix.attributeAffects(DecomposeRowMatrix.inMatrix,
                                            DecomposeRowMatrix.outRow2)
        DecomposeRowMatrix.attributeAffects(
            DecomposeRowMatrix.inNormalizeOutput, DecomposeRowMatrix.outRow2)
        DecomposeRowMatrix.attributeAffects(DecomposeRowMatrix.inMatrix,
                                            DecomposeRowMatrix.outRow3)
        DecomposeRowMatrix.attributeAffects(
            DecomposeRowMatrix.inNormalizeOutput, DecomposeRowMatrix.outRow3)
        DecomposeRowMatrix.attributeAffects(DecomposeRowMatrix.inMatrix,
                                            DecomposeRowMatrix.outRow4)
        DecomposeRowMatrix.attributeAffects(
            DecomposeRowMatrix.inNormalizeOutput, DecomposeRowMatrix.outRow4)

    def compute(self, plug, dataBlock):
        """
        Node computation method:
            * plug is a connection point related to one of our node attributes (either an input or an output).
            * dataBlock contains the data on which we will base our computations.
        """
        # pylint: disable=no-self-use
        mInput = dataBlock.inputValue(
            DecomposeRowMatrix.inMatrix).asFloatMatrix()
        normalize = dataBlock.inputValue(
            DecomposeRowMatrix.inNormalizeOutput).asBool()

        if plug == DecomposeRowMatrix.outRow1:
            vRow1 = om2.MFloatVector(mInput[0], mInput[1], mInput[2])
            if normalize:
                vRow1.normalize()
            outRow1Handle = dataBlock.outputValue(DecomposeRowMatrix.outRow1)
            outRow1Handle.setMFloatVector(vRow1)
            outRow1Handle.setClean()
        elif plug == DecomposeRowMatrix.outRow2:
            vRow2 = om2.MFloatVector(mInput[4], mInput[5], mInput[6])
            if normalize:
                vRow2.normalize()
            outRow2Handle = dataBlock.outputValue(DecomposeRowMatrix.outRow2)
            outRow2Handle.setMFloatVector(vRow2)
            outRow2Handle.setClean()
        elif plug == DecomposeRowMatrix.outRow3:
            vRow3 = om2.MFloatVector(mInput[8], mInput[9], mInput[10])
            if normalize:
                vRow3.normalize()
            outRow3Handle = dataBlock.outputValue(DecomposeRowMatrix.outRow3)
            outRow3Handle.setMFloatVector(vRow3)
            outRow3Handle.setClean()
        elif plug == DecomposeRowMatrix.outRow4:
            vRow4 = om2.MFloatVector(mInput[12], mInput[13], mInput[14])
            if normalize:
                vRow4.normalize()
            outRow4Handle = dataBlock.outputValue(DecomposeRowMatrix.outRow4)
            outRow4Handle.setMFloatVector(vRow4)
            outRow4Handle.setClean()
        else:
            return om2.kUnknownParameter
예제 #6
0
class TwistExtractor(om2.MPxNode):
    """ Main class of gfTwistExtractor node. """

    kNodeName = ""
    kNodeClassify = ""
    kNodeID = ""

    inRotation = om2.MObject()
    inRotationOrder = om2.MObject()
    inUseUpVec = om2.MObject()
    inUpVec = om2.MObject()
    inInvTwist = om2.MObject()
    inRevDist = om2.MObject()
    outTwist = om2.MObject()
    outTwistDist = om2.MObject()

    def __init__(self):
        """ Constructor. """
        om2.MPxNode.__init__(self)

    @staticmethod
    def creator():
        """ Maya creator function. """
        return TwistExtractor()

    @staticmethod
    def initialize():
        """
        Defines the set of attributes for this node. The attributes declared in this function are assigned
        as static members to TwistExtractor class. Instances of TwistExtractor will use these attributes to create plugs
        for use in the compute() method.
        """
        uAttr = om2.MFnUnitAttribute()
        nAttr = om2.MFnNumericAttribute()
        eAttr = om2.MFnEnumAttribute()

        rotX = uAttr.create("rotationX", "rotx", om2.MFnUnitAttribute.kAngle,
                            0.0)
        rotY = uAttr.create("rotationY", "roty", om2.MFnUnitAttribute.kAngle,
                            0.0)
        rotZ = uAttr.create("rotationZ", "rotz", om2.MFnUnitAttribute.kAngle,
                            0.0)
        TwistExtractor.inRotation = nAttr.create("rotation", "rot", rotX, rotY,
                                                 rotZ)
        INPUT_ATTR(nAttr)

        TwistExtractor.inRotationOrder = eAttr.create("rotationOrder", "roo",
                                                      0)
        # eAttr.addField("Twist First (zyx)", 5)
        # eAttr.addField("Twist Last (xyz)", 0)
        # INPUT_ATTR(eAttr)
        eAttr.addField("xyz", 0)
        eAttr.addField("yzx", 1)
        eAttr.addField("zxy", 2)
        eAttr.addField("xzy", 3)
        eAttr.addField("yxz", 4)
        eAttr.addField("zyx", 5)
        INPUT_ATTR(eAttr)

        TwistExtractor.inUseUpVec = nAttr.create("useUpVector", "useup",
                                                 om2.MFnNumericData.kBoolean,
                                                 False)
        INPUT_ATTR(nAttr)

        TwistExtractor.inUpVec = nAttr.createPoint("upVector", "upVector")
        nAttr.default = (0.0, 1.0, 0.0)
        INPUT_ATTR(nAttr)

        TwistExtractor.inInvTwist = nAttr.create("inverseTwist", "itwist",
                                                 om2.MFnNumericData.kBoolean,
                                                 False)
        INPUT_ATTR(nAttr)

        TwistExtractor.inRevDist = nAttr.create("reverseDistribution", "rdist",
                                                om2.MFnNumericData.kBoolean,
                                                False)
        INPUT_ATTR(nAttr)

        TwistExtractor.outTwist = uAttr.create("twist", "twist",
                                               om2.MFnUnitAttribute.kAngle,
                                               0.0)
        OUTPUT_ATTR(uAttr)

        TwistExtractor.outTwistDist = uAttr.create("twistDistribution",
                                                   "twistd",
                                                   om2.MFnUnitAttribute.kAngle,
                                                   0.0)
        uAttr.array = True
        OUTPUT_ATTR(uAttr)

        TwistExtractor.addAttribute(TwistExtractor.inRotation)
        TwistExtractor.addAttribute(TwistExtractor.inRotationOrder)
        TwistExtractor.addAttribute(TwistExtractor.inUseUpVec)
        TwistExtractor.addAttribute(TwistExtractor.inUpVec)
        TwistExtractor.addAttribute(TwistExtractor.inInvTwist)
        TwistExtractor.addAttribute(TwistExtractor.inRevDist)
        TwistExtractor.addAttribute(TwistExtractor.outTwist)
        TwistExtractor.addAttribute(TwistExtractor.outTwistDist)
        TwistExtractor.attributeAffects(rotX, TwistExtractor.outTwist)
        TwistExtractor.attributeAffects(rotY, TwistExtractor.outTwist)
        TwistExtractor.attributeAffects(rotZ, TwistExtractor.outTwist)
        TwistExtractor.attributeAffects(TwistExtractor.inRotationOrder,
                                        TwistExtractor.outTwist)
        TwistExtractor.attributeAffects(TwistExtractor.inUseUpVec,
                                        TwistExtractor.outTwist)
        TwistExtractor.attributeAffects(TwistExtractor.inUpVec,
                                        TwistExtractor.outTwist)
        TwistExtractor.attributeAffects(TwistExtractor.inInvTwist,
                                        TwistExtractor.outTwist)
        TwistExtractor.attributeAffects(rotX, TwistExtractor.outTwistDist)
        TwistExtractor.attributeAffects(rotY, TwistExtractor.outTwistDist)
        TwistExtractor.attributeAffects(rotZ, TwistExtractor.outTwistDist)
        TwistExtractor.attributeAffects(TwistExtractor.inRotationOrder,
                                        TwistExtractor.outTwistDist)
        TwistExtractor.attributeAffects(TwistExtractor.inUseUpVec,
                                        TwistExtractor.outTwistDist)
        TwistExtractor.attributeAffects(TwistExtractor.inUpVec,
                                        TwistExtractor.outTwistDist)
        TwistExtractor.attributeAffects(TwistExtractor.inInvTwist,
                                        TwistExtractor.outTwistDist)
        TwistExtractor.attributeAffects(TwistExtractor.inRevDist,
                                        TwistExtractor.outTwistDist)

    def compute(self, plug, dataBlock):
        """
        Node computation method:
            * plug is a connection point related to one of our node attributes (either an input or an output).
            * dataBlock contains the data on which we will base our computations.
        """
        rotation = dataBlock.inputValue(TwistExtractor.inRotation).asDouble3()
        rotOrder = dataBlock.inputValue(
            TwistExtractor.inRotationOrder).asShort()
        eRoll = om2.MEulerRotation(rotation, rotOrder)
        useUpObj = dataBlock.inputValue(TwistExtractor.inUseUpVec).asBool()
        revTwist = dataBlock.inputValue(TwistExtractor.inInvTwist).asBool()

        # Non flip ROO = XYZ
        # Not working = XZY
        twistOrder = om2.MEulerRotation.kXYZ
        eRoll.reorderIt(twistOrder)

        # Non-Roll orientation
        mtxFn = om2.MTransformationMatrix()
        mtxFn.rotateBy(eRoll, om2.MSpace.kWorld)
        mRoll = mtxFn.asMatrix()

        qNonRoll = om2.MQuaternion()

        nAim = om2.MVector(mRoll[0], mRoll[1], mRoll[2])
        nAim.normalize()
        nAimAxis = om2.MVector.kXaxisVector
        qAim = om2.MQuaternion(nAimAxis, nAim)
        qNonRoll *= qAim

        if useUpObj:
            vUp = om2.MVector(
                dataBlock.inputValue(TwistExtractor.inUpVec).asFloat3())
            nNormal = vUp - ((vUp * nAim) * nAim)
            nNormal.normalize()
            nUp = om2.MVector.kYaxisVector.rotateBy(qAim)
            angle = nUp.angle(nNormal)
            qNormal = om2.MQuaternion(angle, nAim)
            if not nNormal.isEquivalent(nUp.rotateBy(qNormal), 1.0e-5):
                angle = 2.0 * kPI - angle
                qNormal = om2.MQuaternion(angle, nAim)
            qNonRoll *= qNormal
        eNonRoll = qNonRoll.asEulerRotation()
        eNonRoll = om2.MEulerRotation(eNonRoll.x, eNonRoll.y, eNonRoll.z,
                                      twistOrder)

        # Extract Twist from orientations
        qRoll = eRoll.asQuaternion()
        qExtract180 = qNonRoll * qRoll.inverse()
        eExtract180 = qExtract180.asEulerRotation()
        twist = -eExtract180.x
        if revTwist:
            twist *= -1.0

        # Output Twist
        if plug == TwistExtractor.outTwist:
            outTwistHdle = dataBlock.outputValue(TwistExtractor.outTwist)
            outTwistHdle.setMAngle(om2.MAngle(twist))
            outTwistHdle.setClean()

        # Output Twist Distribution
        if plug == TwistExtractor.outTwistDist:
            invDist = dataBlock.inputValue(TwistExtractor.inRevDist).asBool()
            outTwistDistHdle = dataBlock.outputArrayValue(
                TwistExtractor.outTwistDist)
            outputs = len(outTwistDistHdle)
            step = twist / (outputs - 1) if outputs > 1 else twist
            outList = []
            outList.extend(range(outputs))
            if not invDist:
                outList.reverse()
            # pylint: disable=consider-using-enumerate
            for i in range(len(outList)):
                outTwistDistHdle.jumpToLogicalElement(i)
                resultHdle = outTwistDistHdle.outputValue()
                result = step * outList[i] if outputs > 1 else twist
                resultHdle.setMAngle(om2.MAngle(result))
            outTwistDistHdle.setAllClean()

        return
예제 #7
0
class QuadraticCurve(om2.MPxNode):
    """ Main class of gfQuadraticCurve node. """

    kNodeName = ""
    kNodeClassify = ""
    kNodeID = ""

    inControlPoints = om2.MObject()
    inEnableTwist = om2.MObject()
    inStartUpObj = om2.MObject()
    inEndUpObj = om2.MObject()
    inLockLength = om2.MObject()
    inRestLength = om2.MObject()
    inSlide = om2.MObject()
    inPreferredAngle = om2.MObject()
    outTransforms = om2.MObject()
    outCurve = om2.MObject()

    def __init__(self):
        """ Constructor. """
        om2.MPxNode.__init__(self)

    @staticmethod
    def creator():
        """ Maya creator function. """
        return QuadraticCurve()

    @staticmethod
    def initialize():
        """
        Defines the set of attributes for this node. The attributes declared in this function are assigned
        as static members to QuadraticCurve class. Instances of QuadraticCurve will use these attributes to create plugs
        for use in the compute() method.
        """
        mAttr = om2.MFnMatrixAttribute()
        nAttr = om2.MFnNumericAttribute()
        uAttr = om2.MFnUnitAttribute()
        tAttr = om2.MFnTypedAttribute()

        QuadraticCurve.inControlPoints = mAttr.create(
            "controlPoints", "cp", om2.MFnMatrixAttribute.kDouble)
        mAttr.array = True
        INPUT_ATTR(mAttr)

        QuadraticCurve.inEnableTwist = nAttr.create(
            "enableTwist", "etw", om2.MFnNumericData.kBoolean, False)
        INPUT_ATTR(nAttr)

        QuadraticCurve.inStartUpObj = mAttr.create(
            "startUpObjectMatrix", "suom", om2.MFnMatrixAttribute.kFloat)
        INPUT_ATTR(mAttr)

        QuadraticCurve.inEndUpObj = mAttr.create("endUpObjectMatrix", "euom",
                                                 om2.MFnMatrixAttribute.kFloat)
        INPUT_ATTR(mAttr)

        QuadraticCurve.inLockLength = nAttr.create("lockLength", "locklen",
                                                   om2.MFnNumericData.kFloat,
                                                   0.0)
        nAttr.setMin(0.0)
        nAttr.setMax(1.0)
        INPUT_ATTR(nAttr)

        QuadraticCurve.inRestLength = nAttr.create("restLength", "rlength",
                                                   om2.MFnNumericData.kFloat,
                                                   0.0)
        nAttr.setMin(0.0)
        INPUT_ATTR(nAttr)

        QuadraticCurve.inSlide = nAttr.create("slide", "slide",
                                              om2.MFnNumericData.kFloat, 0.0)
        nAttr.setMin(0.0)
        nAttr.setMax(1.0)
        INPUT_ATTR(nAttr)

        QuadraticCurve.inPreferredAngle = uAttr.create(
            "preferredAngle", "pangle", om2.MFnUnitAttribute.kAngle)
        uAttr.setMin(0.0)
        uAttr.setMax(om2.MAngle(360.0, om2.MAngle.kDegrees).asRadians())
        INPUT_ATTR(uAttr)

        QuadraticCurve.outTransforms = mAttr.create(
            "outTransforms", "otrans", om2.MFnMatrixAttribute.kDouble)
        mAttr.array = True
        OUTPUT_ATTR(mAttr)

        QuadraticCurve.outCurve = tAttr.create("outCurve", "ocrv",
                                               om2.MFnData.kNurbsCurve)
        OUTPUT_ATTR(tAttr)

        QuadraticCurve.addAttribute(QuadraticCurve.inControlPoints)
        QuadraticCurve.addAttribute(QuadraticCurve.inEnableTwist)
        QuadraticCurve.addAttribute(QuadraticCurve.inStartUpObj)
        QuadraticCurve.addAttribute(QuadraticCurve.inEndUpObj)
        QuadraticCurve.addAttribute(QuadraticCurve.inLockLength)
        QuadraticCurve.addAttribute(QuadraticCurve.inRestLength)
        QuadraticCurve.addAttribute(QuadraticCurve.inSlide)
        QuadraticCurve.addAttribute(QuadraticCurve.inPreferredAngle)
        QuadraticCurve.addAttribute(QuadraticCurve.outTransforms)
        QuadraticCurve.addAttribute(QuadraticCurve.outCurve)
        QuadraticCurve.attributeAffects(QuadraticCurve.inControlPoints,
                                        QuadraticCurve.outCurve)
        QuadraticCurve.attributeAffects(QuadraticCurve.inControlPoints,
                                        QuadraticCurve.outTransforms)
        QuadraticCurve.attributeAffects(QuadraticCurve.inEnableTwist,
                                        QuadraticCurve.outTransforms)
        QuadraticCurve.attributeAffects(QuadraticCurve.inStartUpObj,
                                        QuadraticCurve.outTransforms)
        QuadraticCurve.attributeAffects(QuadraticCurve.inEndUpObj,
                                        QuadraticCurve.outTransforms)
        QuadraticCurve.attributeAffects(QuadraticCurve.inLockLength,
                                        QuadraticCurve.outTransforms)
        QuadraticCurve.attributeAffects(QuadraticCurve.inRestLength,
                                        QuadraticCurve.outTransforms)
        QuadraticCurve.attributeAffects(QuadraticCurve.inSlide,
                                        QuadraticCurve.outTransforms)
        QuadraticCurve.attributeAffects(QuadraticCurve.inPreferredAngle,
                                        QuadraticCurve.outTransforms)

    def compute(self, plug, dataBlock):
        """
        Node computation method:
            * plug is a connection point related to one of our node attributes (either an input or an output).
            * dataBlock contains the data on which we will base our computations.
        """
        # pylint: disable=no-self-use
        ctrlPntsHandle = dataBlock.inputArrayValue(
            QuadraticCurve.inControlPoints)
        ctrlPnts = om2.MPointArray()

        if len(ctrlPntsHandle) < 3:
            return

        for i in range(3):
            ctrlPntsHandle.jumpToLogicalElement(i)
            mCtrlPnt = ctrlPntsHandle.inputValue().asMatrix()
            ctrlPnt = om2.MPoint(mCtrlPnt[12], mCtrlPnt[13], mCtrlPnt[14])
            ctrlPnts.append(ctrlPnt)

        crvKnots = om2.MDoubleArray([0, 0, 1, 1])
        crvDegree = 2
        crvForm = om2.MFnNurbsCurve.kOpen
        crvIs2d = False
        crvRational = False
        crvData = om2.MFnNurbsCurveData().create()
        crvFn = om2.MFnNurbsCurve(crvData)

        crvFn.create(ctrlPnts, crvKnots, crvDegree, crvForm, crvIs2d,
                     crvRational, crvData)
        crvFn.updateCurve()

        if plug == QuadraticCurve.outCurve:
            outCurveHandle = dataBlock.outputValue(QuadraticCurve.outCurve)
            outCurveHandle.setMObject(crvData)
            outCurveHandle.setClean()

        elif plug == QuadraticCurve.outTransforms:
            outTransHandle = dataBlock.outputArrayValue(
                QuadraticCurve.outTransforms)
            lockLength = dataBlock.inputValue(
                QuadraticCurve.inLockLength).asFloat()
            restLength = dataBlock.inputValue(
                QuadraticCurve.inRestLength).asFloat()
            slide = dataBlock.inputValue(QuadraticCurve.inSlide).asFloat()
            numOutputs = len(outTransHandle)
            crvLength = crvFn.length()
            parRejected = crvFn.findParamFromLength(crvLength - restLength)
            stepFull = 1.0 / (numOutputs - 1) if numOutputs > 1 else 0.0
            stepLock = crvFn.findParamFromLength(restLength) / (
                numOutputs - 1) if numOutputs > 1 else 0.0
            step = (1.0 - lockLength) * stepFull + lockLength * stepLock
            parSlide = parRejected * slide * lockLength
            for i in range(numOutputs):
                parameter = (step * i)  # + parSlide
                pos = crvFn.getPointAtParam(parameter, om2.MSpace.kObject)
                vPos = om2.MVector(pos.x, pos.y, pos.z)
                mtx = [
                    1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0,
                    vPos.x, vPos.y, vPos.z, 1.0
                ]
                mOut = om2.MMatrix(mtx)
                outTransHandle.jumpToLogicalElement(i)
                resultHandle = outTransHandle.outputValue()
                resultHandle.setMMatrix(mOut)
            outTransHandle.setAllClean()

        else:
            return om2.kUnknownParameter
예제 #8
0
class BlendTransform(om2.MPxNode):
    """ Main class of gfUtilBlendTransform node. """

    kNodeName = ""
    kNodeClassify = ""
    kNodeID = ""

    inBlender = om2.MObject()
    inRotInterp = om2.MObject()
    inTrans1 = om2.MObject()
    inRot1 = om2.MObject()
    inSca1 = om2.MObject()
    inRot1Order = om2.MObject()
    inTransform1 = om2.MObject()
    inTrans2 = om2.MObject()
    inRot2 = om2.MObject()
    inSca2 = om2.MObject()
    inRot2Order = om2.MObject()
    inTransform2 = om2.MObject()
    inOutRotOrder = om2.MObject()
    outTrans = om2.MObject()
    outRot = om2.MObject()
    outSca = om2.MObject()
    outVis = om2.MObject()
    outRevVis = om2.MObject()

    def __init__(self):
        """ Constructor. """
        om2.MPxNode.__init__(self)

    @staticmethod
    def creator():
        """ Maya creator function. """
        return BlendTransform()

    @staticmethod
    def initialize():
        """
        Defines the set of attributes for this node. The attributes declared in this function are assigned
        as static members to BlendTransform class. Instances of BlendTransform will use these attributes to create plugs
        for use in the compute() method.
        """
        nAttr = om2.MFnNumericAttribute()
        uAttr = om2.MFnUnitAttribute()
        cAttr = om2.MFnCompoundAttribute()
        eAttr = om2.MFnEnumAttribute()

        BlendTransform.inBlender = nAttr.create("blender", "blender",
                                                om2.MFnNumericData.kFloat, 0.5)
        nAttr.setMin(0.0)
        nAttr.setMax(1.0)
        INPUT_ATTR(nAttr)

        BlendTransform.inRotInterp = eAttr.create("rotationInterpolation",
                                                  "roti", 0)
        eAttr.addField("Euler Lerp", 0)
        eAttr.addField("Quaternion Slerp", 1)
        INPUT_ATTR(eAttr)

        BlendTransform.inTrans1 = nAttr.createPoint("translate1", "t1")
        nAttr.array = True
        INPUT_ATTR(nAttr)

        rot1X = uAttr.create("rotate1X", "ro1x", om2.MFnUnitAttribute.kAngle,
                             0.0)
        rot1Y = uAttr.create("rotate1Y", "ro1y", om2.MFnUnitAttribute.kAngle,
                             0.0)
        rot1Z = uAttr.create("rotate1Z", "ro1z", om2.MFnUnitAttribute.kAngle,
                             0.0)
        BlendTransform.inRot1 = nAttr.create("rotate1", "ro1", rot1X, rot1Y,
                                             rot1Z)
        nAttr.array = True
        INPUT_ATTR(nAttr)

        BlendTransform.inSca1 = nAttr.createPoint("scale1", "sca1")
        nAttr.array = True
        INPUT_ATTR(nAttr)

        BlendTransform.inRot1Order = eAttr.create("rotateOrder1", "rro1", 0)
        eAttr.addField("xyz", 0)
        eAttr.addField("yzx", 1)
        eAttr.addField("zxy", 2)
        eAttr.addField("xzy", 3)
        eAttr.addField("yxz", 4)
        eAttr.addField("zyx", 5)
        eAttr.array = True
        INPUT_ATTR(eAttr)

        BlendTransform.inTransform1 = cAttr.create("transform1", "tr1")
        cAttr.addChild(BlendTransform.inTrans1)
        cAttr.addChild(BlendTransform.inRot1)
        cAttr.addChild(BlendTransform.inSca1)
        cAttr.addChild(BlendTransform.inRot1Order)

        BlendTransform.inTrans2 = nAttr.createPoint("translate2", "t2")
        nAttr.array = True
        INPUT_ATTR(nAttr)

        rot2X = uAttr.create("rotate2X", "ro2x", om2.MFnUnitAttribute.kAngle,
                             0.0)
        rot2Y = uAttr.create("rotate2Y", "ro2y", om2.MFnUnitAttribute.kAngle,
                             0.0)
        rot2Z = uAttr.create("rotate2Z", "ro2z", om2.MFnUnitAttribute.kAngle,
                             0.0)
        BlendTransform.inRot2 = nAttr.create("rotate2", "ro2", rot2X, rot2Y,
                                             rot2Z)
        nAttr.array = True
        INPUT_ATTR(nAttr)

        BlendTransform.inSca2 = nAttr.createPoint("scale2", "sca2")
        nAttr.array = True
        INPUT_ATTR(nAttr)

        BlendTransform.inRot2Order = eAttr.create("rotateOrder2", "rro2", 0)
        eAttr.addField("xyz", 0)
        eAttr.addField("yzx", 1)
        eAttr.addField("zxy", 2)
        eAttr.addField("xzy", 3)
        eAttr.addField("yxz", 4)
        eAttr.addField("zyx", 5)
        eAttr.array = True
        INPUT_ATTR(eAttr)

        BlendTransform.inTransform2 = cAttr.create("transform2", "tr2")
        cAttr.addChild(BlendTransform.inTrans2)
        cAttr.addChild(BlendTransform.inRot2)
        cAttr.addChild(BlendTransform.inSca2)
        cAttr.addChild(BlendTransform.inRot2Order)

        BlendTransform.inOutRotOrder = eAttr.create("outRotateOrder", "orro",
                                                    0)
        eAttr.addField("xyz", 0)
        eAttr.addField("yzx", 1)
        eAttr.addField("zxy", 2)
        eAttr.addField("xzy", 3)
        eAttr.addField("yxz", 4)
        eAttr.addField("zyx", 5)
        eAttr.array = True
        INPUT_ATTR(eAttr)

        BlendTransform.outTrans = nAttr.createPoint("outTranslate", "ot")
        nAttr.array = True
        OUTPUT_ATTR(nAttr)

        oRotX = uAttr.create("outRotateX", "orox", om2.MFnUnitAttribute.kAngle,
                             0.0)
        oRotY = uAttr.create("outRotateY", "oroy", om2.MFnUnitAttribute.kAngle,
                             0.0)
        oRotZ = uAttr.create("outRotateZ", "oroz", om2.MFnUnitAttribute.kAngle,
                             0.0)
        BlendTransform.outRot = nAttr.create("outRotate", "oro", oRotX, oRotY,
                                             oRotZ)
        nAttr.array = True
        OUTPUT_ATTR(nAttr)

        BlendTransform.outSca = nAttr.createPoint("outScale", "osca")
        nAttr.array = True
        OUTPUT_ATTR(nAttr)

        BlendTransform.outVis = nAttr.create("visibility", "vis",
                                             om2.MFnNumericData.kBoolean, True)
        OUTPUT_ATTR(nAttr)

        BlendTransform.outRevVis = nAttr.create("reverseVisibility", "rvis",
                                                om2.MFnNumericData.kBoolean,
                                                False)
        OUTPUT_ATTR(nAttr)

        BlendTransform.addAttribute(BlendTransform.inBlender)
        BlendTransform.addAttribute(BlendTransform.inRotInterp)
        BlendTransform.addAttribute(BlendTransform.inTransform1)
        BlendTransform.addAttribute(BlendTransform.inTransform2)
        BlendTransform.addAttribute(BlendTransform.inOutRotOrder)
        BlendTransform.addAttribute(BlendTransform.outTrans)
        BlendTransform.addAttribute(BlendTransform.outRot)
        BlendTransform.addAttribute(BlendTransform.outSca)
        BlendTransform.addAttribute(BlendTransform.outVis)
        BlendTransform.addAttribute(BlendTransform.outRevVis)
        BlendTransform.attributeAffects(BlendTransform.inBlender,
                                        BlendTransform.outTrans)
        BlendTransform.attributeAffects(BlendTransform.inTrans1,
                                        BlendTransform.outTrans)
        BlendTransform.attributeAffects(BlendTransform.inTrans2,
                                        BlendTransform.outTrans)
        BlendTransform.attributeAffects(BlendTransform.inBlender,
                                        BlendTransform.outRot)
        BlendTransform.attributeAffects(BlendTransform.inRotInterp,
                                        BlendTransform.outRot)
        BlendTransform.attributeAffects(BlendTransform.inRot1,
                                        BlendTransform.outRot)
        BlendTransform.attributeAffects(BlendTransform.inRot1Order,
                                        BlendTransform.outRot)
        BlendTransform.attributeAffects(BlendTransform.inRot2,
                                        BlendTransform.outRot)
        BlendTransform.attributeAffects(BlendTransform.inRot2Order,
                                        BlendTransform.outRot)
        BlendTransform.attributeAffects(BlendTransform.inOutRotOrder,
                                        BlendTransform.outRot)
        BlendTransform.attributeAffects(BlendTransform.inBlender,
                                        BlendTransform.outSca)
        BlendTransform.attributeAffects(BlendTransform.inSca1,
                                        BlendTransform.outSca)
        BlendTransform.attributeAffects(BlendTransform.inSca2,
                                        BlendTransform.outSca)
        BlendTransform.attributeAffects(BlendTransform.inBlender,
                                        BlendTransform.outVis)
        BlendTransform.attributeAffects(BlendTransform.inBlender,
                                        BlendTransform.outRevVis)

    def compute(self, plug, dataBlock):
        """
        Node computation method:
            * plug is a connection point related to one of our node attributes (either an input or an output).
            * dataBlock contains the data on which we will base our computations.
        """
        # pylint: disable=R0201
        blender = dataBlock.inputValue(BlendTransform.inBlender).asFloat()
        if plug == BlendTransform.outTrans:
            trans1Handle = dataBlock.inputArrayValue(BlendTransform.inTrans1)
            trans2Handle = dataBlock.inputArrayValue(BlendTransform.inTrans2)
            outTransHandle = dataBlock.outputArrayValue(
                BlendTransform.outTrans)
            outList = []
            for i in range(min(len(trans1Handle), len(trans2Handle))):
                trans1Handle.jumpToLogicalElement(i)
                trans2Handle.jumpToLogicalElement(i)
                vTrans1 = trans1Handle.inputValue().asFloatVector()
                vTrans2 = trans2Handle.inputValue().asFloatVector()
                vOut = (1.0 - blender) * vTrans1 + blender * vTrans2
                outList.append(vOut)
            for i in range(len(outTransHandle)):
                outTransHandle.jumpToLogicalElement(i)
                resultHandle = outTransHandle.outputValue()
                if i < len(outTransHandle) and i < len(outList):
                    resultHandle.setMFloatVector(outList[i])
                else:
                    resultHandle.setMFloatVector(om2.MFloatVector())
            outTransHandle.setAllClean()

        elif plug == BlendTransform.outRot:
            rotInterp = dataBlock.inputValue(
                BlendTransform.inRotInterp).asShort()
            rot1Handle = dataBlock.inputArrayValue(BlendTransform.inRot1)
            rot2Handle = dataBlock.inputArrayValue(BlendTransform.inRot2)
            outRotHandle = dataBlock.outputArrayValue(BlendTransform.outRot)
            rotOrder1Handle = dataBlock.inputArrayValue(
                BlendTransform.inRot1Order)
            rotOrder2Handle = dataBlock.inputArrayValue(
                BlendTransform.inRot2Order)
            outRotOrderHandle = dataBlock.inputArrayValue(
                BlendTransform.inOutRotOrder)
            outList = []
            for i in range(min(len(rot1Handle), len(rot2Handle))):
                rot1Handle.jumpToLogicalElement(i)
                rot2Handle.jumpToLogicalElement(i)
                rotOrder1 = BlendTransform.checkRotateOrderArrayHandle(
                    rotOrder1Handle, i)
                rotOrder2 = BlendTransform.checkRotateOrderArrayHandle(
                    rotOrder2Handle, i)
                outRotOrder = BlendTransform.checkRotateOrderArrayHandle(
                    outRotOrderHandle, i)
                rot1 = rot1Handle.inputValue().asVector()
                rot2 = rot2Handle.inputValue().asVector()
                eRot1 = om2.MEulerRotation(rot1, rotOrder1)
                eRot2 = om2.MEulerRotation(rot2, rotOrder2)
                eRot1.reorderIt(outRotOrder)
                eRot2.reorderIt(outRotOrder)
                if rotInterp == 0:
                    vRot1 = eRot1.asVector()
                    vRot2 = eRot2.asVector()
                    vOut = (1.0 - blender) * vRot1 + blender * vRot2
                else:
                    qRot1 = eRot1.asQuaternion()
                    qRot2 = eRot2.asQuaternion()
                    eSlerp = om2.MQuaternion.slerp(qRot1, qRot2,
                                                   blender).asEulerRotation()
                    eSlerp.reorderIt(outRotOrder)
                    vOut = eSlerp.asVector()
                outList.append(vOut)
            for i in range(len(outRotHandle)):
                outRotHandle.jumpToLogicalElement(i)
                resultHandle = outRotHandle.outputValue()
                if i < len(outRotHandle) and i < len(outList):
                    resultHandle.setMVector(outList[i])
                else:
                    resultHandle.setMVector(om2.MVector())
            outRotHandle.setAllClean()

        elif plug == BlendTransform.outSca:
            sca1Handle = dataBlock.inputArrayValue(BlendTransform.inSca1)
            sca2Handle = dataBlock.inputArrayValue(BlendTransform.inSca2)
            outScaHandle = dataBlock.outputArrayValue(BlendTransform.outSca)
            outList = []
            for i in range(min(len(sca1Handle), len(sca2Handle))):
                sca1Handle.jumpToLogicalElement(i)
                sca2Handle.jumpToLogicalElement(i)
                vSca1 = sca1Handle.inputValue().asFloatVector()
                vSca2 = sca2Handle.inputValue().asFloatVector()
                vOut = (1.0 - blender) * vSca1 + blender * vSca2
                outList.append(vOut)
            for i in range(len(outScaHandle)):
                outScaHandle.jumpToLogicalElement(i)
                resultHandle = outScaHandle.outputValue()
                if i < len(outScaHandle) and i < len(outList):
                    resultHandle.setMFloatVector(outList[i])
                else:
                    resultHandle.setMFloatVector(om2.MFloatVector())
            outScaHandle.setAllClean()

        elif plug in (BlendTransform.outVis, BlendTransform.outRevVis):
            outVisHandle = dataBlock.outputValue(BlendTransform.outVis)
            outRevVisHandle = dataBlock.outputValue(BlendTransform.outRevVis)
            vis, revVis = BlendTransform.visibilityCalculation(blender)
            outVisHandle.setBool(vis)
            outRevVisHandle.setBool(revVis)
            outVisHandle.setClean()
            outRevVisHandle.setClean()

    @staticmethod
    def visibilityCalculation(blender):
        """
        Calculate the visibility of the objects based on blender value. Threshold can be changed
        in code to affect the calculation.
        """
        threshold = 0.25
        vis = True
        revVis = False
        if blender <= 0.0 + threshold:
            vis = False
            revVis = True
        elif blender >= 1.0 - threshold:
            vis = True
            revVis = False
        else:
            vis = True
            revVis = True

        return vis, revVis

    @staticmethod
    def checkRotateOrderArrayHandle(arrayHandle, iterValue):
        """
        Check if rotate order MArrayDataHandle is done. If it is return default kXYZ, otherwise
        return the input value.
        """
        index = len(arrayHandle)
        if index > 0 and iterValue <= index:
            arrayHandle.jumpToLogicalElement(iterValue)
            value = arrayHandle.inputValue().asShort()
        else:
            value = 0
        return value
예제 #9
0
class MeshController(omui2.MPxLocatorNode):
    """ Main class of gfMeshController node. """

    kNodeName = ""
    kNodeClassify = ""
    kNodeRegistrantID = ""
    kNodeID = ""

    inIndexList = om2.MObject()
    inOffset = om2.MObject()
    inMesh = om2.MObject()
    inColor = om2.MObject()
    inXray = om2.MObject()

    meshVtxPositions = om2.MPointArray()
    meshVtxIndices = om2.MUintArray()
    meshVtxNormals = om2.MVectorArray()
    bBox = om2.MBoundingBox()

    def __init__(self):
        """ Constructor. """
        omui2.MPxLocatorNode.__init__(self)

    def postConstructor(self):
        """ Post Constructor. """
        thisMob = self.thisMObject()
        om2.MFnDependencyNode(thisMob).setName("%sShape#" %
                                               MeshController.kNodeName)

    @staticmethod
    def creator():
        """ Maya creator function. """
        return MeshController()

    @staticmethod
    def initialize():
        """
        Defines the set of attributes for this node. The attributes declared in this function are assigned
        as static members to MeshController class. Instances of MeshController will use these attributes to create plugs
        for use in the compute() method.
        """
        tAttr = om2.MFnTypedAttribute()
        nAttr = om2.MFnNumericAttribute()

        MeshController.inIndexList = tAttr.create("indexList", "index",
                                                  om2.MFnData.kString)
        INPUT_ATTR(tAttr)

        MeshController.inOffset = nAttr.create("offset", "offset",
                                               om2.MFnNumericData.kFloat, 0.0)
        INPUT_ATTR(nAttr)

        MeshController.inMesh = tAttr.create("controlMesh", "controlMesh",
                                             om2.MFnData.kMesh)
        INPUT_ATTR(tAttr)

        MeshController.inColor = nAttr.createColor("color", "color")
        nAttr.default = (1.0, 0.455, 0.086)
        INPUT_ATTR(nAttr)

        MeshController.inXray = nAttr.create("xray", "xray",
                                             om2.MFnNumericData.kBoolean,
                                             False)
        INPUT_ATTR(nAttr)

        MeshController.addAttribute(MeshController.inIndexList)
        MeshController.addAttribute(MeshController.inMesh)
        MeshController.addAttribute(MeshController.inOffset)
        MeshController.addAttribute(MeshController.inColor)
        MeshController.addAttribute(MeshController.inXray)

    def compute(self, plug, dataBlock):
        """
        Node computation method:
            * plug is a connection point related to one of our node attributes (either an input or an output).
            * dataBlock contains the data on which we will base our computations.
        """
        # pylint: disable=unused-argument
        return

    def connectionMade(self, plug, otherPlug, asSrc):
        """
        This method gets called when connections are made to attributes of this node.
            * plug (MPlug) is the attribute on this node.
            * otherPlug (MPlug) is the attribute on the other node.
            * asSrc (bool) is this plug a source of the connection.
        """
        # generate mesh points here initially
        return om2.MPxNode.connectionMade(self, plug, otherPlug, asSrc)

    def connectionBroken(self, plug, otherPlug, asSrc):
        """This method gets called when connections are made to attributes of this node.
            * plug (MPlug) is the attribute on this node.
            * otherPlug (MPlug) is the attribute on the other node.
            * asSrc (bool) is this plug a source of the connection.
        """
        return om2.MPxNode.connectionBroken(self, plug, otherPlug, asSrc)

    def setDependentsDirty(self, plugBeingDirtied, affectedPlugs):
        """
        This method can be overridden in user defined nodes to specify which plugs should be set dirty based
        upon an input plug {plugBeingDirtied} which Maya is marking dirty.
        The list of plugs for Maya to mark dirty is returned by the plug array {affectedPlugs}.
        You must not cause any dependency graph computations.
            * plugBeingDirtied [MPlug] is the plug being dirtied.
            * affectedPlugs [MPlugArray] is the list of dirty plugs returned by Maya.
        """
        # pylint: disable=unused-argument
        if (plugBeingDirtied == MeshController.inIndexList
                or plugBeingDirtied == MeshController.inMesh):
            self.signalDirtyToViewport()

    def preEvaluation(self, context, evaluationNode):
        """ Called before this node is evaluated by Evaluation Manager.
            * context [MDGContext] is the context which the evaluation is happening.
            * evaluationNode [MEvaluationNode] the evaluation node which contains information
                about the dirty plugs that are about to be evaluated for the context.
                Should be only used to query information.
        """
        if not context.isNormal():
            return
        if (evaluationNode.dirtyPlugExists(MeshController.inMesh)
                or evaluationNode.dirtyPlugExists(MeshController.inIndexList)
                or evaluationNode.dirtyPlugExists(MeshController.inOffset)):
            omr2.MRenderer.setGeometryDrawDirty(self.thisMObject())

    @staticmethod
    def listToMIntArray(strList):
        """ Convert a list of int to a MIntArray instance. """
        # pylint: disable=undefined-variable
        instance = om2.MIntArray()
        for i in strList:
            try:
                instance.append(int(i))
            except ValueError:
                pass
        return instance

    @staticmethod
    def generateMesh(meshMob, faceIndicesStr):
        """ Find the info of the geometry who will be drawed. """
        meshFn = om2.MFnMesh(meshMob)

    def draw(self, view, path, style, status):
        """
        Draw custom geometry in the viewport using OpenGL calls.
            * view [M3dView] is a 3D view that is being drawn into.
            * path [MDagPath] to the parent (transform node) of this locator in the DAG.  To obtain the locator shape node,
                use MDagPath::extendToShape() if there is only one shape node under the transform or
                MDagPath::extendToShapeDirectlyBelow(unsigned int index) with the shape index if there are multiple
                shapes under the transform.
            * style [M3dView.DisplayStyle] is the style to draw object in.
            * status [M3dView.DisplayStatus] is the selection status of the object.
        """
        # pylint: disable=unused-argument
        # NO DRAWING IN VIEWPORT 1.0, JUST RETURN
        return

    def isBounded(self):
        """isBounded?"""
        return False
예제 #10
0
class IKVChainSolver(om2.MPxNode):
    """ Main class of gfRigIKVChainSolver node. """

    kNodeName = ""
    kNodeClassify = ""
    kNodeID = ""

    inRoot = om2.MObject()
    inHandle = om2.MObject()
    inPoleVector = om2.MObject()
    inOffset = om2.MObject()
    inJntOri = om2.MObject()
    inParInvMtx = om2.MObject()
    inRestLenStart = om2.MObject()
    inRestLenEnd = om2.MObject()
    inPreferredAngle = om2.MObject()
    inTwist = om2.MObject()
    inPvMode = om2.MObject()
    inHierarchyMode = om2.MObject()
    inFlip = om2.MObject()
    inUseScale = om2.MObject()
    inCompressionLimit = om2.MObject()
    inSnapUpVector = om2.MObject()
    inSnap = om2.MObject()
    inSoftness = om2.MObject()
    inStretch = om2.MObject()
    inClampStretch = om2.MObject()
    inClampValue = om2.MObject()
    # inStretchMultStart = om2.MObject()
    # inStretchMultEnd = om2.MObject()
    inSquash = om2.MObject()
    inSquashMultStart = om2.MObject()
    inSquashMultEnd = om2.MObject()
    outChain = om2.MObject()

    def __init__(self):
        """ Constructor. """
        om2.MPxNode.__init__(self)

    @staticmethod
    def creator():
        """ Maya creator function. """
        return IKVChainSolver()

    @staticmethod
    def initialize():
        """
        Defines the set of attributes for this node. The attributes declared in this function are assigned
        as static members to IKVChainSolver class. Instances of IKVChainSolver will use these attributes to create plugs
        for use in the compute() method.
        """
        mAttr = om2.MFnMatrixAttribute()
        nAttr = om2.MFnNumericAttribute()
        eAttr = om2.MFnEnumAttribute()
        uAttr = om2.MFnUnitAttribute()

        IKVChainSolver.inRoot = mAttr.create("root", "root",
                                             om2.MFnMatrixAttribute.kDouble)
        INPUT_ATTR(mAttr)

        IKVChainSolver.inHandle = mAttr.create("handle", "handle",
                                               om2.MFnMatrixAttribute.kDouble)
        INPUT_ATTR(mAttr)

        IKVChainSolver.inPoleVector = mAttr.create(
            "poleVector", "pole", om2.MFnMatrixAttribute.kDouble)
        INPUT_ATTR(mAttr)

        offX = uAttr.create("offsetX", "offx", om2.MFnUnitAttribute.kAngle,
                            0.0)
        offY = uAttr.create("offsetY", "offy", om2.MFnUnitAttribute.kAngle,
                            0.0)
        offZ = uAttr.create("offsetZ", "offz", om2.MFnUnitAttribute.kAngle,
                            0.0)
        IKVChainSolver.inOffset = nAttr.create("offset", "off", offX, offY,
                                               offZ)
        nAttr.array = True
        INPUT_ATTR(nAttr)

        jntOriX = uAttr.create("jointOrientX", "jox",
                               om2.MFnUnitAttribute.kAngle, 0.0)
        jntOriY = uAttr.create("jointOrientY", "joy",
                               om2.MFnUnitAttribute.kAngle, 0.0)
        jntOriZ = uAttr.create("jointOrientZ", "joz",
                               om2.MFnUnitAttribute.kAngle, 0.0)
        IKVChainSolver.inJntOri = nAttr.create("jointOrient", "jo", jntOriX,
                                               jntOriY, jntOriZ)
        nAttr.array = True
        INPUT_ATTR(nAttr)

        IKVChainSolver.inParInvMtx = mAttr.create(
            "parentInverseMatrix", "pim", om2.MFnMatrixAttribute.kDouble)
        INPUT_ATTR(mAttr)

        IKVChainSolver.inRestLenStart = nAttr.create("restLengthStart", "rls",
                                                     om2.MFnNumericData.kFloat,
                                                     1.0)
        # nAttr.setMin(0.001)
        INPUT_ATTR(nAttr)
        nAttr.channelBox = True

        IKVChainSolver.inRestLenEnd = nAttr.create("restLengthEnd", "rle",
                                                   om2.MFnNumericData.kFloat,
                                                   1.0)
        # nAttr.setMin(0.001)
        INPUT_ATTR(nAttr)
        nAttr.channelBox = True

        IKVChainSolver.inPreferredAngle = uAttr.create(
            "preferredAngle", "pa", om2.MFnUnitAttribute.kAngle, 0.0)
        uAttr.setMin(0.0)
        uAttr.setMax(2.0 * math.pi)
        INPUT_ATTR(uAttr)
        uAttr.channelBox = True

        IKVChainSolver.inTwist = uAttr.create("twist", "twist",
                                              om2.MFnUnitAttribute.kAngle, 0.0)
        INPUT_ATTR(uAttr)

        IKVChainSolver.inPvMode = eAttr.create("pvMode", "pvm", 0)
        eAttr.addField("Manual", 0)
        eAttr.addField("Auto", 1)
        INPUT_ATTR(eAttr)

        IKVChainSolver.inHierarchyMode = nAttr.create(
            "hierarchyMode", "hm", om2.MFnNumericData.kBoolean, True)
        INPUT_ATTR(nAttr)

        IKVChainSolver.inFlip = nAttr.create("flipOrientation", "fori",
                                             om2.MFnNumericData.kBoolean,
                                             False)
        INPUT_ATTR(nAttr)
        nAttr.channelBox = True

        IKVChainSolver.inUseScale = nAttr.create("useStretchAsScale", "usca",
                                                 om2.MFnNumericData.kBoolean,
                                                 False)
        INPUT_ATTR(nAttr)

        IKVChainSolver.inCompressionLimit = nAttr.create(
            "compressionLimit", "cl", om2.MFnNumericData.kFloat, 0.1)
        nAttr.setMin(0.001)
        nAttr.setMax(0.4)
        INPUT_ATTR(nAttr)

        IKVChainSolver.inSnapUpVector = nAttr.create("snapUpVector", "supv",
                                                     om2.MFnNumericData.kFloat,
                                                     0.0)
        nAttr.setMin(0.0)
        nAttr.setMax(1.0)
        INPUT_ATTR(nAttr)

        IKVChainSolver.inSnap = mAttr.create("snap", "snap",
                                             om2.MFnMatrixAttribute.kDouble)
        INPUT_ATTR(mAttr)

        IKVChainSolver.inSoftness = nAttr.create("softness", "soft",
                                                 om2.MFnNumericData.kFloat,
                                                 0.0)
        nAttr.setMin(0.0)
        nAttr.setSoftMax(0.2)
        nAttr.setMax(1.0)
        INPUT_ATTR(nAttr)

        IKVChainSolver.inStretch = nAttr.create("stretch", "st",
                                                om2.MFnNumericData.kDouble,
                                                0.0)
        nAttr.setMin(0.0)
        nAttr.setMax(1.0)
        INPUT_ATTR(nAttr)

        IKVChainSolver.inClampStretch = nAttr.create(
            "clampStretch", "cst", om2.MFnNumericData.kDouble, 0.0)
        nAttr.setMin(0.0)
        nAttr.setMax(1.0)
        INPUT_ATTR(nAttr)

        IKVChainSolver.inClampValue = nAttr.create("clampValue", "cstv",
                                                   om2.MFnNumericData.kDouble,
                                                   1.5)
        nAttr.setMin(1.0)
        nAttr.setSoftMax(1.8)
        INPUT_ATTR(nAttr)

        # IKVChainSolver.inStretchMultStart = nAttr.create("stretchMultStart", "stms", om2.MFnNumericData.kFloat, 1.0)
        # nAttr.setMin(0.001)
        # INPUT_ATTR(nAttr)

        # IKVChainSolver.inStretchMultEnd = nAttr.create("stretchMultEnd", "stme", om2.MFnNumericData.kFloat, 1.0)
        # nAttr.setMin(0.001)
        # INPUT_ATTR(nAttr)

        IKVChainSolver.inSquash = nAttr.create("squash", "sq",
                                               om2.MFnNumericData.kDouble, 0.0)
        nAttr.setMin(0.0)
        nAttr.setMax(1.0)
        INPUT_ATTR(nAttr)

        startSqX = nAttr.create("squashMultStartX", "sqmsx",
                                om2.MFnNumericData.kFloat, 1.0)
        startSqY = nAttr.create("squashMultStartY", "sqmsy",
                                om2.MFnNumericData.kFloat, 1.0)
        IKVChainSolver.inSquashMultStart = nAttr.create(
            "squashMultStart", "sqms", startSqX, startSqY)
        nAttr.setMin([0.001, 0.001])
        INPUT_ATTR(nAttr)

        endSqX = nAttr.create("squashMultEndX", "sqmex",
                              om2.MFnNumericData.kFloat, 1.0)
        endSqY = nAttr.create("squashMultEndY", "sqmey",
                              om2.MFnNumericData.kFloat, 1.0)
        IKVChainSolver.inSquashMultEnd = nAttr.create("squashMultEnd", "sqme",
                                                      endSqX, endSqY)
        nAttr.setMin([0.001, 0.001])
        INPUT_ATTR(nAttr)

        IKVChainSolver.outChain = mAttr.create("outChain", "oc",
                                               om2.MFnMatrixAttribute.kDouble)
        mAttr.array = True
        OUTPUT_ATTR(mAttr)

        IKVChainSolver.addAttribute(IKVChainSolver.inRoot)
        IKVChainSolver.addAttribute(IKVChainSolver.inHandle)
        IKVChainSolver.addAttribute(IKVChainSolver.inPoleVector)
        IKVChainSolver.addAttribute(IKVChainSolver.inOffset)
        IKVChainSolver.addAttribute(IKVChainSolver.inJntOri)
        IKVChainSolver.addAttribute(IKVChainSolver.inParInvMtx)
        IKVChainSolver.addAttribute(IKVChainSolver.inRestLenStart)
        IKVChainSolver.addAttribute(IKVChainSolver.inRestLenEnd)
        IKVChainSolver.addAttribute(IKVChainSolver.inPreferredAngle)
        IKVChainSolver.addAttribute(IKVChainSolver.inTwist)
        IKVChainSolver.addAttribute(IKVChainSolver.inPvMode)
        IKVChainSolver.addAttribute(IKVChainSolver.inHierarchyMode)
        IKVChainSolver.addAttribute(IKVChainSolver.inFlip)
        IKVChainSolver.addAttribute(IKVChainSolver.inUseScale)
        IKVChainSolver.addAttribute(IKVChainSolver.inCompressionLimit)
        IKVChainSolver.addAttribute(IKVChainSolver.inSnapUpVector)
        IKVChainSolver.addAttribute(IKVChainSolver.inSnap)
        IKVChainSolver.addAttribute(IKVChainSolver.inSoftness)
        IKVChainSolver.addAttribute(IKVChainSolver.inStretch)
        IKVChainSolver.addAttribute(IKVChainSolver.inClampStretch)
        IKVChainSolver.addAttribute(IKVChainSolver.inClampValue)
        # IKVChainSolver.addAttribute(IKVChainSolver.inStretchMultStart)
        # IKVChainSolver.addAttribute(IKVChainSolver.inStretchMultEnd)
        IKVChainSolver.addAttribute(IKVChainSolver.inSquash)
        IKVChainSolver.addAttribute(IKVChainSolver.inSquashMultStart)
        IKVChainSolver.addAttribute(IKVChainSolver.inSquashMultEnd)
        IKVChainSolver.addAttribute(IKVChainSolver.outChain)
        IKVChainSolver.attributeAffects(IKVChainSolver.inRoot,
                                        IKVChainSolver.outChain)
        IKVChainSolver.attributeAffects(IKVChainSolver.inHandle,
                                        IKVChainSolver.outChain)
        IKVChainSolver.attributeAffects(IKVChainSolver.inPoleVector,
                                        IKVChainSolver.outChain)
        IKVChainSolver.attributeAffects(IKVChainSolver.inOffset,
                                        IKVChainSolver.outChain)
        IKVChainSolver.attributeAffects(IKVChainSolver.inJntOri,
                                        IKVChainSolver.outChain)
        IKVChainSolver.attributeAffects(IKVChainSolver.inParInvMtx,
                                        IKVChainSolver.outChain)
        IKVChainSolver.attributeAffects(IKVChainSolver.inRestLenStart,
                                        IKVChainSolver.outChain)
        IKVChainSolver.attributeAffects(IKVChainSolver.inRestLenEnd,
                                        IKVChainSolver.outChain)
        IKVChainSolver.attributeAffects(IKVChainSolver.inPreferredAngle,
                                        IKVChainSolver.outChain)
        IKVChainSolver.attributeAffects(IKVChainSolver.inTwist,
                                        IKVChainSolver.outChain)
        IKVChainSolver.attributeAffects(IKVChainSolver.inPvMode,
                                        IKVChainSolver.outChain)
        IKVChainSolver.attributeAffects(IKVChainSolver.inHierarchyMode,
                                        IKVChainSolver.outChain)
        IKVChainSolver.attributeAffects(IKVChainSolver.inFlip,
                                        IKVChainSolver.outChain)
        IKVChainSolver.attributeAffects(IKVChainSolver.inUseScale,
                                        IKVChainSolver.outChain)
        IKVChainSolver.attributeAffects(IKVChainSolver.inCompressionLimit,
                                        IKVChainSolver.outChain)
        IKVChainSolver.attributeAffects(IKVChainSolver.inSnapUpVector,
                                        IKVChainSolver.outChain)
        IKVChainSolver.attributeAffects(IKVChainSolver.inSnap,
                                        IKVChainSolver.outChain)
        IKVChainSolver.attributeAffects(IKVChainSolver.inSoftness,
                                        IKVChainSolver.outChain)
        IKVChainSolver.attributeAffects(IKVChainSolver.inStretch,
                                        IKVChainSolver.outChain)
        IKVChainSolver.attributeAffects(IKVChainSolver.inClampStretch,
                                        IKVChainSolver.outChain)
        IKVChainSolver.attributeAffects(IKVChainSolver.inClampValue,
                                        IKVChainSolver.outChain)
        # IKVChainSolver.attributeAffects(IKVChainSolver.inStretchMultStart, IKVChainSolver.outChain)
        # IKVChainSolver.attributeAffects(IKVChainSolver.inStretchMultEnd, IKVChainSolver.outChain)
        IKVChainSolver.attributeAffects(IKVChainSolver.inSquash,
                                        IKVChainSolver.outChain)
        IKVChainSolver.attributeAffects(IKVChainSolver.inSquashMultStart,
                                        IKVChainSolver.outChain)
        IKVChainSolver.attributeAffects(IKVChainSolver.inSquashMultEnd,
                                        IKVChainSolver.outChain)

    def compute(self, plug, dataBlock):
        """
        Node computation method:
            * plug is a connection point related to one of our node attributes (either an input or an output).
            * dataBlock contains the data on which we will base our computations.
        """
        if plug != IKVChainSolver.outChain:
            return om2.kUnknownParameter

        # Get Basis Quaternion
        mRoot = dataBlock.inputValue(IKVChainSolver.inRoot).asMatrix()
        mHandle = dataBlock.inputValue(IKVChainSolver.inHandle).asMatrix()
        mPoleVector = dataBlock.inputValue(
            IKVChainSolver.inPoleVector).asMatrix()
        pvMode = dataBlock.inputValue(IKVChainSolver.inPvMode).asShort()
        prefAngle = dataBlock.inputValue(
            IKVChainSolver.inPreferredAngle).asAngle().asRadians()
        twist = dataBlock.inputValue(
            IKVChainSolver.inTwist).asAngle().asRadians()
        snap = dataBlock.inputValue(IKVChainSolver.inSnapUpVector).asFloat()
        mSnap = dataBlock.inputValue(IKVChainSolver.inSnap).asMatrix()
        flip = dataBlock.inputValue(IKVChainSolver.inFlip).asBool()

        vRoot = om2.MVector(mRoot[12], mRoot[13], mRoot[14])
        vHandle = om2.MVector(mHandle[12], mHandle[13], mHandle[14])
        vPoleVector = om2.MVector(mPoleVector[12], mPoleVector[13],
                                  mPoleVector[14])
        vSnap = om2.MVector(mSnap[12], mSnap[13], mSnap[14])

        primAxis = om2.MVector.kXaxisVector
        secAxis = om2.MVector.kYaxisVector
        if flip:
            primAxis = -om2.MVector.kXaxisVector
            secAxis = -om2.MVector.kYaxisVector
        binAxis = primAxis ^ secAxis
        qBasis = om2.MQuaternion()

        vAim = vHandle - vRoot
        nAim = vAim.normal()
        qAim = om2.MQuaternion(primAxis, nAim)
        qBasis *= qAim

        vStartSnap = vSnap - vRoot
        vEndSnap = vSnap - vHandle

        if pvMode == 0:
            vUp = vPoleVector - vRoot
        else:
            qTwist = om2.MQuaternion(prefAngle + twist, nAim)
            vUp = secAxis.rotateBy(qTwist)
        nNormalPole = vUp - ((vUp * nAim) * nAim)
        nNormalPole.normalize()
        if snap > 0.0:
            nNormalSnap = vStartSnap - ((vStartSnap * nAim) * nAim)
            nNormalSnap.normalize()
            nNormal = (1.0 - snap) * nNormalPole + snap * nNormalSnap
        else:
            nNormal = nNormalPole

        nUp = secAxis.rotateBy(qAim)
        angle = nUp.angle(nNormal)
        qNormal = om2.MQuaternion(angle, nAim)
        if not nNormal.isEquivalent(nUp.rotateBy(qNormal), 1.0e-5):
            angle = 2.0 * math.pi - angle
            qNormal = om2.MQuaternion(angle, nAim)
        qBasis *= qNormal

        # Solver Triangle
        restStartLen = dataBlock.inputValue(
            IKVChainSolver.inRestLenStart).asFloat()
        restEndLen = dataBlock.inputValue(
            IKVChainSolver.inRestLenEnd).asFloat()
        compressionLimit = dataBlock.inputValue(
            IKVChainSolver.inCompressionLimit).asFloat()
        softVal = dataBlock.inputValue(IKVChainSolver.inSoftness).asFloat()

        startSnapLen = vStartSnap.length()
        endSnapLen = vEndSnap.length()

        startLen = (1.0 - snap) * restStartLen + snap * startSnapLen
        endLen = (1.0 - snap) * restEndLen + snap * endSnapLen
        chainLen = (1.0 - snap) * (restStartLen + restEndLen) + snap * (
            startSnapLen + endSnapLen)
        handleLen = vAim.length()

        rigidLen = max(min(handleLen, chainLen), chainLen * compressionLimit)
        dc = chainLen
        da = (1.0 - softVal) * dc
        if handleLen > da and softVal > 0.0:
            ds = dc - da
            softLen = ds * (1.0 - math.pow(math.e, (da - handleLen) / ds)) + da
            solverLen = (1.0 - snap) * softLen + snap * rigidLen
        else:
            solverLen = rigidLen

        # Pre Calculations
        startLenSquared = math.pow(startLen, 2.0)
        endLenSquared = math.pow(endLen, 2.0)
        solverLenSquared = math.pow(solverLen, 2.0)
        stretch = dataBlock.inputValue(IKVChainSolver.inStretch).asDouble()
        squashMultStart = dataBlock.inputValue(
            IKVChainSolver.inSquashMultStart).asFloat2()
        squashMultEnd = dataBlock.inputValue(
            IKVChainSolver.inSquashMultEnd).asFloat2()
        if stretch > 0.0:
            clampStretch = dataBlock.inputValue(
                IKVChainSolver.inClampStretch).asDouble()
            clampValue = dataBlock.inputValue(
                IKVChainSolver.inClampValue).asDouble()
            squash = dataBlock.inputValue(IKVChainSolver.inSquash).asDouble()
            if handleLen > da and softVal > 0.0:
                scaleFactor = handleLen / solverLen
            else:
                scaleFactor = handleLen / chainLen
            if handleLen >= da:
                clampFactor = (
                    1.0 - clampStretch) * scaleFactor + clampStretch * min(
                        scaleFactor, clampValue)
                stretchFactor = (1.0 - stretch) + stretch * clampFactor
            else:
                stretchFactor = 1.0
            squashFactor = (1.0 -
                            squash) + squash * (1.0 / math.sqrt(stretchFactor))
        else:
            stretchFactor = 1.0
            squashFactor = 1.0

        hierarchyMode = dataBlock.inputValue(
            IKVChainSolver.inHierarchyMode).asBool()
        useScale = dataBlock.inputValue(IKVChainSolver.inUseScale).asBool()
        outChainHandle = dataBlock.outputArrayValue(IKVChainSolver.outChain)
        offsetHandle = dataBlock.inputArrayValue(IKVChainSolver.inOffset)
        jntOriHandle = dataBlock.inputArrayValue(IKVChainSolver.inJntOri)
        mParInv = dataBlock.inputValue(IKVChainSolver.inParInvMtx).asMatrix()
        srtList = []
        offsetList = []
        jntOriList = []

        for i in range(len(offsetHandle)):
            offsetHandle.jumpToLogicalElement(i)
            eOff = om2.MEulerRotation(offsetHandle.inputValue().asDouble3())
            qOff = eOff.asQuaternion()
            offsetList.append(qOff)

        for i in range(len(jntOriHandle)):
            jntOriHandle.jumpToLogicalElement(i)
            eOri = om2.MEulerRotation(jntOriHandle.inputValue().asDouble3())
            qOri = eOri.asQuaternion()
            jntOriList.append(qOri)

        # First Output
        # Scale
        firstStretch = stretchFactor
        firstScaX = firstStretch
        if not useScale:
            firstStretch = 1.0
        firstSquash = [
            squashFactor * squashMultStart[0],
            squashFactor * squashMultStart[1]
        ]
        firstSca = [firstStretch, firstSquash[0], firstSquash[1]]
        # Rotation
        betaCosPure = (startLenSquared + solverLenSquared -
                       endLenSquared) / (2.0 * startLen * solverLen)
        betaCos = min(max(betaCosPure, -1.0), 1.0)
        beta = math.acos(betaCos)
        qBeta = om2.MQuaternion(beta, binAxis)
        qFirstRotW = qBeta * qBasis
        qFirstRot = om2.MQuaternion()
        if len(offsetList) >= 1:
            qFirstRot *= offsetList[0].invertIt()
        qFirstRot *= qFirstRotW
        if len(jntOriList) >= 1:
            qFirstRot *= jntOriList[0].invertIt()
        # Translation
        vFirstPos = vRoot
        # Matrix Output
        mtxFn = om2.MTransformationMatrix()
        mtxFn.setScale(firstSca, om2.MSpace.kTransform)
        mtxFn.setRotation(qFirstRot)
        mtxFn.setTranslation(vFirstPos, om2.MSpace.kTransform)
        mFirst = mtxFn.asMatrix()
        mFirst *= mParInv
        srtList.append(mFirst)

        # Second Output
        # Scale
        secondStretch = stretchFactor
        secondScaX = secondStretch
        if not useScale:
            secondStretch = 1.0
        secondSquash = [
            squashFactor * squashMultEnd[0], squashFactor * squashMultEnd[1]
        ]
        secondSca = [secondStretch, secondSquash[0], secondSquash[1]]
        # Rotation
        gammaCosPure = (startLenSquared + endLenSquared -
                        solverLenSquared) / (2.0 * startLen * endLen)
        gammaCos = min(max(gammaCosPure, -1.0), 1.0)
        gamma = math.acos(gammaCos)
        gammaCmp = gamma + beta - math.pi
        qGamma = om2.MQuaternion(gammaCmp, binAxis)
        qSecondRotW = qGamma * qBasis
        qSecondRot = om2.MQuaternion()
        if len(offsetList) >= 2:
            qSecondRot *= offsetList[1].invertIt()
        qSecondRot *= qSecondRotW
        if hierarchyMode:
            qSecondRot *= qFirstRotW.invertIt()
            if len(offsetList) >= 1:
                qSecondRot *= offsetList[0].invertIt()
        if len(jntOriList) >= 2:
            qSecondRot *= jntOriList[1].invertIt()
        # Translation
        if hierarchyMode:
            vSecondPos = primAxis * startLen
            if not useScale:
                vSecondPos *= firstScaX
        else:
            vSecondOri = nAim.rotateBy(om2.MQuaternion(
                beta, nAim ^ nNormal)) * startLen
            if not useScale:
                vSecondOri *= firstScaX
            vSecondPos = vRoot + vSecondOri
        # Matrix Output
        mtxFn = om2.MTransformationMatrix()
        mtxFn.setScale(secondSca, om2.MSpace.kTransform)
        mtxFn.setRotation(qSecondRot)
        mtxFn.setTranslation(vSecondPos, om2.MSpace.kTransform)
        mSecond = mtxFn.asMatrix()
        if not hierarchyMode:
            mSecond *= mParInv
        srtList.append(mSecond)

        # Third Output
        # Rotation
        qThirdRot = qBasis
        if hierarchyMode:
            qThirdRot *= qSecondRotW.invertIt()
            if len(offsetList) >= 2:
                qThirdRot *= offsetList[1].invertIt()
        # Translation
        if hierarchyMode:
            vThirdPos = primAxis * endLen
            if not useScale:
                vThirdPos *= secondScaX
        else:
            vThirdPos = vRoot + nAim * solverLen
            if not useScale:
                vThirdPos = vRoot + nAim * solverLen * stretchFactor
        # Matrix Output
        mtxFn = om2.MTransformationMatrix()
        mtxFn.setRotation(qThirdRot)
        mtxFn.setTranslation(vThirdPos, om2.MSpace.kTransform)
        mThird = mtxFn.asMatrix()
        if not hierarchyMode:
            mThird *= mParInv
        srtList.append(mThird)

        # Set outputs
        for i in range(len(outChainHandle)):
            outChainHandle.jumpToLogicalElement(i)
            resultHandle = outChainHandle.outputValue()
            if i < len(outChainHandle) and i < len(srtList):
                resultHandle.setMMatrix(srtList[i])
            else:
                resultHandle.setMMatrix(om2.MMatrix.kIdentity)

        outChainHandle.setAllClean()
예제 #11
0
class EulerToVector(om2.MPxNode):
    """ Main class of gfUtilEulerToVector node. """

    kNodeName = ""
    kNodeClassify = ""
    kNodeID = ""

    inEuler = om2.MObject()
    inEulerX = om2.MObject()
    inEulerY = om2.MObject()
    inEulerZ = om2.MObject()
    inToDegrees = om2.MObject()
    outVector = om2.MObject()

    def __init__(self):
        """ Constructor. """
        om2.MPxNode.__init__(self)

    @staticmethod
    def creator():
        """ Maya creator function. """
        return EulerToVector()

    @staticmethod
    def initialize():
        """
        Defines the set of attributes for this node. The attributes declared in this function are assigned
        as static members to EulerToVector class. Instances of EulerToVector will use these attributes to create plugs
        for use in the compute() method.
        """
        uAttr = om2.MFnUnitAttribute()
        nAttr = om2.MFnNumericAttribute()

        EulerToVector.inEulerX = uAttr.create("eulerX", "ex",
                                              om2.MFnUnitAttribute.kAngle, 0.0)
        EulerToVector.inEulerY = uAttr.create("eulerY", "ey",
                                              om2.MFnUnitAttribute.kAngle, 0.0)
        EulerToVector.inEulerZ = uAttr.create("eulerZ", "ez",
                                              om2.MFnUnitAttribute.kAngle, 0.0)
        EulerToVector.inEuler = nAttr.create("euler", "e",
                                             EulerToVector.inEulerX,
                                             EulerToVector.inEulerY,
                                             EulerToVector.inEulerZ)
        INPUT_ATTR(nAttr)

        EulerToVector.inToDegrees = nAttr.create("convertToDegrees", "todeg",
                                                 om2.MFnNumericData.kBoolean,
                                                 True)
        INPUT_ATTR(nAttr)

        EulerToVector.outVector = nAttr.createPoint("outVector", "ov")
        OUTPUT_ATTR(nAttr)

        EulerToVector.addAttribute(EulerToVector.inEuler)
        EulerToVector.addAttribute(EulerToVector.inToDegrees)
        EulerToVector.addAttribute(EulerToVector.outVector)
        EulerToVector.attributeAffects(EulerToVector.inEuler,
                                       EulerToVector.outVector)
        EulerToVector.attributeAffects(EulerToVector.inToDegrees,
                                       EulerToVector.outVector)

    def compute(self, plug, dataBlock):
        """
        Node computation method:
            * plug is a connection point related to one of our node attributes (either an input or an output).
            * dataBlock contains the data on which we will base our computations.
        """
        # pylint: disable=no-self-use
        euler = dataBlock.inputValue(EulerToVector.inEuler).asDouble3()
        toDegrees = dataBlock.inputValue(EulerToVector.inToDegrees).asBool()

        if toDegrees:
            euler = [angle * (180.0 / math.pi) for angle in euler]
        vVector = om2.MFloatVector(euler)

        outVectorHandle = dataBlock.outputValue(EulerToVector.outVector)
        outVectorHandle.setMFloatVector(vVector)
        outVectorHandle.setClean()
class VectorAnglePSD(om2.MPxNode):
    """ Main class of gfRigPSDVectorAngle node. """

    kNodeName = ""
    kNodeClassify = ""
    kNodeID = ""

    inBase = om2.MObject()
    inSource = om2.MObject()
    inTarget = om2.MObject()
    inTargetEnvelope = om2.MObject()
    inTargetFalloff = om2.MObject()
    inRampWeights = om2.MObject()
    outWeights = om2.MObject()

    def __init__(self):
        """ Constructor. """
        om2.MPxNode.__init__(self)

    def postConstructor(self):
        """ Post Constructor. """
        thisMob = self.thisMObject()
        attr = VectorAnglePSD.inRampWeights
        ramp = om2.MRampAttribute(thisMob, attr)
        pos = om2.MFloatArray()
        val = om2.MFloatArray()
        interp = om2.MIntArray()
        pos.append(1.0)
        val.append(1.0)
        interp.append(om2.MRampAttribute.kLinear)
        ramp.addEntries(pos, val, interp)

    @staticmethod
    def creator():
        """ Maya creator function. """
        return VectorAnglePSD()

    @staticmethod
    def initialize():
        """
        Defines the set of attributes for this node. The attributes declared in this function are assigned
        as static members to IKVChain class. Instances of IKVChain will use these attributes to create plugs
        for use in the compute() method.
        """
        mAttr = om2.MFnMatrixAttribute()
        nAttr = om2.MFnNumericAttribute()
        rAttr = om2.MRampAttribute()

        VectorAnglePSD.inBase = mAttr.create("base", "base",
                                             om2.MFnMatrixAttribute.kFloat)
        INPUT_ATTR(mAttr)

        VectorAnglePSD.inSource = mAttr.create("source", "source",
                                               om2.MFnMatrixAttribute.kFloat)
        INPUT_ATTR(mAttr)

        VectorAnglePSD.inTarget = mAttr.create("target", "target",
                                               om2.MFnMatrixAttribute.kFloat)
        mAttr.array = True
        INPUT_ATTR(mAttr)

        VectorAnglePSD.inTargetEnvelope = nAttr.create(
            "targetEnvelope", "te", om2.MFnNumericData.kFloat, 1.0)
        nAttr.setMin(0.0)
        nAttr.setMax(1.0)
        nAttr.array = True
        INPUT_ATTR(nAttr)

        VectorAnglePSD.inTargetFalloff = nAttr.create(
            "targetFalloff", "tf", om2.MFnNumericData.kFloat, 90.0)
        nAttr.setMin(0.0)
        nAttr.setMax(180.0)
        nAttr.array = True
        INPUT_ATTR(nAttr)

        VectorAnglePSD.inRampWeights = rAttr.createCurveRamp(
            "rampWeights", "rw")

        VectorAnglePSD.outWeights = nAttr.create("outWeights", "ow",
                                                 om2.MFnNumericData.kFloat,
                                                 0.0)
        nAttr.array = True
        OUTPUT_ATTR(nAttr)

        VectorAnglePSD.addAttribute(VectorAnglePSD.inBase)
        VectorAnglePSD.addAttribute(VectorAnglePSD.inSource)
        VectorAnglePSD.addAttribute(VectorAnglePSD.inTarget)
        VectorAnglePSD.addAttribute(VectorAnglePSD.inTargetEnvelope)
        VectorAnglePSD.addAttribute(VectorAnglePSD.inTargetFalloff)
        VectorAnglePSD.addAttribute(VectorAnglePSD.inRampWeights)
        VectorAnglePSD.addAttribute(VectorAnglePSD.outWeights)
        VectorAnglePSD.attributeAffects(VectorAnglePSD.inBase,
                                        VectorAnglePSD.outWeights)
        VectorAnglePSD.attributeAffects(VectorAnglePSD.inSource,
                                        VectorAnglePSD.outWeights)
        VectorAnglePSD.attributeAffects(VectorAnglePSD.inTarget,
                                        VectorAnglePSD.outWeights)
        VectorAnglePSD.attributeAffects(VectorAnglePSD.inTargetEnvelope,
                                        VectorAnglePSD.outWeights)
        VectorAnglePSD.attributeAffects(VectorAnglePSD.inTargetFalloff,
                                        VectorAnglePSD.outWeights)
        VectorAnglePSD.attributeAffects(VectorAnglePSD.inRampWeights,
                                        VectorAnglePSD.outWeights)

    def compute(self, plug, dataBlock):
        """
        Node computation method:
            * plug is a connection point related to one of our node attributes (either an input or an output).
            * dataBlock contains the data on which we will base our computations.
        """
        # pylint: disable=R0201
        if plug != VectorAnglePSD.outWeights:
            return om2.kUnknownParameter

        mBase = dataBlock.inputValue(VectorAnglePSD.inBase).asFloatMatrix()
        mSource = dataBlock.inputValue(VectorAnglePSD.inSource).asFloatMatrix()

        targetHandle = dataBlock.inputArrayValue(VectorAnglePSD.inTarget)
        targetEnvelopeHandle = dataBlock.inputArrayValue(
            VectorAnglePSD.inTargetEnvelope)
        targetFalloffHandle = dataBlock.inputArrayValue(
            VectorAnglePSD.inTargetFalloff)
        outWeightsHandle = dataBlock.outputArrayValue(
            VectorAnglePSD.outWeights)

        vBase = om2.MFloatVector(mBase[12], mBase[13], mBase[14])
        vSource = om2.MFloatVector(mSource[12], mSource[13], mSource[14])

        vCurPose = vSource - vBase
        nCurPose = vCurPose.normal()

        targetList = []
        envelopeList = []
        falloffList = []

        for i in range(len(targetHandle)):
            targetHandle.jumpToLogicalElement(i)
            mtx = targetHandle.inputValue().asFloatMatrix()
            vec = om2.MFloatVector(mtx[12], mtx[13], mtx[14])
            vTargetPose = vec - vBase
            nTargetPose = vTargetPose.normal()
            targetList.append(nTargetPose)

        for i in range(len(targetEnvelopeHandle)):
            targetEnvelopeHandle.jumpToLogicalElement(i)
            env = targetEnvelopeHandle.inputValue().asFloat()
            envelopeList.append(env)

        for i in range(len(targetFalloffHandle)):
            targetFalloffHandle.jumpToLogicalElement(i)
            fall = targetFalloffHandle.inputValue().asFloat()
            falloffList.append(fall)

        for i in range(len(outWeightsHandle)):
            outWeightsHandle.jumpToLogicalElement(i)
            resultHandle = outWeightsHandle.outputValue()
            if (i < len(outWeightsHandle) and i < len(targetHandle)
                    and i < len(targetEnvelopeHandle)
                    and i < len(targetFalloffHandle)):
                theta = math.acos(targetList[i] * nCurPose)
                ratio = min(max(theta / math.radians(falloffList[i]), -1.0),
                            1.0)
                if ratio == 0.0:
                    weight = envelopeList[i] * 1.0
                elif ratio > 0.0:
                    weight = envelopeList[i] * (1.0 - ratio)
                elif ratio < 0.0:
                    weight = envelopeList[i] * (1.0 + ratio)

                thisMob = self.thisMObject()
                rampAttr = om2.MRampAttribute(thisMob,
                                              VectorAnglePSD.inRampWeights)
                resultWeight = rampAttr.getValueAtPosition(weight)
                resultHandle.setFloat(resultWeight)
            else:
                resultHandle.setFloat(0.0)
class ParentConstraint(om2.MPxNode):
    """ Main class of gfUtilParentConstraint node. """

    kNodeName = ""
    kNodeClassify = ""
    kNodeID = ""

    inConstraintJntOri = om2.MObject()
    inConstraintRotOrder = om2.MObject()
    inConstraintParInvMtx = om2.MObject()
    inConstraintParSca = om2.MObject()
    # inTargetJntOri = om2.MObject()
    # inTargetRotOrder = om2.MObject()
    inTargetWorldMatrix = om2.MObject()
    inTargetOffset = om2.MObject()
    inTargetWeight = om2.MObject()
    inTargetList = om2.MObject()
    outConstTrans = om2.MObject()
    outConstRot = om2.MObject()
    outConstSca = om2.MObject()

    def __init__(self):
        """ Constructor. """
        om2.MPxNode.__init__(self)

    @staticmethod
    def creator():
        """ Maya creator function. """
        return ParentConstraint()

    @staticmethod
    def initialize():
        """
        Defines the set of attributes for this node. The attributes declared in this function are assigned
        as static members to ParentConstraint class. Instances of ParentConstraint will use these attributes to create plugs
        for use in the compute() method.
        """
        mAttr = om2.MFnMatrixAttribute()
        nAttr = om2.MFnNumericAttribute()
        uAttr = om2.MFnUnitAttribute()
        eAttr = om2.MFnEnumAttribute()
        cAttr = om2.MFnCompoundAttribute()

        constJntOriX = uAttr.create("constraintJointOrientX", "cjorx",
                                    om2.MFnUnitAttribute.kAngle, 0.0)
        constJntOriY = uAttr.create("constraintJointOrientY", "cjory",
                                    om2.MFnUnitAttribute.kAngle, 0.0)
        constJntOriZ = uAttr.create("constraintJointOrientZ", "cjorz",
                                    om2.MFnUnitAttribute.kAngle, 0.0)
        ParentConstraint.inConstraintJntOri = nAttr.create(
            "constraintJointOrient", "cjor", constJntOriX, constJntOriY,
            constJntOriZ)
        INPUT_ATTR(nAttr)

        ParentConstraint.inConstraintRotOrder = eAttr.create(
            "constraintRotateOrder", "croo", 0)
        eAttr.addField("xyz", 0)
        eAttr.addField("yzx", 1)
        eAttr.addField("zxy", 2)
        eAttr.addField("xzy", 3)
        eAttr.addField("yxz", 4)
        eAttr.addField("zyx", 5)
        INPUT_ATTR(eAttr)

        ParentConstraint.inConstraintParInvMtx = mAttr.create(
            "constraintParentInverseMatrix", "cpim",
            om2.MFnMatrixAttribute.kDouble)
        INPUT_ATTR(mAttr)

        ParentConstraint.inConstraintParSca = nAttr.createPoint(
            "constraintParentScale", "cps")
        nAttr.default = (1.0, 1.0, 1.0)
        INPUT_ATTR(nAttr)

        ParentConstraint.inTargetWorldMatrix = mAttr.create(
            "targetWorldMatrix", "twmtx", om2.MFnMatrixAttribute.kDouble)
        INPUT_ATTR(mAttr)

        ParentConstraint.inTargetOffset = mAttr.create(
            "targetOffset", "toff", om2.MFnMatrixAttribute.kDouble)
        INPUT_ATTR(mAttr)

        # targetJntOriX = uAttr.create("targetJointOrientX", "tjorx", om2.MFnUnitAttribute.kAngle, 0.0)
        # targetJntOriY = uAttr.create("targetJointOrientY", "tjory", om2.MFnUnitAttribute.kAngle, 0.0)
        # targetJntOriZ = uAttr.create("targetJointOrientZ", "tjorz", om2.MFnUnitAttribute.kAngle, 0.0)
        # ParentConstraint.inTargetJntOri = nAttr.create("targetJointOrient", "tjor", targetJntOriX, targetJntOriY, targetJntOriZ)
        # INPUT_ATTR(nAttr)

        # ParentConstraint.inTargetRotOrder = eAttr.create("targetRotateOrder", "troo", 0)
        # eAttr.addField("xyz", 0)
        # eAttr.addField("yzx", 1)
        # eAttr.addField("zxy", 2)
        # eAttr.addField("xzy", 3)
        # eAttr.addField("yxz", 4)
        # eAttr.addField("zyx", 5)
        # INPUT_ATTR(eAttr)

        ParentConstraint.inTargetWeight = nAttr.create(
            "targetWeight", "twght", om2.MFnNumericData.kFloat, 1.0)
        INPUT_ATTR(nAttr)

        ParentConstraint.inTargetList = cAttr.create("targetList", "tlist")
        cAttr.addChild(ParentConstraint.inTargetWorldMatrix)
        cAttr.addChild(ParentConstraint.inTargetOffset)
        # cAttr.addChild(ParentConstraint.inTargetJntOri)
        # cAttr.addChild(ParentConstraint.inTargetRotOrder)
        cAttr.addChild(ParentConstraint.inTargetWeight)
        cAttr.array = True

        ParentConstraint.outConstTrans = nAttr.createPoint(
            "constraintTranslate", "ctrans")
        OUTPUT_ATTR(nAttr)

        outConstRotX = uAttr.create("constraintRotateX", "crox",
                                    om2.MFnUnitAttribute.kAngle, 0.0)
        outConstRotY = uAttr.create("constraintRotateY", "croy",
                                    om2.MFnUnitAttribute.kAngle, 0.0)
        outConstRotZ = uAttr.create("constraintRotateZ", "croz",
                                    om2.MFnUnitAttribute.kAngle, 0.0)
        ParentConstraint.outConstRot = nAttr.create("constraintRotate", "cro",
                                                    outConstRotX, outConstRotY,
                                                    outConstRotZ)
        OUTPUT_ATTR(nAttr)

        ParentConstraint.outConstSca = nAttr.createPoint(
            "constraintScale", "csca")
        nAttr.default = (1.0, 1.0, 1.0)
        OUTPUT_ATTR(nAttr)

        ParentConstraint.addAttribute(ParentConstraint.inConstraintJntOri)
        ParentConstraint.addAttribute(ParentConstraint.inConstraintRotOrder)
        ParentConstraint.addAttribute(ParentConstraint.inConstraintParInvMtx)
        ParentConstraint.addAttribute(ParentConstraint.inConstraintParSca)
        ParentConstraint.addAttribute(ParentConstraint.inTargetList)
        ParentConstraint.addAttribute(ParentConstraint.outConstTrans)
        ParentConstraint.addAttribute(ParentConstraint.outConstRot)
        ParentConstraint.addAttribute(ParentConstraint.outConstSca)
        ParentConstraint.attributeAffects(ParentConstraint.inConstraintJntOri,
                                          ParentConstraint.outConstTrans)
        ParentConstraint.attributeAffects(
            ParentConstraint.inConstraintRotOrder,
            ParentConstraint.outConstTrans)
        ParentConstraint.attributeAffects(
            ParentConstraint.inConstraintParInvMtx,
            ParentConstraint.outConstTrans)
        ParentConstraint.attributeAffects(ParentConstraint.inConstraintParSca,
                                          ParentConstraint.outConstTrans)
        ParentConstraint.attributeAffects(ParentConstraint.inTargetWorldMatrix,
                                          ParentConstraint.outConstTrans)
        ParentConstraint.attributeAffects(ParentConstraint.inTargetOffset,
                                          ParentConstraint.outConstTrans)
        # ParentConstraint.attributeAffects(ParentConstraint.inTargetJntOri, ParentConstraint.outConstTrans)
        # ParentConstraint.attributeAffects(ParentConstraint.inTargetRotOrder, ParentConstraint.outConstTrans)
        ParentConstraint.attributeAffects(ParentConstraint.inTargetWeight,
                                          ParentConstraint.outConstTrans)
        ParentConstraint.attributeAffects(ParentConstraint.inConstraintJntOri,
                                          ParentConstraint.outConstRot)
        ParentConstraint.attributeAffects(
            ParentConstraint.inConstraintRotOrder,
            ParentConstraint.outConstRot)
        ParentConstraint.attributeAffects(
            ParentConstraint.inConstraintParInvMtx,
            ParentConstraint.outConstRot)
        ParentConstraint.attributeAffects(ParentConstraint.inConstraintParSca,
                                          ParentConstraint.outConstRot)
        ParentConstraint.attributeAffects(ParentConstraint.inTargetWorldMatrix,
                                          ParentConstraint.outConstRot)
        ParentConstraint.attributeAffects(ParentConstraint.inTargetOffset,
                                          ParentConstraint.outConstRot)
        # ParentConstraint.attributeAffects(ParentConstraint.inTargetJntOri, ParentConstraint.outConstRot)
        # ParentConstraint.attributeAffects(ParentConstraint.inTargetRotOrder, ParentConstraint.outConstRot)
        ParentConstraint.attributeAffects(ParentConstraint.inTargetWeight,
                                          ParentConstraint.outConstRot)
        ParentConstraint.attributeAffects(ParentConstraint.inConstraintJntOri,
                                          ParentConstraint.outConstSca)
        ParentConstraint.attributeAffects(
            ParentConstraint.inConstraintRotOrder,
            ParentConstraint.outConstSca)
        ParentConstraint.attributeAffects(
            ParentConstraint.inConstraintParInvMtx,
            ParentConstraint.outConstSca)
        ParentConstraint.attributeAffects(ParentConstraint.inConstraintParSca,
                                          ParentConstraint.outConstSca)
        ParentConstraint.attributeAffects(ParentConstraint.inTargetWorldMatrix,
                                          ParentConstraint.outConstSca)
        ParentConstraint.attributeAffects(ParentConstraint.inTargetOffset,
                                          ParentConstraint.outConstSca)
        # ParentConstraint.attributeAffects(ParentConstraint.inTargetJntOri, ParentConstraint.outConstSca)
        # ParentConstraint.attributeAffects(ParentConstraint.inTargetRotOrder, ParentConstraint.outConstSca)
        ParentConstraint.attributeAffects(ParentConstraint.inTargetWeight,
                                          ParentConstraint.outConstSca)

    def compute(self, plug, dataBlock):
        """
        Node computation method:
            * plug is a connection point related to one of our node attributes (either an input or an output).
            * dataBlock contains the data on which we will base our computations.
        """
        # pylint: disable=no-self-use
        eConstJntOri = om2.MEulerRotation(
            dataBlock.inputValue(
                ParentConstraint.inConstraintJntOri).asDouble3())
        mConstParInv = dataBlock.inputValue(
            ParentConstraint.inConstraintParInvMtx).asMatrix()
        constRotOrder = dataBlock.inputValue(
            ParentConstraint.inConstraintRotOrder).asShort()
        constParSca = dataBlock.inputValue(
            ParentConstraint.inConstraintParSca).asFloat3()
        targetListHandle = dataBlock.inputArrayValue(
            ParentConstraint.inTargetList)
        mTargetsAdded = om2.MMatrix()
        mtxFn = om2.MTransformationMatrix()
        mtxFn.scaleBy(constParSca, om2.MSpace.kTransform)
        mInvSca = mtxFn.asMatrix()

        for i in range(len(targetListHandle)):
            targetListHandle.jumpToLogicalElement(i)
            targetHandle = targetListHandle.inputValue()
            # targetJntOri = om2.MEulerRotation(targetHandle.child(ParentConstraint.inTargetJntOri).asDouble3())
            # targetRotOrder = targetHandle.child(ParentConstraint.inTargetRotOrder).asShort()
            mTargetW = targetHandle.child(
                ParentConstraint.inTargetWorldMatrix).asMatrix()
            mOffset = targetHandle.child(
                ParentConstraint.inTargetOffset).asMatrix()
            targetWeight = targetHandle.child(
                ParentConstraint.inTargetWeight).asFloat()

            mTarget = mOffset * (mTargetW * targetWeight)
            if mTargetsAdded == om2.MMatrix():
                mTargetsAdded = mTarget
            else:
                mTargetsAdded += mTarget

        mResult = mTargetsAdded * mConstParInv * mInvSca

        if plug == ParentConstraint.outConstTrans:
            outTransHandle = dataBlock.outputValue(
                ParentConstraint.outConstTrans)
            outTrans = om2.MFloatVector(mResult[12], mResult[13], mResult[14])
            outTransHandle.setMFloatVector(outTrans)
            outTransHandle.setClean()
        if plug == ParentConstraint.outConstRot:
            outRotHandle = dataBlock.outputValue(ParentConstraint.outConstRot)
            mtxFn = om2.MTransformationMatrix(mResult)
            eRotMtx = mtxFn.rotation(asQuaternion=False)
            qRotMtx = eRotMtx.asQuaternion()
            qConstJntOri = eConstJntOri.asQuaternion()
            qOutRot = qRotMtx * qConstJntOri.invertIt()
            outRot = qOutRot.asEulerRotation().reorderIt(constRotOrder)
            outRotHandle.setMVector(outRot.asVector())
            outRotHandle.setClean()
        if plug == ParentConstraint.outConstSca:
            outScaHandle = dataBlock.outputValue(ParentConstraint.outConstSca)
            mtxFn = om2.MTransformationMatrix(mResult)
            outSca = mtxFn.scale(om2.MSpace.kWorld)
            outScaHandle.set3Float(outSca[0], outSca[1], outSca[2])
            outScaHandle.setClean()
예제 #14
0
class DebugMatrix(omui2.MPxLocatorNode):
    """ Main class of gfDebugMatrix node. """

    kNodeName = ""
    kNodeClassify = ""
    kNodeRegistrantID = ""
    kNodeID = ""

    inMatrix = om2.MObject()
    inNameColor = om2.MObject()
    inMtxColor = om2.MObject()
    inDistance = om2.MObject()
    inLineHeight = om2.MObject()

    fNameColor = om2.MColor([0.90588, 0.41961, 0.41961])
    fMtxColor = om2.MColor([0.93725, 0.87843, 0.69412])

    def __init__(self):
        """ Constructor. """
        omui2.MPxLocatorNode.__init__(self)

    def postConstructor(self):
        """ Post Constructor. """
        thisMob = self.thisMObject()
        nodeFn = om2.MFnDependencyNode(thisMob)
        nodeFn.setName("%sShape#" % DebugMatrix.kNodeName)
        # localPosPlug = nodeFn.findPlug("localPosition", False)
        # localPosPlug.isChannelBox = False
        # localPosPlug

    @staticmethod
    def creator():
        """ Maya creator function. """
        return DebugMatrix()

    @staticmethod
    def initialize():
        """
        Defines the set of attributes for this node. The attributes declared in this function are assigned
        as static members to DebugMatrix class. Instances of DebugMatrix will use these attributes to create plugs
        for use in the compute() method.
        """
        mAttr = om2.MFnMatrixAttribute()
        nAttr = om2.MFnNumericAttribute()

        DebugMatrix.inMatrix = mAttr.create("matrixInput", "mtxi",
                                            om2.MFnMatrixAttribute.kDouble)
        INPUT_ATTR(mAttr)
        mAttr.storable = False
        mAttr.keyable = True

        DebugMatrix.inNameColor = nAttr.createColor("nameColor", "nColor")
        nAttr.default = (DebugMatrix.fNameColor.r, DebugMatrix.fNameColor.g,
                         DebugMatrix.fNameColor.b)
        INPUT_ATTR(nAttr)

        DebugMatrix.inMtxColor = nAttr.createColor("matrixColor", "mColor")
        nAttr.default = (DebugMatrix.fMtxColor.r, DebugMatrix.fMtxColor.g,
                         DebugMatrix.fMtxColor.b)
        INPUT_ATTR(nAttr)

        DebugMatrix.inDistance = nAttr.create("distance", "dist",
                                              om2.MFnNumericData.kFloat, 0.0)
        INPUT_ATTR(nAttr)

        DebugMatrix.inLineHeight = nAttr.create("lineHeight", "lHeight",
                                                om2.MFnNumericData.kFloat, 0.7)
        nAttr.setMin(0.001)
        nAttr.setMax(2.0)
        INPUT_ATTR(nAttr)

        DebugMatrix.addAttribute(DebugMatrix.inMatrix)
        DebugMatrix.addAttribute(DebugMatrix.inNameColor)
        DebugMatrix.addAttribute(DebugMatrix.inMtxColor)
        DebugMatrix.addAttribute(DebugMatrix.inDistance)
        DebugMatrix.addAttribute(DebugMatrix.inLineHeight)

    def compute(self, plug, dataBlock):
        """
        Node computation method:
            * plug is a connection point related to one of our node attributes (either an input or an output).
            * dataBlock contains the data on which we will base our computations.
        """
        # pylint: disable=unused-argument
        return None

    def connectionMade(self, plug, otherPlug, asSrc):
        """This method gets called when connections are made to attributes of this node.
            * plug (MPlug) is the attribute on this node.
            * otherPlug (MPlug) is the attribute on the other node.
            * asSrc (bool) is this plug a source of the connection.
        """
        if plug == DebugMatrix.inMatrix:
            thisMob = self.thisMObject()
            distancePlug = om2.MPlug(thisMob, DebugMatrix.inDistance)
            dagFn = om2.MFnDagNode(otherPlug.node())
            bBox = dagFn.boundingBox
            offset = bBox.width / 2.0
            distancePlug.setFloat(offset + 2.0)
        return omui2.MPxLocatorNode.connectionMade(self, plug, otherPlug,
                                                   asSrc)

    def connectionBroken(self, plug, otherPlug, asSrc):
        """This method gets called when connections are broken with attributes of this node.
            * plug (MPlug) is the attribute on this node.
            * otherPlug (MPlug) is the attribute on the other node.
            * asSrc (bool) is this plug a source of the connection.
        """
        if plug == DebugMatrix.inMatrix:
            thisMob = self.thisMObject()
            distancePlug = om2.MPlug(thisMob, DebugMatrix.inDistance)
            distancePlug.setFloat(0.0)
        return omui2.MPxLocatorNode.connectionBroken(self, plug, otherPlug,
                                                     asSrc)

    def drawText(self,
                 mtx,
                 dist,
                 colorList,
                 status,
                 cameraPath,
                 lineH,
                 view=None,
                 drawManager=None):
        """Draw the matrix text.
        """
        mCamera = cameraPath.inclusiveMatrix()
        camFn = om2.MFnCamera(cameraPath)
        thisMob = self.thisMObject()
        worldMtxPlug = om2.MPlug(thisMob, DebugMatrix.inMatrix)
        destPlugList = worldMtxPlug.connectedTo(True, False)
        if len(destPlugList) >= 1:
            node = destPlugList[0].node()
            attr = destPlugList[0].attribute()
            dagFn = om2.MFnDagNode(node)
            name = dagFn.name()
            attrName = "%s   (%s)" % ("  " * len(name),
                                      om2.MFnAttribute(attr).name)
            bBox = dagFn.boundingBox
        else:
            attrName = ""
            name = "NO MATRIX INPUT"
            bBox = om2.MBoundingBox()

        offsetY = bBox.height / 2.0

        pntCamera = om2.MPoint(mCamera[12], mCamera[13], mCamera[14])
        pntPos = om2.MPoint(mtx[12] + dist, mtx[13] + offsetY, mtx[14])
        vCamera = pntCamera - pntPos
        distFromCamera = vCamera.length()
        pntLineOffset = om2.MPoint(0.0, (distFromCamera / camFn.focalLength) *
                                   lineH, 0.0)
        rowList = []

        pntRow1 = om2.MPoint(mtx[0], mtx[1], mtx[2], mtx[3])
        row1 = "%s | %s | %s | %s" % ("%.3f" % pntRow1.x, "%.3f" % pntRow1.y,
                                      "%.3f" % pntRow1.z, "%.3f" % pntRow1.w)
        rowList.append(row1)
        pntRow2 = om2.MPoint(mtx[4], mtx[5], mtx[6], mtx[7])
        row2 = "%s | %s | %s | %s" % ("%.3f" % pntRow2.x, "%.3f" % pntRow2.y,
                                      "%.3f" % pntRow2.z, "%.3f" % pntRow2.w)
        rowList.append(row2)
        pntRow3 = om2.MPoint(mtx[8], mtx[9], mtx[10], mtx[11])
        row3 = "%s | %s | %s | %s" % ("%.3f" % pntRow3.x, "%.3f" % pntRow3.y,
                                      "%.3f" % pntRow3.z, "%.3f" % pntRow3.w)
        rowList.append(row3)
        pntRow4 = om2.MPoint(mtx[12], mtx[13], mtx[14], mtx[15])
        row4 = "%s | %s | %s | %s" % ("%.3f" % pntRow4.x, "%.3f" % pntRow4.y,
                                      "%.3f" % pntRow4.z, "%.3f" % pntRow4.w)
        rowList.append(row4)

        if status == omui2.M3dView.kActive:
            view.setDrawColor(om2.MColor([0.3, 1.0, 1.0]))
        elif status == omui2.M3dView.kLead:
            view.setDrawColor(om2.MColor([1.0, 1.0, 1.0]))

        if status == omui2.M3dView.kDormant:
            view.setDrawColor(colorList[0])
        view.drawText(name, pntPos, omui2.M3dView.kLeft)

        if status == omui2.M3dView.kDormant:
            view.setDrawColor(colorList[1])
        view.drawText(attrName, pntPos, omui2.M3dView.kLeft)
        if worldMtxPlug.isConnected:
            for i in range(1, 5):
                pos = om2.MPoint(pntPos - (pntLineOffset * i))
                view.drawText(rowList[i - 1], pos, omui2.M3dView.kLeft)

    def draw(self, view, path, style, status):
        """
        Draw custom geometry in the viewport using OpenGL calls.
            * view [M3dView] is a 3D view that is being drawn into.
            * path [MDagPath] to the parent (transform node) of this locator in the DAG.  To obtain the locator shape node,
                use MDagPath::extendToShape() if there is only one shape node under the transform or
                MDagPath::extendToShapeDirectlyBelow(unsigned int index) with the shape index if there are multiple
                shapes under the transform.
            * style [M3dView.DisplayStyle] is the style to draw object in.
            * status [M3dView.DisplayStatus] is the selection status of the object.
        """
        # pylint: disable=unused-argument

        thisMob = self.thisMObject()
        mInput = om2.MPlug(thisMob,
                           DebugMatrix.inMatrix).asMDataHandle().asMatrix()
        nameColor = om2.MPlug(
            thisMob, DebugMatrix.inNameColor).asMDataHandle().asFloatVector()
        mtxColor = om2.MPlug(
            thisMob, DebugMatrix.inMtxColor).asMDataHandle().asFloatVector()
        dist = om2.MPlug(thisMob, DebugMatrix.inDistance).asFloat()
        lineHeight = om2.MPlug(thisMob, DebugMatrix.inLineHeight).asFloat()
        colorList = om2.MColorArray()
        colorList.append(om2.MColor([nameColor.x, nameColor.y, nameColor.z]))
        colorList.append(om2.MColor([mtxColor.x, mtxColor.y, mtxColor.z]))
        cameraPath = view.getCamera()

        view.beginGL()

        glRenderer = omr1.MHardwareRenderer.theRenderer()
        glFT = glRenderer.glFunctionTable()

        glFT.glPushAttrib(omr1.MGL_CURRENT_BIT)
        glFT.glDisable(omr1.MGL_CULL_FACE)

        self.drawText(mInput, dist, colorList, status, cameraPath, lineHeight,
                      view)

        view.endGL()
        return None
예제 #15
0
class DistributeAlongSurface(om2.MPxNode):
    """ Main class of gfDistributeAlongSurface node. """

    kNodeName = ""
    kNodeClassify = ""
    kNodeID = ""

    inSurface = om2.MObject()
    inDistributeAlong = om2.MObject()
    inDisplace = om2.MObject()
    inAlwaysUniform = om2.MObject()
    outTransform = om2.MObject()

    def __init__(self):
        """ Constructor. """
        om2.MPxNode.__init__(self)

    @staticmethod
    def creator():
        """ Maya creator function. """
        return DistributeAlongSurface()

    @staticmethod
    def initialize():
        """
        Defines the set of attributes for this node. The attributes declared in this function are assigned
        as static members to DistributeAlongSurface class. Instances of DistributeAlongSurface will use these attributes to create plugs
        for use in the compute() method.
        """
        tAttr = om2.MFnTypedAttribute()
        eAttr = om2.MFnEnumAttribute()
        nAttr = om2.MFnNumericAttribute()
        mAttr = om2.MFnMatrixAttribute()

        DistributeAlongSurface.inSurface = tAttr.create("inputSurface", "isurf", om2.MFnData.kNurbsSurface)
        INPUT_ATTR(tAttr)

        DistributeAlongSurface.inDistributeAlong = eAttr.create("distributeAlong", "da", 0)
        eAttr.addField("U", 0)
        eAttr.addField("V", 1)
        INPUT_ATTR(eAttr)

        DistributeAlongSurface.inDisplace = nAttr.create("displaceTangent", "dtan", om2.MFnNumericData.kFloat, 0.0)
        nAttr.setMin(0.0)
        nAttr.setMax(1.0)
        INPUT_ATTR(nAttr)

        DistributeAlongSurface.inAlwaysUniform = nAttr.create("alwaysUniform", "auni", om2.MFnNumericData.kBoolean, False)
        INPUT_ATTR(nAttr)

        DistributeAlongSurface.outTransform = mAttr.create("outputTransform", "ot", om2.MFnMatrixAttribute.kDouble)
        mAttr.array = True
        OUTPUT_ATTR(mAttr)

        DistributeAlongSurface.addAttribute(DistributeAlongSurface.inSurface)
        DistributeAlongSurface.addAttribute(DistributeAlongSurface.inDistributeAlong)
        DistributeAlongSurface.addAttribute(DistributeAlongSurface.inDisplace)
        DistributeAlongSurface.addAttribute(DistributeAlongSurface.inAlwaysUniform)
        DistributeAlongSurface.addAttribute(DistributeAlongSurface.outTransform)
        DistributeAlongSurface.attributeAffects(DistributeAlongSurface.inSurface, DistributeAlongSurface.outTransform)
        DistributeAlongSurface.attributeAffects(DistributeAlongSurface.inDistributeAlong, DistributeAlongSurface.outTransform)
        DistributeAlongSurface.attributeAffects(DistributeAlongSurface.inDisplace, DistributeAlongSurface.outTransform)
        DistributeAlongSurface.attributeAffects(DistributeAlongSurface.inAlwaysUniform, DistributeAlongSurface.outTransform)

    def compute(self, plug, dataBlock):
        """
        Node computation method:
            * plug is a connection point related to one of our node attributes (either an input or an output).
            * dataBlock contains the data on which we will base our computations.
        """
        # pylint: disable=no-self-use
        if plug != DistributeAlongSurface.outTransform:
            return om2.kUnknownParameter

        surfaceHandle = dataBlock.inputValue(DistributeAlongSurface.inSurface)
        surface = surfaceHandle.asNurbsSurface()
        distAlong = dataBlock.inputValue(DistributeAlongSurface.inDistributeAlong).asShort()
        displace = dataBlock.inputValue(DistributeAlongSurface.inDisplace).asFloat()
        alwaysUniform = dataBlock.inputValue(DistributeAlongSurface.inAlwaysUniform).asBool()
        outTransHandle = dataBlock.outputArrayValue(DistributeAlongSurface.outTransform)

        numOutputs = len(outTransHandle)
        surfaceFn = om2.MFnNurbsSurface(surface)
        step = 1.0 / (numOutputs - 1) if numOutputs > 1 else 0.0
        curveData = om2.MFnNurbsCurveData().create()
        curveFn = om2.MFnNurbsCurve(curveData)

        if alwaysUniform:
            numCVs = surfaceFn.numCVsInU if distAlong == 0 else surfaceFn.numCVsInV
            curvePnts = om2.MPointArray()
            curveKnots = surfaceFn.knotsInU() if distAlong == 0 else surfaceFn.knotsInV()
            curveDegree = surfaceFn.degreeInU if distAlong == 0 else surfaceFn.degreeInV
            curveForm = surfaceFn.formInU if distAlong == 0 else surfaceFn.formInV
            curveIs2d = False
            curveRational = False
            for i in range(numCVs):
                if distAlong == 0:
                    curvePnts.append(surfaceFn.cvPosition(i, int(displace)))
                else:
                    curvePnts.append(surfaceFn.cvPosition(int(displace), i))
            curveFn.create(curvePnts, curveKnots, curveDegree, curveForm, curveIs2d, curveRational, curveData)
            curveLength = curveFn.length()

        for i in range(numOutputs):
            if alwaysUniform:
                parU = curveFn.findParamFromLength(curveLength * step * i) if distAlong == 0 else displace
                parV = displace if distAlong == 0 else curveFn.findParamFromLength(curveLength * step * i)
            else:
                parU = step * i if distAlong == 0 else displace
                parV = displace if distAlong == 0 else step * i
            pos = surfaceFn.getPointAtParam(parU, parV, om2.MSpace.kWorld)
            tangents = surfaceFn.tangents(parU, parV, om2.MSpace.kWorld)
            aim = tangents[0].normalize() if distAlong == 0 else tangents[1].normalize()
            normal = surfaceFn.normal(parU, parV, om2.MSpace.kWorld).normalize()
            binormal = tangents[1].normalize() if distAlong == 0 else tangents[0].normalize()
            mtx = [
                aim.x, aim.y, aim.z, 0.0,
                normal.x, normal.y, normal.z, 0.0,
                binormal.x, binormal.y, binormal.z, 0.0,
                pos.x, pos.y, pos.z, 1.0
            ]
            mOut = om2.MMatrix(mtx)
            outTransHandle.jumpToLogicalElement(i)
            resultHandle = outTransHandle.outputValue()
            resultHandle.setMMatrix(mOut)

        surfaceHandle.setClean()
        outTransHandle.setAllClean()

        cmds.refresh()
예제 #16
0
class VectorToEuler(om2.MPxNode):
    """ Main class of gfUtilVectorToEuler node. """

    kNodeName = ""
    kNodeClassify = ""
    kNodeID = ""

    inVector = om2.MObject()
    outEuler = om2.MObject()
    outEulerX = om2.MObject()
    outEulerY = om2.MObject()
    outEulerZ = om2.MObject()

    def __init__(self):
        """ Constructor. """
        om2.MPxNode.__init__(self)

    @staticmethod
    def creator():
        """ Maya creator function. """
        return VectorToEuler()

    @staticmethod
    def initialize():
        """
        Defines the set of attributes for this node. The attributes declared in this function are assigned
        as static members to VectorToEuler class. Instances of VectorToEuler will use these attributes to create plugs
        for use in the compute() method.
        """
        uAttr = om2.MFnUnitAttribute()
        nAttr = om2.MFnNumericAttribute()

        VectorToEuler.inVector = nAttr.createPoint("vector", "vec")
        INPUT_ATTR(nAttr)

        VectorToEuler.outEulerX = uAttr.create("outEulerX", "oex",
                                               om2.MFnUnitAttribute.kAngle,
                                               0.0)
        VectorToEuler.outEulerY = uAttr.create("outEulerY", "oey",
                                               om2.MFnUnitAttribute.kAngle,
                                               0.0)
        VectorToEuler.outEulerZ = uAttr.create("outEulerZ", "oez",
                                               om2.MFnUnitAttribute.kAngle,
                                               0.0)
        VectorToEuler.outEuler = nAttr.create("outEuler", "oe",
                                              VectorToEuler.outEulerX,
                                              VectorToEuler.outEulerY,
                                              VectorToEuler.outEulerZ)
        OUTPUT_ATTR(nAttr)

        VectorToEuler.addAttribute(VectorToEuler.inVector)
        VectorToEuler.addAttribute(VectorToEuler.outEuler)
        VectorToEuler.attributeAffects(VectorToEuler.inVector,
                                       VectorToEuler.outEuler)

    def compute(self, plug, dataBlock):
        """
        Node computation method:
            * plug is a connection point related to one of our node attributes (either an input or an output).
            * dataBlock contains the data on which we will base our computations.
        """
        # pylint: disable=no-self-use
        vector = dataBlock.inputValue(VectorToEuler.inVector).asFloat3()
        vVector = om2.MVector([unit * (math.pi / 180.0) for unit in vector])

        eEuler = om2.MEulerRotation(vVector)

        outEulerHandle = dataBlock.outputValue(VectorToEuler.outEuler)
        outEulerHandle.set3Double(eEuler.x, eEuler.y, eEuler.z)
        outEulerHandle.setClean()
class AngularTrigMath(om2.MPxNode):
    """ Main class of gfUtilAngularTrigMath node. """

    kNodeName = ""
    kNodeClassify = ""
    kNodeID = ""

    inAngle1 = om2.MObject()
    inAngle2 = om2.MObject()
    inOperation = om2.MObject()
    outAngle = om2.MObject()

    def __init__(self):
        """ Constructor. """
        om2.MPxNode.__init__(self)

    @staticmethod
    def creator():
        """ Maya creator function. """
        return AngularTrigMath()

    @staticmethod
    def initialize():
        """
        Defines the set of attributes for this node. The attributes declared in this function are assigned
        as static members to AngularTrigMath class. Instances of AngularTrigMath will use these attributes to create plugs
        for use in the compute() method.
        """
        uAttr = om2.MFnUnitAttribute()
        eAttr = om2.MFnEnumAttribute()

        AngularTrigMath.inAngle1 = uAttr.create("angle1", "a1",
                                                om2.MFnUnitAttribute.kAngle,
                                                0.0)
        INPUT_ATTR(uAttr)

        AngularTrigMath.inAngle2 = uAttr.create("angle2", "a2",
                                                om2.MFnUnitAttribute.kAngle,
                                                0.0)
        INPUT_ATTR(uAttr)

        AngularTrigMath.inOperation = eAttr.create("operation", "operation", 0)
        eAttr.addField("No Operation", 0)
        eAttr.addField("Cosine", 1)
        eAttr.addField("Sine", 2)
        eAttr.addField("Tangent", 3)
        eAttr.addField("Arccos", 4)
        eAttr.addField("Arcsin", 5)
        eAttr.addField("Arctan", 6)
        eAttr.addField("Arctan2", 7)
        INPUT_ATTR(eAttr)

        AngularTrigMath.outAngle = uAttr.create("outAngle", "oa",
                                                om2.MFnUnitAttribute.kAngle,
                                                0.0)
        OUTPUT_ATTR(uAttr)

        AngularTrigMath.addAttribute(AngularTrigMath.inOperation)
        AngularTrigMath.addAttribute(AngularTrigMath.inAngle1)
        AngularTrigMath.addAttribute(AngularTrigMath.inAngle2)
        AngularTrigMath.addAttribute(AngularTrigMath.outAngle)
        AngularTrigMath.attributeAffects(AngularTrigMath.inAngle1,
                                         AngularTrigMath.outAngle)
        AngularTrigMath.attributeAffects(AngularTrigMath.inAngle2,
                                         AngularTrigMath.outAngle)
        AngularTrigMath.attributeAffects(AngularTrigMath.inOperation,
                                         AngularTrigMath.outAngle)

    def compute(self, plug, dataBlock):
        """
        Node computation method:
            * plug is a connection point related to one of our node attributes (either an input or an output).
            * dataBlock contains the data on which we will base our computations.
        """
        # pylint: disable=no-self-use
        if plug != AngularTrigMath.outAngle:
            return om2.kUnknownParameter

        angle1 = dataBlock.inputValue(AngularTrigMath.inAngle1).asAngle()
        operation = dataBlock.inputValue(AngularTrigMath.inOperation).asShort()

        outAngleHandle = dataBlock.outputValue(AngularTrigMath.outAngle)

        if operation == 0:
            outAngleHandle.setMAngle(angle1)
        elif operation == 1:
            outAngle = math.cos(angle1.asRadians())
            outAngleHandle.setMAngle(om2.MAngle(outAngle, om2.MAngle.kDegrees))
        elif operation == 2:
            outAngle = math.sin(angle1.asRadians())
            outAngleHandle.setMAngle(om2.MAngle(outAngle, om2.MAngle.kDegrees))
        elif operation == 3:
            outAngle = math.tan(angle1.asRadians())
            outAngleHandle.setMAngle(om2.MAngle(outAngle, om2.MAngle.kDegrees))
        elif operation == 4:
            resAngle = angle1.asDegrees()
            if resAngle > 1.0:
                resAngle = 1.0
            elif resAngle < -1.0:
                resAngle = -1.0
            outAngle = math.acos(resAngle)
            outAngleHandle.setMAngle(om2.MAngle(outAngle))
        elif operation == 5:
            resAngle = angle1.asDegrees()
            if resAngle > 1.0:
                resAngle = 1.0
            elif resAngle < -1.0:
                resAngle = -1.0
            outAngle = math.asin(resAngle)
            outAngleHandle.setMAngle(om2.MAngle(outAngle))
        elif operation == 6:
            outAngle = math.atan(angle1.asRadians())
            outAngleHandle.setMAngle(om2.MAngle(outAngle, om2.MAngle.kRadians))
        elif operation == 7:
            angle2 = dataBlock.inputValue(AngularTrigMath.inAngle2).asAngle()
            outAngle = math.atan2(angle1.asRadians(), angle2.asRadians())
            outAngleHandle.setMAngle(om2.MAngle(outAngle, om2.MAngle.kRadians))

        outAngleHandle.setClean()
예제 #18
0
class AngularScalarMath(om2.MPxNode):
    """ Main class of gfUtilAngularScalarMath node. """

    kNodeName = ""
    kNodeClassify = ""
    kNodeID = ""

    inAngle = om2.MObject()
    inScalar = om2.MObject()
    inOperation = om2.MObject()
    outAngle = om2.MObject()

    def __init__(self):
        """ Constructor. """
        om2.MPxNode.__init__(self)

    @staticmethod
    def creator():
        """ Maya creator function. """
        return AngularScalarMath()

    @staticmethod
    def initialize():
        """
        Defines the set of attributes for this node. The attributes declared in this function are assigned
        as static members to AngularScalarMath class. Instances of AngularScalarMath will use these attributes to create plugs
        for use in the compute() method.
        """
        uAttr = om2.MFnUnitAttribute()
        nAttr = om2.MFnNumericAttribute()
        eAttr = om2.MFnEnumAttribute()

        AngularScalarMath.inAngle = uAttr.create("angle", "angle",
                                                 om2.MFnUnitAttribute.kAngle,
                                                 0.0)
        INPUT_ATTR(uAttr)

        AngularScalarMath.inScalar = nAttr.create("scalar", "scalar",
                                                  om2.MFnNumericData.kDouble,
                                                  0.0)
        INPUT_ATTR(nAttr)

        AngularScalarMath.inOperation = eAttr.create("operation", "operation",
                                                     0)
        eAttr.addField("No Operation", 0)
        eAttr.addField("Add", 1)
        eAttr.addField("Subtract", 2)
        eAttr.addField("Multiply", 3)
        eAttr.addField("Divide", 4)
        eAttr.addField("Power", 5)
        eAttr.addField("Min", 6)
        eAttr.addField("Max", 7)
        INPUT_ATTR(eAttr)

        AngularScalarMath.outAngle = uAttr.create("outAngle", "oa",
                                                  om2.MFnUnitAttribute.kAngle,
                                                  0.0)
        OUTPUT_ATTR(uAttr)

        AngularScalarMath.addAttribute(AngularScalarMath.inOperation)
        AngularScalarMath.addAttribute(AngularScalarMath.inAngle)
        AngularScalarMath.addAttribute(AngularScalarMath.inScalar)
        AngularScalarMath.addAttribute(AngularScalarMath.outAngle)
        AngularScalarMath.attributeAffects(AngularScalarMath.inAngle,
                                           AngularScalarMath.outAngle)
        AngularScalarMath.attributeAffects(AngularScalarMath.inScalar,
                                           AngularScalarMath.outAngle)
        AngularScalarMath.attributeAffects(AngularScalarMath.inOperation,
                                           AngularScalarMath.outAngle)

    def compute(self, plug, dataBlock):
        """
        Node computation method:
            * plug is a connection point related to one of our node attributes (either an input or an output).
            * dataBlock contains the data on which we will base our computations.
        """
        # pylint: disable=no-self-use
        if plug != AngularScalarMath.outAngle:
            return om2.kUnknownParameter

        angle = dataBlock.inputValue(
            AngularScalarMath.inAngle).asAngle().asDegrees()
        scalar = dataBlock.inputValue(AngularScalarMath.inScalar).asDouble()
        operation = dataBlock.inputValue(
            AngularScalarMath.inOperation).asShort()

        outAngleHandle = dataBlock.outputValue(AngularScalarMath.outAngle)

        if operation == 0:
            outAngleHandle.setMAngle(om2.MAngle(angle, om2.MAngle.kDegrees))
        elif operation == 1:
            outAngle = angle + scalar
            outAngleHandle.setMAngle(om2.MAngle(outAngle, om2.MAngle.kDegrees))
        elif operation == 2:
            outAngle = angle - scalar
            outAngleHandle.setMAngle(om2.MAngle(outAngle, om2.MAngle.kDegrees))
        elif operation == 3:
            outAngle = angle * scalar
            outAngleHandle.setMAngle(om2.MAngle(outAngle, om2.MAngle.kDegrees))
        elif operation == 4:
            if scalar != 0.0:
                outAngle = angle / scalar
            else:
                outAngle = 9999.999
            outAngleHandle.setMAngle(om2.MAngle(outAngle, om2.MAngle.kDegrees))
        elif operation == 5:
            outAngle = math.pow(angle, scalar)
            outAngleHandle.setMAngle(om2.MAngle(outAngle, om2.MAngle.kDegrees))
        elif operation == 6:
            outAngle = min(angle, scalar)
            outAngleHandle.setMAngle(om2.MAngle(outAngle, om2.MAngle.kDegrees))
        elif operation == 7:
            outAngle = max(angle, scalar)
            outAngleHandle.setMAngle(om2.MAngle(outAngle, om2.MAngle.kDegrees))

        outAngleHandle.setClean()
예제 #19
0
class AimConstraint(om2.MPxNode):
    """ Main class of gfUtilAimConstraint node. """

    kNodeName = ""
    kNodeClassify = ""
    kNodeID = ""

    inUpVecType = om2.MObject()
    inOffset = om2.MObject()
    inWorldUpVector = om2.MObject()
    inWorldUpMtx = om2.MObject()
    inAngleUp = om2.MObject()
    inTargetWMtx = om2.MObject()
    inTargetWeight = om2.MObject()
    inConstWMtx = om2.MObject()
    inConstParInvMtx = om2.MObject()
    inConstJntOri = om2.MObject()
    inConstRotOrder = om2.MObject()
    outConstraint = om2.MObject()

    def __init__(self):
        """ Constructor. """
        om2.MPxNode.__init__(self)

    @staticmethod
    def creator():
        """ Maya creator function. """
        return AimConstraint()

    @staticmethod
    def initialize():
        """
        Defines the set of attributes for this node. The attributes declared in this function are assigned
        as static members to AimConstraint class. Instances of AimConstraint will use these attributes to create plugs
        for use in the compute() method.
        """
        eAttr = om2.MFnEnumAttribute()
        mAttr = om2.MFnMatrixAttribute()
        nAttr = om2.MFnNumericAttribute()
        uAttr = om2.MFnUnitAttribute()

        AimConstraint.inUpVecType = eAttr.create("upVectorType", "upt", 0)
        eAttr.addField("None", 0)
        eAttr.addField("World Up", 1)
        eAttr.addField("Object Up", 2)
        eAttr.addField("Angle Up", 3)
        INPUT_ATTR(eAttr)
        eAttr.channelBox = True

        offsetX = uAttr.create("offsetX", "offsetX",
                               om2.MFnUnitAttribute.kAngle, 0.0)
        offsetY = uAttr.create("offsetY", "offsetY",
                               om2.MFnUnitAttribute.kAngle, 0.0)
        offsetZ = uAttr.create("offsetZ", "offsetZ",
                               om2.MFnUnitAttribute.kAngle, 0.0)
        AimConstraint.inOffset = nAttr.create("offset", "offset", offsetX,
                                              offsetY, offsetZ)
        INPUT_ATTR(nAttr)

        AimConstraint.inWorldUpVector = nAttr.createPoint(
            "worldUpVector", "wuv")
        nAttr.default = (0.0, 1.0, 0.0)
        INPUT_ATTR(nAttr)

        AimConstraint.inWorldUpMtx = mAttr.create(
            "worldUpMatrix", "wum", om2.MFnMatrixAttribute.kDouble)
        INPUT_ATTR(mAttr)

        AimConstraint.inAngleUp = uAttr.create("angleUp", "angle",
                                               om2.MFnUnitAttribute.kAngle,
                                               0.0)
        uAttr.setMin(0.0)
        uAttr.setMax(2.0 * math.pi)
        INPUT_ATTR(uAttr)

        AimConstraint.inTargetWMtx = mAttr.create(
            "targetWorldMatrix", "twmtx", om2.MFnMatrixAttribute.kDouble)
        INPUT_ATTR(mAttr)

        AimConstraint.inTargetWeight = nAttr.create("targetWeight", "tw",
                                                    om2.MFnNumericData.kDouble,
                                                    1.0)
        INPUT_ATTR(nAttr)

        AimConstraint.inConstWMtx = mAttr.create(
            "constraintWorldMatrix", "cwmtx", om2.MFnMatrixAttribute.kDouble)
        INPUT_ATTR(mAttr)

        AimConstraint.inConstParInvMtx = mAttr.create(
            "constraintParentInverseMatrix", "cpim",
            om2.MFnMatrixAttribute.kDouble)
        INPUT_ATTR(mAttr)

        jntOriX = uAttr.create("constraintJointOrientX", "cjorx",
                               om2.MFnUnitAttribute.kAngle, 0.0)
        jntOriY = uAttr.create("constraintJointOrientY", "cjory",
                               om2.MFnUnitAttribute.kAngle, 0.0)
        jntOriZ = uAttr.create("constraintJointOrientZ", "cjorz",
                               om2.MFnUnitAttribute.kAngle, 0.0)
        AimConstraint.inConstJntOri = nAttr.create("constraintJointOrient",
                                                   "cjor", jntOriX, jntOriY,
                                                   jntOriZ)
        INPUT_ATTR(nAttr)

        AimConstraint.inConstRotOrder = eAttr.create("constraintRotateOrder",
                                                     "cro", 0)
        eAttr.addField("xyz", 0)
        eAttr.addField("yzx", 1)
        eAttr.addField("zxy", 2)
        eAttr.addField("xzy", 3)
        eAttr.addField("yxz", 4)
        eAttr.addField("zyx", 5)
        INPUT_ATTR(eAttr)

        outConstraintX = uAttr.create("constraintX", "cx",
                                      om2.MFnUnitAttribute.kAngle, 0.0)
        outConstraintY = uAttr.create("constraintY", "cy",
                                      om2.MFnUnitAttribute.kAngle, 0.0)
        outConstraintZ = uAttr.create("constraintZ", "cz",
                                      om2.MFnUnitAttribute.kAngle, 0.0)
        AimConstraint.outConstraint = nAttr.create("constraint", "const",
                                                   outConstraintX,
                                                   outConstraintY,
                                                   outConstraintZ)
        OUTPUT_ATTR(nAttr)

        AimConstraint.addAttribute(AimConstraint.inUpVecType)
        AimConstraint.addAttribute(AimConstraint.inOffset)
        AimConstraint.addAttribute(AimConstraint.inWorldUpVector)
        AimConstraint.addAttribute(AimConstraint.inWorldUpMtx)
        AimConstraint.addAttribute(AimConstraint.inAngleUp)
        AimConstraint.addAttribute(AimConstraint.inTargetWMtx)
        AimConstraint.addAttribute(AimConstraint.inTargetWeight)
        AimConstraint.addAttribute(AimConstraint.inConstWMtx)
        AimConstraint.addAttribute(AimConstraint.inConstParInvMtx)
        AimConstraint.addAttribute(AimConstraint.inConstJntOri)
        AimConstraint.addAttribute(AimConstraint.inConstRotOrder)
        AimConstraint.addAttribute(AimConstraint.outConstraint)
        AimConstraint.attributeAffects(AimConstraint.inUpVecType,
                                       AimConstraint.outConstraint)
        AimConstraint.attributeAffects(AimConstraint.inOffset,
                                       AimConstraint.outConstraint)
        AimConstraint.attributeAffects(AimConstraint.inWorldUpVector,
                                       AimConstraint.outConstraint)
        AimConstraint.attributeAffects(AimConstraint.inWorldUpMtx,
                                       AimConstraint.outConstraint)
        AimConstraint.attributeAffects(AimConstraint.inAngleUp,
                                       AimConstraint.outConstraint)
        AimConstraint.attributeAffects(AimConstraint.inTargetWMtx,
                                       AimConstraint.outConstraint)
        AimConstraint.attributeAffects(AimConstraint.inTargetWeight,
                                       AimConstraint.outConstraint)
        AimConstraint.attributeAffects(AimConstraint.inConstWMtx,
                                       AimConstraint.outConstraint)
        AimConstraint.attributeAffects(AimConstraint.inConstParInvMtx,
                                       AimConstraint.outConstraint)
        AimConstraint.attributeAffects(AimConstraint.inConstJntOri,
                                       AimConstraint.outConstraint)
        AimConstraint.attributeAffects(AimConstraint.inConstRotOrder,
                                       AimConstraint.outConstraint)

    def compute(self, plug, dataBlock):
        """
        Node computation method:
            * plug is a connection point related to one of our node attributes (either an input or an output).
            * dataBlock contains the data on which we will base our computations.
        """
        # pylint: disable=no-self-use
        if plug != AimConstraint.outConstraint:
            return om2.kUnknownParameter

        upVecType = dataBlock.inputValue(AimConstraint.inUpVecType).asShort()
        eOffset = om2.MEulerRotation(
            dataBlock.inputValue(AimConstraint.inOffset).asDouble3())
        qOffset = eOffset.asQuaternion()
        mTargetW = dataBlock.inputValue(AimConstraint.inTargetWMtx).asMatrix()
        targetWeight = dataBlock.inputValue(
            AimConstraint.inTargetWeight).asDouble()
        mConstW = dataBlock.inputValue(AimConstraint.inConstWMtx).asMatrix()
        mConstParInv = dataBlock.inputValue(
            AimConstraint.inConstParInvMtx).asMatrix()
        eConstJntOri = om2.MEulerRotation(
            dataBlock.inputValue(AimConstraint.inConstJntOri).asDouble3())
        qConstJntOri = eConstJntOri.asQuaternion()
        constRotOrder = dataBlock.inputValue(
            AimConstraint.inConstRotOrder).asShort()

        vTarget = om2.MVector(mTargetW[12], mTargetW[13], mTargetW[14])
        vConst = om2.MVector(mConstW[12], mConstW[13], mConstW[14])
        mtxFn = om2.MTransformationMatrix(mConstParInv)
        qConstParInv = mtxFn.rotation(asQuaternion=True)

        primAxis = om2.MVector.kXaxisVector
        secAxis = om2.MVector.kYaxisVector
        qAimConst = om2.MQuaternion()

        nAim = vTarget - vConst
        nAim.normalize()
        qAim = om2.MQuaternion(primAxis, nAim)
        qAimConst *= qAim

        if upVecType != 0:
            if upVecType == 1:
                # World Up
                nWorldUp = om2.MVector(
                    dataBlock.inputValue(
                        AimConstraint.inWorldUpVector).asFloat3())
                nWorldUp.normalize()
                vUp = nWorldUp
            elif upVecType == 2:
                # Object Up
                mWorldUp = dataBlock.inputValue(
                    AimConstraint.inWorldUpMtx).asMatrix()
                vWorldUp = om2.MVector(mWorldUp[12], mWorldUp[13],
                                       mWorldUp[14])
                vUp = vWorldUp - vConst
            elif upVecType == 3:
                # Angle Up
                angleUp = dataBlock.inputValue(
                    AimConstraint.inAngleUp).asAngle().asRadians()
                qTwist = om2.MQuaternion(angleUp, nAim)
                vUp = secAxis.rotateBy(qTwist)
            nNormal = vUp - ((vUp * nAim) * nAim)
            nNormal.normalize()

            nUp = secAxis.rotateBy(qAim)
            angle = nUp.angle(nNormal)
            qNormal = om2.MQuaternion(angle, nAim)
            if not nNormal.isEquivalent(nUp.rotateBy(qNormal), 1.0e-5):
                angle = 2.0 * math.pi - angle
                qNormal = om2.MQuaternion(angle, nAim)
            qAimConst *= qNormal

        qResult = om2.MQuaternion()
        qResult *= qOffset.invertIt()
        qResult *= qAimConst
        qResult *= qConstParInv
        qResult *= qConstJntOri.invertIt()
        eResult = qResult.asEulerRotation()
        eResult.reorderIt(constRotOrder)
        eResult *= targetWeight
        vResult = eResult.asVector()
        outConstraintHandle = dataBlock.outputValue(
            AimConstraint.outConstraint)
        outConstraintHandle.setMVector(vResult)
        outConstraintHandle.setClean()
예제 #20
0
class EulerMath(om2.MPxNode):
    """ Main class of gfUtilEulerMath node. """

    kNodeName = ""
    kNodeClassify = ""
    kNodeID = ""

    inOperation = om2.MObject()
    inEuler1 = om2.MObject()
    inEuler1X = om2.MObject()
    inEuler1Y = om2.MObject()
    inEuler1Z = om2.MObject()
    inEuler1RotOrder = om2.MObject()
    inEuler2 = om2.MObject()
    inEuler2X = om2.MObject()
    inEuler2Y = om2.MObject()
    inEuler2Z = om2.MObject()
    inEuler2RotOrder = om2.MObject()
    inResRotOrder = om2.MObject()
    outEuler = om2.MObject()
    outEulerX = om2.MObject()
    outEulerY = om2.MObject()
    outEulerZ = om2.MObject()

    def __init__(self):
        """ Constructor. """
        om2.MPxNode.__init__(self)

    @staticmethod
    def creator():
        """ Maya creator function. """
        return EulerMath()

    @staticmethod
    def initialize():
        """
        Defines the set of attributes for this node. The attributes declared in this function are assigned
        as static members to EulerMath class. Instances of EulerMath will use these attributes to create plugs
        for use in the compute() method.
        """
        eAttr = om2.MFnEnumAttribute()
        uAttr = om2.MFnUnitAttribute()
        nAttr = om2.MFnNumericAttribute()

        EulerMath.inOperation = eAttr.create("operation", "operation", 0)
        eAttr.addField("No Operation", 0)
        eAttr.addField("Add", 1)
        eAttr.addField("Subtract", 2)
        eAttr.addField("Multiply", 3)
        INPUT_ATTR(eAttr)

        EulerMath.inEuler1X = uAttr.create("euler1X", "e1x",
                                           om2.MFnUnitAttribute.kAngle, 0.0)
        EulerMath.inEuler1Y = uAttr.create("euler1Y", "e1y",
                                           om2.MFnUnitAttribute.kAngle, 0.0)
        EulerMath.inEuler1Z = uAttr.create("euler1Z", "e1z",
                                           om2.MFnUnitAttribute.kAngle, 0.0)
        EulerMath.inEuler1 = nAttr.create("euler1", "e1", EulerMath.inEuler1X,
                                          EulerMath.inEuler1Y,
                                          EulerMath.inEuler1Z)
        INPUT_ATTR(nAttr)

        EulerMath.inEuler1RotOrder = eAttr.create("rotateOrderEuler1", "roe1",
                                                  0)
        eAttr.addField("xyz", 0)
        eAttr.addField("yzx", 1)
        eAttr.addField("zxy", 2)
        eAttr.addField("xzy", 3)
        eAttr.addField("yxz", 4)
        eAttr.addField("zyx", 5)
        INPUT_ATTR(eAttr)

        EulerMath.inEuler2X = uAttr.create("euler2X", "e2x",
                                           om2.MFnUnitAttribute.kAngle, 0.0)
        EulerMath.inEuler2Y = uAttr.create("euler2Y", "e2y",
                                           om2.MFnUnitAttribute.kAngle, 0.0)
        EulerMath.inEuler2Z = uAttr.create("euler2Z", "e2z",
                                           om2.MFnUnitAttribute.kAngle, 0.0)
        EulerMath.inEuler2 = nAttr.create("euler2", "e2", EulerMath.inEuler2X,
                                          EulerMath.inEuler2Y,
                                          EulerMath.inEuler2Z)
        INPUT_ATTR(nAttr)

        EulerMath.inEuler2RotOrder = eAttr.create("rotateOrderEuler2", "roe2",
                                                  0)
        eAttr.addField("xyz", 0)
        eAttr.addField("yzx", 1)
        eAttr.addField("zxy", 2)
        eAttr.addField("xzy", 3)
        eAttr.addField("yxz", 4)
        eAttr.addField("zyx", 5)
        INPUT_ATTR(eAttr)

        EulerMath.outEulerX = uAttr.create("outEulerX", "oex",
                                           om2.MFnUnitAttribute.kAngle, 0.0)
        EulerMath.outEulerY = uAttr.create("outEulerY", "oey",
                                           om2.MFnUnitAttribute.kAngle, 0.0)
        EulerMath.outEulerZ = uAttr.create("outEulerZ", "oez",
                                           om2.MFnUnitAttribute.kAngle, 0.0)
        EulerMath.outEuler = nAttr.create("outEuler", "oe",
                                          EulerMath.outEulerX,
                                          EulerMath.outEulerY,
                                          EulerMath.outEulerZ)
        OUTPUT_ATTR(nAttr)

        EulerMath.inResRotOrder = eAttr.create("rotateOrderOutEuler", "rooe",
                                               0)
        eAttr.addField("xyz", 0)
        eAttr.addField("yzx", 1)
        eAttr.addField("zxy", 2)
        eAttr.addField("xzy", 3)
        eAttr.addField("yxz", 4)
        eAttr.addField("zyx", 5)
        INPUT_ATTR(eAttr)

        EulerMath.addAttribute(EulerMath.inOperation)
        EulerMath.addAttribute(EulerMath.inEuler1)
        EulerMath.addAttribute(EulerMath.inEuler1RotOrder)
        EulerMath.addAttribute(EulerMath.inEuler2)
        EulerMath.addAttribute(EulerMath.inEuler2RotOrder)
        EulerMath.addAttribute(EulerMath.inResRotOrder)
        EulerMath.addAttribute(EulerMath.outEuler)
        EulerMath.attributeAffects(EulerMath.inOperation, EulerMath.outEuler)
        EulerMath.attributeAffects(EulerMath.inEuler1, EulerMath.outEuler)
        EulerMath.attributeAffects(EulerMath.inEuler1RotOrder,
                                   EulerMath.outEuler)
        EulerMath.attributeAffects(EulerMath.inEuler2, EulerMath.outEuler)
        EulerMath.attributeAffects(EulerMath.inEuler2RotOrder,
                                   EulerMath.outEuler)
        EulerMath.attributeAffects(EulerMath.inResRotOrder, EulerMath.outEuler)

    def compute(self, plug, dataBlock):
        """
        Node computation method:
            * plug is a connection point related to one of our node attributes (either an input or an output).
            * dataBlock contains the data on which we will base our computations.
        """
        # pylint: disable=no-self-use
        if (plug != EulerMath.outEuler and plug != EulerMath.outEulerX
                and plug != EulerMath.outEulerY
                and plug != EulerMath.outEulerZ):
            return om2.kUnknownParameter

        operation = dataBlock.inputValue(EulerMath.inOperation).asShort()
        euler1 = dataBlock.inputValue(EulerMath.inEuler1).asDouble3()
        euler2 = dataBlock.inputValue(EulerMath.inEuler2).asDouble3()
        euler1RotOrder = dataBlock.inputValue(
            EulerMath.inEuler1RotOrder).asShort()
        euler2RotOrder = dataBlock.inputValue(
            EulerMath.inEuler2RotOrder).asShort()
        outRotOrder = dataBlock.inputValue(EulerMath.inResRotOrder).asShort()

        eEuler1 = om2.MEulerRotation(euler1, euler1RotOrder)
        eEuler2 = om2.MEulerRotation(euler2, euler2RotOrder)

        outEulerHdle = dataBlock.outputValue(EulerMath.outEuler)

        if operation == 0:
            eEuler1.reorderIt(outRotOrder)
            outEulerHdle.set3Double(eEuler1.x, eEuler1.y, eEuler1.z)
        elif operation == 1:
            eEuler1.reorderIt(outRotOrder)
            eEuler2.reorderIt(outRotOrder)
            eOutEuler = eEuler1 + eEuler2
            outEulerHdle.set3Double(eOutEuler.x, eOutEuler.y, eOutEuler.z)
        elif operation == 2:
            eEuler1.reorderIt(outRotOrder)
            eEuler2.reorderIt(outRotOrder)
            eOutEuler = eEuler1 - eEuler2
            outEulerHdle.set3Double(eOutEuler.x, eOutEuler.y, eOutEuler.z)
        elif operation == 3:
            eEuler1.reorderIt(outRotOrder)
            eEuler2.reorderIt(outRotOrder)
            eOutEuler = eEuler1 * eEuler2
            outEulerHdle.set3Double(eOutEuler.x, eOutEuler.y, eOutEuler.z)

        outEulerHdle.setClean()
예제 #21
0
class HelperJoint(om2.MPxNode):
    """ Main class of gfRigHelperJoint node. """

    kNodeName = ""
    kNodeClassify = ""
    kNodeID = ""

    inSource = om2.MObject()
    inSourceParent = om2.MObject()
    inParInvMtx = om2.MObject()
    inSourceParSca = om2.MObject()
    inPositionOffset = om2.MObject()
    inRotationOffset = om2.MObject()
    inRotAngle = om2.MObject()
    inRestAngle = om2.MObject()
    inRotInterp = om2.MObject()
    inPosMult = om2.MObject()
    inNegMult = om2.MObject()
    inTargetList = om2.MObject()
    outTransform = om2.MObject()

    def __init__(self):
        """ Constructor. """
        om2.MPxNode.__init__(self)

    @staticmethod
    def creator():
        """ Maya creator function. """
        return HelperJoint()

    @staticmethod
    def initialize():
        """
        Defines the set of attributes for this node. The attributes declared in this function are assigned
        as static members to HelperJoint class. Instances of HelperJoint will use these attributes to create plugs
        for use in the compute() method.
        """
        nAttr = om2.MFnNumericAttribute()
        mAttr = om2.MFnMatrixAttribute()
        uAttr = om2.MFnUnitAttribute()
        cAttr = om2.MFnCompoundAttribute()

        HelperJoint.inSource = mAttr.create("source", "s", om2.MFnMatrixAttribute.kDouble)
        INPUT_ATTR(mAttr)

        HelperJoint.inSourceParent = mAttr.create("sourceParent", "sp", om2.MFnMatrixAttribute.kDouble)
        INPUT_ATTR(mAttr)

        HelperJoint.inParInvMtx = mAttr.create("targetParentInverseMatrix", "tpimtx", om2.MFnMatrixAttribute.kDouble)
        INPUT_ATTR(mAttr)

        HelperJoint.inSourceParSca = nAttr.createPoint("sourceParentScale", "spsca")
        nAttr.default = (1.0, 1.0, 1.0)
        INPUT_ATTR(nAttr)

        HelperJoint.inPositionOffset = nAttr.createPoint("positionOffset", "posoff")
        INPUT_ATTR(nAttr)

        rotOffX = uAttr.create("rotationOffsetX", "rotoffx", om2.MFnUnitAttribute.kAngle, 0.0)
        rotOffY = uAttr.create("rotationOffsetY", "rotoffy", om2.MFnUnitAttribute.kAngle, 0.0)
        rotOffZ = uAttr.create("rotationOffsetZ", "rotoffz", om2.MFnUnitAttribute.kAngle, 0.0)
        HelperJoint.inRotationOffset = nAttr.create("rotationOffset", "rotoff", rotOffX, rotOffY, rotOffZ)
        INPUT_ATTR(nAttr)

        HelperJoint.inRotAngle = uAttr.create("rotationAngle", "rotangle", om2.MFnUnitAttribute.kAngle, 0.0)
        INPUT_ATTR(uAttr)

        HelperJoint.inRestAngle = uAttr.create("restAngle", "rang", om2.MFnUnitAttribute.kAngle, 0.0)
        INPUT_ATTR(uAttr)

        HelperJoint.inRotInterp = nAttr.create("rotationInterpolation", "roti", om2.MFnNumericData.kFloat, 0.5)
        nAttr.setMin(0.0)
        nAttr.setMax(1.0)
        INPUT_ATTR(nAttr)

        HelperJoint.inPosMult = nAttr.create("positiveMultiplier", "posmult", om2.MFnNumericData.kFloat, 0.0)
        INPUT_ATTR(nAttr)

        HelperJoint.inNegMult = nAttr.create("negativeMultiplier", "negmult", om2.MFnNumericData.kFloat, 0.0)
        INPUT_ATTR(nAttr)

        HelperJoint.inTargetList = cAttr.create("targetList", "tgtl")
        cAttr.addChild(HelperJoint.inPositionOffset)
        cAttr.addChild(HelperJoint.inRotationOffset)
        cAttr.addChild(HelperJoint.inRotAngle)
        cAttr.addChild(HelperJoint.inRestAngle)
        cAttr.addChild(HelperJoint.inRotInterp)
        cAttr.addChild(HelperJoint.inPosMult)
        cAttr.addChild(HelperJoint.inNegMult)
        cAttr.array = True

        HelperJoint.outTransform = mAttr.create("outTransform", "outtrans", om2.MFnMatrixAttribute.kDouble)
        mAttr.array = True
        OUTPUT_ATTR(mAttr)

        HelperJoint.addAttribute(HelperJoint.inSource)
        HelperJoint.addAttribute(HelperJoint.inSourceParent)
        HelperJoint.addAttribute(HelperJoint.inParInvMtx)
        HelperJoint.addAttribute(HelperJoint.inSourceParSca)
        HelperJoint.addAttribute(HelperJoint.inTargetList)
        HelperJoint.addAttribute(HelperJoint.outTransform)
        HelperJoint.attributeAffects(HelperJoint.inSource, HelperJoint.outTransform)
        HelperJoint.attributeAffects(HelperJoint.inSourceParent, HelperJoint.outTransform)
        HelperJoint.attributeAffects(HelperJoint.inParInvMtx, HelperJoint.outTransform)
        HelperJoint.attributeAffects(HelperJoint.inSourceParSca, HelperJoint.outTransform)
        HelperJoint.attributeAffects(HelperJoint.inPositionOffset, HelperJoint.outTransform)
        HelperJoint.attributeAffects(HelperJoint.inRotationOffset, HelperJoint.outTransform)
        HelperJoint.attributeAffects(HelperJoint.inRotAngle, HelperJoint.outTransform)
        HelperJoint.attributeAffects(HelperJoint.inRestAngle, HelperJoint.outTransform)
        HelperJoint.attributeAffects(HelperJoint.inRotInterp, HelperJoint.outTransform)
        HelperJoint.attributeAffects(HelperJoint.inPosMult, HelperJoint.outTransform)
        HelperJoint.attributeAffects(HelperJoint.inNegMult, HelperJoint.outTransform)

    def compute(self, plug, dataBlock):
        """
        Node computation method:
            * plug is a connection point related to one of our node attributes (either an input or an output).
            * dataBlock contains the data on which we will base our computations.
        """
        # pylint: disable=no-self-use
        if plug != HelperJoint.outTransform:
            return om2.kUnknownParameter

        mSource = dataBlock.inputValue(HelperJoint.inSource).asMatrix()
        mtxFn = om2.MTransformationMatrix(mSource)
        mtxFn.setScale([1.0, 1.0, 1.0], om2.MSpace.kTransform)
        mSource = mtxFn.asMatrix()
        mSourceParent = dataBlock.inputValue(HelperJoint.inSourceParent).asMatrix()

        mParInv = dataBlock.inputValue(HelperJoint.inParInvMtx).asMatrix()
        sourceParSca = dataBlock.inputValue(HelperJoint.inSourceParSca).asFloat3()
        mtxFn = om2.MTransformationMatrix()
        mtxFn.scaleBy(sourceParSca, om2.MSpace.kTransform)
        mInvSca = mtxFn.asMatrix()
        targetListHandle = dataBlock.inputArrayValue(HelperJoint.inTargetList)

        outputList = []

        for i in range(len(targetListHandle)):
            targetListHandle.jumpToLogicalElement(i)
            targetHandle = targetListHandle.inputValue()
            vPosOffset = om2.MVector(targetHandle.child(HelperJoint.inPositionOffset).asFloat3())
            eRotOffset = om2.MEulerRotation(targetHandle.child(HelperJoint.inRotationOffset).asDouble3())
            angle = targetHandle.child(HelperJoint.inRotAngle).asAngle().asRadians()
            restAngle = targetHandle.child(HelperJoint.inRestAngle).asAngle().asRadians()
            rotInterp = targetHandle.child(HelperJoint.inRotInterp).asFloat()
            posMult = targetHandle.child(HelperJoint.inPosMult).asFloat()
            negMult = targetHandle.child(HelperJoint.inNegMult).asFloat()

            mPositionOffset = om2.MMatrix()
            mPositionOffset[12] = vPosOffset.x
            mPositionOffset[13] = vPosOffset.y
            mPositionOffset[14] = vPosOffset.z
            multTranslation = abs(angle) * posMult
            if angle < restAngle:
                multTranslation = abs(angle) * negMult
            vPosOffset.normalize()
            mMultiplier = om2.MMatrix()
            mMultiplier[12] = vPosOffset.x * multTranslation
            mMultiplier[13] = vPosOffset.y * multTranslation
            mMultiplier[14] = vPosOffset.z * multTranslation
            mTargetPoint = mMultiplier * mPositionOffset * mSource
            mTargetOrient = mInvSca * (mSource * (1.0 - rotInterp)) + (mSourceParent * rotInterp)

            vResultPos = om2.MVector(mTargetPoint[12], mTargetPoint[13], mTargetPoint[14])
            mtxFn = om2.MTransformationMatrix(mTargetOrient)
            eResultOri = eRotOffset + mtxFn.rotation(asQuaternion=False)
            mtxFn = om2.MTransformationMatrix()
            mtxFn.setRotation(eResultOri)
            mtxFn.setTranslation(vResultPos, om2.MSpace.kTransform)
            mResult = mtxFn.asMatrix() * mParInv
            outputList.append(mResult)

        outTransHandle = dataBlock.outputArrayValue(HelperJoint.outTransform)
        for i in range(len(outTransHandle)):
            outTransHandle.jumpToLogicalElement(i)
            resultHandle = outTransHandle.outputValue()
            if i < len(outTransHandle) and i < len(outputList):
                resultHandle.setMMatrix(outputList[i])
            else:
                resultHandle.setMMatrix(om2.MMatrix.kIdentity)
예제 #22
0
class DebugVector(omui2.MPxLocatorNode):
    """ Main class of gfDebugVector node. """

    kNodeName = ""
    kNodeClassify = ""
    kNodeRegistrantID = ""
    kNodeID = ""

    inLineWidth = om2.MObject()
    inColor = om2.MObject()
    inRadius = om2.MObject()
    inTipSize = om2.MObject()
    inSubdivisions = om2.MObject()
    inXRay = om2.MObject()
    inDashed = om2.MObject()
    inOperation = om2.MObject()
    inVec1 = om2.MObject()
    inVec2 = om2.MObject()
    inNormalize = om2.MObject()
    outVector = om2.MObject()

    def __init__(self):
        """ Constructor. """
        omui2.MPxLocatorNode.__init__(self)

    def postConstructor(self):
        """ Post Constructor. """
        thisMob = self.thisMObject()
        om2.MFnDependencyNode(thisMob).setName("%sShape#" %
                                               DebugVector.kNodeName)

    @staticmethod
    def creator():
        """ Maya creator function. """
        return DebugVector()

    @staticmethod
    def initialize():
        """
        Defines the set of attributes for this node. The attributes declared in this function are assigned
        as static members to DebugVector class. Instances of DebugVector will use these attributes to create plugs
        for use in the compute() method.
        """
        eAttr = om2.MFnEnumAttribute()
        nAttr = om2.MFnNumericAttribute()

        DebugVector.inLineWidth = nAttr.create("lineWidth", "lw",
                                               om2.MFnNumericData.kFloat, 3.0)
        nAttr.setMin(1.0)
        nAttr.setSoftMax(5.0)
        INPUT_ATTR(nAttr)

        DebugVector.inColor = nAttr.createColor("color", "color")
        nAttr.default = (1.0, 1.0, 0.0)
        INPUT_ATTR(nAttr)

        DebugVector.inTipSize = nAttr.create("tipSize", "tipSize",
                                             om2.MFnNumericData.kFloat, 0.1)
        nAttr.setMin(0.1)
        nAttr.setMax(1.0)
        INPUT_ATTR(nAttr)

        DebugVector.inSubdivisions = nAttr.create("subdivisions", "subd",
                                                  om2.MFnNumericData.kInt, 4)
        nAttr.setMin(2)
        nAttr.setMax(12)
        INPUT_ATTR(nAttr)

        DebugVector.inRadius = nAttr.create("radius", "radius",
                                            om2.MFnNumericData.kFloat, 1.0)
        nAttr.setMin(0.0)
        nAttr.setSoftMax(5.0)
        INPUT_ATTR(nAttr)

        DebugVector.inXRay = nAttr.create("XRay", "xray",
                                          om2.MFnNumericData.kBoolean, False)
        INPUT_ATTR(nAttr)

        DebugVector.inDashed = nAttr.create("dashed", "dashed",
                                            om2.MFnNumericData.kBoolean, False)
        INPUT_ATTR(nAttr)

        DebugVector.inOperation = eAttr.create("operation", "op", 0)
        eAttr.addField("No Operation", 0)
        eAttr.addField("Add", 1)
        eAttr.addField("Subtract", 2)
        eAttr.addField("Cross Product", 3)
        eAttr.addField("Vector Project", 4)
        INPUT_ATTR(eAttr)

        DebugVector.inVec1 = nAttr.createPoint("vector1", "v1")
        INPUT_ATTR(nAttr)

        DebugVector.inVec2 = nAttr.createPoint("vector2", "v2")
        INPUT_ATTR(nAttr)

        DebugVector.inNormalize = nAttr.create("normalizeOutput", "no",
                                               om2.MFnNumericData.kBoolean,
                                               False)
        INPUT_ATTR(nAttr)

        DebugVector.outVector = nAttr.createPoint("outVector", "ov")
        OUTPUT_ATTR(nAttr)

        DebugVector.addAttribute(DebugVector.inLineWidth)
        DebugVector.addAttribute(DebugVector.inColor)
        DebugVector.addAttribute(DebugVector.inTipSize)
        DebugVector.addAttribute(DebugVector.inSubdivisions)
        DebugVector.addAttribute(DebugVector.inRadius)
        DebugVector.addAttribute(DebugVector.inXRay)
        DebugVector.addAttribute(DebugVector.inDashed)
        DebugVector.addAttribute(DebugVector.inOperation)
        DebugVector.addAttribute(DebugVector.inVec1)
        DebugVector.addAttribute(DebugVector.inVec2)
        DebugVector.addAttribute(DebugVector.inNormalize)
        DebugVector.addAttribute(DebugVector.outVector)
        DebugVector.attributeAffects(DebugVector.inOperation,
                                     DebugVector.outVector)
        DebugVector.attributeAffects(DebugVector.inVec1, DebugVector.outVector)
        DebugVector.attributeAffects(DebugVector.inVec2, DebugVector.outVector)
        DebugVector.attributeAffects(DebugVector.inNormalize,
                                     DebugVector.outVector)

    @staticmethod
    def drawArrow(startPnt,
                  endPnt,
                  size,
                  radius,
                  subd,
                  lineW,
                  vp2=False,
                  glFT=None,
                  lineList=None):
        """Draw an aim arrow

        Args:
            startPnt (MFloatVector): The base of the vector.
            endPnt (MFloatVector): The end of the vector.
            size (float): The size of the arrow.
            radius (float): The radius of the arrow.
            subd (int): The number of subdivisions of the arrow.
            lineW (float): The width of the lines.
            vp2 (bool: False [Optional]): Draw inside of drawing override for viewport 2.0.
            glFT (instance: None [Optional]): The GL Function Table to draw in viewport 1.0.
            lineList (MPointArray: None [Optional]): The line list to append for drawing override.
        """
        tipSize = 1.0 - size
        step = 2.0 * math.pi / subd
        vAim = endPnt - startPnt
        vBaseOrigin = vAim * tipSize
        nAim = vAim.normal()
        nWorld = om2.MFloatVector(0.0, 1.0, 0.0)
        nBinormal = nWorld ^ nAim
        nBinormal.normalize()
        nNormal = nAim ^ nBinormal
        nNormal.normalize()
        aim = [
            nAim.x, nAim.y, nAim.z, 0.0, nNormal.x, nNormal.y, nNormal.z, 0.0,
            nBinormal.x, nBinormal.y, nBinormal.z, 0.0, startPnt.x, startPnt.y,
            startPnt.z, 1.0
        ]
        mBase = om2.MMatrix(aim)
        mOrigin = om2.MMatrix()
        mOrigin[12] = vBaseOrigin.length()
        mBaseOrigin = mOrigin * mBase
        if vp2:
            lineList.append(om2.MPoint(startPnt))
            lineList.append(om2.MPoint(endPnt))
        else:
            glFT.glLineWidth(lineW)
            glFT.glBegin(omr1.MGL_LINES)
            glFT.glVertex3f(startPnt.x, startPnt.y, startPnt.z)
            glFT.glVertex3f(endPnt.x, endPnt.y, endPnt.z)
            glFT.glEnd()
        for i in range(subd):
            theta = step * i
            mPoint = om2.MMatrix()
            mPoint[13] = math.cos(theta) * radius
            mPoint[14] = math.sin(theta) * radius
            mArrow = mPoint * mBaseOrigin
            if vp2:
                lineList.append(
                    om2.MPoint(mBaseOrigin[12], mBaseOrigin[13],
                               mBaseOrigin[14]))
                lineList.append(om2.MPoint(mArrow[12], mArrow[13], mArrow[14]))
                lineList.append(om2.MPoint(mArrow[12], mArrow[13], mArrow[14]))
                lineList.append(om2.MPoint(endPnt))
            else:
                glFT.glBegin(omr1.MGL_LINES)
                glFT.glVertex3f(mBaseOrigin[12], mBaseOrigin[13],
                                mBaseOrigin[14])
                glFT.glVertex3f(mArrow[12], mArrow[13], mArrow[14])
                glFT.glVertex3f(mArrow[12], mArrow[13], mArrow[14])
                glFT.glVertex3f(endPnt.x, endPnt.y, endPnt.z)
                glFT.glEnd()
        return None

    def compute(self, plug, dataBlock):
        """
        Node computation method:
            * plug is a connection point related to one of our node attributes (either an input or an output).
            * dataBlock contains the data on which we will base our computations.
        """
        if plug == DebugVector.outVector:
            operation = dataBlock.inputValue(DebugVector.inOperation).asShort()
            vVector1 = dataBlock.inputValue(DebugVector.inVec1).asFloatVector()
            vVector2 = dataBlock.inputValue(DebugVector.inVec2).asFloatVector()
            normalize = dataBlock.inputValue(DebugVector.inNormalize).asBool()

            if operation == 0:
                vEnd = vVector1
            elif operation == 1:
                vFinal = vVector1 + vVector2
                vEnd = vFinal
            elif operation == 2:
                vFinal = vVector1 - vVector2
                vEnd = vFinal
            elif operation == 3:
                vFinal = vVector1 ^ vVector2
                vEnd = vFinal
            elif operation == 4:
                if vVector2.length() < 0.001:
                    vFinal = om2.MFloatVector(0.0, 0.0, 0.0)
                else:
                    vFinal = ((vVector1 * vVector2) /
                              math.pow(vVector2.length(), 2.0)) * vVector2
                vEnd = vFinal

            if normalize:
                vEnd.normalize()

            outVectorHandle = dataBlock.outputValue(DebugVector.outVector)
            outVectorHandle.setMFloatVector(vEnd)
            outVectorHandle.setClean()

    def draw(self, view, path, style, status):
        """
        Draw custom geometry in the viewport using OpenGL calls.
            * view [M3dView] is a 3D view that is being drawn into.
            * path [MDagPath] to the parent (transform node) of this locator in the DAG.  To obtain the locator shape node,
                use MDagPath::extendToShape() if there is only one shape node under the transform or
                MDagPath::extendToShapeDirectlyBelow(unsigned int index) with the shape index if there are multiple
                shapes under the transform.
            * style [M3dView.DisplayStyle] is the style to draw object in.
            * status [M3dView.DisplayStatus] is the selection status of the object.
        """
        # pylint: disable=unused-argument

        thisMob = self.thisMObject()
        lineW = om2.MPlug(thisMob, DebugVector.inLineWidth).asFloat()
        color = om2.MPlug(thisMob,
                          DebugVector.inColor).asMDataHandle().asFloatVector()
        tipSize = om2.MPlug(thisMob, DebugVector.inTipSize).asFloat()
        subd = om2.MPlug(thisMob, DebugVector.inSubdivisions).asInt()
        radius = om2.MPlug(thisMob, DebugVector.inRadius).asFloat()
        xray = om2.MPlug(thisMob, DebugVector.inXRay).asBool()
        dashed = om2.MPlug(thisMob, DebugVector.inDashed).asBool()

        operation = om2.MPlug(thisMob, DebugVector.inOperation).asShort()
        vVector1 = om2.MPlug(
            thisMob, DebugVector.inVec1).asMDataHandle().asFloatVector()
        vVector2 = om2.MPlug(
            thisMob, DebugVector.inVec2).asMDataHandle().asFloatVector()
        normalize = om2.MPlug(thisMob, DebugVector.inNormalize).asBool()

        if operation == 0:
            vEnd = vVector1
        elif operation == 1:
            vFinal = vVector1 + vVector2
            vEnd = vFinal
        elif operation == 2:
            vFinal = vVector1 - vVector2
            vEnd = vFinal
        elif operation == 3:
            vFinal = vVector1 ^ vVector2
            vEnd = vFinal
        elif operation == 4:
            if vVector2.length() < 0.001:
                vFinal = om2.MFloatVector(0.0, 0.0, 0.0)
            else:
                vFinal = ((vVector1 * vVector2) /
                          math.pow(vVector2.length(), 2.0)) * vVector2
            vEnd = vFinal

        vStart = om2.MFloatVector()
        if normalize:
            vEnd.normalize()

        view.beginGL()

        glRenderer = omr1.MHardwareRenderer.theRenderer()
        glFT = glRenderer.glFunctionTable()

        glFT.glPushAttrib(omr1.MGL_CURRENT_BIT)
        glFT.glDisable(omr1.MGL_CULL_FACE)
        if dashed:
            glFT.glEnable(omr1.MGL_LINE_STIPPLE)
        if xray:
            glFT.glEnable(omr1.MGL_DEPTH_TEST)
            glFT.glClear(omr1.MGL_DEPTH_BUFFER_BIT)

        if status == omui2.M3dView.kActive:
            glFT.glColor3f(0.3, 1.0, 1.0)
        elif status == omui2.M3dView.kLead:
            glFT.glColor3f(1.0, 1.0, 1.0)
        elif status == omui2.M3dView.kDormant:
            glFT.glColor3f(color.x, color.y, color.z)

        if dashed:
            glFT.glLineStipple(1, 0x00FF)
        DebugVector.drawArrow(vStart,
                              vEnd,
                              tipSize,
                              radius,
                              subd,
                              lineW,
                              glFT=glFT)

        if dashed:
            glFT.glDisable(omr1.MGL_LINE_STIPPLE)
        if xray:
            glFT.glDisable(omr1.MGL_DEPTH_TEST)
        glFT.glPopAttrib()
        glFT.glLineWidth(1.0)

        view.endGL()
예제 #23
0
class FindParamFromLength(om2.MPxNode):
    """ Main class of gfFindParamFromLength node. """

    kNodeName = ""
    kNodeClassify = ""
    kNodeID = ""

    inCurve = om2.MObject()
    inArcLength = om2.MObject()
    outParam = om2.MObject()

    def __init__(self):
        """ Constructor. """
        om2.MPxNode.__init__(self)

    @staticmethod
    def creator():
        """ Maya creator function. """
        return FindParamFromLength()

    @staticmethod
    def initialize():
        """
        Defines the set of attributes for this node. The attributes declared in this function are assigned
        as static members to DistributeAlongSurface class. Instances of DistributeAlongSurface will use these attributes to create plugs
        for use in the compute() method.
        """
        tAttr = om2.MFnTypedAttribute()
        nAttr = om2.MFnNumericAttribute()
        uAttr = om2.MFnUnitAttribute()

        FindParamFromLength.inCurve = tAttr.create("inputCurve", "icrv",
                                                   om2.MFnData.kNurbsCurve)
        INPUT_ATTR(tAttr)

        FindParamFromLength.inArcLength = uAttr.create(
            "arcLength", "length", om2.MFnUnitAttribute.kDistance, 0.0)
        INPUT_ATTR(uAttr)

        FindParamFromLength.outParam = nAttr.create("outParam", "param",
                                                    om2.MFnNumericData.kFloat,
                                                    0.0)
        OUTPUT_ATTR(nAttr)

        FindParamFromLength.addAttribute(FindParamFromLength.inCurve)
        FindParamFromLength.addAttribute(FindParamFromLength.inArcLength)
        FindParamFromLength.addAttribute(FindParamFromLength.outParam)
        FindParamFromLength.attributeAffects(FindParamFromLength.inCurve,
                                             FindParamFromLength.outParam)
        FindParamFromLength.attributeAffects(FindParamFromLength.inArcLength,
                                             FindParamFromLength.outParam)

    def compute(self, plug, dataBlock):
        """
        Node computation method:
            * plug is a connection point related to one of our node attributes (either an input or an output).
            * dataBlock contains the data on which we will base our computations.
        """
        # pylint: disable=no-self-use
        if plug == FindParamFromLength.outParam:
            curveHandle = dataBlock.inputValue(FindParamFromLength.inCurve)
            curveMob = curveHandle.asNurbsCurve()
            arcLen = dataBlock.inputValue(
                FindParamFromLength.inArcLength).asDouble()

            curveFn = om2.MFnNurbsCurve(curveMob)
            param = curveFn.findParamFromLength(arcLen)

            outParamHandle = dataBlock.outputValue(
                FindParamFromLength.outParam)
            outParamHandle.setFloat(param)
            outParamHandle.setClean()
class PoleVectorConstraint(om2.MPxNode):
    """ Main class of gfUtilPoleVectorConstraint node. """

    kNodeName = ""
    kNodeClassify = ""
    kNodeID = ""

    inRootWMtx = om2.MObject()
    inTargetWMtx = om2.MObject()
    inTargetWeight = om2.MObject()
    inConstParInvMtx = om2.MObject()
    inRestPosition = om2.MObject()
    inNormalizeOutput = om2.MObject()
    outConstraint = om2.MObject()

    def __init__(self):
        """ Constructor. """
        om2.MPxNode.__init__(self)

    @staticmethod
    def creator():
        """ Maya creator function. """
        return PoleVectorConstraint()

    @staticmethod
    def initialize():
        """
        Defines the set of attributes for this node. The attributes declared in this function are assigned
        as static members to PoleVectorConstraint class. Instances of PoleVectorConstraint will use these attributes to create plugs
        for use in the compute() method.
        """
        mAttr = om2.MFnMatrixAttribute()
        nAttr = om2.MFnNumericAttribute()

        PoleVectorConstraint.inRootWMtx = mAttr.create(
            "rootWorldMatrix", "rootm", om2.MFnMatrixAttribute.kDouble)
        INPUT_ATTR(mAttr)

        PoleVectorConstraint.inTargetWMtx = mAttr.create(
            "targetWorldMatrix", "tgtm", om2.MFnMatrixAttribute.kDouble)
        INPUT_ATTR(mAttr)

        PoleVectorConstraint.inTargetWeight = nAttr.create(
            "targetWeight", "tw", om2.MFnNumericData.kDouble, 1.0)
        nAttr.setMin(0.0)
        nAttr.setMax(1.0)
        INPUT_ATTR(nAttr)

        PoleVectorConstraint.inConstParInvMtx = mAttr.create(
            "constraintParentInverseMatrix", "cpim",
            om2.MFnMatrixAttribute.kDouble)
        INPUT_ATTR(mAttr)

        PoleVectorConstraint.inRestPosition = nAttr.createPoint(
            "restPosition", "rest")
        nAttr.writable = True
        nAttr.readable = True
        nAttr.storable = True
        nAttr.keyable = False

        PoleVectorConstraint.inNormalizeOutput = nAttr.create(
            "normalizeOutput", "normalize", om2.MFnNumericData.kBoolean, False)
        INPUT_ATTR(nAttr)

        PoleVectorConstraint.outConstraint = nAttr.createPoint(
            "constraint", "const")
        OUTPUT_ATTR(nAttr)

        PoleVectorConstraint.addAttribute(PoleVectorConstraint.inRootWMtx)
        PoleVectorConstraint.addAttribute(PoleVectorConstraint.inTargetWMtx)
        PoleVectorConstraint.addAttribute(PoleVectorConstraint.inTargetWeight)
        PoleVectorConstraint.addAttribute(
            PoleVectorConstraint.inConstParInvMtx)
        PoleVectorConstraint.addAttribute(PoleVectorConstraint.inRestPosition)
        PoleVectorConstraint.addAttribute(
            PoleVectorConstraint.inNormalizeOutput)
        PoleVectorConstraint.addAttribute(PoleVectorConstraint.outConstraint)
        PoleVectorConstraint.attributeAffects(
            PoleVectorConstraint.inRootWMtx,
            PoleVectorConstraint.outConstraint)
        PoleVectorConstraint.attributeAffects(
            PoleVectorConstraint.inTargetWMtx,
            PoleVectorConstraint.outConstraint)
        PoleVectorConstraint.attributeAffects(
            PoleVectorConstraint.inTargetWeight,
            PoleVectorConstraint.outConstraint)
        PoleVectorConstraint.attributeAffects(
            PoleVectorConstraint.inConstParInvMtx,
            PoleVectorConstraint.outConstraint)
        PoleVectorConstraint.attributeAffects(
            PoleVectorConstraint.inRestPosition,
            PoleVectorConstraint.outConstraint)
        PoleVectorConstraint.attributeAffects(
            PoleVectorConstraint.inNormalizeOutput,
            PoleVectorConstraint.outConstraint)

    def connectionMade(self, plug, otherPlug, asSrc):
        """This method gets called when connections are made to attributes of this node.
            * plug (MPlug) is the attribute on this node.
            * otherPlug (MPlug) is the attribute on the other node.
            * asSrc (bool) is this plug a source of the connection.
        """
        if plug == PoleVectorConstraint.inTargetWMtx:
            thisMob = self.thisMObject()
            restPosPlug = om2.MPlug(thisMob,
                                    PoleVectorConstraint.inRestPosition)
            targetMob = otherPlug.asMObject()
            mtxDataFn = om2.MFnMatrixData(targetMob)
            mTarget = mtxDataFn.matrix()
            vTarget = om2.MFloatVector(mTarget[12], mTarget[13], mTarget[14])
            restPosHdle = restPosPlug.asMDataHandle()
            restPosHdle.setMFloatVector(vTarget)
            restPosPlug.setMDataHandle(restPosHdle)
        return om2.MPxNode.connectionMade(self, plug, otherPlug, asSrc)

    def compute(self, plug, dataBlock):
        """
        Node computation method:
            * plug is a connection point related to one of our node attributes (either an input or an output).
            * dataBlock contains the data on which we will base our computations.
        """
        # pylint: disable=no-self-use
        if plug != PoleVectorConstraint.outConstraint:
            return om2.kUnknownParameter

        mRoot = dataBlock.inputValue(
            PoleVectorConstraint.inRootWMtx).asMatrix()
        mTarget = dataBlock.inputValue(
            PoleVectorConstraint.inTargetWMtx).asMatrix()
        mConstParInv = dataBlock.inputValue(
            PoleVectorConstraint.inConstParInvMtx).asMatrix()
        targetWeight = dataBlock.inputValue(
            PoleVectorConstraint.inTargetWeight).asDouble()
        vRest = om2.MVector(
            dataBlock.inputValue(
                PoleVectorConstraint.inRestPosition).asFloat3())
        normalize = dataBlock.inputValue(
            PoleVectorConstraint.inNormalizeOutput).asBool()

        vRoot = om2.MVector(mRoot[12], mRoot[13], mRoot[14])
        vTarget = om2.MVector(mTarget[12], mTarget[13], mTarget[14])

        vPoleDirection = (vTarget - vRoot) * mConstParInv
        vRestDirection = (vRest - vRoot) * mConstParInv
        vPole = (1.0 -
                 targetWeight) * vRestDirection + targetWeight * vPoleDirection

        vResult = om2.MFloatVector(vPole)
        if normalize:
            vResult.normalize()
        outConstHdle = dataBlock.outputValue(
            PoleVectorConstraint.outConstraint)
        outConstHdle.setMFloatVector(vResult)
        outConstHdle.setClean()
예제 #25
0
class TestLocator(omui2.MPxLocatorNode):
    """ Main class of gfTestLocator node. """

    kNodeName = ""
    kNodeClassify = ""
    kNodeRegistrantID = ""
    kNodeID = ""

    inSize = om2.MObject()
    inAttr = om2.MObject()
    outAttr = om2.MObject()

    def __init__(self):
        """ Constructor. """
        omui2.MPxLocatorNode.__init__(self)

    def postConstructor(self):
        """ Post Constructor. """
        thisMob = self.thisMObject()
        om2.MFnDependencyNode(thisMob).setName("%sShape#" % TestLocator.kNodeName)

    @staticmethod
    def creator():
        """ Maya creator function. """
        return TestLocator()

    @staticmethod
    def initialize():
        """
        Defines the set of attributes for this node. The attributes declared in this function are assigned
        as static members to TestLocator class. Instances of TestLocator will use these attributes to create plugs
        for use in the compute() method.
        """
        nAttr = om2.MFnNumericAttribute()

        TestLocator.inSize = nAttr.create("size", "size", om2.MFnNumericData.kDouble, 1.0)
        INPUT_ATTR(nAttr)

        TestLocator.inAttr = nAttr.createPoint("inAttr", "inAttr")
        INPUT_ATTR(nAttr)

        TestLocator.outAttr = nAttr.createPoint("outAttr", "outAttr")
        OUTPUT_ATTR(nAttr)

        TestLocator.addAttribute(TestLocator.inSize)
        TestLocator.addAttribute(TestLocator.inAttr)
        TestLocator.addAttribute(TestLocator.outAttr)
        TestLocator.attributeAffects(TestLocator.inAttr, TestLocator.outAttr)

    def compute(self, plug, dataBlock):
        """
        Node computation method:
            * plug is a connection point related to one of our node attributes (either an input or an output).
            * dataBlock contains the data on which we will base our computations.
        """
        if plug == TestLocator.outAttr:
            inAttrValue = dataBlock.inputValue(TestLocator.inAttr).asVector()

            outAttrHandle = dataBlock.outputValue(TestLocator.outAttr)
            outAttrHandle.set3Float(inAttrValue.x, inAttrValue.y, inAttrValue.z)
            outAttrHandle.setClean()

    def draw(self, view, path, style, status):
        """
        Draw custom geometry in the viewport using OpenGL calls.
            * view [M3dView] is a 3D view that is being drawn into.
            * path [MDagPath] to the parent (transform node) of this locator in the DAG.  To obtain the locator shape node,
                use MDagPath::extendToShape() if there is only one shape node under the transform or
                MDagPath::extendToShapeDirectlyBelow(unsigned int index) with the shape index if there are multiple
                shapes under the transform.
            * style [M3dView.DisplayStyle] is the style to draw object in.
            * status [M3dView.DisplayStatus] is the selection status of the object.
        """
        # pylint: disable=unused-argument

        thisMob = self.thisMObject()
        size = om2.MPlug(thisMob, TestLocator.inSize).asDouble()

        view.beginGL()

        glRenderer = omr1.MHardwareRenderer.theRenderer()
        glFT = glRenderer.glFunctionTable()

        glFT.glPushAttrib(omr1.MGL_CURRENT_BIT)
        glFT.glDisable(omr1.MGL_CULL_FACE)

        if status == omui2.M3dView.kActive:
            glFT.glColor3f(0.3, 1.0, 1.0)
        elif status == omui2.M3dView.kLead:
            glFT.glColor3f(1.0, 1.0, 1.0)
        elif status == omui2.M3dView.kDormant:
            glFT.glColor3f(1.0, 1.0, 0.0)

        vPoint1 = om2.MVector(1.0, 0.0, -1.0) * size
        vPoint2 = om2.MVector(-1.0, 0.0, -1.0) * size
        vPoint3 = om2.MVector(-1.0, 0.0, 1.0) * size
        vPoint4 = om2.MVector(1.0, 0.0, 1.0) * size

        glFT.glBegin(omr1.MGL_QUADS)
        glFT.glVertex3f(vPoint1.x, vPoint1.y, vPoint1.z)
        glFT.glVertex3f(vPoint2.x, vPoint2.y, vPoint2.z)
        glFT.glVertex3f(vPoint3.x, vPoint3.y, vPoint3.z)
        glFT.glVertex3f(vPoint4.x, vPoint4.y, vPoint4.z)
        glFT.glEnd()

        glFT.glPopAttrib()

        view.endGL()

    def isBounded(self):
        """isBounded?"""
        return True

    def boundingBox(self):
        """Return the boundingBox"""
        thisMob = self.thisMObject()
        size = om2.MPlug(thisMob, TestLocator.inSize).asDouble()

        corner1 = om2.MPoint(1.0, 0.0, -1.0) * size
        corner2 = om2.MPoint(-1.0, 0.0, 1.0) * size

        return om2.MBoundingBox(corner1, corner2)