def compute(self, plug, dataBlock):
        if (plug == AM_HipConstraintNode.rotate or plug == AM_HipConstraintNode.angle):
            # ----------------------------------------------------------------
            # Get the incoming data
            # ----------------------------------------------------------------
            # the constrained node's rotateOrder attribute
            dataHandle = dataBlock.inputValue(AM_HipConstraintNode.rotateOrder)
            eRotateOrder = dataHandle.asShort()
            # axis pointing down the length of the upper leg
            dataHandle = dataBlock.inputValue(AM_HipConstraintNode.hipAim)
            vHipForward = (dataHandle.asVector()).normal()
            # axis pointing to the character's front
            dataHandle = dataBlock.inputValue(AM_HipConstraintNode.hipFront)
            vHipUp = (dataHandle.asVector()).normal()
            # axis pointing to the character's the pelvis
            dataHandle = dataBlock.inputValue(AM_HipConstraintNode.pelvisAim)
            vPelvisForward = (dataHandle.asVector()).normal()
            # axis pointing to the character's front
            dataHandle = dataBlock.inputValue(AM_HipConstraintNode.pelvisFront)
            vPelvisUp = (dataHandle.asVector()).normal()
            # the rotatePivot attribute of the upper leg
            dataHandle = dataBlock.inputValue(AM_HipConstraintNode.hipPivot)
            vHipPivot = dataHandle.asVector()
            # the rotatePivot attribute of the pelvis
            dataHandle = dataBlock.inputValue(AM_HipConstraintNode.pelvisPivot)
            vPelvisPivot = dataHandle.asVector()
            # the jointOrient attribute (Euler XYZ offset) of the constrained node
            dataHandle = dataBlock.inputValue(AM_HipConstraintNode.jointOrient)
            vJointOrient = dataHandle.asVector()
            eJointOrient = OM.MEulerRotation(math.radians(vJointOrient.x), math.radians(vJointOrient.y),
                                             math.radians(vJointOrient.z), 0)
            qJointOrient = eJointOrient.asQuaternion()
            qJointOrient.conjugateIt()
            # the pelvis's worldMatrix attribute
            dataHandle = dataBlock.inputValue(AM_HipConstraintNode.pelvis)
            mPelvis = dataHandle.asMatrix()
            mPelvis = OM.MTransformationMatrix(mPelvis)
            qPelvis = mPelvis.rotation()
            # the hip's worldMatrix attribute
            dataHandle = dataBlock.inputValue(AM_HipConstraintNode.hip)
            mHip = dataHandle.asMatrix()
            mHip = OM.MTransformationMatrix(mHip)
            qHip = mHip.rotation()
            # the constrained node's parentInverseMatrix attribute
            dataHandle = dataBlock.inputValue(AM_HipConstraintNode.parentInverseMatrix)
            mParent = dataHandle.asMatrix()
            mParent = OM.MTransformationMatrix(mParent)
            qParent = mParent.rotation()

            # ----------------------------------------------------------------
            # Orthonormalize provided axes for the hip and pelvis
            # ----------------------------------------------------------------
            vHipRight = OM.MVector(vHipUp ^ vHipForward).normal()
            vHipUp = vHipForward ^ vHipRight
            vPelvisRight = OM.MVector(vPelvisUp ^ vPelvisForward).normal()
            vPelvisUp = vPelvisForward ^ vPelvisRight

            # ----------------------------------------------------------------
            # Interpolate the target up-vector based on hip's orientation
            # ----------------------------------------------------------------
            # rotate the pelvis and hip vectors into their respective spaces to get the current elevation angle
            vPelvisForwardRotated = vPelvisForward.rotateBy(qPelvis)
            vPelvisUpRotated = vPelvisUp.rotateBy(qPelvis)
            vHipForwardRotated = vHipForward.rotateBy(qHip)
            dDotPitch = vPelvisForwardRotated * vHipForwardRotated
            dDotYaw = vPelvisUpRotated * (vHipForwardRotated - vPelvisForwardRotated * dDotPitch).normal()
            dAngle = math.degrees(math.acos(min(max(-1.0, -dDotPitch), 1.0)))

            # compute interpolation factor
            dInterpAmt = (2.0 - (1.0 - dDotPitch)) * abs(dDotYaw)
            # interpolate up-vector
            vTargetUp = vPelvisUp.rotateBy(OM.MQuaternion(cmp(dDotYaw, 0.0) * dInterpAmt * math.pi * 0.5, vPelvisRight))

            # rotate the target up-vector into world space
            vTargetUp = vTargetUp.rotateBy(qPelvis)

            # ----------------------------------------------------------------
            # Compute the local orientation for the constrained node
            # ----------------------------------------------------------------
            # orthonormalize target axes and get target normal orientation for constrained object
            vTargetRight = (vTargetUp ^ vHipForwardRotated).normal()
            vTargetUp = vHipForwardRotated ^ vTargetRight
            mList = [vTargetRight.x, vTargetRight.y, vTargetRight.z, 0.0,
                     vTargetUp.x, vTargetUp.y, vTargetUp.z, 0.0,
                     vHipForwardRotated.x, vHipForwardRotated.y, vHipForwardRotated.z, 0.0,
                     0.0, 0.0, 0.0, 1.0]
            mTarget = OM.MMatrix()
            OM.MScriptUtil.createMatrixFromList(mList, mTarget)
            qTarget = OM.MQuaternion(OM.MTransformationMatrix(mTarget).rotation())

            # get offset orientation of the constrained object (from z-forward, y-up)
            mList = [vHipRight.x, vHipRight.y, vHipRight.z, 0.0,
                     vHipUp.x, vHipUp.y, vHipUp.z, 0.0,
                     vHipForward.x, vHipForward.y, vHipForward.z, 0.0,
                     0.0, 0.0, 0.0, 1.0]
            mFromNormal = OM.MMatrix()
            OM.MScriptUtil.createMatrixFromList(mList, mFromNormal)
            qFromNormal = OM.MQuaternion(OM.MTransformationMatrix(mFromNormal).rotation())
            if (qFromNormal.w > 0.0):
                qFromNormal.invertIt()

            # composite final quaternion to get local-space value
            qFinal = OM.MQuaternion(qFromNormal * qTarget * qParent * qJointOrient)

            # output as Euler angles for the constrained node
            eFinal = qFinal.asEulerRotation()
            eFinal.reorderIt(eRotateOrder)

            # ----------------------------------------------------------------
            # Set the outgoing plugs
            # ----------------------------------------------------------------
            outputHandle = dataBlock.outputValue(AM_HipConstraintNode.rotate)
            outputHandle.set3Double(math.degrees(eFinal.x), math.degrees(eFinal.y), math.degrees(eFinal.z))
            outputHandle = dataBlock.outputValue(AM_HipConstraintNode.angle)
            outputHandle.setDouble(dAngle)
            dataBlock.setClean(plug)

        else:
            return OM.kUnknownParameter
Compute the upper leg's elevation angle as well as the orientation for the first twist joint in the hip.
dataset/ETHPy150Open CountZer0/PipelineConstructionSet/maya/plugins/2014/win64/AM_HipConstraint.py/AM_HipConstraintNode.compute