def parent(self): buf = unicode(self).split('|')[:-1] if len(buf)==2 and buf[0] == buf[1] and _versions.current() < _versions.v2011: # pre-2011, windows with menus can have a strange name: # ex. window1|window1|menu1 buf = buf[:1] return PyUI( '|'.join(buf) )
def exit_maya(): import sys # If we are in standalone we need to make a new file and uninitialize then the virtual machines crash # if we do not use os._exit to properly exit Maya in CIRCLECI. # https://groups.google.com/forum/#!topic/python_inside_maya/chpuSyLbryI try: import maya.standalone as ms sys.stdout.write('Anvil is exiting Standalone Maya.') mc.file(new=True, force=True) sys.stdout.write('.') sys.stdout.flush() from pymel import versions if not str(versions.current()).startswith('2016'): ms.uninitialize() sys.stdout.write('.') sys.stdout.flush() except: pass finally: sys.stdout.write('Success...exiting.\n') sys.stdout.flush() import os if os.getenv('CIRCLECI'): os._exit(0)
def assertMelError(self, cmd): # in maya 2014, a RuntimeError is raised... yay! if versions.current() >= versions.v2014: self.assertRaises(RuntimeError, mel.eval, cmd) else: # tried catch/catchQuiet, but they always return 0... self.assertEqual(mel.eval(cmd), None)
def test_vectorArray(self): if versions.current() < versions.v2011: cmds.setAttr( 'node.vectorArrayAttr', 2, (1,2,3), "", (1,2,3), type='vectorArray' ) assert cmds.getAttr( 'node.vectorArrayAttr' ) == [1.0, 2.0, 3.0, 1.0, 2.0, 3.0] else: cmds.setAttr( 'node.vectorArrayAttr', 2, (1,2,3), (1,2,3), type='vectorArray' ) assert cmds.getAttr( 'node.vectorArrayAttr' ) == [(1.0, 2.0, 3.0), (1.0, 2.0, 3.0)]
def menu(*args, **kwargs): """ Modifications - added ability to query parent """ if _versions.current() < _versions.v2011: # on create only if not ( kwargs.get('query', False) or kwargs.get('q', False) ) \ and not ( kwargs.get('edit', False) or kwargs.get('e', False) ) \ and not ( kwargs.get('parent', False) or kwargs.get('p', False) ): kwargs['parent'] = cmds.setParent(q=1) if ( kwargs.get('query', False) or kwargs.get('q', False) ) \ and ( kwargs.get('parent', False) or kwargs.get('p', False) ): name = unicode(args[0]) if '|' not in name: try: name = _findLongName(name, 'menu') except ValueError: name = _findLongName(name, 'popupMenu') return name.rsplit('|',1)[0] result = cmds.menu(*args, **kwargs) if ( kwargs.get('query', False) or kwargs.get('q', False) ) \ and ( kwargs.get('itemArray', False) or kwargs.get('ia', False) ) \ and result is None: result = [] return result
def _makeDgModGhostObject(mayaType, dagMod, dgMod): if versions.current() >= versions.v2012: # only time post-2012 when we should have to call this func is when # rebuilding caches - ie, running from inside ApiCache if not GhostObjsOkHere.OK(): _logger.raiseLog(_logger.WARNING, '_makeDgModGhostObject should be unnecessary in maya versions past 2012 (except when rebuilding cache)') # we create a dummy object of this type in a dgModifier (or dagModifier) # as the dgModifier.doIt() method is never called, the object # is never actually created in the scene # Note: at one point, if we didn't call the dgMod/dagMod.deleteNode method, # and we call this function while loading a scene (for instance, if the scene requires # a plugin that isn't loaded, and defines custom node types), then the nodes were still # somehow created, despite never explicitly calling doIt()... # ... however, this seems to no longer be the case, and the deleteNode calls are apparently # harmful if type(dagMod) is not api.MDagModifier or type(dgMod) is not api.MDGModifier : raise ValueError, "Need a valid MDagModifier and MDGModifier or cannot return a valid MObject" # Regardless of whether we're making a DG or DAG node, make a parent first - # for some reason, this ensures good cleanup (don't ask me why...??) parent = dagMod.createNode ( 'transform', api.MObject()) try : # DependNode obj = dgMod.createNode ( mayaType ) except RuntimeError: # DagNode try: obj = dagMod.createNode ( mayaType, parent ) except Exception, err: _logger.debug("Error trying to create ghost node for '%s': %s" % (mayaType, err)) return None
def mayaInit(forversion=None) : """ Try to init Maya standalone module, use when running pymel from an external Python inerpreter, it is possible to pass the desired Maya version number to define which Maya to initialize Part of the complexity of initializing maya in standalone mode is that maya does not populate os.environ when parsing Maya.env. If we initialize normally, the env's are available via maya (via the shell), but not in python via os.environ. Note: the following example assumes that MAYA_SCRIPT_PATH is not set in your shell environment prior to launching python or mayapy. >>> import maya.standalone #doctest: +SKIP >>> maya.standalone.initialize() #doctest: +SKIP >>> import maya.mel as mm #doctest: +SKIP >>> print mm.eval("getenv MAYA_SCRIPT_PATH") #doctest: +SKIP /Network/Servers/sv-user.luma-pictures.com/luma ..... >>> import os #doctest: +SKIP >>> 'MAYA_SCRIPT_PATH' in os.environ #doctest: +SKIP False The solution lies in `refreshEnviron`, which copies the environment from the shell to os.environ after maya.standalone initializes. :rtype: bool :return: returns True if maya.cmds required initializing ( in other words, we are in a standalone python interpreter ) """ setupFormatting() global isInitializing # test that Maya actually is loaded and that commands have been initialized,for the requested version aboutExists = False try : from maya.cmds import about aboutExists = True except ImportError: pass if aboutExists and mayaStartupHasStarted(): # if this succeeded, we're initialized isInitializing = False return False _logger.debug( "startup.initialize running" ) # for use with pymel compatible maya package os.environ['MAYA_SKIP_USERSETUP_PY'] = 'on' if not aboutExists and not sys.modules.has_key('maya.standalone'): try : import maya.standalone #@UnresolvedImport maya.standalone.initialize(name="python") if versions.current() < versions.v2009: refreshEnviron() except ImportError, e: raise e, str(e) + ": pymel was unable to intialize maya.standalone"
def objectTypeUI(name, **kwargs): try: return cmds.objectTypeUI(name, **kwargs) except RuntimeError, topError: try: # some ui types (radioCollections) can only be identified with their shortname return cmds.objectTypeUI(name.split('|')[-1], **kwargs) except RuntimeError: # we cannot query the type of rowGroupLayout children: check common types for these uiType = None typesToCheck = 'checkBox floatField button floatSlider intSlider ' \ 'floatField textField intField optionMenu radioButton'.split() if _versions.current() >= _versions.v2012_SP2: # 2012 SP2 introducted a bug where doing: # win = cmds.window(menuBar=True) # cmds.objectTypeUI(win) # would error... typesToCheck.append('window') for cmdName in typesToCheck: if getattr(cmds, cmdName)(name, ex=1, q=1): uiType = cmdName break if uiType: return uiType raise topError
def reload_riggingShelf(): version=str(versions.current())[:4] result = '/software/tools/maya/2012/mel/riggingTools/4.24/rig/ui/shelf_rigging.mel' if result: shelf_name = result.split('/')[-1:][0].split('.')[0].split('_')[1] if pm.shelfLayout(shelf_name,q=True,exists=True): f=open(result,'r') createMyShelf( shelf_name, f.read())
def test_pointArray(self): if versions.current() < versions.v2011: # complex array cmds.setAttr( 'node.pointArrayAttr', 2, (1,2,3,4), "", (1,2,3,4), type='pointArray' ) assert cmds.getAttr( 'node.pointArrayAttr' ) == [(1.0, 2.0, 3.0, 4.0), (1.0, 2.0, 3.0, 4.0)] else: cmds.setAttr( 'node.pointArrayAttr', 2, (1,2,3,4), (1,2,3,4), type='pointArray' ) assert cmds.getAttr( 'node.pointArrayAttr' ) == [(1.0, 2.0, 3.0, 4.0), (1.0, 2.0, 3.0, 4.0)]
def get_user_shelves_dir(): """ Returns the current user's shelves directory Args: None Returns (str): string for the user's shelves directory based on the version of maya """ version=str(versions.current())[:4] return os.path.join(os.path.expanduser('~'), '/maya/%s-x64/prefs/shelves/' % version)
def _installCallbacks(): """install the callbacks that trigger new nodes and commands to be added to pymel when a plugin loads. This is called from pymel.__init__ """ global _pluginLoadedCB if _pluginLoadedCB is None: _pluginLoadedCB = True _logger.debug("Adding pluginLoaded callback") #_pluginLoadedCB = pluginLoadedCallback(module) if _versions.current() >= _versions.v2009: id = _api.MSceneMessage.addStringArrayCallback( _api.MSceneMessage.kAfterPluginLoad, _pluginLoaded ) if hasattr(id, 'disown'): id.disown() else: # BUG: this line has to be a string, because using a function causes a 'pure virtual' error every time maya shuts down cmds.loadPlugin( addCallback='import pymel.core; pymel.core._pluginLoaded("%s")' ) else: _logger.debug("PluginLoaded callback already exists") global _pluginUnloadedCB if _pluginUnloadedCB is None: _pluginUnloadedCB = True # BUG: autodesk still has not add python callback support, and calling this as MEL is not getting the plugin name passed to it #mel.unloadPlugin( addCallback='''python("import pymel; pymel._pluginUnloaded('#1')")''' ) if _versions.current() >= _versions.v2009: _logger.debug("Adding pluginUnloaded callback") id = _api.MSceneMessage.addStringArrayCallback( _api.MSceneMessage.kAfterPluginUnload, _pluginUnloaded ) if hasattr(id, 'disown'): id.disown() else: _logger.debug("PluginUnloaded callback already exists") # add commands and nodes for plugins loaded prior to importing pymel preLoadedPlugins = cmds.pluginInfo( q=1, listPlugins=1 ) if preLoadedPlugins: _logger.info("Updating pymel with pre-loaded plugins: %s" % ', '.join( preLoadedPlugins )) for plugin in preLoadedPlugins: _pluginLoaded( plugin )
def read(self, raw=False): data = super(ApiCache, self).read() if not raw: # Before 2012, we cached reservedMayaTypes and reservedApiTypes, # even though they weren't used... if data is not None and len(data) != len(self._CACHE_NAMES): if len(data) == 8 and versions.current() < versions.v2012: data = data[2:6] + data[7:] else: # we need to rebuild, return None data = None return data
def _getNodeHierarchy( version=None ): """ get node hierarchy as a list of 3-value tuples: ( nodeType, parents, children ) """ import pymel.util.trees as trees if versions.current() >= versions.v2012: # We now have nodeType(isTypeName)! yay! # For whatever reason, we can't query these objects from the hierarchy # correctly using nodeType(isTypeName) inheritances = {'file':[u'texture2d', u'file']} for nodeType in cmds.allNodeTypes(): inheritance = cmds.nodeType(nodeType, inherited=True, isTypeName=True) if inheritance is None: if nodeType in inheritances: pass else: raise RuntimeError("Could not query the inheritance of node type %s" % nodeType) else: inheritances[nodeType] = inheritance parentTree = {} # Convert inheritance lists node=>parent dict for nodeType, inheritance in inheritances.iteritems(): assert inheritance[-1] == nodeType for i in xrange(len(inheritance)): child = inheritance[i] if i == 0: if child == 'dependNode': continue else: parent = 'dependNode' else: parent = inheritance[i - 1] if child in parentTree: assert parentTree[child] == parent else: parentTree[child] = parent nodeHierarchyTree = trees.treeFromDict(parentTree) else: from parsers import NodeHierarchyDocParser parser = NodeHierarchyDocParser(version) nodeHierarchyTree = trees.IndexedTree(parser.parse()) return [ (x.value, tuple( [y.value for y in x.parents()]), tuple( [y.value for y in x.childs()] ) ) \ for x in nodeHierarchyTree.preorder() ]
def shelf_reloader(customShelf=None): version=str(versions.current())[:4] prefs=os.path.join(os.path.expanduser('~') + '/maya/%s-x64/prefs/shelves/' % version) if customShelf: shelf_name = customShelf.split('/')[-1:][0].split('.')[0].split('_')[1] f=open(customShelf,'r') createMyShelf( shelf_name, f.read()) else: if os.path.exists(prefs): result=pm.fileDialog2(ff='*.mel', ds=2, fm=4,dir=prefs) if result: shelf_name = result[0].split('/')[-1:][0].split('.')[0].split('_')[1] print 'Replacing shelf %s from file:\n%s' % (shelf_name,result) if pm.shelfLayout(shelf_name,q=True,exists=True): f=open(result[0],'r') createMyShelf( shelf_name, f.read())
def _getNodeHierarchy(version=None): """ get node hierarchy as a list of 3-value tuples: ( nodeType, parents, children ) """ import pymel.util.trees as trees import pymel.internal.apicache as apicache if versions.current() >= versions.v2012: # We now have nodeType(isTypeName)! yay! inheritances = {} for nodeType in apicache._getAllMayaTypes(): try: inheritances[nodeType] = apicache.getInheritance(nodeType) except apicache.ManipNodeTypeError: continue except Exception: print "Error getting inheritance: %s" % nodeType raise parentTree = {} # Convert inheritance lists node=>parent dict for nodeType, inheritance in inheritances.iteritems(): for i in xrange(len(inheritance)): child = inheritance[i] if i == 0: if child == 'dependNode': continue else: parent = 'dependNode' else: parent = inheritance[i - 1] if child in parentTree: assert parentTree[child] == parent, "conflicting parents: node type '%s' previously determined parent was '%s'. now '%s'" % (child, parentTree[child], parent) else: parentTree[child] = parent nodeHierarchyTree = trees.treeFromDict(parentTree) else: from .parsers import NodeHierarchyDocParser parser = NodeHierarchyDocParser(version) nodeHierarchyTree = trees.IndexedTree(parser.parse()) return [(x.value, tuple(y.value for y in x.parents()), tuple(y.value for y in x.childs())) for x in nodeHierarchyTree.preorder()]
def menu(*args, **kwargs): """ Modifications - added ability to query parent """ if _versions.current() < _versions.v2011: # on create only if not ( kwargs.get('query', False) or kwargs.get('q', False) ) \ and not ( kwargs.get('edit', False) or kwargs.get('e', False) ) \ and not ( kwargs.get('parent', False) or kwargs.get('p', False) ): kwargs['parent'] = cmds.setParent(q=1) if ( kwargs.get('query', False) or kwargs.get('q', False) ) \ and ( kwargs.get('parent', False) or kwargs.get('p', False) ): name = unicode(args[0]) if '|' not in name: name = _findLongName(name, 'menu') return name.rsplit('|',1)[0] return cmds.menu(*args, **kwargs)
def menu(*args, **kwargs): """ Modifications - added ability to query parent """ if _versions.current() < _versions.v2011: # on create only if ( not (kwargs.get("query", False) or kwargs.get("q", False)) and not (kwargs.get("edit", False) or kwargs.get("e", False)) and not (kwargs.get("parent", False) or kwargs.get("p", False)) ): kwargs["parent"] = cmds.setParent(q=1) if (kwargs.get("query", False) or kwargs.get("q", False)) and ( kwargs.get("parent", False) or kwargs.get("p", False) ): name = unicode(args[0]) if "|" not in name: name = _findLongName(name, "menu") return name.rsplit("|", 1)[0] return cmds.menu(*args, **kwargs)
def parse(self): docloc = mayaDocsLocation(self.version) if not os.path.isdir( docloc ): raise IOError, "Cannot find maya documentation. Expected to find it at %s" % docloc f = open( os.path.join( docloc , 'Nodes/index_hierarchy.html' ) ) try: rawdata = f.read() finally: f.close() if versions.v2011 <= versions.current() < versions.v2012: # The maya 2011 doc doesn't parse correctly with HTMLParser - the # '< < <' lines get left out. Use beautiful soup instead. soup = BeautifulSoup( rawdata, convertEntities='html' ) for tag in soup.findAll(['tt', 'a']): # piggypack on current handle_starttag / handle_data self.handle_starttag(tag.name, tag.attrs) data = tag.string if data is not None: self.handle_data(data) else: self.feed( rawdata ) return self.tree
def create(self): """ Generates a new maya window object and binds it to the singleton instance. """ SCENE = Scene() self._win = window(title=self.window_title, resizeToFitChildren=True) with self._win: template = uiTemplate('LocalSubmitTemplate', force=True ) template.define(frameLayout, bs='etchedIn', mw=6, mh=6, labelVisible=False) template.define(columnLayout, adj=True, rs=4) template.define(formLayout, nd=100) # padding adjustment for pre-qt maya versions if versions.current() <= versions.v2010: template.define(text, align='right', h=22) else: template.define(text, align='right', h=20) with template: with formLayout() as mainForm: with frameLayout() as setFrame: with formLayout() as setForm: with columnLayout() as setCol1: text(label="Title:") text(label="Start Frame:") text(label="End Frame:") text(label="Frame Step:") text(label="Emulation:", annotation='If selected, the local render will behave in the same environtment as the Cluster, otherwise it will act as a normal local batch render') with columnLayout() as setCol2: self._controls['title'] = textField(text=get_scene_name()) self._controls['start'] = intField(value=get_frame_range()[0]) self._controls['end'] = intField(value=get_frame_range()[1]) self._controls['step'] = intField(value=int(SCENE.defaultRenderGlobals.byFrameStep.get())) self._controls['emulate'] = checkBox(label="Cluster Emulation", annotation='If selected, the local render will behave in the same environtment as the Cluster, otherwise it will act as a normal local batch render') self._controls['pause'] = checkBox(label="Pause before exit") # self._controls['debug'] = checkBox(label="Show debug messages") setForm.attachForm(setCol1, 'left', 4) setForm.attachControl(setCol1, 'right', 2, setCol2) setForm.attachForm(setCol2, 'right', 4) setForm.attachPosition(setCol2, 'left', 40, 20) with frameLayout() as subFrame: submit_btn = button(label="Submit", width=200, height=40, align='center') submit_btn.setCommand(self.submit_job) mainForm.attachForm(setFrame, 'top', 4) mainForm.attachForm(setFrame, 'left', 4) mainForm.attachForm(setFrame, 'right', 4) mainForm.attachControl(setFrame, 'bottom', 4, subFrame) mainForm.attachForm(subFrame, 'bottom', 4) mainForm.attachForm(subFrame, 'left', 4) mainForm.attachForm(subFrame, 'right', 4) """ We force the closure of an open submit window on scene open to ensure the new scene's settings are reflected. """ scriptJob(parent=self._win, runOnce=True, event=('SceneOpened', SubmitGui.destroy))
def _pluginLoaded(*args): global _pluginData if len(args) > 1: # 2009 API callback, the args are ( [ pathToPlugin, pluginName ], clientData ) pluginName = args[0][1] else: pluginName = args[0] if not pluginName: return # Check to see if plugin is really loaded if not (cmds.pluginInfo(pluginName, query=1, loaded=1)): return # Make sure there are no registered callbacks for this plug-in. It has been # reported that some 3rd party plug-ins will enter here twice, causing a # "callback id leak" which potentially leads to a crash. The reported # scenario was: # - Launching mayapy.exe # - Opening a Maya scene having a requires statement (to the plug-in) # - The plug-in imports pymel, causing initialization and entering here. if (pluginName in _pluginData) and 'callbackId' in _pluginData[ pluginName] and _pluginData[pluginName]['callbackId'] != None: _api.MEventMessage.removeCallback( _pluginData[pluginName]['callbackId']) _logger.debug("Plugin loaded: %s", pluginName) _pluginData[pluginName] = {} # Commands commands = _plugins.pluginCommands(pluginName) if commands: # clear out the command list first _pluginData[pluginName]['commands'] = [] for funcName in commands: try: _addPluginCommand(pluginName, funcName) except Exception as e: _logger.error("Error adding command %s from plugin %s - %s" % (funcName, pluginName, e)) _logger.debug(traceback.format_exc()) # Nodes try: mayaTypes = cmds.pluginInfo(pluginName, query=1, dependNode=1) except Exception: _logger.error("Failed to get depend nodes list from %s", pluginName) mayaTypes = None #apiEnums = cmds.pluginInfo(pluginName, query=1, dependNodeId=1) if mayaTypes: def addPluginPyNodes(*args): try: id = _pluginData[pluginName].get('callbackId') except KeyError: _logger.warning("could not find callback id!") else: if id is not None: _api.MEventMessage.removeCallback(id) if hasattr(id, 'disown'): id.disown() _pluginData[pluginName]['dependNodes'] = [] allTypes = set(cmds.ls(nodeTypes=1)) for mayaType in mayaTypes: # make sure it's a 'valid' type - some plugins list node types # that don't show up in ls(nodeTypes=1), and aren't creatable # ...perhaps they're abstract types? # Unfortunately, can't check this, as only plugin I know of # that has such a node - mayalive, mlConstraint - is only # available up to 2009, which has a bug with allNodeTypes... # Oddly enough, mlConstraint WILL show up in allTypes here, # but not after the plugin is loaded / callback finishes...? if mayaType not in allTypes: continue _addPluginNode(pluginName, mayaType) # Note - in my testing, a single _api.MFileIO.isReadingFile() call would # also catch opening + referencing operations... but in commit # 6e53d7818e9363d55d417c3a80ea7df94c4998ec, a check only against # isReadingFile is commented out... so I'm playing it safe, and assuming # there are edge cases where isOpeningFile is True but isReadingFile is # not # Detect if we are currently opening/importing a file and load as a callback versus execute now if (_api.MFileIO.isReadingFile() or _api.MFileIO.isOpeningFile() or (_versions.current() >= _versions.v2012 and _api.MFileIO.isReferencingFile())): if _versions.current( ) >= _versions.v2012 and _api.MFileIO.isReferencingFile(): _logger.debug( "Installing temporary plugin-loaded nodes callback - PostSceneRead" ) id = _api.MEventMessage.addEventCallback( 'PostSceneRead', addPluginPyNodes) elif _api.MFileIO.isImportingFile(): _logger.debug( "Installing temporary plugin-loaded nodes callback - SceneImported" ) id = _api.MEventMessage.addEventCallback( 'SceneImported', addPluginPyNodes) else: # pre-2012 referencing operations will fall into this branch, # which will not work (ie, pre-2012, plugins loaded due to # reference loads will not trigger adding of that plugin's # PyNodes). # While this is obviously less than ideal, no 2011 versions were # available for testing when I made the fix for 2012+, and we # decided that making nothing worse would be better than # potentially introducing problems/instabilities (ie, see # messages in commits 6e53d7818e9363d55d417c3a80ea7df94c4998ec # and 81bc5ee28f1775a680449fec8724e21e703a52b8). _logger.debug( "Installing temporary plugin-loaded nodes callback - SceneOpened" ) id = _api.MEventMessage.addEventCallback( 'SceneOpened', addPluginPyNodes) _pluginData[pluginName]['callbackId'] = id # scriptJob not respected in batch mode, had to use _api #cmds.scriptJob( event=('SceneOpened',doSomethingElse), runOnce=1 ) else: _logger.debug("Running plugin-loaded nodes callback") # add the callback id as None, so addPluginPyNodes SHOULD know that # SOMETHING is always in _pluginData[pluginName]['callbackId'], and # if there isn't, then something is wrong... _pluginData[pluginName]['callbackId'] = None addPluginPyNodes()
def getInheritance(mayaType, checkManip3D=True, checkCache=True, updateCache=True): """Get parents as a list, starting from the node after dependNode, and ending with the mayaType itself. Raises a ManipNodeTypeError if the node type fed in was a manipulator """ # To get the inheritance post maya2012, we use nodeType(isTypeName=True), # which means we don't need a real node. However, in maya < 2012, nodeType # requires a real node. To do get these without poluting the scene we use the # _GhostObjMaker, which on enter, uses a dag/dg modifier, and calls the doIt # method; we then get the lineage, and on exit, it calls undoIt. global _cachedInheritances if checkCache and mayaType in _cachedInheritances: return _cachedInheritances[mayaType] import maya.cmds as cmds lineage = None if versions.current() >= versions.v2012: # We now have nodeType(isTypeName)! yay! try: lineage = cmds.nodeType(mayaType, isTypeName=True, inherited=True) except RuntimeError: pass else: with _GhostObjMaker(mayaType) as obj: if obj is not None: if obj.hasFn(api.MFn.kDagNode): name = api.MFnDagNode(obj).partialPathName() else: name = api.MFnDependencyNode(obj).name() if not obj.isNull() and not obj.hasFn( api.MFn.kManipulator3D) and not obj.hasFn( api.MFn.kManipulator2D): lineage = cmds.nodeType(name, inherited=1) if lineage is None: global _fixedLineages if not _fixedLineages: if versions.current() >= versions.v2012: controlPoint = cmds.nodeType('controlPoint', isTypeName=True, inherited=True) else: controlPoint = [ u'containerBase', u'entity', u'dagNode', u'shape', u'geometryShape', u'deformableShape', u'controlPoint' ] # maya2013 introduced shadingDependNode... if versions.current() >= versions.v2013: texture2d = ['shadingDependNode', 'texture2d'] else: texture2d = ['texture2d'] # For whatever reason, nodeType(isTypeName) returns # None for the following mayaTypes: _fixedLineages = { 'node': [], 'file': texture2d + [u'file'], 'lattice': controlPoint + [u'lattice'], 'mesh': controlPoint + [u'surfaceShape', u'mesh'], 'nurbsCurve': controlPoint + [u'curveShape', u'nurbsCurve'], 'nurbsSurface': controlPoint + [u'surfaceShape', u'nurbsSurface'], 'time': [u'time'] } if mayaType in _fixedLineages: lineage = _fixedLineages[mayaType] else: raise RuntimeError( "Could not query the inheritance of node type %s" % mayaType) elif checkManip3D and 'manip3D' in lineage: raise ManipNodeTypeError try: assert (mayaType == 'node' and lineage == []) or lineage[-1] == mayaType except Exception: print mayaType, lineage raise if len(set(lineage)) != len(lineage): # cyclical lineage: first discovered with xgen nodes. # might be a result of multiple inheritance being returned strangely by nodeType. # # an example lineage is: # [u'containerBase', u'entity', u'dagNode', u'shape', u'geometryShape', u'locator', u'THlocatorShape', u'SphereLocator', # u'containerBase', u'entity', u'dagNode', u'shape', u'geometryShape', u'locator', u'THlocatorShape', u'aiSkyDomeLight'] # note the repeat - we will try to fix lineages like this, resolving to: # [u'containerBase', u'entity', u'dagNode', u'shape', u'geometryShape', u'locator', u'THlocatorShape', u'SphereLocator', u'aiSkyDomeLight'] # first pop the rightmost element, which is the mayaType... if lineage.pop() != mayaType: raise RuntimeError( "lineage for %s did not end with it's own node type" % mayaType) # then try to find the first element somewhere else - this should indicate the start of the repeated chain... try: nextIndex = lineage.index(lineage[0], 1) except ValueError: # unknown case, don't know how to fix... pass else: firstLineage = lineage[:nextIndex] secondLineage = lineage[nextIndex:] if len(firstLineage) < len(secondLineage): shorter = firstLineage longer = secondLineage else: shorter = secondLineage longer = firstLineage if longer[:len(shorter)] == shorter: # yay! we know how to fix! lineage = longer lineage.append(mayaType) if updateCache and lineage: if len(set(lineage)) != len(lineage): # cyclical lineage: first discovered with xgen nodes. # might be a result of multiple inheritance being returned strangely by nodeType. print mayaType, lineage _logger.raiseLog( _logger.WARNING, "lineage for node %s is cyclical: %s" % (mayaType, lineage)) _cachedInheritances[mayaType] = lineage # don't cache any of the parents return lineage # add not just this lineage, but all parent's lineages as well... for i in xrange(len(lineage), 0, -1): thisLineage = lineage[:i] thisNode = thisLineage[-1] oldVal = _cachedInheritances.get(thisNode) if oldVal is None: _cachedInheritances[thisNode] = thisLineage elif oldVal != thisLineage: _logger.raiseLog( _logger.WARNING, "lineage for node %s changed:\n from %s\n to %s)" % (thisNode, oldVal, thisLineage)) _cachedInheritances[thisNode] = thisLineage return lineage
class testCase_mayaSetAttr(unittest.TestCase): """ sanity check: make sure we know how to set and get attributes via maya's setAttr. this serves mostly to document all the inconsistencies in setAttr so that we can sort them out in our own wrap. it will also alert us to any changes that Autodesk makes. """ def setUp(self): _makeAllAttrTypes('node') def test_short2(self): # compound cmds.setAttr('node.short2Attr', 1, 2) assert cmds.getAttr('node.short2Attr') == [(1, 2)] def test_short3(self): cmds.setAttr('node.short3Attr', 1, 2, 3) assert cmds.getAttr('node.short3Attr') == [(1, 2, 3)] def test_long2(self): cmds.setAttr('node.long2Attr', 1, 2) assert cmds.getAttr('node.long2Attr') == [(1, 2)] def test_long3(self): cmds.setAttr('node.long3Attr', 1, 2, 3) assert cmds.getAttr('node.long3Attr') == [(1, 2, 3)] def test_float2(self): cmds.setAttr('node.float2Attr', 1, 2) assert cmds.getAttr('node.float2Attr') == [(1.0, 2.0)] def test_float(self): cmds.setAttr('node.float3Attr', 1, 2, 3) assert cmds.getAttr('node.float3Attr') == [(1.0, 2.0, 3.0)] def test_double2(self): cmds.setAttr('node.double2Attr', 1, 2) assert cmds.getAttr('node.double2Attr') == [(1.0, 2.0)] def test_double3(self): cmds.setAttr('node.double3Attr', 1, 2, 3) assert cmds.getAttr('node.double3Attr') == [(1.0, 2.0, 3.0)] def test_int32Array(self): # array cmds.setAttr('node.Int32ArrayAttr', (1, 2, 3, 4), type='Int32Array') assert cmds.getAttr('node.Int32ArrayAttr') == [1, 2, 3, 4] def test_doubleArray(self): cmds.setAttr('node.doubleArrayAttr', (1, 2, 3, 4), type='doubleArray') assert cmds.getAttr('node.doubleArrayAttr') == [1.0, 2.0, 3.0, 4.0] def test_pointArray(self): if versions.current() < versions.v2011: # complex array cmds.setAttr('node.pointArrayAttr', 2, (1, 2, 3, 4), "", (1, 2, 3, 4), type='pointArray') assert cmds.getAttr('node.pointArrayAttr') == [ (1.0, 2.0, 3.0, 4.0), (1.0, 2.0, 3.0, 4.0) ] else: cmds.setAttr('node.pointArrayAttr', 2, (1, 2, 3, 4), (1, 2, 3, 4), type='pointArray') assert cmds.getAttr('node.pointArrayAttr') == [ (1.0, 2.0, 3.0, 4.0), (1.0, 2.0, 3.0, 4.0) ] def test_vectorArray(self): if versions.current() < versions.v2011: cmds.setAttr('node.vectorArrayAttr', 2, (1, 2, 3), "", (1, 2, 3), type='vectorArray') assert cmds.getAttr('node.vectorArrayAttr') == [ 1.0, 2.0, 3.0, 1.0, 2.0, 3.0 ] else: cmds.setAttr('node.vectorArrayAttr', 2, (1, 2, 3), (1, 2, 3), type='vectorArray') assert cmds.getAttr('node.vectorArrayAttr') == [(1.0, 2.0, 3.0), (1.0, 2.0, 3.0)] def test_stringArray(self): # string array cmds.setAttr('node.stringArrayAttr', 3, 'one', 'two', 'three', type='stringArray') assert cmds.getAttr('node.stringArrayAttr') == [ u'one', u'two', u'three' ] def test_string(self): cmds.setAttr('node.stringAttr', 'one', type='string') assert cmds.getAttr('node.stringAttr') == u'one' if versions.current() >= versions.v2011: def test_matrix(self): # matrix # Fails in versions < 2011 cmds.setAttr('node.matrixAttr', 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, type='matrix') assert cmds.getAttr('node.matrixAttr') == [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] def test_sphere(self): # non-numeric: can't get cmds.setAttr('node.sphereAttr', 1.0, type='sphere') #assert cmds.getAttr( 'node.sphereAttr' ) == 1.0 def test_cone(self): cmds.setAttr('node.coneAttr', 45, 45, type='cone') #assert cmds.getAttr( 'node.coneAttr' ) == 1.0 def test_reflectanceRGB(self): cmds.setAttr('node.reflectanceRGBAttr', 1, 1, 1, type='reflectanceRGB')
def mayaInit(forversion=None): """ Try to init Maya standalone module, use when running pymel from an external Python interpreter, it is possible to pass the desired Maya version number to define which Maya to initialize Part of the complexity of initializing maya in standalone mode is that maya does not populate os.environ when parsing Maya.env. If we initialize normally, the env's are available via maya (via the shell), but not in python via os.environ. Note: the following example assumes that MAYA_SCRIPT_PATH is not set in your shell environment prior to launching python or mayapy. >>> import maya.standalone #doctest: +SKIP >>> maya.standalone.initialize() #doctest: +SKIP >>> import maya.mel as mm #doctest: +SKIP >>> print mm.eval("getenv MAYA_SCRIPT_PATH") #doctest: +SKIP /Network/Servers/sv-user.luma-pictures.com/luma ..... >>> import os #doctest: +SKIP >>> 'MAYA_SCRIPT_PATH' in os.environ #doctest: +SKIP False The solution lies in `refreshEnviron`, which copies the environment from the shell to os.environ after maya.standalone initializes. :rtype: bool :return: returns True if maya.cmds required initializing ( in other words, we are in a standalone python interpreter ) """ _logger.debug("startup.mayaInit: called") setupFormatting() global isInitializing # test that Maya actually is loaded and that commands have been initialized,for the requested version aboutExists = False try: from maya.cmds import about aboutExists = True except ImportError: pass if aboutExists and mayaStartupHasStarted(): # if this succeeded, we're initialized _logger.debug("startup.mayaInit: maya already started - exiting") isInitializing = False return False _logger.debug("startup.mayaInit: running") # for use with pymel compatible maya package os.environ['MAYA_SKIP_USERSETUP_PY'] = 'on' if not aboutExists and not sys.modules.has_key('maya.standalone'): try: _logger.debug("startup.mayaInit: running standalone.initialize") import maya.standalone #@UnresolvedImport maya.standalone.initialize(name="python") if versions.current() < versions.v2009: refreshEnviron() except ImportError, e: raise e, str( e) + ": pymel was unable to initialize maya.standalone"
class PyUI(unicode): def __new__(cls, name=None, create=False, **kwargs): """ Provides the ability to create the PyUI Element when creating a class:: import pymel.core as pm n = pm.Window("myWindow",create=True) n.__repr__() # Result: Window('myWindow') """ if cls is PyUI: try: uiType = objectTypeUI(name) except RuntimeError: uiType = 'PyUI' uiType = _uiTypesToCommands.get(uiType, uiType) try: newcls = getattr(dynModule, _util.capitalize(uiType)) except AttributeError: newcls = PyUI # objectTypeUI for panels seems to return weird results - # ie, TmodelPane ... check for them this way. # Other types should be detected correctly by objectTypeUI, # but this just provides a failsafe... for testType in 'panel scriptedPanel window control layout menu'.split( ): if getattr(cmds, testType)(name, ex=1, q=1): newcls = getattr(dynModule, _util.capitalize(testType), PyUI) if newcls != PyUI: break else: newcls = cls if not newcls is PyUI: if cls._isBeingCreated(name, create, kwargs): name = newcls.__melcmd__(name, **kwargs) _logger.debug("PyUI: created... %s" % name) else: # find the long name if '|' not in name and not issubclass( newcls, (Window, Panel, dynModule.ScriptedPanel, dynModule.RadioCollection, dynModule.ToolCollection)): import windows try: if issubclass(newcls, Layout): parent = windows.layout(name, q=1, p=1) elif issubclass(newcls, OptionMenu): parent = windows.optionMenu(name, q=1, p=1) elif issubclass(newcls, Menu): parent = windows.menu(name, q=1, p=1) else: parent = windows.control(name, q=1, p=1) if parent: name = parent + '|' + name except RuntimeError: # editors don't have a long name, so we keep the short name if name not in cmds.lsUI(long=True, editors=True): raise # correct for optionMenu if newcls == PopupMenu and cmds.optionMenu(name, ex=1): newcls = OptionMenu return unicode.__new__(newcls, name) @staticmethod def _isBeingCreated(name, create, kwargs): """ create a new node when any of these conditions occur: name is None create is True parent flag is set """ return not name or create or ('q' not in kwargs and kwargs.get( 'parent', kwargs.get('p', None))) def __repr__(self): return u"ui.%s('%s')" % (self.__class__.__name__, self) def parent(self): buf = unicode(self).split('|')[:-1] if len(buf) == 2 and buf[0] == buf[1] and _versions.current( ) < _versions.v2011: # pre-2011, windows with menus can have a strange name: # ex. window1|window1|menu1 buf = buf[:1] if not buf: return None return PyUI('|'.join(buf)) getParent = parent def shortName(self): return unicode(self).split('|')[-1] def name(self): return unicode(self) def window(self): return Window(self.name().split('|')[0]) delete = _factories.functionFactory('deleteUI', rename='delete') rename = _factories.functionFactory('renameUI', rename='rename') type = objectTypeUI @classmethod def exists(cls, name): return cls.__melcmd__(name, exists=True) if _versions.current() >= _versions.v2011: asQtObject = toQtControl
import sys Dir = 'C:/Users/Administrator/Documents/GitHub/PyQt_For_Maya-2016-2017' PyQt4Dir = 'C:/Python27/Lib/site-packages' from pymel import versions try: versions.v2017 except: versions.v2017 = 201700 try: versions.v2015 except: versions.v2015 = 201500 if versions.current() >= versions.v2017: import PySide2.QtCore as qc import PySide2.QtWidgets as qw import PySide2.QtGui as qg if Dir not in sys.path: sys.path.append(Dir) import PraLib.utils.generic as generic reload(generic) from PraLib.utils.generic import loadUiType elif versions.current() >= versions.v2015: import PySide.QtCore as qc import PySide.QtGui as qw import PySide.QtGui as qg if Dir not in sys.path: sys.path.append(Dir) import PraLib.utils.generic as generic
import os import pymel.util as util import pymel.versions as versions #import mayautils import maya.cmds import warnings __all__ = ['getMelRepresentation'] _thisModule = sys.modules[__name__] # In Maya <= 2011, the error would be: # TypeError: Object foo.bar is invalid # In Maya 2012, it is: # ValueError: No object matches name: foo.bar if versions.current() < versions.v2012: objectErrorType = TypeError objectErrorReg = re.compile(',?Object (.*) is invalid,?$') else: objectErrorType = ValueError objectErrorReg = re.compile(',?No object matches name: ,?(.*)$') def _testDecorator(function): def newFunc(*args, **kwargs): print "wrapped function for %s" % function.__name__ return function(*args, **kwargs) newFunc.__name__ = function.__name__ newFunc.__doc__ = function.__doc__ return newFunc
('MFnSubdNames', 'methods', 'baseFaceIndexFromId', 0, 'doc'), # This is a valid fix - MFnIkJoint::getPreferedAngle (the mispelled, # obsolete one) formerly had 'rotation' improperly marked as an in arg ('MFnIkJoint', 'methods', 'getPreferedAngle', 0, 'args', 0, 2), ('MFnIkJoint', 'methods', 'getPreferedAngle', 0, 'inArgs', 0), ('MFnIkJoint', 'methods', 'getPreferedAngle', 0, 'outArgs', 0), # A valid fix - 'const unsigned short' was formerly parsed (in the xml) # as a type of "const unsigned" and a name of "short" ('MFloatPoint', 'methods', '__imul__', 4, 'argInfo', 'factor', 'type'), ('MFloatPoint', 'methods', '__imul__', 4, 'args', 0, 1), ('MFloatPoint', 'methods', '__imul__', 4, 'types', 'factor'), ('MPoint', 'methods', '__imul__', 4, 'argInfo', 'factor', 'type'), ('MPoint', 'methods', '__imul__', 4, 'args', 0, 1), ('MPoint', 'methods', '__imul__', 4, 'types', 'factor'), ] if versions.current() // 10000 == cacheversions['new']: for multiKey in CAN_IGNORE_2021: delDiff(multiKey) ################################################################################ # KNOWN PROBLEMS # place to temporarily put issues that need fixing, but you want to filter KNOWN_PROBLEMS_2021 = [] if versions.current() // 10000 == cacheversions['new']: for multiKey in KNOWN_PROBLEMS_2021: delDiff(multiKey)
lookup.insert(0, preferredBinding) for binding in lookup: try: return _qt_import(binding, shi, cui) except Exception: pass raise _qt_import("ThisBindingSurelyDoesNotExist", False, False) ############################################# # helper Maya pyQt functions ############################################# if versions.current() < 20220000: compileUi = qt_import(shi=True, cui=True)[-1] def ui2py(filePath=None, *args): """Convert qtDesigner .ui files to .py""" if not filePath: startDir = pm.workspace(q=True, rootDirectory=True) filePath = pm.fileDialog2( dialogStyle=2, fileMode=1, startingDirectory=startDir, fileFilter='PyQt Designer (*%s)' % UI_EXT, okc="Compile to .py") if not filePath: return False
def addCtl(self, parent, name, m, color, iconShape, tp=None, lp=True, mirrorConf=[0, 0, 0, 0, 0, 0, 0, 0, 0], **kwargs): """ Create the control and apply the shape, if this is alrealdy stored in the guide controllers grp. Args: parent (dagNode): The control parent name (str): The control name. m (matrix): The transfromation matrix for the control. color (int or list of float): The color for the control in index or RGB. iconShape (str): The controls default shape. tp (dagNode): Tag Parent Control object to connect as a parent controller lp (bool): Lock the parent controller channels kwargs (variant): Other arguments for the iconShape type variations Returns: dagNode: The Control. """ if "degree" not in kwargs.keys(): kwargs["degree"] = 1 fullName = self.getName(name) bufferName = fullName + "_controlBuffer" if bufferName in self.rig.guide.controllers.keys(): ctl_ref = self.rig.guide.controllers[bufferName] ctl = primitive.addTransform(parent, fullName, m) for shape in ctl_ref.getShapes(): ctl.addChild(shape, shape=True, add=True) pm.rename(shape, fullName + "Shape") icon.setcolor(ctl, color) else: ctl = icon.create(parent, fullName, m, color, iconShape, **kwargs) # create the attributes to handlde mirror and symetrical pose attribute.add_mirror_config_channels(ctl, mirrorConf) if self.settings["ctlGrp"]: ctlGrp = self.settings["ctlGrp"] self.addToGroup(ctl, ctlGrp, "controllers") else: ctlGrp = "controllers" self.addToGroup(ctl, ctlGrp) # lock the control parent attributes if is not a control if parent not in self.groups[ctlGrp] and lp: self.transform2Lock.append(parent) # Set the control shapes isHistoricallyInteresting for oShape in ctl.getShapes(): oShape.isHistoricallyInteresting.set(False) # set controller tag if versions.current() >= 201650: try: oldTag = pm.PyNode(ctl.name() + "_tag") if not oldTag.controllerObject.connections(): # NOTE: The next line is comment out. Because this will # happend alot since maya does't clean # controller tags after deleting the control Object of the # tag. This have been log to Autodesk. # If orphane tags are found, it will be clean in silence. # pm.displayWarning("Orphane Tag: %s will be delete and # created new for: %s"%(oldTag.name(), ctl.name())) pm.delete(oldTag) except TypeError: pass self.add_controller_tag(ctl, tp) return ctl
import pickle #from maya.cmds import encodeString isInitializing = False # Setting this to False will make finalize() do nothing finalizeEnabled = True _finalizeCalled = False _mayaExitCallbackId = None _mayaUninitialized = False _atExitCallbackInstalled = False # tells whether this maya package has been modified to work with pymel pymelMayaPackage = hasattr( maya.utils, 'shellLogHandler') or versions.current() >= versions.v2011 # used to test by using hasattr(maya.standalone, 'uninitialize')... # but that requires importing maya.standalone, and pymel actually checks for # it's existence in maya.cmds # would like to remove that check, but could potentially break backward compat - # ie, if someone does: # import maya.standalone # import pymel # import maya.standalone.initialize() _hasUninitialize = versions.current() >= versions.v2016 def _moduleJoin(*args): """ Joins with the base pymel directory.
_logger.warning("using pickle instead of cPickle: load performance will be affected") import pickle #from maya.cmds import encodeString isInitializing = False # Setting this to False will make finalize() do nothing finalizeEnabled = True _finalizeCalled = False _mayaExitCallbackId = None _mayaUninitialized = False _atExitCallbackInstalled = False # tells whether this maya package has been modified to work with pymel pymelMayaPackage = hasattr(maya.utils, 'shellLogHandler') or versions.current() >= versions.v2011 # used to test by using hasattr(maya.standalone, 'uninitialize')... # but that requires importing maya.standalone, and pymel actually checks for # it's existence in maya.cmds # would like to remove that check, but could potentially break backward compat - # ie, if someone does: # import maya.standalone # import pymel # import maya.standalone.initialize() _hasUninitialize = versions.current() >= versions.v2016 def _moduleJoin(*args): """ Joins with the base pymel directory. :rtype: string
#coding=cp936 #coding=utf-8 from pymel import versions import sys import os def pySource(filePath): myFile = os.path.basename(filePath) dir = os.path.dirname(filePath) fileName = os.path.splitext(myFile)[0] if( os.path.exists( dir ) ): paths = sys.path pathfound = 0 for path in paths: if(dir == path): pathfound = 1 if not pathfound: sys.path.append( dir ) exec('import ' +fileName) in globals() exec( 'reload( ' + fileName + ' )' ) in globals() return fileName ver = versions.current() if str(ver) =="201300": pySource( '//10.99.1.12/数码电影/临时交换/02生产二线/02G角色/员工文件/X_徐思健/python_source/python_source_2013/SJMtoolbox_2013.pyc') print "This is SJtoolbox of Maya2013Version,enjoy it" if str(ver) =="201516": pySource( '//10.99.1.12/数码电影/临时交换/02生产二线/02G角色/员工文件/X_徐思健/python_source/python_source_2015/SJMtoolbox_2015.pyc') print "This is SJtoolbox of Maya2015Version,enjoy it"
def initialHierarchy(self): """Build the initial hierarchy of the rig. Create the rig model, the main properties, and a couple of base organisation nulls. Get the global size of the rig. """ mgear.log("Initial Hierarchy") # -------------------------------------------------- # Model self.model = primitive.addTransformFromPos(None, self.options["rig_name"]) attribute.lockAttribute(self.model) # -------------------------------------------------- # INFOS self.isRig_att = attribute.addAttribute(self.model, "is_rig", "bool", True) self.rigName_att = attribute.addAttribute(self.model, "rig_name", "string", self.options["rig_name"]) self.user_att = attribute.addAttribute(self.model, "user", "string", getpass.getuser()) self.isWip_att = attribute.addAttribute(self.model, "wip", "bool", self.options["mode"] != 0) self.date_att = attribute.addAttribute(self.model, "date", "string", str(datetime.datetime.now())) self.mayaVersion_att = attribute.addAttribute( self.model, "maya_version", "string", str(pm.mel.eval("getApplicationVersionAsFloat"))) self.gearVersion_att = attribute.addAttribute(self.model, "gear_version", "string", mgear.getVersion()) self.synoptic_att = attribute.addAttribute( self.model, "synoptic", "string", str(self.options["synoptic"])) self.comments_att = attribute.addAttribute( self.model, "comments", "string", str(self.options["comments"])) self.ctlVis_att = attribute.addAttribute(self.model, "ctl_vis", "bool", True) if versions.current() >= 201650: self.ctlVisPlayback_att = attribute.addAttribute( self.model, "ctl_vis_on_playback", "bool", True) self.jntVis_att = attribute.addAttribute(self.model, "jnt_vis", "bool", True) self.qsA_att = attribute.addAttribute(self.model, "quickselA", "string", "") self.qsB_att = attribute.addAttribute(self.model, "quickselB", "string", "") self.qsC_att = attribute.addAttribute(self.model, "quickselC", "string", "") self.qsD_att = attribute.addAttribute(self.model, "quickselD", "string", "") self.qsE_att = attribute.addAttribute(self.model, "quickselE", "string", "") self.qsF_att = attribute.addAttribute(self.model, "quickselF", "string", "") self.rigGroups = self.model.addAttr("rigGroups", at='message', m=1) self.rigPoses = self.model.addAttr("rigPoses", at='message', m=1) self.rigCtlTags = self.model.addAttr("rigCtlTags", at='message', m=1) # ------------------------- ------------------------- # Global Ctl if self.options["worldCtl"]: self.global_ctl = self.addCtl(self.model, "world_ctl", datatypes.Matrix(), self.options["C_color_fk"], "circle", w=10) else: self.global_ctl = self.addCtl(self.model, "global_C0_ctl", datatypes.Matrix(), self.options["C_color_fk"], "crossarrow", w=10) attribute.setRotOrder(self.global_ctl, "ZXY") # Connect global visibility pm.connectAttr(self.ctlVis_att, self.global_ctl.attr("visibility")) if versions.current() >= 201650: pm.connectAttr(self.ctlVisPlayback_att, self.global_ctl.attr("hideOnPlayback")) attribute.lockAttribute(self.global_ctl, ['v']) # -------------------------------------------------- # Setup in world Space self.setupWS = primitive.addTransformFromPos(self.model, "setup") attribute.lockAttribute(self.setupWS) # -------------------------------------------------- # Basic set of null if self.options["joint_rig"]: self.jnt_org = primitive.addTransformFromPos(self.model, "jnt_org") pm.connectAttr(self.jntVis_att, self.jnt_org.attr("visibility"))
except AttributeError: try: cls = getattr(dynModule, name) return cls.__melcmd__() except (KeyError, AttributeError): pass else: import inspect if inspect.isfunction(name): return name elif inspect.isclass(name) and issubclass(name, PyUI): name.__melcmd__() raise ValueError, "%r is not a known ui type" % name if _versions.current() >= _versions.v2011: def toPyQtObject(mayaName): """ Given the name of a Maya UI element of any type, return the corresponding QWidget or QAction. If the object does not exist, returns None When using this function you don't need to specify whether UI type is a control, layout, window, or menuItem, the first match -- in that order -- will be returned. If you have the full path to a UI object this should always be correct, however, if you only have the short name of the UI object, consider using one of the more specific variants: `toQtControl`, `toQtLayout`, `toQtWindow`, or `toQtMenuItem`. .. note:: Requires PyQt """ import maya.OpenMayaUI as mui import sip
import os import re import sys import pymel.core as pm from pymel import versions import maya.mel as mel if not versions.current()>201299: from mpc.maya.animationTools.utils import anim_shelfUtils reload (anim_shelfUtils) def reload_jimmyShelf(): jimmy_shelf = '/usr/people/jimmy-s/maya/2012-x64/prefs/shelves/shelf_MerFab_LGT.mel' if os.path.exists(jimmy_shelf): shelf_name = jimmy_shelf.split('/')[-1:][0].split('.')[0].split('_')[1] f=open(jimmy_shelf,'r') createMyShelf( shelf_name, f.read()) def reload_animShelf(): show = os.environ[ "JOB" ] shelfName = "%sAnim" %show shelfFileName = "shelf_mpcAnim.mel" shelfDir = anim_shelfUtils.getShelfDir () if shelfDir: checkJobShelf = os.path.isfile ( os.path.join (shelfDir,shelfFileName)) if checkJobShelf: shelfPath = os.path.join ( shelfDir, shelfFileName) elif os.path.isfile ( os.path.join (shelfDir, "shelf_mpcAnim.mel")): shelfName = "mpcAnim" shelfFileName = "shelf_mpcAnim.mel"
def getInheritance(mayaType, checkManip3D=True, checkCache=True, updateCache=True): """Get parents as a list, starting from the node after dependNode, and ending with the mayaType itself. Raises a ManipNodeTypeError if the node type fed in was a manipulator """ # To get the inheritance post maya2012, we use nodeType(isTypeName=True), # which means we don't need a real node. However, in maya < 2012, nodeType # requires a real node. To do get these without poluting the scene we use the # _GhostObjMaker, which on enter, uses a dag/dg modifier, and calls the doIt # method; we then get the lineage, and on exit, it calls undoIt. global _cachedInheritances if checkCache and mayaType in _cachedInheritances: return _cachedInheritances[mayaType] import maya.cmds as cmds lineage = None if versions.current() >= versions.v2012: # We now have nodeType(isTypeName)! yay! try: lineage = cmds.nodeType(mayaType, isTypeName=True, inherited=True) except RuntimeError: pass else: with _GhostObjMaker(mayaType) as obj: if obj is not None: if obj.hasFn(api.MFn.kDagNode): name = api.MFnDagNode(obj).partialPathName() else: name = api.MFnDependencyNode(obj).name() if not obj.isNull() and not obj.hasFn( api.MFn.kManipulator3D) and not obj.hasFn( api.MFn.kManipulator2D): lineage = cmds.nodeType(name, inherited=1) if lineage is None: global _fixedLineages if not _fixedLineages: if versions.current() >= versions.v2012: controlPoint = cmds.nodeType('controlPoint', isTypeName=True, inherited=True) else: controlPoint = [ u'containerBase', u'entity', u'dagNode', u'shape', u'geometryShape', u'deformableShape', u'controlPoint' ] # maya2013 introduced shadingDependNode... if versions.current() >= versions.v2013: texture2d = ['shadingDependNode', 'texture2d'] else: texture2d = ['texture2d'] # For whatever reason, nodeType(isTypeName) returns # None for the following mayaTypes: _fixedLineages = { 'node': [], 'file': texture2d + [u'file'], 'lattice': controlPoint + [u'lattice'], 'mesh': controlPoint + [u'surfaceShape', u'mesh'], 'nurbsCurve': controlPoint + [u'curveShape', u'nurbsCurve'], 'nurbsSurface': controlPoint + [u'surfaceShape', u'nurbsSurface'], 'time': [u'time'] } if mayaType in _fixedLineages: lineage = _fixedLineages[mayaType] else: raise RuntimeError( "Could not query the inheritance of node type %s" % mayaType) elif checkManip3D and 'manip3D' in lineage: raise ManipNodeTypeError try: assert (mayaType == 'node' and lineage == []) or lineage[-1] == mayaType except Exception: print mayaType, lineage raise if updateCache and lineage: # add not just this lineage, but all parent's lineages as well... for i in xrange(len(lineage), 0, -1): thisLineage = lineage[:i] thisNode = thisLineage[-1] oldVal = _cachedInheritances.get(thisNode) if oldVal and oldVal != thisLineage: _logger.raiseLog( _logger.WARNING, "lineage for node %s changed (from %s to %s)" % (thisNode, oldVal, thisLineage)) _cachedInheritances[thisNode] = thisLineage return lineage
def getMayaVersions(numeric=False): from pymel import versions if not numeric: return str(versions.current())[:4]+'-x64' else: return versions.current()
import cPickle as pickle except: _logger.warning( "using pickle instead of cPickle: load performance will be affected") import pickle #from maya.cmds import encodeString isInitializing = False # Setting this to False will make finalize() do nothing finalizeEnabled = True _finalizeCalled = False # tells whether this maya package has been modified to work with pymel pymelMayaPackage = hasattr( maya.utils, 'shellLogHandler') or versions.current() >= versions.v2011 def _moduleJoin(*args): """ Joins with the base pymel directory. :rtype: string """ moduleDir = os.path.dirname(os.path.dirname( sys.modules[__name__].__file__)) return os.path.realpath(os.path.join(moduleDir, *args)) def mayaStartupHasRun(): """ Returns True if maya.app.startup has already finished, False otherwise.
from mgear.vendor.Qt import QtCore from mgear.vendor.Qt import QtWidgets # debugging # from PySide2 import QtGui # from PySide2 import QtCore # from PySide2 import QtWidgets # module from mgear.core import pyqt from mgear.anim_picker.handlers import __EDIT_MODE__ # Some platforms have issue with OpenGl and PySide2-2.0.0.alpha platform_name = platform.system() if platform_name == "Windows": if versions.current() >= 20220000: __USE_OPENGL__ = False else: __USE_OPENGL__ = True elif platform_name == "Linux": __USE_OPENGL__ = True elif platform_name == "Darwin": __USE_OPENGL__ = False else: __USE_OPENGL__ = False # ============================================================================= # generic functions # =============================================================================
def fixMayapy2011SegFault(): if versions.v2011 <= versions.current() < versions.v2013: import platform if platform.system() == 'Linux': if om.MGlobal.mayaState() == om.MGlobal.kLibraryApp: # mayapy only # In linux maya 2011, once maya has been initialized, if you try # to do a 'normal' sys.exit, it will crash with a segmentation # fault.. # do a 'hard' os._exit to avoid this # note that, since there is no built-in support to tell from # within atexit functions what the exit code is, we cannot # guarantee returning the "correct" exit code... for instance, # if someone does: # raise SystemExit(300) # we will instead return a 'normal' exit code of 0 # ... but in general, the return code is a LOT more reliable now, # since it used to ALWAYS return non-zero... import sys import atexit # First, wrap sys.exit to store the exit code... _orig_exit = sys.exit # This is just in case anybody else needs to access the # original exit function... if not hasattr('sys', '_orig_exit'): sys._orig_exit = _orig_exit def exit(status): sys._exit_status = status _orig_exit(status) sys.exit = exit def hardExit(): # run all the other exit handlers registered with # atexit, then hard exit... this is easy, because # atexit._run_exitfuncs pops funcs off the stack as it goes... # so all we need to do is call it again import sys atexit._run_exitfuncs() try: print "pymel: hard exiting to avoid mayapy crash..." except Exception: pass import os import sys exitStatus = getattr(sys, '_exit_status', None) if exitStatus is None: last_value = getattr(sys, 'last_value', None) if last_value is not None: if isinstance(last_value, SystemExit): try: exitStatus = last_value.args[0] except Exception: pass if exitStatus is None: exitStatus = 1 if exitStatus is None: exitStatus = 0 os._exit(exitStatus) atexit.register(hardExit)
def fixMayapy2011SegFault(): currentVer = versions.current() # this was fixed in 2014, but in 2014, it will crash consistently if you use # the sceneAseembly plugin, and inconsistently even if you don't... if versions.v2011 <= currentVer < versions.v2013 or currentVer >= versions.v2014: import platform if platform.system() == 'Linux': if om.MGlobal.mayaState() == om.MGlobal.kLibraryApp: # mayapy only # In linux maya 2011, once maya has been initialized, if you try # to do a 'normal' sys.exit, it will crash with a segmentation # fault.. # do a 'hard' os._exit to avoid this # note that, since there is no built-in support to tell from # within atexit functions what the exit code is, we cannot # guarantee returning the "correct" exit code... for instance, # if someone does: # raise SystemExit(300) # we will instead return a 'normal' exit code of 0 # ... but in general, the return code is a LOT more reliable now, # since it used to ALWAYS return non-zero... import sys import atexit # First, wrap sys.exit to store the exit code... _orig_exit = sys.exit # This is just in case anybody else needs to access the # original exit function... if not hasattr('sys', '_orig_exit'): sys._orig_exit = _orig_exit def exit(status): sys._exit_status = status _orig_exit(status) sys.exit = exit def hardExit(): # run all the other exit handlers registered with # atexit, then hard exit... this is easy, because # atexit._run_exitfuncs pops funcs off the stack as it goes... # so all we need to do is call it again import sys atexit._run_exitfuncs() try: print "pymel: hard exiting to avoid mayapy crash..." except Exception: pass import os import sys exitStatus = getattr(sys, '_exit_status', None) if exitStatus is None: last_value = getattr(sys, 'last_value', None) if last_value is not None: if isinstance(last_value, SystemExit): try: exitStatus = last_value.args[0] except Exception: pass if exitStatus is None: exitStatus = 1 if exitStatus is None: exitStatus = 0 os._exit(exitStatus) atexit.register(hardExit)
# They will be imported / redefined later in Pymel, but we temporarily need them here import inspect import re import itertools import pymel.api as api import pymel.versions as versions import pymel.util as _util import startup import plogging as _plogging from pymel.api.plugins import mpxNamesToApiEnumNames _logger = _plogging.getLogger(__name__) if versions.current() < versions.v2014: NUCLEUS_MFNDAG_BUG = True SYMMETRY_CONSTRAINT_MFNDAG_BUG = False elif versions.current() < versions.v2015: NUCLEUS_MFNDAG_BUG = False SYMMETRY_CONSTRAINT_MFNDAG_BUG = True else: NUCLEUS_MFNDAG_BUG = False SYMMETRY_CONSTRAINT_MFNDAG_BUG = False #=============================================================================== # Utility classes #=============================================================================== class ApiEnum(tuple):
def editAtUI(i_s_oSels): import platform if platform.system() == "Windows": i_windowSize = (410, 406) i_LockAtNumEight = 100 i_ReAtEnumEight = 215 i_NumRows = (5, 90, 50) i_UpRows = (86, 150, 155) i_names = (73, 118, 73, 118) i_attrColumWidth = (30, 120) i_EnumEight = 134 i_enumScrollEight = 77 i_EnumWidth = 152 i_NameEight = 27 i_NameWidth = 394 i_ReaSep = 10 i_ReaSep2 = 15 i_NameFrame = 386 i_numWidth = 50 i_AddEight = 30 i_AddButtonWidth = 83 elif platform.system() == "Linux": i_windowSize = (415, 395) i_LockAtNumEight = 97 i_ReAtEnumEight = 209 i_NumRows = (5, 91, 51) i_UpRows = (87, 151, 156) i_names = (74, 119, 74, 119) i_attrColumWidth = (31, 121) i_EnumEight = 130 i_enumScrollEight = 75 i_EnumWidth = 153 i_NameEight = 26 i_NameWidth = 398 i_ReaSep = 10 i_ReaSep2 = 15 i_NameFrame = 390 i_numWidth = 51 i_AddEight = 29 i_AddButtonWidth = 84 else: print "It is not configured for this operating system." s_sel = "select one object" if len(i_s_oSels) == 1: s_sel = i_s_oSels[0] s_UiName = "rs Edit Atribute >> " + s_sel if cmds.window("rsEditAtribute", exists=True): cmds.deleteUI("rsEditAtribute") s_window = cmds.window("rsEditAtribute", title=s_UiName) s_wincol1 = cmds.columnLayout(columnAttach=('both', 5), rowSpacing=1, columnWidth=i_windowSize[0], parent=s_window) cmds.separator(parent=s_wincol1, height=i_ReaSep, style="none", hr=True) s_winRow1 = cmds.rowLayout(numberOfColumns=3, columnWidth3=(i_UpRows), columnAlign=(1, 'right'), columnAttach=[(1, 'both', 0), (2, 'both', 0), (3, 'both', 0)], parent=s_wincol1) s_winColOr = cmds.columnLayout(adjustableColumn=True, parent=s_winRow1) s_winLayOr = cmds.frameLayout(label='Rearrange', labelAlign='bottom', borderStyle='etchedIn', height=i_ReAtEnumEight, parent=s_winColOr) s_winColOr1 = cmds.columnLayout(adjustableColumn=True, parent=s_winLayOr) cmds.separator(height=i_ReaSep, style="none", parent=s_winColOr1) srsUpAtt = lambda: rsMvAtt(-1) srsDwAtt = lambda: rsMvAtt(1) cmds.iconTextButton(style='iconAndTextVertical', image1='Up.png', font="smallFixedWidthFont", label='Up', command=srsUpAtt, parent=s_winColOr1) cmds.iconTextButton(style='iconAndTextVertical', image1='Down.png', font="smallFixedWidthFont", label='Down', command=srsDwAtt, parent=s_winColOr1) cmds.iconTextButton(style='iconAndTextVertical', image1='ReOrder.png', font="smallFixedWidthFont", label='Rearrange', command=rsReAtt, parent=s_winColOr1) cmds.separator(height=i_ReaSep2, style="none", parent=s_winColOr1) cmds.checkBox("rsLockVectors", label='Lock Vectors', align='center', value=True, parent=s_winColOr1) s_winColAt = cmds.columnLayout(adjustableColumn=True, parent=s_winRow1) s_winLayAtDisplay = cmds.frameLayout(label='Display Attributes', labelAlign='bottom', borderStyle='etchedIn', height=i_ReAtEnumEight, parent=s_winColAt) cmds.textScrollList("rsAttributeScroll", allowMultiSelection=False, sc=attSelected, parent=s_winLayAtDisplay) s_winColEn = cmds.columnLayout(adjustableColumn=True, width=i_EnumWidth, parent=s_winRow1) if versions.current() >= 201500: s_winLayAtHidden = cmds.frameLayout(label='Hidden Attributes', labelAlign='bottom', borderStyle='etchedIn', height=80, parent=s_winColEn) else: s_winLayAtHidden = cmds.frameLayout(label='Hidden Attributes', labelAlign='bottom', borderStyle='etchedIn', parent=s_winColEn) cmds.textScrollList("rsAttributeScrollHidden", numberOfRows=4, allowMultiSelection=False, sc=attSelectedHidden, parent=s_winLayAtHidden) s_winLayEn = cmds.frameLayout(label='Enum Strings', labelAlign='bottom', borderStyle='etchedIn', height=i_EnumEight, parent=s_winColEn) s_winColEn1 = cmds.columnLayout(adjustableColumn=True, parent=s_winLayEn) cmds.textScrollList("rsEnumScroll", numberOfRows=8, allowMultiSelection=False, sc=attEnumSelected, height=i_enumScrollEight, parent=s_winColEn1) cmds.text(label='New String') cmds.textField("StringText", enterCommand=attEnumModify, parent=s_winColEn1) lNewName = lambda x: rsChName(x, "NewName") lNiceName = lambda x: rsChName(x, "NiceName") s_winColEnum = cmds.columnLayout(adjustableColumn=False, width=i_NameFrame, parent=s_wincol1) s_winLayNames = cmds.frameLayout(label=' Names', labelVisible=False, labelAlign='bottom', borderStyle='etchedIn', height=i_NameEight, width=i_NameWidth, parent=s_winColEnum) s_winRowNammes = cmds.rowLayout(numberOfColumns=4, columnWidth4=(i_names), columnAttach=[(1, 'both', 7), (2, 'both', 0), (3, 'both', 7), (4, 'both', 0)], parent=s_winLayNames) cmds.text(label='New Name', align='center', parent=s_winRowNammes) cmds.textField("rsNewNameText", enterCommand=lNewName, parent=s_winRowNammes) cmds.text(label='Nice Name', align='center', parent=s_winRowNammes) cmds.textField("rsNiceNameText", enterCommand=lNiceName, parent=s_winRowNammes) s_winRow2 = cmds.rowLayout(numberOfColumns=3, columnWidth3=(i_UpRows), columnAlign=(1, 'right'), columnAttach=[(1, 'both', 0), (2, 'both', 0), (3, 'both', 0)], parent=s_wincol1) lockButton = lambda x: rsChLock(x, "Lock") UnlockButton = lambda x: rsChLock(x, "UnLock") s_winColLck = cmds.columnLayout(adjustableColumn=True, parent=s_winRow2) s_winLayLck = cmds.frameLayout(label=' Lock', labelAlign='bottom', borderStyle='etchedIn', height=i_LockAtNumEight, parent=s_winColLck) s_winColLck2 = cmds.columnLayout(adjustableColumn=True, parent=s_winLayLck) cmds.separator(parent=s_winColLck2, height=i_ReaSep, style="none") cmds.radioCollection(parent=s_winColLck2) cmds.radioButton("rsLock", label='Lock', align='center', onCommand=lockButton) cmds.radioButton("rsUnLock", label='UnLock', align='center', onCommand=UnlockButton) s_winColPro = cmds.columnLayout(adjustableColumn=True, parent=s_winRow2) s_winLayPro = cmds.frameLayout(label='Attribute Properties', labelAlign='bottom', borderStyle='etchedIn', height=i_LockAtNumEight, parent=s_winColPro) s_winColPro2 = cmds.columnLayout(adjustableColumn=True, parent=s_winLayPro) cmds.separator(parent=s_winColPro2, height=i_ReaSep, style="none") cmds.radioCollection() s_winRowPro1 = cmds.rowLayout(numberOfColumns=2, columnWidth2=(i_attrColumWidth), parent=s_winColPro2) cmds.separator(style='none', parent=s_winRowPro1) dbutton = lambda x: rsChProperties(x, "rsDisplayable") kbutton = lambda x: rsChProperties(x, "rsKeyable") hbutton = lambda x: rsChProperties(x, "rsHidden") cmds.radioButton("rsDisplayable", label='Displayable', align='center', onCommand=dbutton, parent=s_winRowPro1) s_winRowPro2 = cmds.rowLayout(numberOfColumns=2, columnWidth2=(i_attrColumWidth), parent=s_winColPro2) cmds.separator(style='none', parent=s_winRowPro2) cmds.radioButton("rsKeyable", label='Keyable', align='center', onCommand=kbutton, parent=s_winRowPro2) s_winRowPro3 = cmds.rowLayout(numberOfColumns=2, columnWidth2=(i_attrColumWidth), parent=s_winColPro2) cmds.separator(style='none', parent=s_winRowPro3) cmds.radioButton("rsHidden", label='Hidden', align='center', onCommand=hbutton, parent=s_winRowPro3) fMin = lambda x: rsChangeCheck(x, "rsMinField") fMax = lambda x: rsChangeCheck(x, "rsMaxField") s_winColNum = cmds.columnLayout(adjustableColumn=True, parent=s_winRow2) s_winLayNum = cmds.frameLayout(label='Numeric Values', labelAlign='bottom', borderStyle='etchedIn', height=i_LockAtNumEight, width=149, parent=s_winColNum) s_winColNum2 = cmds.columnLayout(adjustableColumn=True, parent=s_winLayNum) cmds.separator(parent=s_winColNum2, height=3, style="none") s_winRowNum1 = cmds.rowLayout(numberOfColumns=3, columnWidth3=(i_NumRows), parent=s_winColNum2) cmds.separator(style='none', parent=s_winRowNum1) fieldMin = lambda x: rsSetValue(x, "minValue") fieldMax = lambda x: rsSetValue(x, "maxValue") cmds.checkBox("rsMinBox", label='Minimum', align='center', changeCommand=fMin, parent=s_winRowNum1) cmds.floatField("rsMinField", width=i_numWidth, precision=3, enterCommand=fieldMin, parent=s_winRowNum1) s_winRowNum2 = cmds.rowLayout(numberOfColumns=3, columnWidth3=(i_NumRows), parent=s_winColNum2) cmds.separator(style='none', parent=s_winRowNum2) cmds.checkBox("rsMaxBox", label='Maximum', align='center', changeCommand=fMax, parent=s_winRowNum2) cmds.floatField("rsMaxField", width=i_numWidth, precision=3, enterCommand=fieldMax, parent=s_winRowNum2) s_winRowNum3 = cmds.rowLayout(numberOfColumns=3, columnWidth3=(i_NumRows), parent=s_winColNum2) cmds.separator(style='none', parent=s_winRowNum3) cmds.button("rsDefaultButton", label='Set Default', command=rsChangeDefault, parent=s_winRowNum3) cmds.floatField("rsDefaultField", width=i_numWidth, precision=3, parent=s_winRowNum3) cmds.scriptJob(event=["SelectionChanged", rsSelChange], parent=s_window) s_addsColEnum = cmds.rowLayout(numberOfColumns=3, parent=s_wincol1) s_addsLayNames = cmds.frameLayout(label=' Adds', labelVisible=False, labelAlign='bottom', borderStyle='etchedIn', height=i_AddEight, width=(3 * i_NameFrame / 5) + 5, parent=s_addsColEnum) s_addsRowNammes = cmds.rowLayout(numberOfColumns=3, adjustableColumn=2, columnAlign=(1, 'right'), columnAttach=[(1, 'both', 0), (2, 'both', 0)], parent=s_addsLayNames) cmds.button(label='Add Separator', command=rsAddSeparator, width=i_AddButtonWidth, align='left', parent=s_addsRowNammes) cmds.textField("rsSeparatorName", text="Separator", parent=s_addsRowNammes) cmds.separator(style='none', width=1, parent=s_addsColEnum) s_addAttLayNames = cmds.frameLayout(label=' AddAtt', labelVisible=False, labelAlign='bottom', borderStyle='etchedIn', height=i_AddEight, width=(2 * i_NameFrame / 5) - 1, parent=s_addsColEnum) s_addAttRow = cmds.rowLayout(numberOfColumns=2, parent=s_addAttLayNames) cmds.button(label='Del Attribute', command=rsDeleteAttr, align='center', parent=s_addAttRow) cmds.button(label='Add Attribute', command=rsAddAttr, align='center', parent=s_addAttRow) cmds.showWindow(s_window) cmds.window(s_window, edit=True, widthHeight=(i_windowSize), s=False) return True
class ApiCache(startup.SubItemCache): NAME = 'mayaApi' DESC = 'the API cache' COMPRESSED = True USE_VERSION = True _CACHE_NAMES = '''apiTypesToApiEnums apiEnumsToApiTypes mayaTypesToApiTypes apiTypesToApiClasses apiClassInfo'''.split() EXTRA_GLOBAL_NAMES = tuple(['mayaTypesToApiEnums']) # Descriptions of various elements: # Maya static info : # Initializes various static look-ups to speed up Maya types conversions # self.apiClassInfo # self.apiTypesToApiEnums # self.apiEnumsToApiTypes # self.apiTypesToApiClasses # Lookup of currently existing Maya types as keys with their corresponding API type as values. # Not a read only (static) dict as these can change (if you load a plugin) # self.mayaTypesToApiTypes # lookup tables for a direct conversion between Maya type to their MFn::Types enum # self.mayaTypesToApiEnums # creating these will crash Maya! CRASH_TYPES = { 'xformManip': 'kXformManip', 'moveVertexManip': 'kMoveVertexManip', } # For some reason, a bunch of nodes crashed Maya 2016 Ext1, but they # apparently worked with 2016.5 / 2016 Ext2 (since it didn't crash when I # built it's cache - though it was a pre-release, so perhaps it didn't have # all plugins?) if versions.v2016_EXT1 <= versions.current() < versions.v2016_EXT2: CRASH_TYPES.update({ 'type': 'kPluginDependNode', 'vectorExtrude': 'kPluginDependNode', 'shellDeformer': 'kPluginDependNode', 'displayPoints': 'kPluginLocatorNode', 'svgToPoly': 'kPluginDependNode', 'objectGrpToComp': 'kPluginDependNode', 'vectorAdjust': 'kPluginDeformerNode', 'objectGrpToComp': 'kPluginDependNode', 'objectGrpToComp': 'kPluginDependNode', 'objectGrpToComp': 'kPluginDependNode', 'objectGrpToComp': 'kPluginDependNode', 'objectGrpToComp': 'kPluginDependNode', 'objectGrpToComp': 'kPluginDependNode', }) # hold any overrides for mayaTypesToApiTypes... # ie, for cases where the name guess is wrong, or for weird plugin types # that don't inherit from an mpx type (ie, vectorRenderGlobals), etc MAYA_TO_API_OVERRIDES = { # this what is returned by # allNodeTypes(includeAbstract=True) 'node': 'kDependencyNode', # this is the name pymel uses 'dependNode': 'kDependencyNode', # a strange one - a plugin node that has an # apitype... is in studioImport.so... also has a # doc entry... 'smear': 'kSmear', # plugin node that's not in all distributions # (ie, it's missing in Linux), so just include it # here 'vectorRenderGlobals': 'kDependencyNode', } # TODO: if nucleus/symmetryConstraint bug ever fixed: # - remove entry in apiCache.ApiCache.API_TO_MFN_OVERRIDES # - remove hard-code setting of Nucleus's parent to DependNode # - remove 2 checks in allapi.toApiObject for objects which can have an # MDagPath but can't use MFnDagNode API_TO_MFN_OVERRIDES = { 'kHikHandle': api. MFnTransform, # hikHandle inherits from ikHandle, but is not compatible with MFnIkHandle 'kFfdDualBase': api. MFnDependencyNode, # jointFfd inherits from ffd, but is not compatible with MFnLatticeDeformer 'kTransferAttributes': api. MFnDependencyNode, # transferAttributes inherits from weightGeometryFilter, but is not compatible with MFnWeightGeometryFilter or MFnGeometryFilter } if NUCLEUS_MFNDAG_BUG: # fun one - even though it can be parented and inherits from transform, # it's incompatible with MFnTransform or even MFnDagNode API_TO_MFN_OVERRIDES['kNucleus'] = api.MFnDependencyNode if SYMMETRY_CONSTRAINT_MFNDAG_BUG: API_TO_MFN_OVERRIDES['kSymmetryConstraint'] = api.MFnDependencyNode DEFAULT_API_TYPE = 'kDependencyNode' def __init__(self, docLocation=None): super(ApiCache, self).__init__() for name in self.EXTRA_GLOBAL_NAMES: setattr(self, name, {}) self.docLocation = docLocation def _buildMayaToApiInfo(self): self._buildMayaNodeInfo() # Fixes for types that don't have a MFn by doing a node creation and testing it unknownTypes = set() toCreate = [] self.mayaTypesToApiTypes = self._buildMayaReservedTypes() # do real nodes first - on pre-2012, can't directly query inheritance of # abstract nodes, so relying on caching of parent hierarchies when # querying a real hierarchy is the only way to get inheritance info # for abstract types for mayaType in itertools.chain(self.realMayaTypes, self.abstractMayaTypes): if mayaType not in self.mayaTypesToApiTypes: toCreate.append(mayaType) if toCreate: # Put in a debug, because ghost nodes can be problematic... _logger.debug("Starting to create ghost nodes...") with GhostObjsOkHere(): with _GhostObjMaker(toCreate, manipError=False, multi=True) as typeToObj: for mayaType in toCreate: obj = typeToObj[mayaType] if obj: apiType = obj.apiTypeStr() self.mayaTypesToApiTypes[mayaType] = apiType else: unknownTypes.add(mayaType) # Put in a debug, because ghost nodes can be problematic... _logger.debug("...finished creating ghost nodes") if len(unknownTypes) > 0: _logger.warn( "Unable to get maya-to-api type info for the following nodes: %s" % ", ".join(unknownTypes)) for mayaType in unknownTypes: # For unknown types, use the parent type try: inheritance = getInheritance(mayaType) except (ManipNodeTypeError, RuntimeError): continue apiType = None # if we have a node A, and we get back it's inheritance as: # [E, D, C, B, A] # ...and 'D' is the first parent that we can find info for, we # may as well set the types for 'B' and 'C' parents as well... # also, this means that we may already have set THIS mayaType # (if it was the parent of another unknown node we already set), # so we loop through all nodes in inheritance, including this # type toSet = [mayaType] if inheritance: for parent in reversed(inheritance): apiType = self.mayaTypesToApiTypes.get(parent) if apiType: break else: toSet.append(parent) if not apiType: apiType = self.DEFAULT_API_TYPE for node in toSet: self.mayaTypesToApiTypes[node] = apiType for mayaType, apiType in self.mayaTypesToApiTypes.iteritems(): self.addMayaType(mayaType, apiType) def _buildApiTypesList(self): """the list of api types is static. even when a plugin registers a new maya type, it will be associated with an existing api type""" self.apiTypesToApiEnums = dict( inspect.getmembers(api.MFn, lambda x: type(x) is int)) self.apiEnumsToApiTypes = dict((self.apiTypesToApiEnums[k], k) for k in self.apiTypesToApiEnums.keys()) def _buildMayaReservedTypes(self, force=False): """ Build a list of Maya reserved types. These cannot be created directly from the API, thus the dgMod trick to find the corresponding Maya type won't work """ reservedMayaTypes = {} # start with plugin types import pymel.api.plugins as plugins for mpxName, mayaNode in plugins.mpxNamesToMayaNodes.iteritems(): reservedMayaTypes[mayaNode] = plugins.mpxNamesToApiEnumNames[ mpxName] for mayaType in self.abstractMayaTypes: if mayaType in reservedMayaTypes: continue apiGuess = self._guessApiTypeByName(mayaType) if apiGuess: reservedMayaTypes[mayaType] = apiGuess reservedMayaTypes.update(self.MAYA_TO_API_OVERRIDES) reservedMayaTypes.update(self.CRASH_TYPES) # filter to make sure all these types exist in current version (some are Maya2008 only) reservedMayaTypes = dict((item[0], item[1]) for item in reservedMayaTypes.iteritems() if item[1] in self.apiTypesToApiEnums) return reservedMayaTypes # TODO: eventually, would like to move the node-heirarchy-building stuff # from cmdcache into here... we could then cache the node inheritance info, # instead of constantly re-querying it in various places... def _buildMayaNodeInfo(self): '''Stores tempory information about maya nodes + names ''' if getattr(self, '_builtMayaNodeInfo', False): return if not self.apiTypesToApiEnums: self._buildApiTypesList() self.realMayaTypes, self.abstractMayaTypes = _getAllMayaTypes( returnRealAbstract=True) self.allMayaTypes = self.realMayaTypes | self.abstractMayaTypes self.uniqueLowerMaya, self.multiLowerMaya = getLowerCaseMapping( self.allMayaTypes) self.allLowerMaya = set(self.uniqueLowerMaya) | set( self.multiLowerMaya) self.uniqueLowerApi, self.multiLowerApi = getLowerCaseMapping( self.apiTypesToApiEnums) self._builtMayaNodeInfo = True return # _buildMayaNodeInfo must already have been called... def _guessApiTypeByName(self, nodeName): # first, try the easy case... apiName = nodeToApiName(nodeName) if apiName in self.apiTypesToApiEnums: return apiName lowerNode = nodeName.lower() if lowerNode not in self.uniqueLowerMaya: return None # now, try with various modifications... possibleApiNames = set() possibleModifications = [(find, replace) for find, replace in API_NAME_MODIFIERS if find.search(lowerNode)] # find all possible combinations of all possible modifications for modifyNum in xrange(len(possibleModifications) + 1): for modifyCombo in itertools.combinations(possibleModifications, modifyNum): baseName = lowerNode for find, replace in modifyCombo: baseName = find.sub(replace, baseName) if not baseName: # if we've eliminated the name with our changes - ie, # 'shape' would go to '' - then skip continue if baseName != lowerNode and baseName in self.allLowerMaya: # if after modification, our new name is the name of another # maya node, skip continue apiLower = 'k' + baseName if apiLower in self.uniqueLowerApi: possibleApiNames.add(self.uniqueLowerApi[apiLower]) else: for suffix in apiSuffixes: apiWithSuffix = apiLower + suffix if apiWithSuffix in self.uniqueLowerApi: possibleApiNames.add( self.uniqueLowerApi[apiWithSuffix]) if len(possibleApiNames) == 1: return list(possibleApiNames)[0] return None # Note - it's possible there are multiple substrings of the same length # that are all "tied" for longest - this method will only return the first # it finds @staticmethod def _longestCommonSubstring(str1, str2): if str1 == str2: return [str1] if len(str1) > len(str2): longer = str1 shorter = str2 else: longer = str2 shorter = str1 maxSize = len(shorter) for strSize in xrange(maxSize, 0, -1): for startPos in xrange(0, maxSize - strSize + 1): subStr = shorter[startPos:startPos + strSize] if subStr in longer: return subStr return '' @staticmethod def _bestMatches(theStr, otherStrings, minLength=2, caseSensitive=False): if not caseSensitive: theStr = theStr.lower() byLength = {} for otherString in otherStrings: if caseSensitive: compOther = otherString else: compOther = otherString.lower() size = len(_longestCommonSubstring(theStr, compOther)) byLength.setdefault(size, []).append(otherString) longest = max(byLength) if longest >= minLength: return byLength[longest] else: return [] def _buildApiClassInfo(self): _logger.debug("Starting ApiCache._buildApiClassInfo...") from pymel.internal.parsers import ApiDocParser self.apiClassInfo = {} parser = ApiDocParser(api, enumClass=ApiEnum, docLocation=self.docLocation) for name, obj in inspect.getmembers( api, lambda x: type(x) == type and x.__name__.startswith('M')): if not name.startswith('MPx'): try: info = parser.parse(name) self.apiClassInfo[name] = info except (IOError, OSError, ValueError, IndexError), e: import errno baseMsg = "failed to parse docs for %r:" % name if isinstance( e, (IOError, OSError)) and e.errno == errno.ENOENT: # If we couldn't parse because we couldn't find the # file, only raise a warning... there are many classes # (ie, MClothTriangle) that don't have a doc page... _logger.warning(baseMsg) _logger.warning("%s: %s" % (name, e)) else: import traceback _logger.error(baseMsg) _logger.error(traceback.format_exc()) _logger.debug("...finished ApiCache._buildApiClassInfo")
#!/usr/bin/env python #encoding:utf-8 # -*- coding: utf-8 -*- import pymel.core as pm import maya.cmds as cmds import maya.mel as mel import os, sys, re import time print "+++++++++++++++++++++++++++++++++the prerender strat++++++++++++++++++++++++++++++++++++++++++++++++" premel_start_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) print "the prerender strat time :: %s \n" % premel_start_time ## Edit by shen 2018.1.19 try: from pymel import versions print("The Maya version with update: %s" % str(versions.current())) RenderNode = pm.PyNode("defaultRenderGlobals") Renderer_name = RenderNode.currentRenderer.get() w = cmds.getAttr("defaultResolution.width") h = cmds.getAttr("defaultResolution.height") print("Current renderner: %s" % Renderer_name) print("Current Outpu setting: %s" % RenderNode.attr("imageFilePrefix").get()) print("Current Outpu format: %s" % RenderNode.attr("imageFormat").get()) print("Current Resolution: %s %s" % (str(w), str(h))) if Renderer_name == "arnold": print( "Arnold base settings for threads and tex Memory: full thread/40960" ) aiop = pm.PyNode("defaultArnoldRenderOptions")
# They will be imported / redefined later in Pymel, but we temporarily need them here import inspect import re import itertools import pymel.api as api import pymel.versions as versions import pymel.util as _util import startup import plogging as _plogging from pymel.api.plugins import mpxNamesToApiEnumNames _logger = _plogging.getLogger(__name__) if versions.current() < versions.v2014: NUCLEUS_MFNDAG_BUG = True SYMMETRY_CONSTRAINT_MFNDAG_BUG = False elif versions.current() < versions.v2015: NUCLEUS_MFNDAG_BUG = False SYMMETRY_CONSTRAINT_MFNDAG_BUG = True else: NUCLEUS_MFNDAG_BUG = False SYMMETRY_CONSTRAINT_MFNDAG_BUG = False #=============================================================================== # Utility classes #=============================================================================== class ApiEnum(tuple): def __str__(self): return '.'.join( [str(x) for x in self] )
rg.isWip_att = attribute.addAttribute(rg.model, "wip", "bool", rg.options["mode"] != 0) rg.date_att = attribute.addAttribute(rg.model, "date", "string", str(datetime.datetime.now())) rg.mayaVersion_att = attribute.addAttribute( rg.model, "maya_version", "string", str(pm.mel.eval("getApplicationVersionAsFloat"))) rg.gearVersion_att = attribute.addAttribute(rg.model, "gear_version", "string", rigging.beam.getVersion()) rg.synoptic_att = attribute.addAttribute(rg.model, "synoptic", "string", str(rg.options["synoptic"])) rg.comments_att = attribute.addAttribute(rg.model, "comments", "string", str(rg.options["comments"])) rg.ctlVis_att = attribute.addAttribute(rg.model, "ctl_vis", "bool", True) if versions.current() >= 201650: rg.ctlVisPlayback_att = attribute.addAttribute(rg.model, "ctl_vis_on_playback", "bool", True) rg.jntVis_att = attribute.addAttribute(rg.model, "jnt_vis", "bool", True) rg.qsA_att = attribute.addAttribute(rg.model, "quickselA", "string", "") rg.qsB_att = attribute.addAttribute(rg.model, "quickselB", "string", "") rg.qsC_att = attribute.addAttribute(rg.model, "quickselC", "string", "") rg.qsD_att = attribute.addAttribute(rg.model, "quickselD", "string", "") rg.qsE_att = attribute.addAttribute(rg.model, "quickselE", "string", "") rg.qsF_att = attribute.addAttribute(rg.model, "quickselF", "string", "") rg.rigGroups = rg.model.addAttr("rigGroups", at='message', m=1) rg.rigPoses = rg.model.addAttr("rigPoses", at='message', m=1) rg.rigCtlTags = rg.model.addAttr("rigCtlTags", at='message', m=1)
def getInheritance( mayaType, checkManip3D=True, checkCache=True, updateCache=True ): """Get parents as a list, starting from the node after dependNode, and ending with the mayaType itself. Raises a ManipNodeTypeError if the node type fed in was a manipulator """ # To get the inheritance post maya2012, we use nodeType(isTypeName=True), # which means we don't need a real node. However, in maya < 2012, nodeType # requires a real node. To do get these without poluting the scene we use the # _GhostObjMaker, which on enter, uses a dag/dg modifier, and calls the doIt # method; we then get the lineage, and on exit, it calls undoIt. global _cachedInheritances if checkCache and mayaType in _cachedInheritances: return _cachedInheritances[mayaType] import maya.cmds as cmds lineage = None if versions.current() >= versions.v2012: # We now have nodeType(isTypeName)! yay! try: lineage = cmds.nodeType(mayaType, isTypeName=True, inherited=True) except RuntimeError: pass else: with _GhostObjMaker(mayaType) as obj: if obj is not None: if obj.hasFn( api.MFn.kDagNode ): name = api.MFnDagNode(obj).partialPathName() else: name = api.MFnDependencyNode(obj).name() if not obj.isNull() and not obj.hasFn( api.MFn.kManipulator3D ) and not obj.hasFn( api.MFn.kManipulator2D ): lineage = cmds.nodeType( name, inherited=1) if lineage is None: global _fixedLineages if not _fixedLineages: if versions.current() >= versions.v2012: controlPoint = cmds.nodeType('controlPoint', isTypeName=True, inherited=True) else: controlPoint = [u'containerBase', u'entity', u'dagNode', u'shape', u'geometryShape', u'deformableShape', u'controlPoint'] # maya2013 introduced shadingDependNode... if versions.current() >= versions.v2013: texture2d = ['shadingDependNode', 'texture2d'] else: texture2d = ['texture2d'] # For whatever reason, nodeType(isTypeName) returns # None for the following mayaTypes: _fixedLineages = { 'node':[], 'file':texture2d + [u'file'], 'lattice':controlPoint + [u'lattice'], 'mesh':controlPoint + [u'surfaceShape', u'mesh'], 'nurbsCurve':controlPoint + [u'curveShape', u'nurbsCurve'], 'nurbsSurface':controlPoint + [u'surfaceShape', u'nurbsSurface'], 'time':[u'time'] } if mayaType in _fixedLineages: lineage = _fixedLineages[mayaType] else: raise RuntimeError("Could not query the inheritance of node type %s" % mayaType) elif checkManip3D and 'manip3D' in lineage: raise ManipNodeTypeError try: assert (mayaType == 'node' and lineage == []) or lineage[-1] == mayaType except Exception: print mayaType, lineage raise if updateCache and lineage: # add not just this lineage, but all parent's lineages as well... for i in xrange(len(lineage), 0, -1): thisLineage = lineage[:i] thisNode = thisLineage[-1] oldVal = _cachedInheritances.get(thisNode) if oldVal and oldVal != thisLineage: _logger.raiseLog(_logger.WARNING, "lineage for node %s changed (from %s to %s)" % (thisNode, oldVal, thisLineage)) _cachedInheritances[thisNode] = thisLineage return lineage
def addCtl(self, parent, name, m, color, icon, tp=None, **kwargs): """ Create the control and apply the shape, if this is alrealdy stored in the guide controllers grp. Args: parent (dagNode): The control parent name (str): The control name. m (matrix): The transfromation matrix for the control. color (int or list of float): The color for the control in idex or RGB. icon (str): The controls default shape. tp (dagNode): Tag Parent Control object to connect as a parent controller kwargs (variant): Other arguments for the icon type variations. Returns: dagNode: The Control. """ fullName = self.getName(name) bufferName = fullName + "_controlBuffer" if bufferName in self.rig.guide.controllers.keys(): ctl_ref = self.rig.guide.controllers[bufferName] ctl = pri.addTransform(parent, fullName, m) for shape in ctl_ref.getShapes(): ctl.addChild(shape, shape=True, add=True) pm.rename(shape, fullName + "Shape") ico.setcolor(ctl, color) else: ctl = ico.create(parent, fullName, m, color, icon, **kwargs) # create the attributes to handlde mirror and symetrical pose att.addAttribute(ctl, "invTx", "bool", 0, keyable=False, niceName="Invert Mirror TX") att.addAttribute(ctl, "invTy", "bool", 0, keyable=False, niceName="Invert Mirror TY") att.addAttribute(ctl, "invTz", "bool", 0, keyable=False, niceName="Invert Mirror TZ") att.addAttribute(ctl, "invRx", "bool", 0, keyable=False, niceName="Invert Mirror RX") att.addAttribute(ctl, "invRy", "bool", 0, keyable=False, niceName="Invert Mirror RY") att.addAttribute(ctl, "invRz", "bool", 0, keyable=False, niceName="Invert Mirror RZ") att.addAttribute(ctl, "invSx", "bool", 0, keyable=False, niceName="Invert Mirror SX") att.addAttribute(ctl, "invSy", "bool", 0, keyable=False, niceName="Invert Mirror SY") att.addAttribute(ctl, "invSz", "bool", 0, keyable=False, niceName="Invert Mirror SZ") if self.settings["ctlGrp"]: ctlGrp = self.settings["ctlGrp"] self.addToGroup(ctl, ctlGrp, "controllers") else: ctlGrp = "controllers" self.addToGroup(ctl, ctlGrp) #lock the control parent attributes if is not a control if parent not in self.groups[ctlGrp]: self.transform2Lock.append(parent) # Set the control shapes isHistoricallyInteresting for oShape in ctl.getShapes(): oShape.isHistoricallyInteresting.set(False) #set controller tag if versions.current() >= 201650: try: oldTag = pm.PyNode(ctl.name() + "_tag") if not oldTag.controllerObject.connections(): # NOTE: The next line is comment out. Because this will happend alot since maya does't clean # controller tags after deleting the control Object of the tag. This have been log to Autodesk. # If orphane tags are found, it will be clean in silence. # pm.displayWarning("Orphane Tag: %s will be delete and created new for: %s"%(oldTag.name(), ctl.name())) pm.delete(oldTag) except: pass pm.controller(ctl) if tp: ctt = pm.PyNode(pm.controller(ctl, q=True)[0]) tpTagNode = pm.PyNode(pm.controller(tp, q=True)[0]) tpTagNode.cycleWalkSibling.set(True) pm.connectAttr(tpTagNode.prepopulate, ctt.prepopulate, f=True) # The connectAttr to the children attribute is giving error # i.e: pm.connectAttr(ctt.attr("parent"), tpTagNode.attr("children"), na=True) # if using the next available option tag # I was expecting to use ctt.setParent(tp) but doest't work as expected. # After reading the documentation this method looks prety useless. # Looks like is boolean and works based on selection :( # this is a dirty loop workaround. Naaah! i = 0 while True: try: pm.connectAttr(ctt.parent, tpTagNode.attr("children[%s]" % str(i))) break except: i += 1 if i > 100: pm.displayWarning( "The controller tag for %s has reached the limit index of 100 children" % ctl.name()) break return ctl
def toApiObject(nodeName, plugs=True, comps=True, dagPlugs=True): # type: (Any, bool, bool, bool) -> None """ Get the API MPlug, MObject or (MObject, MComponent) tuple given the name of an existing node, attribute, components selection Parameters ---------- plugs : bool if True, check if nodeName is an attribute/plug, and if it is, return a pair of (MDagPath, MPlug) if it's a dag node and dagPlugs is True, or just an MPlug if it's not a dag node or dagPlugs is False comps : bool if True, check if nodeName is a component name, and if it is, return a pair of (MDagPath, MObject), where the MObject contains the component. dagPlugs : bool if True, plug result will be a tuple of type (MDagPath, MPlug) for dag nodes If we were unable to retrieve the node/attribute/etc, returns None. None is also returned if name is of the form `validNodeName.invalidAttrOrComponent`, or if comps/plugs is False. That is, if the given name is one that should be an attribute or component, it will either return None or the plug or component - it should never return just the node. """ # special case check for empty string for speed... if not nodeName: return None # preferPlugs : Optional[bool] # If both plugs and comps are True, and the given nodeName could yield # EITHER a plug or component, then preferPlugs controls which is returned. # If True, then the plug is returned; if False otherwise the component is. preferPlugs = True # Behavior of MSelectionList.getPlug changed in 2020.1, # where it would attempt to find a "related" plug when # a component was selected. (Previously, it just # errored.) import pymel.versions as versions if versions.current() >= versions.v2020_1: preferPlugs = False splitName = nodeName.split('.') sel = MSelectionList() try: sel.add(nodeName) except Exception: if len(splitName) > 1 and plugs: # Compound Attributes # sometimes the index might be left off somewhere in a compound attribute # (ex 'Nexus.auxiliary.input' instead of 'Nexus.auxiliary[0].input' ) # but we can still get a representative plug. this will return the equivalent of 'Nexus.auxiliary[-1].input' try: obj = toApiObject(splitName[0], plugs=False, comps=False) if obj is None: return None if isinstance(obj, MDagPath): mfn = MFnDagNode(obj) else: mfn = MFnDependencyNode(obj) plug = mfn.findPlug(splitName[-1], False) if isinstance(obj, MDagPath) and dagPlugs: return (obj, plug) return plug except (RuntimeError, ValueError): pass return None if sel.length() != 1: return None if len(splitName) > 1: # early out - it's comp or plug name, but they didnt want either! if not (plugs or comps): return None def getAsPlug(): plug = MPlug() try: sel.getPlug(0, plug) except RuntimeError: return None else: if dagPlugs and not plug.isNull(): # Check if it's a dag node - if so, want to return # (MDagPath, MPlug) pair try: # Plugs with DagPaths sel.add(splitName[0]) dag = MDagPath() sel.getDagPath(1, dag) # used to be a bug with some types that inherited from DagNode, # but were not compatibile w/ MFnDagNode... these have been # fixed, but we leave check in case another one crops up if not dag.node().hasFn(MFn.kDagNode): obj = MObject() sel.getDependNode(1, obj) return (obj, plug) # if isValidMDagPath(dag) : return (dag, plug) except RuntimeError: pass if plug.isNull(): return None return plug def getAsComp(): # Components dag = MDagPath() comp = MObject() try: sel.getDagPath(0, dag, comp) except RuntimeError: return None # if not isValidMDagPath(dag) : return if comp.isNull(): return None return (dag, comp) getters = [] if plugs: getters.append(getAsPlug) if comps: getters.append(getAsComp) if not preferPlugs: getters.reverse() for getter in getters: result = getter() if result is not None: return result # We've failed to get either a plug or comp... # ...but we may have gotten a published container attribute, which # auto- magically converts to the contained node it references # when added to an MSelectionList if len(splitName) == 2: # Thankfully, it seems you can't index / get children off an # aliased attribute - ie, myNode.myAlias[0] and # myNode.myAlias.childAttr don't work, even if myAlias point # to a multi / compound attr obj = MObject() try: sel.add(splitName[0]) sel.getDependNode(1, obj) except RuntimeError: pass else: # Since it seems there's no api way to get at the plug for # a published / aliased container attr, we just check for # aliases... mfn = MFnDependencyNode(obj) aliases = [] if mfn.getAliasList(aliases): for aliasName, trueName in util.pairIter(aliases): if aliasName == splitName[1]: return toApiObject('.'.join( (splitName[0], trueName)), plugs=plugs, comps=comps) # Ok, nothing worked (plug or comp), but we were given a plug/comp name. # Give up and return None return None else: # This is not a plug or component name! try: # DagPaths dag = MDagPath() sel.getDagPath(0, dag) # if not isValidMDagPath(dag) : return # used to be a bug with some types that inherited from DagNode, # but were not compatibile w/ MFnDagNode... these have been # fixed, but we leave check in case another one crops up if not dag.node().hasFn(MFn.kDagNode): raise RuntimeError return dag except RuntimeError: # Objects obj = MObject() sel.getDependNode(0, obj) # if not isValidMObject(obj) : return return obj
# data: # version: 0.001 import pymel.core as pm from pymel import versions import maya.OpenMayaUI as apiUI from Qt import QtWidgets, QtCore import shutil import os import texturePathResetUI import customProgress reload(customProgress) version = str(versions.current()) iv = int(version[0:4]) if iv < 2017: import shiboken else: import shiboken2 def getMayaWindow(): ptr = apiUI.MQtUtil_mainWindow() if ptr is not None: if iv < 2017: return shiboken.wrapInstance(long(ptr), QtWidgets.QWidget) else: return shiboken2.wrapInstance(long(ptr), QtWidgets.QWidget)
try: cls = getattr(dynModule, name) return cls.__melcmd__() except (KeyError, AttributeError): pass else: import inspect if inspect.isfunction(name): return name elif inspect.isclass(name) and issubclass(name, PyUI): name.__melcmd__() raise ValueError, "%r is not a known ui type" % name if _versions.current() >= _versions.v2011: def toQtObject(mayaName): """ Given the name of a Maya UI element of any type, return the corresponding QWidget or QAction. If the object does not exist, returns None When using this function you don't need to specify whether UI type is a control, layout, window, or menuItem, the first match -- in that order -- will be returned. If you have the full path to a UI object this should always be correct, however, if you only have the short name of the UI object, consider using one of the more specific variants: `toQtControl`, `toQtLayout`, `toQtWindow`, or `toQtMenuItem`. .. note:: Requires PyQt """ import maya.OpenMayaUI as mui import sip
def _constraint( func ): def constraintWithWeightSyntax(*args, **kwargs): """ Maya Bug Fix: - when queried, angle offsets would be returned in radians, not current angle unit Modifications: - added new syntax for querying the weight of a target object, by passing the constraint first:: aimConstraint( 'pCube1_aimConstraint1', q=1, weight ='pSphere1' ) aimConstraint( 'pCube1_aimConstraint1', q=1, weight =['pSphere1', 'pCylinder1'] ) aimConstraint( 'pCube1_aimConstraint1', q=1, weight =[] ) """ if kwargs.get( 'query', kwargs.get('q', False) and len(args)==1) : # Fix the big with angle offset query always being in radians if kwargs.get( 'offset', kwargs.get('o', None) ): return _general.getAttr(str(args[0]) + ".offset") # try seeing if we can apply the new weight query syntax targetObjects = kwargs.get( 'weight', kwargs.get('w', None) ) if targetObjects is not None: # old way caused KeyError if 'w' not in kwargs, even if 'weight' was! # targetObjects = kwargs.get( 'weight', kwargs['w'] ) constraint = args[0] if 'constraint' in cmds.nodeType( constraint, inherited=1 ): if not _util.isIterable( targetObjects ): targetObjects = [targetObjects] elif not targetObjects: targetObjects = func( constraint, q=1, targetList=1 ) constraintObj = cmds.listConnections( constraint + '.constraintParentInverseMatrix', s=1, d=0 )[0] args = targetObjects + [constraintObj] kwargs.pop('w',None) kwargs['weight'] = True res = func(*args, **kwargs) if kwargs.get( 'query', kwargs.get('q', False) and len(args)==1) : if kwargs.get( 'weightAliasList', kwargs.get('wal', None) ): res = [_general.Attribute(args[0] + '.' + attr) for attr in res] elif kwargs.get( 'worldUpObject', kwargs.get('wuo', None) ): res = _factories.unwrapToPyNode(res) elif kwargs.get( 'targetList', kwargs.get('tl', None) ): res = _factories.toPyNodeList(res) return res constraint = constraintWithWeightSyntax if versions.current() < versions.v2009: def constraintWithVectorFix(*args, **kwargs): """ Maya Bug Fix: - when queried, upVector, worldUpVector, and aimVector returned the name of the constraint instead of the desired values """ if kwargs.get( 'query', kwargs.get('q', False) and len(args)==1) : # Fix the big with upVector, worldUpVector, and aimVector attrs = [ 'upVector', 'u', 'worldUpVector', 'wu', 'aimVector', 'a' ] for attr in attrs: if attr in kwargs: return _general.datatypes.Vector( _general.getAttr(str(args[0]) + "." + attr ) ) return constraintWithWeightSyntax(*args, **kwargs) constraintWithVectorFix.__doc__ += constraintWithWeightSyntax.__doc__ constraint = constraintWithVectorFix constraint.__name__ = func.__name__ return constraint
class Layout(PyUI): def __enter__(self): global _withParentStack _withParentStack.append(self) self.makeDefault() return self def __exit__(self, type, value, traceback): global _withParentStack _withParentStack.pop() if _withParentStack: parent = _withParentStack[-1] else: parent = self.pop() while parent and objectTypeUI(parent) == u'rowGroupLayout': parent = parent.pop() cmds.setParent(parent) def children(self): #return [ PyUI( self.name() + '|' + x) for x in self.__melcmd__(self, q=1, childArray=1) ] kids = cmds.layout(self, q=1, childArray=1) if kids: return [PyUI(self.name() + '|' + x) for x in kids] return [] getChildren = children # TODO: add depth firt and breadth first options def walkChildren(self): """ recursively yield all children of this layout """ for child in self.children(): yield child if hasattr(child, 'walkChildren'): for subChild in child.walkChildren(): yield subChild def findChild(self, shortName, recurse=False): if recurse: for child in self.walkChildren(): if child.shortName() == shortName: return child else: for child in self.children(): if child.shortName() == shortName: return child def addChild(self, uiType, name=None, **kwargs): if isinstance(uiType, basestring): uiType = getattr(dynModule, uiType) assert hasattr( uiType, '__call__' ), 'argument uiType must be the name of a known ui type, a UI subclass, or a callable object' args = [] if name: args.append(name) if kwargs: if 'parent' in kwargs or 'p' in kwargs: _logger.warn( 'parent flag is set by addChild automatically. passed value will be ignored' ) kwargs.pop('parent', None) kwargs.pop('p', None) kwargs['parent'] = self res = uiType(*args, **kwargs) if not isinstance(res, PyUI): res = PyUI(res) return res def makeDefault(self): """ set this layout as the default parent """ cmds.setParent(self) def pop(self): """ set the default parent to the parent of this layout """ p = self.parent() cmds.setParent(p) return p def clear(self): children = self.getChildArray() if children: for child in self.getChildArray(): cmds.deleteUI(child) if _versions.current() >= _versions.v2011: asQtObject = toQtLayout
def getInheritance(mayaType, checkManip3D=True, checkCache=True, updateCache=True): """Get parents as a list, starting from the node after dependNode, and ending with the mayaType itself. Raises a ManipNodeTypeError if the node type fed in was a manipulator """ # To get the inheritance post maya2012, we use nodeType(isTypeName=True), # which means we don't need a real node. However, in maya < 2012, nodeType # requires a real node. To do get these without poluting the scene we use the # _GhostObjMaker, which on enter, uses a dag/dg modifier, and calls the doIt # method; we then get the lineage, and on exit, it calls undoIt. global _cachedInheritances if checkCache and mayaType in _cachedInheritances: return _cachedInheritances[mayaType] import maya.cmds as cmds lineage = None if versions.current() >= versions.v2012: # We now have nodeType(isTypeName)! yay! try: lineage = cmds.nodeType(mayaType, isTypeName=True, inherited=True) except RuntimeError: pass else: with _GhostObjMaker(mayaType) as obj: if obj is not None: if obj.hasFn(api.MFn.kDagNode): name = api.MFnDagNode(obj).partialPathName() else: name = api.MFnDependencyNode(obj).name() if not obj.isNull() and not obj.hasFn(api.MFn.kManipulator3D) and not obj.hasFn(api.MFn.kManipulator2D): lineage = cmds.nodeType(name, inherited=1) if lineage is None: global _fixedLineages if not _fixedLineages: if versions.current() >= versions.v2012: controlPoint = cmds.nodeType('controlPoint', isTypeName=True, inherited=True) else: controlPoint = [u'containerBase', u'entity', u'dagNode', u'shape', u'geometryShape', u'deformableShape', u'controlPoint'] # maya2013 introduced shadingDependNode... if versions.current() >= versions.v2013: texture2d = ['shadingDependNode', 'texture2d'] else: texture2d = ['texture2d'] # For whatever reason, nodeType(isTypeName) returns # None for the following mayaTypes: _fixedLineages = { 'node': [], 'file': texture2d + [u'file'], 'lattice': controlPoint + [u'lattice'], 'mesh': controlPoint + [u'surfaceShape', u'mesh'], 'nurbsCurve': controlPoint + [u'curveShape', u'nurbsCurve'], 'nurbsSurface': controlPoint + [u'surfaceShape', u'nurbsSurface'], 'time': [u'time'] } if mayaType in _fixedLineages: lineage = _fixedLineages[mayaType] else: raise RuntimeError("Could not query the inheritance of node type %s" % mayaType) elif checkManip3D and 'manip3D' in lineage: raise ManipNodeTypeError try: assert (mayaType == 'node' and lineage == []) or lineage[-1] == mayaType except Exception: print mayaType, lineage raise if len(set(lineage)) != len(lineage): # cyclical lineage: first discovered with xgen nodes. # might be a result of multiple inheritance being returned strangely by nodeType. # # an example lineage is: # [u'containerBase', u'entity', u'dagNode', u'shape', u'geometryShape', u'locator', u'THlocatorShape', u'SphereLocator', # u'containerBase', u'entity', u'dagNode', u'shape', u'geometryShape', u'locator', u'THlocatorShape', u'aiSkyDomeLight'] # note the repeat - we will try to fix lineages like this, resolving to: # [u'containerBase', u'entity', u'dagNode', u'shape', u'geometryShape', u'locator', u'THlocatorShape', u'SphereLocator', u'aiSkyDomeLight'] # first pop the rightmost element, which is the mayaType... if lineage.pop() != mayaType: raise RuntimeError("lineage for %s did not end with it's own node type" % mayaType) # then try to find the first element somewhere else - this should indicate the start of the repeated chain... try: nextIndex = lineage.index(lineage[0], 1) except ValueError: # unknown case, don't know how to fix... pass else: firstLineage = lineage[:nextIndex] secondLineage = lineage[nextIndex:] if len(firstLineage) < len(secondLineage): shorter = firstLineage longer = secondLineage else: shorter = secondLineage longer = firstLineage if longer[:len(shorter)] == shorter: # yay! we know how to fix! lineage = longer lineage.append(mayaType) if updateCache and lineage: if len(set(lineage)) != len(lineage): # cyclical lineage: first discovered with xgen nodes. # might be a result of multiple inheritance being returned strangely by nodeType. print mayaType, lineage _logger.raiseLog(_logger.WARNING, "lineage for node %s is cyclical: %s" % (mayaType, lineage)) _cachedInheritances[mayaType] = lineage # don't cache any of the parents return lineage # add not just this lineage, but all parent's lineages as well... for i in xrange(len(lineage), 0, -1): thisLineage = lineage[:i] thisNode = thisLineage[-1] oldVal = _cachedInheritances.get(thisNode) if oldVal is None: _cachedInheritances[thisNode] = thisLineage elif oldVal != thisLineage: _logger.raiseLog(_logger.WARNING, "lineage for node %s changed:\n from %s\n to %s)" % (thisNode, oldVal, thisLineage)) _cachedInheritances[thisNode] = thisLineage return lineage
_logger = plogging.getLogger(__name__) try: import cPickle as pickle except: _logger.warning("using pickle instead of cPickle: load performance will be affected") import pickle #from maya.cmds import encodeString isInitializing = False # Setting this to False will make finalize() do nothing finalizeEnabled = True _finalizeCalled = False # tells whether this maya package has been modified to work with pymel pymelMayaPackage = hasattr(maya.utils, 'shellLogHandler') or versions.current() >= versions.v2011 def _moduleJoin(*args): """ Joins with the base pymel directory. :rtype: string """ moduleDir = os.path.dirname( os.path.dirname( sys.modules[__name__].__file__ ) ) return os.path.realpath(os.path.join( moduleDir, *args)) def mayaStartupHasRun(): """ Returns True if maya.app.startup has already finished, False otherwise. """
def bakeAnimation(self, switch_attr_name, val_src_nodes, key_src_nodes, key_dst_nodes, startFrame, endFrame, onlyKeyframes=True, restoreTangents=True, channels=["tx", "ty", "tz", "rx", "ry", "rz", "sx", "sy", "sz"]): # type: (str, List[pm.nodetypes.Transform], # List[pm.nodetypes.Transform], # List[pm.nodetypes.Transform], int, int, bool) -> None # Temporaly turn off cycle check to avoid misleading cycle message # on Maya 2016. With Maya 2016.5 and 2017 the cycle warning doesn't # show up if versions.current() < 201650: pm.cycleCheck(e=False) pm.displayWarning("Maya version older than: 2016.5: " "CycleCheck temporal turn OFF") channels = ["tx", "ty", "tz", "rx", "ry", "rz", "sx", "sy", "sz"] worldMatrixList = self.getWorldMatrices(startFrame, endFrame, val_src_nodes) keyframes = pm.keyframe(key_src_nodes, at=["t", "r", "s"], q=True) keyframeList = list(set(keyframes)) keyframeList.sort() # store source transform values and key tangents worldMatrixList = self.getWorldMatrices(startFrame, endFrame, val_src_nodes) if restoreTangents: tangents = self.gather_tangent_informations(key_src_nodes, channels, startFrame, endFrame) # delete animation in the space switch channel and destination ctrls pm.cutKey(key_dst_nodes, at=channels, time=(startFrame, endFrame)) pm.cutKey(switch_attr_name, time=(startFrame, endFrame)) for i, x in enumerate(range(startFrame, endFrame + 1)): if onlyKeyframes and x not in keyframeList: continue pm.currentTime(x) # set the new space in the channel self.changeAttrToBoundValue() # bake the stored transforms to the cotrols for j, n in enumerate(key_dst_nodes): n.setMatrix(worldMatrixList[i][j], worldSpace=True) pm.setKeyframe(key_dst_nodes, at=channels) if restoreTangents: self.restore_tangent_information(key_dst_nodes, tangents, startFrame, endFrame) if versions.current() < 201650: pm.cycleCheck(e=True) pm.displayWarning("CycleCheck turned back ON")