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 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 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 iterSwapPlugs(plug): """ This takes a well formed plug that is an array of compounds with two children and yields dictionaries containing those two sub plugs indexed by their expected (shortest) names :param plug: `MPlug` Array of Compounds of two plugs with children named as indicated in preceding constant :return: `dict` {origin:MPlug, guided:MPlug} """ assert plug.isArray, "input plug is not an array" assert plug.isCompound, "plug is not compound" elemCount = plug.evaluateNumElements() for i in xrange(elemCount): plug_swapCpd = plug.elementByPhysicalIndex(i) childrenCount = plug_swapCpd.numChildren() assert childrenCount == 2, "plug has unexpected number of children" trackedPlugsDict = { TRACKER_PLUG_NAMES[0]: None, TRACKER_PLUG_NAMES[1]: None } for j in xrange(childrenCount): subPlug = plug_swapCpd.child(j) plugKey = subPlug.partialName().rsplit('.', 1)[-1] trackedPlugsDict[plugKey] = om2.MPlug().copy(subPlug) yield trackedPlugsDict
def prepareForDraw(self, objPath, cameraPath, frameContext, oldData): """ Called by Maya each time the object needs to be drawn. Any data needed from the Maya dependency graph must be retrieved and cached in this stage. Returns the data to be passed to the draw callback method. * objPath [MDagPath] is the path to the object being drawn. * cameraPath [MDagPath] is the path to the camera that is being used to draw. * frameContext [MFrameContext] is the frame level context information. * oldData [MUserData] is the data cached by the previous draw of the instance. """ # pylint: disable=unused-argument startTime = time.time() data = oldData if not isinstance(data, MeshControllerData): data = MeshControllerData() node = objPath.node() transformPath = om2.MDagPath.getAPathTo( om2.MFnDagNode(objPath).parent(0)) mWorldInv = transformPath.inclusiveMatrixInverse() indexStr = om2.MPlug(node, MeshController.inIndexList).asString() offset = om2.MPlug(node, MeshController.inOffset).asFloat() mesh = om2.MPlug(node, MeshController.inMesh).asMDataHandle().asMesh() color = om2.MPlug( node, MeshController.inColor).asMDataHandle().asFloatVector() # If plugs are dirty calculate the geometry points MeshController.getGeometryPoints(mesh, indexStr, offset, mWorldInv) data.fVtxPositions = MeshController.ctrlVertices status = omr2.MGeometryUtilities.displayStatus(objPath) if status == omr2.MGeometryUtilities.kDormant: # Not selected alpha = 0.25 elif status == omr2.MGeometryUtilities.kActive: # Multiselection alpha = 0.65 elif status == omr2.MGeometryUtilities.kLead: # Selected alpha = 0.5 data.fColor = om2.MColor([color.x, color.y, color.z, alpha]) runTime = round((time.time() - startTime) * 1000, 5) om2.MGlobal.displayInfo("prepareForDraw time: %s ms" % str(runTime)) return data
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)
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()))
def msgConnectedPlugs(plug): """ :param plug: [MPlug] plug on a node owning message plug we wish to retrieve all destination plugs from :return: [tuple(MPlug)] all plugs on other nodes receiving a message connection coming from the one owning the argument plug """ mfn_dep = om2.MFnDependencyNode(plug.node()) msgPlug = mfn_dep.findPlug('message', False) return tuple([om2.MPlug(otherP) for otherP in msgPlug.destinations()])
def boundingBox(self, objPath, cameraPath): """ Return the boundingBox """ # pylint: disable=unused-argument node = objPath.node() size = om2.MPlug(node, 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)
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 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 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
def boundingBox(self, objPath, cameraPath): """ Return the boundingBox """ # pylint: disable=unused-argument node = objPath.node() operation = om2.MPlug(node, DebugVector.inOperation).asShort() vVector1 = om2.MPlug( node, DebugVector.inVec1).asMDataHandle().asFloatVector() vVector2 = om2.MPlug( node, DebugVector.inVec2).asMDataHandle().asFloatVector() normalize = om2.MPlug(node, 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() corner1 = om2.MPoint(vStart.x, vStart.y, vStart.z) corner2 = om2.MPoint(vEnd.x, vEnd.y, vEnd.z) return om2.MBoundingBox(corner1, corner2)
def prepareForDraw(self, objPath, cameraPath, frameContext, oldData): """ Called by Maya each time the object needs to be drawn. Any data needed from the Maya dependency graph must be retrieved and cached in this stage. Returns the data to be passed to the draw callback method. * objPath [MDagPath] is the path to the object being drawn. * cameraPath [MDagPath] is the path to the camera that is being used to draw. * frameContext [MFrameContext] is the frame level context information. * oldData [MUserData] is the data cached by the previous draw of the instance. """ # pylint: disable=unused-argument data = oldData if not isinstance(data, DebugMatrixData): data = DebugMatrixData() node = objPath.node() mInput = om2.MPlug(node, DebugMatrix.inMatrix).asMDataHandle().asMatrix() color = om2.MPlug( node, DebugMatrix.inNameColor).asMDataHandle().asFloatVector() dist = om2.MPlug(node, DebugMatrix.inDistance).asFloat() pntPos = om2.MPoint(mInput[12], mInput[13], mInput[14]) pntRow1 = om2.MPoint(mInput[0], mInput[1], mInput[2], mInput[3]) row1 = "%s | %s | %s | %s" % (str(pntRow1.x), str( pntRow1.y), str(pntRow1.z), str(pntRow1.w)) data.fDormantColor = om2.MColor([color.x, color.y, color.z]) data.fActiveColor = om2.MColor([0.3, 1.0, 1.0]) data.fLeadColor = om2.MColor([1.0, 1.0, 1.0]) data.fDist = dist data.fPntPos = pntPos data.fRow1 = row1 return data
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 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 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 prepareForDraw(self, objPath, cameraPath, frameContext, oldData): """ Called by Maya each time the object needs to be drawn. Any data needed from the Maya dependency graph must be retrieved and cached in this stage. Returns the data to be passed to the draw callback method. * objPath [MDagPath] is the path to the object being drawn. * cameraPath [MDagPath] is the path to the camera that is being used to draw. * frameContext [MFrameContext] is the frame level context information. * oldData [MUserData] is the data cached by the previous draw of the instance. """ # pylint: disable=unused-argument data = oldData if not isinstance(data, TestLocatorData): data = TestLocatorData() node = objPath.node() size = om2.MPlug(node, TestLocator.inSize).asDouble() data.fDormantColor = om2.MColor([1.0, 1.0, 0.0]) data.fActiveColor = om2.MColor([0.3, 1.0, 1.0]) data.fLeadColor = om2.MColor([1.0, 1.0, 1.0]) data.fSize = size 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 data.fQuadList.clear() data.fQuadList.append(om2.MPoint(vPoint1)) data.fQuadList.append(om2.MPoint(vPoint2)) data.fQuadList.append(om2.MPoint(vPoint3)) data.fQuadList.append(om2.MPoint(vPoint4)) data.fQuadList.append(om2.MPoint(vPoint1)) return data
return rot # A dictionary of all attributes we're interested in by name, ready # to accept values for each. attribs = { 'blendedRotation': None, 'fk_bfr_mtx': None, 'ik_bfr_mtx': None, 'ikPedalOffset': None, } mobTuple = tuple(iterSelection()) if mobTuple: mfn_dep = om2.MFnDependencyNode(mobTuple[0]) plug = om2.MPlug() if mfn_dep.hasAttribute("FKIK_switch"): plug = mfn_dep.findPlug("FKIK_switch", False) if plug.isNull: print( "invalid selection, no FKIK_switch attribute found on first selected item" ) else: for eachPName in attribs.iterkeys(): plug = mfn_dep.findPlug(eachPName, False) attribs[eachPName] = plug isValid = True for p in attribs.itervalues(): if p is None:
def prepareForDraw(self, objPath, cameraPath, frameContext, oldData): """ Called by Maya each time the object needs to be drawn. Any data needed from the Maya dependency graph must be retrieved and cached in this stage. Returns the data to be passed to the draw callback method. * objPath [MDagPath] is the path to the object being drawn. * cameraPath [MDagPath] is the path to the camera that is being used to draw. * frameContext [MFrameContext] is the frame level context information. * oldData [MUserData] is the data cached by the previous draw of the instance. """ # pylint: disable=unused-argument data = oldData if not isinstance(data, DebugVectorData): data = DebugVectorData() node = objPath.node() lineW = om2.MPlug(node, DebugVector.inLineWidth).asFloat() color = om2.MPlug(node, DebugVector.inColor).asMDataHandle().asFloatVector() tipSize = om2.MPlug(node, DebugVector.inTipSize).asFloat() subd = om2.MPlug(node, DebugVector.inSubdivisions).asInt() radius = om2.MPlug(node, DebugVector.inRadius).asFloat() xray = om2.MPlug(node, DebugVector.inXRay).asBool() dashed = om2.MPlug(node, DebugVector.inDashed).asBool() operation = om2.MPlug(node, DebugVector.inOperation).asShort() vVector1 = om2.MPlug( node, DebugVector.inVec1).asMDataHandle().asFloatVector() vVector2 = om2.MPlug( node, DebugVector.inVec2).asMDataHandle().asFloatVector() normalize = om2.MPlug(node, DebugVector.inNormalize).asBool() data.fDormantColor = om2.MColor([color.x, color.y, color.z]) data.fActiveColor = om2.MColor([0.3, 1.0, 1.0]) data.fLeadColor = om2.MColor([1.0, 1.0, 1.0]) data.fLineWidth = lineW data.fTipSize = tipSize data.fSubd = subd data.fRadius = radius data.fXRay = xray data.fDashed = dashed data.fOperation = operation 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() data.fLineList.clear() DebugVector.drawArrow(vStart, vEnd, tipSize, radius, subd, lineW, vp2=True, lineList=data.fLineList) return data
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()
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 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
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