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 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 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 boundingBox(self): """Return the boundingBox""" bBox = om2.MBoundingBox() for i in range(len(DebugGeometry.kPnts)): bBox.expand(DebugGeometry.kPnts[i]) return bBox
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())
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
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
def boundingBox(self, objPath, cameraPath): """ Return the boundingBox """ # pylint: disable=unused-argument return om2.MBoundingBox()
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)