def mtxFromPlugSource(plug): """ takes a plug and retrieves the plug's source plug then will try to initialise matrix data from it and return it if valid :param plug: [MPlug] a plug connected to a matrix type source :return: [MMatrix | None] """ if plug.isDestination: mtxPlug = plug.source() node_mob_attr = mtxPlug.asMObject() if node_mob_attr.hasFn(om2.MFn.kMatrixAttribute): mfn_mtxData = om2.MFnMatrixData(node_mob_attr) return mfn_mtxData.matrix() return None
def wMtxFromMob(node_mob): """ finds the world matrix attribute and returns its value in matrix form :param node_mob: [MObject] the node to get the world matrix from :return: [MMatrix] the matrix value of the world transform on the argument node """ if not node_mob.hasFn(om2.MFn.kDagNode): return None mfn_dag = om2.MFnDagNode(node_mob) wMtxPlug = mfn_dag.findPlug(_MAYA_MATRIX_ATTRIBUTE_NAME, False) elPlug = wMtxPlug.elementByLogicalIndex(0) node_mob_attr = elPlug.asMObject() mfn_mtxData = om2.MFnMatrixData(node_mob_attr) return mfn_mtxData.matrix()
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 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 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 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