def iter_input(component_mob): if is_component(component_mob): fn = om2.MFnDagNode(component_mob) child_count = fn.childCount() for i in range(child_count): child_mob = fn.child(i) child_name = om2.MFnDagNode(child_mob).name() if child_name.endswith('_input'): yield child_mob
def iter_components(rig_mob): if is_control_rig(rig_mob): fn = om2.MFnDagNode(rig_mob) child_count = fn.childCount() for i in range(child_count): child_mob = fn.child(i) child_name = om2.MFnDagNode(child_mob).name() if child_name.endswith('_cmpnt'): yield child_mob
def is_control_rig(mob): fn = om2.MFnDagNode(mob) is_named_correctly = fn.name() == "rig" is_two_from_world = False if (is_named_correctly): parent_mob = fn.parent(0) parent_fn = om2.MFnDagNode(parent_mob) if parent_fn.name() != 'world': granny_mob = parent_fn.parent(0) granny_fn = om2.MFnDagNode(granny_mob) is_two_from_world = granny_fn.name() == 'world' return is_named_correctly and is_two_from_world
def is_component(mob): fn = om2.MFnDagNode(mob) is_under_rig = is_control_rig(fn.parent(0)) if is_under_rig: return fn.name().endswith('_cmpnt') else: return False
def iter_output(component_mob): if is_component(component_mob): fn = om2.MFnDagNode(component_mob) child_count = fn.childCount() for i in range(child_count): child_mob = fn.child(i) child_name = om2.MFnDagNode(child_mob).name() if child_name.endswith('_output'): yield child_mob itr_dag = om2.MItDag() itr_dag.reset(child_mob) itr_dag.next() while (not itr_dag.isDone()): curr_node = itr_dag.currentItem() yield curr_node itr_dag.next()
def container_from_component(component_mob): assert is_component(component_mob) comp_fn = om2.MFnDagNode(component_mob) comp_dag_name = comp_fn.name() container_name = "{}_container".format(comp_dag_name[:-6]) sel = om2.MSelectionList() sel.add(container_name) container_mob = sel.getDependNode(0) return container_mob
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 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 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 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 importantObjectsFromContainer(containerHandle): """ This takes a component name for some filtering and a container handle and isolates the key objects related to it that represent our component interesting items. :param containerHandle: `MObjectHandle` :return: `dict` k,v pairs for interesting objects and their handle, None if unavailable """ mfn_cont = om2.MFnContainerNode(containerHandle.object()) mobaMembers = mfn_cont.getMembers() fullname = mfn_cont.name() tokens = fullname.rsplit('_', 1) componentName = tokens[0] keyObsDict = { 'componentName': componentName, CONTROL_KEY: None, GUIDE_KEY: None, DEFORM_KEY: None, TOOLPARAMETERS_SUFFIX: None, } toolParametersObjName = '{}_{}'.format(componentName, TOOLPARAMETERS_SUFFIX) for eachMob in mobaMembers: if not eachMob.hasFn(om2.MFn.kDagNode): continue mfn_dag = om2.MFnDagNode(eachMob) objectName = mfn_dag.name() if objectName == CONTROL_KEY: keyObsDict[CONTROL_KEY] = om2.MObjectHandle(eachMob) elif objectName == GUIDE_KEY: keyObsDict[GUIDE_KEY] = om2.MObjectHandle(eachMob) elif objectName == DEFORM_KEY: keyObsDict[DEFORM_KEY] = om2.MObjectHandle(eachMob) elif objectName == toolParametersObjName: keyObsDict[TOOLPARAMETERS_SUFFIX] = om2.MObjectHandle(eachMob) return keyObsDict
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 parent(self): if self._parent is not None and \ (self._parent.isNull() or not len(om2.MFnDagNode(self._parent).fullPathName())): self._parent = None return self._parent
def doIt(self, args): """ Maya Factory method :param args: in new-api mode this is probably going to be a tuple :return: `None` """ if not RUN_LOCAL_INSTANCE_MODE: argDB = om2.MArgDatabase(self.syntax(), args) obList = argDB.getObjectList() sw = argDB.isFlagSet('-sw') rd = argDB.isFlagSet('-rd') rg = argDB.isFlagSet('-rg') else: # debug only case, set manually as needed obList = om2.MGlobal.getActiveSelectionList() sw = True rd = False rg = False # We assume there can only be one object in the list we received # based on the constraints we established for the arguments mob = obList.getDependNode(0) containerNode = containerFromNode(mob) self.__containerHandle = om2.MObjectHandle(containerNode) if containerNode is None or containerNode.isNull(): return else: self.__componentDict = importantObjectsFromContainer( self.__containerHandle) self.__toolParsMobha = self.__componentDict[TOOLPARAMETERS_SUFFIX] requiresPanel = sw or rg if requiresPanel and (self.__toolParsMobha is None or not self.__toolParsMobha.isValid()): return if sw: # This section is responsible for, if invoked, swapping the plugs # that set the state of the component to guided or unguided mfn_panelDag = om2.MFnDagNode(self.__toolParsMobha.object()) plug_toSwap = mfn_panelDag.findPlug('toSwap', False) for eachNamedCouple in iterSwapPlugs(plug_toSwap): trPlug_origin = eachNamedCouple[ TRACKER_PLUG_NAMES[0]] # origin on tracker panel trPlug_guided = eachNamedCouple[ TRACKER_PLUG_NAMES[1]] # guided on tracker panel actPlug_origin = None # source of tracked origin plug, might remain None actPlug_originSource = None # source of active origin plug, might remain None actPlug_guided = None # source of tracked guided plug, might remain None actPlug_guidedSource = None # most upstream plug to swap, might remain None if trPlug_origin.isDestination: actPlug_origin = trPlug_origin.source() if actPlug_origin.isDestination: actPlug_originSource = actPlug_origin.source() if trPlug_guided.isDestination: actPlug_guided = trPlug_guided.source() if actPlug_guided.isDestination: actPlug_guidedSource = actPlug_guided.source() doNothing = (actPlug_origin is None) and (actPlug_guidedSource is None) if doNothing: continue else: # else is redundant here, it's only for clarity and legibility self.__needsUndoing = 1 name_trOrigin = cmdFriendlyNameFromPlug(trPlug_origin) name_trGuided = cmdFriendlyNameFromPlug(trPlug_guided) name_actOrigin = cmdFriendlyNameFromPlug(actPlug_origin) name_actOriginSource = cmdFriendlyNameFromPlug( actPlug_originSource) name_actGuided = cmdFriendlyNameFromPlug(actPlug_guided) name_actGuidedSource = cmdFriendlyNameFromPlug( actPlug_guidedSource) connect = actPlug_origin is not None and actPlug_guidedSource is None disconnect = actPlug_origin is None and actPlug_guidedSource is not None swap = actPlug_origin is not None and actPlug_guidedSource is not None if connect: m_cmds.connectAttr(name_actOrigin, name_actGuided) m_cmds.disconnectAttr(name_actOrigin, name_trOrigin) elif disconnect: m_cmds.disconnectAttr(name_actGuidedSource, name_actGuided) m_cmds.connectAttr(name_actGuidedSource, name_trOrigin) elif swap: m_cmds.connectAttr(name_actGuidedSource, name_trOrigin, force=True) m_cmds.connectAttr(name_actOrigin, name_actGuided, force=True) else: # if things get to this point it means that no combination of # flags ever took place and all cases are False. # This error should literally be impossible since check coverage is complete. # If this occurs something might have mutated the various branching flags # between checks, which would be extremely unlikely to happen raise RuntimeError("WTF, mate?!") # end swap if rg: # This section, if invoked, is responsible to iterate the plugs # flagging what objects require deletion and issuing # the command to delete each mfn_panelDag = om2.MFnDagNode(self.__toolParsMobha.object()) plug_toDelete = mfn_panelDag.findPlug('toDelete', False) elemCount = plug_toDelete.evaluateNumElements() foundAtLeastOne = 0 for i in xrange(elemCount): elemPlug = plug_toDelete.elementByPhysicalIndex(i) if elemPlug.isDestination: foundAtLeastOne = 2 sourceNode = elemPlug.source().node() if sourceNode.hasFn(om2.MFn.kDagNode): om2.MDagPath.getAPathTo(sourceNode) pathToNode = om2.MDagPath.getAPathTo( sourceNode).fullPathName() else: pathToNode = om2.MFnDependencyNode(sourceNode).name() if pathToNode: m_cmds.delete(pathToNode) self.__needsUndoing += foundAtLeastOne # end delete DG nodes if rd: # This section, if invoked, is responsible to delete the guide DAG object # for the component, which should take with it the entire hierarchy guideMobha = self.__componentDict[GUIDE_KEY] if guideMobha is None or not guideMobha.isValid( ) or guideMobha.object().isNull(): self.__needsUndoing = self.__needsUndoing or 0 return guideMob = guideMobha.object() assert guideMob.hasFn( om2.MFn.kDagNode ), "guide object stored in dictionary doesn't seem to be a DAG node" pathToGuide = om2.MDagPath.getAPathTo( guideMobha.object()).fullPathName() m_cmds.delete(pathToGuide)
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)