def type(self): # Lazy evaluate if self._type is None: plug = self.plug attr = plug.attribute() if attr.hasFn(OpenMaya.MFn.kMessageAttribute): self._type = Plug.kMessage elif plug.isArray: self._type = Plug.kArray elif attr.hasFn(OpenMaya.MFn.kCompoundAttribute): self._type = Plug.kColor if OpenMaya.MFnAttribute(attr).usedAsColor else \ [ child.type for child in self._children() ] elif attr.hasFn(OpenMaya.MFn.kNumericAttribute): self._type = Plug._numericToPlugTypes.get( OpenMaya.MFnNumericAttribute(attr).numericType(), Plug.kInvalid) elif attr.hasFn(OpenMaya.MFn.kTypedAttribute): dataType = OpenMaya.MFnTypedAttribute(attr).attrType() if dataType == OpenMaya.MFnData.kString: self._type = Plug.kString else: self._type = Plug.kInvalid elif attr.hasFn(OpenMaya.MFn.kEnumAttribute): self._type = Plug.kEnum elif attr.hasFn(OpenMaya.MFn.kUnitAttribute): self._type = Plug._unitToPlugTypes.get( OpenMaya.MFnUnitAttribute(attr).unitType(), Plug.kInvalid) elif attr.hasFn(OpenMaya.MFn.kGenericAttribute): handle = plug.asMDataHandle() isGeneric, isGenericNumeric, isGenericNull = handle.isGeneric() if isGeneric and isGenericNumeric: # It's a generic simple attribute. # According to docs there is no method to check the type # of a generic simple attribute: # http://help.autodesk.com/view/MAYAUL/2016/ENU/?guid=__cpp_ref_class_m_data_handle_html # So always return as double here self._type = Plug.kDouble elif not isGenericNull: obj = handle.data() if obj.hasFn(OpenMaya.MFn.kStringData): self._type = Plug.kString else: # if handle.data() didn't raise an exception, # plug can be read as MObject self._type = Plug.kObject else: raise RuntimeError(kUnknownType % self.name) else: raise RuntimeError(kUnsupportedAttribute % self.name) return self._type
def api_listAttr(path, shortNames=False): sel = om.MSelectionList() try: sel.add(path) except RuntimeError: return [] if not sel.length(): return [] try: plug = sel.getPlug(0) except TypeError: try: node = om.MFnDependencyNode(sel.getDependNode(0)) except RuntimeWarning: return [] attrs = [ om.MFnAttribute(node.attribute(i)) for i in xrange(node.attributeCount()) ] if shortNames: return [x.shortName for x in attrs] else: return [x.name for x in attrs] else: return [ plug.child(i).partialName(useLongNames=not shortNames) for i in xrange(plug.numChildren()) ]
def _encodeProperties(self, dict): """ Encode the properties of this plug's attribute into a dictionary. """ fn = OpenMaya.MFnAttribute(self._plug.attribute()) dict['type'] = Plug._typeToString(self.type) dict['connectable'] = fn.connectable if fn.keyable: dict['keyable'] = True val = self.value if val is not None: dict['value'] = val if self.hasLimits: limits = self.getAttributeLimits() # There is no need to save None values for (key, value) in limits.items(): if value is not None: dict[key] = value if self.type == Plug.kEnum: fn2 = OpenMaya.MFnEnumAttribute(self._plug.attribute()) enum = {} for val in range(fn2.getMin(), fn2.getMax() + 1): try: # Need to catch exception here because all values in # range min -> max are not always used, but there is no # way to query the attribute if a value is used or not. # An exception is raised if a value is not used. enum[val] = fn2.fieldName(val) except: pass dict['enum'] = enum
def getAddAttrCmd(sNodeAttr, longName=True): sNode, sAttr = sNodeAttr.split(".") node = api.getNode(sNode) fnNode = om.MFnDependencyNode(node) mAttr = om.MFnAttribute(fnNode.attribute(sAttr)) return mAttr.getAddAttrCmd(longName)
def doIt(self, args): # gather the values from args argParser = om.MArgParser(self.syntax(), args) plugString = argParser.commandArgumentString(0) sel = om.MSelectionList() sel.add(plugString) self.plug = sel.getPlug(0) attributeMObj = self.plug.attribute() fnAttr = om.MFnAttribute(attributeMObj) if fnAttr.affectsWorldSpace: self.modifier = om.MDGModifier() # self.modifier = om.MDagModifier() else: self.modifier = om.MDGModifier() if not self.plug.source().isNull: self.displayError('{} is connected and cannot be set.'.format( self.plug.name())) return if argParser.isFlagSet('double') or argParser.isFlagSet('d'): self.plugType = 'double' self.value = argParser.flagArgumentDouble('d', 0) self.redoIt() elif argParser.isFlagSet('boolean') or argParser.isFlagSet('b'): self.plugType = 'boolean' self.value = argParser.flagArgumentBool('b', 0) self.redoIt() elif argParser.isFlagSet('string') or argParser.isFlagSet('s'): self.plugType = 'string' self.value = argParser.flagArgumentString('s', 0) self.redoIt() elif argParser.isFlagSet('float') or argParser.isFlagSet('f'): self.plugType = 'float' self.value = argParser.flagArgumentFloat('f', 0) self.redoIt() elif argParser.isFlagSet('int') or argParser.isFlagSet('i'): self.plugType = 'int' self.value = argParser.flagArgumentInt('i', 0) self.redoIt() elif argParser.isFlagSet('angle') or argParser.isFlagSet('a'): self.plugType = 'angle' self.value = argParser.flagArgumentMAngle('a', 0) self.redoIt()
def doIt(self, args): # gather the values from args argParser = om.MArgParser(self.syntax(), args) sourcePlugStr = argParser.commandArgumentString(0) destPlugStr = argParser.commandArgumentString(1) sel = om.MSelectionList() sel.add(sourcePlugStr) sel.add(destPlugStr) self.sourcePlug = sel.getPlug(0) self.destPlug = sel.getPlug(1) if argParser.isFlagSet('f') or argParser.isFlagSet('forceConnection'): self.forceConnection = argParser.flagArgumentBool('f', 0) else: self.forceConnection = False sourceFnAttr = om.MFnAttribute(self.sourcePlug.attribute()) destFnAttr = om.MFnAttribute(self.destPlug.attribute()) if not sourceFnAttr.connectable: self.displayError('{} is not connectable'.format( self.sourcePlug.name())) return elif not destFnAttr.connectable: self.displayError('{} is not connectable'.format( self.destPlug.name())) return elif not destFnAttr.writable: self.displayError('{} is not writable'.format( self.destPlug.name())) return # Create a new MDGModifier for this action self.modifier = om.MDGModifier() self.redoIt()
def copyAttrs(srcNode, destNode, *sAttrList, **kwargs): logMsg(log='all') if "values" not in kwargs: kwargs["values"] = True bDelete = kwargs.pop("delete", False) bCreate = kwargs.pop("create", False) sSrcNode = argToStr(srcNode) sDestNode = argToStr(destNode) mObj = api.getNode(sSrcNode) fnNode = om.MFnDependencyNode(mObj) sCopyAttrList = [] for sAttr in sAttrList: if not getObject(sDestNode + "." + sAttr): if bCreate: mAttr = om.MFnAttribute(fnNode.attribute(sAttr)) sAddAttrCmd = mAttr.getAddAttrCmd(False).replace(";", " {};".format(sDestNode)) logMsg("Copy attr. '{}' from '{}' to '{}'." .format(sAttr, sSrcNode, sDestNode), log="info") pm.mel.eval(sAddAttrCmd) else: sAttr = "" else: if bCreate: logMsg("Attr. '{}' already exists on '{}'.".format(sAttr, sDestNode), log="info") if sAttr: sCopyAttrList.append(sAttr) mc.copyAttr(sSrcNode, sDestNode, attribute=sCopyAttrList, **kwargs) #copyAttrState(sSrcNode, sDestNode , *sCopyAttrList) if bDelete: for sAttr in sCopyAttrList: mc.deleteAttr(sSrcNode + "." + sAttr) return sCopyAttrList
def findPlug(node, attr): """ Return the MPlug corresponding to attr on argument node or None if not found. The node argument can be an MObject or a node string name. The attr argument can be an MObject or a attr string name. Raises RuntimeError if plug is ambiguous.""" if isinstance(node, basestring): attrName = attr if isinstance( attr, basestring) else OpenMaya.MFnAttribute(attr).name return nameToPlug(node + "." + attrName) if isinstance(attr, OpenMaya.MObject): plg = OpenMaya.MPlug(node, attr) else: if attr.find('[') != -1: # fn.findPlug doesn't work for elements of arrays # use a selection list to find the plug return nameToPlug(nodeToLongName(node) + "." + attr) if attr.find('.') != -1: # fn.findPlug doesn't work for compound paths # use last name in compound path as it is unique attr = attr.split('.')[-1] fn = OpenMaya.MFnDependencyNode(node) plg = fn.findPlug(attr, True) if fn.hasAttribute(attr) else None if not plg or plg.isNull or plg.isArray: # an array of plug is not a plug return None if plg.isChild and plg.parent( ).isElement and plg.parent().logicalIndex() < 0: # MAYA-66726: Plugs satisfying this should not be valid plugs # Example: "miDefaultOptions.name" satisfies this and is said to be a valid plug # its parent is miDefaultOptions.stringOptions[-1] which is an element with invalid logical index... return None return plg
# 1. Current input convert to MObject # currentObject = 'pSphere1' objSelection = om.MSelectionList() objSelection.add(currentObject) objMObject = objSelection.getDependNode(0) # 2.Find the attributes of current object mfnDependencyNode = om.MFnDependencyNode(objMObject) attributeCount = mfnDependencyNode.attributeCount() nodeAnimInfomationList = {} for attriIndex in range(attributeCount): attriMObject = mfnDependencyNode.attribute(attriIndex) mfnAttribute = om.MFnAttribute(attriMObject) attriName = mfnAttribute.name.encode() # 3. Find the Attribute - Animation curve is connected currentPlug = mfnDependencyNode.findPlug(attriName, 1) if currentPlug.connectedTo(1, 0): connectedList = currentPlug.connectedTo(1, 0) # Find the connected node type conNodeMObject = connectedList[0].node() # Check its is a Animation curve if conNodeMObject.hasFn(om.MFn.kAnimCurve): # Read Anim Curve Attribute valus mfnAnimCurve = oma.MFnAnimCurve(conNodeMObject)
def __init__(self, mplug): if isinstance(mplug, om.MPlug): self.mobject = mplug.attribute() elif isinstance(mplug, om.MObject): self.mobject = mplug self.attr = om.MFnAttribute(self.mobject)
def parseAttribute(self, jsonInfo): """ Create an attribute using the JSON parameters to decode the structure and values for the attribute. If the attribute is a compound then this method will be recursively called so as to create the entire attribute tree below it. jsonInfo = JSON object containing the attribute's information Returns the newly created attribute. """ if JsonKeys.kKeyName not in jsonInfo: self.reportError('Missing attribute name') self.currentAttribute = jsonInfo[JsonKeys.kKeyName] jsonDebug('parseAttribute(%s)' % str(jsonInfo)) attr = None # Short name must always be present so find or generate one now if JsonKeys.kKeyShortName in jsonInfo: shortName = jsonInfo[JsonKeys.kKeyShortName] else: shortName = self.currentAttribute jsonDebug('...got short name %s' % shortName) #---------------------------------------- # Create the specific type of attribute requested and handle the # type-specific parameters. # if JsonKeys.kKeyAttrType not in jsonInfo: self.reportError('Required keyword "%s" missing' % JsonKeys.kKeyAttrType) elif jsonInfo[JsonKeys.kKeyAttrType] in JsonKeys.kNumericTypes: attr = self.parseNumericAttribute(self.currentAttribute, shortName, jsonInfo[JsonKeys.kKeyAttrType], jsonInfo) elif jsonInfo[JsonKeys.kKeyAttrType] == JsonKeys.kTypeCompound: attr = self.parseCompoundAttribute(self.currentAttribute, shortName, jsonInfo) elif jsonInfo[JsonKeys.kKeyAttrType] == JsonKeys.kTypeEnum: attr = self.parseEnumAttribute(self.currentAttribute, shortName, jsonInfo) elif jsonInfo[JsonKeys.kKeyAttrType] == JsonKeys.kTypeString: attr = self.parseStringAttribute(self.currentAttribute, shortName, jsonInfo) elif jsonInfo[JsonKeys.kKeyAttrType] in JsonKeys.kTypeMatrix: attr = self.parseMatrixAttribute(self.currentAttribute, shortName, jsonInfo) elif jsonInfo[JsonKeys.kKeyAttrType] == JsonKeys.kTypeTyped: attr = self.parseTypedAttribute(self.currentAttribute, shortName, jsonInfo) elif jsonInfo[JsonKeys.kKeyAttrType] == JsonKeys.kTypeLightData: attr = self.parseLightDataAttribute(self.currentAttribute, shortName, jsonInfo) elif jsonInfo[JsonKeys.kKeyAttrType] == JsonKeys.kTypeMessage: attr = self.parseMessageAttribute(self.currentAttribute, shortName, jsonInfo) else: self.reportError('Unknown attribute type "%s"' % jsonInfo[JsonKeys.kKeyAttrType]) return None jsonDebug( 'Done creating attribute "%s", now setting shared parameters' % str(attr)) #---------------------------------------- # Handle the parameters common to all attribute types # aBase = omAPI.MFnAttribute(attr) jsonDebug('...handling common attribute flags for "%s"' % str(aBase)) # Handle the standard flags if JsonKeys.kKeyFlags in jsonInfo: self.parseStandardFlags(aBase, jsonInfo[JsonKeys.kKeyFlags]) # Look for a nice name override if JsonKeys.kKeyNiceName in jsonInfo: jsonDebug('...Overriding nice name with "%s"' % jsonInfo[JsonKeys.kKeyNiceName]) aBase.setNiceNameOverride(jsonInfo[JsonKeys.kKeyNiceName]) # See if the attribute has been added to any categories if JsonKeys.kKeyCategories in jsonInfo: for category in jsonInfo[JsonKeys.kKeyCategories]: jsonDebug('...Adding category "%s"' % category) aBase.addToCategory(category) jsonDebug('...Done on category "%s"' % category) jsonDebug('...Done the categories') # See if there is any special disconnection behaviour if JsonKeys.kKeyDisconnect in jsonInfo: behavior = jsonInfo[JsonKeys.kKeyDisconnect] jsonDebug('...Setting disconnect behaviour to "%s"' % behavior) if behavior in JsonKeys.kDisconnectBehaviors: aBase.disconnectBehavior = JsonKeys.kDisconnectBehaviors[ behavior] else: self.reportError('Unknown behavior type "%s"' % behavior) return attr
def attribute(self): """Returns the attribute (MFnAttribute) of the plug """ return OpenMaya.MFnAttribute(self.plug.attribute())
def setDependentsDirty(self, plug, plugArray): if plug.attribute() == MntLocatorNode.iconType: iconMainAxisAttr = OpenMaya.MFnAttribute(MntLocatorNode.iconMainAxis)
def get_anim_curves_from_objects(nodes): """ Gets the animation curves connected to nodes. :param nodes: List with MFnDependencyNode :type nodes: list of om.MFnDependencyNode :return: Tuple of curves and plugs :rtype: (list of om.MFnDependencyNode, list of om.MPlug) """ curves = [] plugs = [] channelbox_attr = get_channelbox_attributes() animlayers.cache.reset( ) # always reset cache before querying for animation layers! has_anim_layers = animlayers.has_anim_layers() if has_anim_layers and animlayers.all_layers_locked(): cmds.warning('All animation layers are locked!') # get curves for node in nodes: # get all attributes attr_count = node.attributeCount() for index in range(attr_count): attr = node.attribute(index) plug = node.findPlug(attr, True) if plug.isLocked or not plug.isKeyable: continue connections = plug.connectedTo(True, False) # if the attribute has a connection if connections: conn_node = connections[0].node() api = conn_node.apiType() if api in ANIM_CURVE_TYPES: # filter out attributes not selected in channelbox if channelbox_attr: attr_name = om.MFnAttribute(attr).shortName if attr_name not in channelbox_attr: continue # add the node if it matches one of the types we want curves.append(om.MFnDependencyNode(conn_node)) plugs.append(plug) # find curve in animation layer elif has_anim_layers and api in animlayers.BLEND_NODE_TYPES: # filter out attributes not selected in channelbox if channelbox_attr: attr_name = om.MFnAttribute(attr).shortName if attr_name not in channelbox_attr: continue # for testing purposes # print('Attribute: %s' % plug) # benchmark_start = time.clock() best_layer = animlayers.get_best_layer(plug) if not best_layer: continue # for testing purposes # try: # print('-> Best layer is %s' % (om.MFnDependencyNode(best_layer).name())) # except Exception as e: # pass curve_node = animlayers.get_anim_curve(plug, best_layer) # animlayers.cache.benchmark += time.clock() - benchmark_start if curve_node: curves.append(om.MFnDependencyNode(curve_node)) plugs.append(plug) # sys.stdout.write('# Retrieved %d curves in %.4f sec\n' % (len(curve_list), animlayers.cache.benchmark)) return curves, plugs
def exportAnimCurve(selectionList, animPath, animName, animGIFPath, iconPath): animDataDict = {} for currentObject in selectionList: objMSL = om.MSelectionList() objMSL.add(currentObject) objMObject = objMSL.getDependNode(0) # find the attribute of current object objMFnDPNode = om.MFnDependencyNode(objMObject) attributeCount = objMFnDPNode.attributeCount() nodeAnimInformationDict = {} for attributeIndex in range(attributeCount): attributeMObject = objMFnDPNode.attribute(attributeIndex) MFnAttribute = om.MFnAttribute(attributeMObject) attributeName = MFnAttribute.name # find the attribute that anim curve connected currentPlug = objMFnDPNode.findPlug(attributeName, 1) if currentPlug.connectedTo(1, 0): currentConnectedList = currentPlug.connectedTo(1, 0) # find the connected node type currentConnectNodeMObject = currentConnectedList[0].node() # check it is an anim curve if currentConnectNodeMObject.hasFn(om.MFn.kAnimCurve): # get anim curve MFnAnimCurve = oma.MFnAnimCurve(currentConnectNodeMObject) # get attribute animCurveType = MFnAnimCurve.animCurveType preInfinity = MFnAnimCurve.preInfinityType postInfinity = MFnAnimCurve.postInfinityType weightedTangents = int(MFnAnimCurve.isWeighted) # get value of each key numKeys = MFnAnimCurve.numKeys timeList = [] valueList = [] inTangentTypeList = [] inTangentAngleList = [] inTangentAngleWeightList = [] outTangentTypeList = [] outTangentAngleList = [] outTangentAngleWeightList = [] for index in range(numKeys): # time input = MFnAnimCurve.input(index) mTime = om.MTime(input) currentTime = mTime.value timeList.append(currentTime) # value value = MFnAnimCurve.value(index) valueList.append(value) # inTangent inTangentType = MFnAnimCurve.inTangentType(index) inTangentTypeList.append(inTangentType) inTangentAngleWeight = MFnAnimCurve.getTangentAngleWeight(index, 1) inTangentAngleMAngle = om.MAngle(inTangentAngleWeight[0]) inTangentValue = inTangentAngleMAngle.value inTangentAngleList.append(inTangentValue) inTangentAngleWeightList.append(inTangentAngleWeight[1]) # outTangent outTangentType = MFnAnimCurve.outTangentType(index) outTangentTypeList.append(outTangentType) outTangentAngleWeight = MFnAnimCurve.getTangentAngleWeight(index, 0) outTangentAngleMAngle = om.MAngle(outTangentAngleWeight[0]) outTangetValue = outTangentAngleMAngle.value outTangentAngleList.append(outTangetValue) outTangentAngleWeightList.append(outTangentAngleWeight[1]) attributeDataDict = {'animCurveType': animCurveType, 'preInfinity': preInfinity, 'postInfinity': postInfinity, 'weightedTangents': weightedTangents, 'numKeys': numKeys, 'timeList': timeList, 'valueList': valueList, 'inTangentTypeList': inTangentTypeList, 'inTangentAngleList': inTangentAngleList, 'inTangentAngleWeightList': inTangentAngleWeightList, 'outTangentAngleList': outTangentAngleList, 'outTangentTypeList': outTangentTypeList, 'outTangentAngleWeightList': outTangentAngleWeightList} nodeAnimInformationDict.setdefault(attributeName, attributeDataDict) animDataDict.setdefault(currentObject.encode(), nodeAnimInformationDict) # Data History owner = os.getenv('USERNAME') time = datetime.datetime.now().strftime("%A, %B, %d, %Y %H:%M %p") mayaVersion = cmds.about(q=1, v=1) version = '0.1' dataList = {'animCurve': animDataDict, 'history': [owner, time, mayaVersion, version]} dataPath = '%s/%s.anim' % (animPath, animName) if os.path.isfile(dataPath): try: os.chmod(dataPath, 0777) os.remove(dataPath) except Exception, result: print result