def containerFromNode(mayaNode): """ Inspects a node connection set for standard containered topology and returns the owning container if one is found, None otherwise :param mayaNode: `MObject` any dependency node in Maya :return: `MObject | None` the container object the argument is linked to if there is one otherwise None """ fnDep = om2.MFnDependencyNode(mayaNode) plug = fnDep.findPlug("message", False) for eachDestinationPlug in plug.destinations(): destinationNode = eachDestinationPlug.node() if not destinationNode.hasFn(om2.MFn.kHyperLayout): continue # at this point we're dealing with an interesting node # and we should find if it's connected to a container mfnDestinationNode = om2.MFnDependencyNode(destinationNode) layoutNodeMsgPlug = mfnDestinationNode.findPlug("message", False) msgDestinations = layoutNodeMsgPlug.destinations() for eachLayoutDestination in msgDestinations: if eachLayoutDestination.node().hasFn(om2.MFn.kContainer): return eachLayoutDestination.node()
def cb(msg, plug1, plug2, payload): if msg != 2056: #check most common case first and return unless it's return # an attribute edit type of callback if not plug1.partialName(includeNodeName=False, useAlias=False) == fkik_attrName: # We ensure if the attribute being changed is uninteresting we do nothing return isFK = plug1.asBool() == False # Switched To FK isIK = not isFK # Switched to IK settingsAttrs = { # all interesting attribute names in keys, respective plugs in values 'fkRotation': None, 'ikRotation': None, 'fk_ctrl_rotx': None, 'ik_ctrl_translate': None, 'ikPedalOffset': None, } mfn_dep = om2.MFnDependencyNode(plug1.node()) # We populate the dictionary of interesting attributes with their plugs for eachPName in settingsAttrs.iterkeys(): plug = mfn_dep.findPlug(eachPName, False) settingsAttrs[eachPName] = plug for p in settingsAttrs.itervalues(): # We will exit early and do nothing if a plug couldn't be initialised, the object # is malformed, or we installed the callback on an object that is only # conformant by accident and can't operate as we expect it to. if p is None: return angle = None # empty init if isFK: # Simplest case, if we switched to FK we copy the roation from IK # to the FK control's X rotation value angle = -settingsAttrs.get("ikRotation").source().asDouble() fkSourcePlug = settingsAttrs.get("fk_ctrl_rotx").source() fkSourcePlug.setDouble(angle) elif isIK: # If instead we switched to IK we need to # derive the translation of the IK control that produces the result # of an equivalent rotation to the one coming from the FK control angle = settingsAttrs.get("fkRotation").source().asDouble() projectedLen = settingsAttrs.get("ikPedalOffset").source().asDouble() y = (math.cos(angle) * projectedLen) - projectedLen z = math.sin(angle) * projectedLen ikSourcePlug = settingsAttrs.get("ik_ctrl_translate").source() for i in xrange(ikSourcePlug.numChildren()): realName = ikSourcePlug.child(i).partialName(includeNodeName=False, useAlias=False) if realName == 'ty': ikSourcePlug.child(i).setDouble(y) elif realName == 'tz': ikSourcePlug.child(i).setDouble(z)
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 translationPlugsFromAnyPlug(plug): """ :param plug: [MPlug] plug on a node to retrieve translation related plugs from :return: [tuple(MPlug)] tuple of compound translate plug, and three axes translate plugs """ node = plug.node() if not node.hasFn(om2.MFn.kTransform ): # this should exclude nodes without translate plugs return mfn_dep = om2.MFnDependencyNode(node) pNames = ('translate', 'tx', 'ty', 'tz') return tuple([mfn_dep.findPlug(eachName, False) for eachName in pNames])
def getMRotFromNodeOutput(node_mob, rotOrder=om2.MEulerRotation.kXYZ): """ finds the angular output of the argument node and returns it as a Euler rotation where that angle is the X element :param node_mob: [MObject] the node to get the output port from :param rotOrder: [int] the factory constant for the desired rotation order the returned Euler rotation should be set to :return: [MEulerRotation] the Euler rotation composition where the angular output on the argument node is the X value """ mfn_dep = om2.MFnDependencyNode(node_mob) angle = om2.MAngle(0.0) if node_mob.hasFn(om2.MFn.kAnimBlend) and mfn_dep.hasAttribute( _MAYA_OUTPUT_ATTRIBUTE_NAME): plug = mfn_dep.findPlug(_MAYA_OUTPUT_ATTRIBUTE_NAME, False) angle = plug.asMAngle() rot = om2.MEulerRotation(angle.asRadians(), 0.0, 0.0, rotOrder) return rot
rot = om2.MEulerRotation(angle.asRadians(), 0.0, 0.0, rotOrder) 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():
def postConstructor(self): """ Post Constructor. """ thisMob = self.thisMObject() om2.MFnDependencyNode(thisMob).setName("%sShape#" % DebugVector.kNodeName)
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)
selection = om.MGlobal.getActiveSelectionList() print(selection) # Iterate over each selected object and use the appropriate function set # to query type specific data for i in range(selection.length()): if i > 0: print('-------------') obj = selection.getDependNode(i) # returns an MObject print('API Type: {0}'.format(obj.apiTypeStr)) if obj.hasFn(om.MFn.kDependencyNode ): # Check if the function set is compatible with the MObject depend_fn = om.MFnDependencyNode( obj) # Attach supported function set to the MObject print('Dependency Node: {0}'.format( depend_fn.name())) # Use function set to query data if obj.hasFn(om.MFn.kTransform): transform_fn = om.MFnTransform(obj) print('Translation: {0}'.format( transform_fn.translation(om.MSpace.kTransform))) elif obj.hasFn(om.MFn.kMesh): mesh_fn = om.MFnMesh(obj) print('Mesh Vertices: {0}'.format(mesh_fn.getVertices())) elif obj.hasFn(om.MFn.kCamera): camera_fn = om.MFnCamera(obj) print('Clipping Planes: {0} {1}'.format( camera_fn.nearClippingPlane, camera_fn.farClippingPlane))
def postConstructor(self): """ Post Constructor. """ thisMob = self.thisMObject() nodeFn = om2.MFnDependencyNode(thisMob) nodeFn.setName("%sShape#" % DebugMatrix.kNodeName)