def getControlShapeFiles(): dir = CONTROL_DIRECTORY if isinstance(dir, basestring): dir = Path(dir) if not isinstance(dir, Path) or not dir.exists(): dir = Path(__file__).up() shapes = [] if dir.exists(): shapes = [f for f in dir.files() if f.hasExtension('shape')] if not shapes: searchPaths = map(Path, sys.path) searchPaths += map(Path, os.environ.get('MAYA_SCRIPT_PATH', '').split(';')) searchPaths = removeDupes(searchPaths) for d in searchPaths: try: shapes += [f for f in d.files() if f.hasExtension('shape')] except WindowsError: continue return shapes
def build_popup(self, parent, *a): cmd.setParent(parent, m=True) cmd.menu(parent, e=True, dai=True) thisFile = Path(cmd.file(q=True, sn=True)) #if the file doesn't exist, then use teh cwd if not thisFile.exists(): thisFile = thisFile.getcwd() / "tmp.ma" dir = thisFile.up() curFile = Path(cmd.textField(self.UI_file, q=True, tx=True)) for f in dir.files(): if f.hasExtension(skinWeights.EXTENSION): cmd.menuItem(l=f.name(), cb=f == curFile, c=Callback(cmd.textField, self.UI_file, e=True, tx=f)) cmd.menuItem(d=True) cmd.menuItem(l="browse", c=self.on_browseWeightFile) cmd.menuItem(d=True) cmd.menuItem(l="clear", c=lambda *a: cmd.textField(self.UI_file, e=True, tx='')) if curFile.exists(): cmd.menuItem(d=True) addExploreToMenuItems(curFile)
def getFilePartDict(): ''' returns a dictionary keyed by scene name containing a list of the parts contained in that scene ''' scenePartDict = {} #special case! we want to skip parts that are of this exact type - in older rigs this class was a RigSubPart, not a super class for the biped limb classes IkFkBaseCls = RigPart.GetNamedSubclass( 'IkFkBase' ) for rigPart in RigPart.IterAllParts(): if IkFkBaseCls: if type( rigPart ) is IkFkBaseCls: continue isReferenced = rigPart.isReferenced() if isReferenced: rigScene = Path( referenceQuery( rigPart.getContainer(), filename=True ) ) else: rigScene = Path( file( q=True, sn=True ) ) scenePartDict.setdefault( rigScene, [] ) partList = scenePartDict[ rigScene ] partList.append( rigPart ) return scenePartDict
def setValue(self, value, executeChangeCB=False): ''' the value we recieve should be a fullpath - but we want to store is as a scene relative path ''' value = Path(value) #make sure it is actually an absolute path... if value.isAbs(): curSceneDir = Path(cmd.file(q=True, sn=True)).up() value = value - curSceneDir self.UI_filepath.setValue(value, executeChangeCB)
def flush(): pluginPaths = map( Path, melUtils.melEval( 'getenv MAYA_PLUG_IN_PATH' ).split( os.pathsep ) ) #NOTE: os.environ is different from the getenv call, and getenv isn't available via python... yay! #before we do anything we need to see if there are any plugins in use that are python scripts - if there are, we need to ask the user to close the scene #now as you might expect maya is a bit broken here - querying the plugins in use doesn't return reliable information - instead we ask for all loaded #plugins, to which maya returns a list of extension-less plugin names. We then have to map those names back to disk by searching the plugin path and #determining whether the plugins are binary or scripted plugins, THEN we need to see which the scripted ones are unloadable. loadedPluginNames = cmd.pluginInfo( q=True, ls=True ) or [] loadedScriptedPlugins = [] for pluginName in loadedPluginNames: for p in pluginPaths: possiblePluginPath = (p / pluginName).setExtension( 'py' ) if possiblePluginPath.exists(): loadedScriptedPlugins.append( possiblePluginPath[-1] ) initialScene = None for plugin in loadedScriptedPlugins: if not cmd.pluginInfo( plugin, q=True, uo=True ): BUTTONS = YES, NO = 'Yes', 'NO' ret = cmd.confirmDialog( t='Plugins in Use!', m="Your scene has python plugins in use - these need to be unloaded to properly flush.\n\nIs it cool if I close the current scene? I'll prompt to save your scene...\n\nNOTE: No flushing has happened yet!", b=BUTTONS, db=NO ) if ret == NO: print "!! FLUSH ABORTED !!" return initialScene = cmd.file( q=True, sn=True ) #prompt to make new scene if there are unsaved changes... melUtils.mel.saveChanges( 'file -f -new' ) break #now unload all scripted plugins for plugin in loadedScriptedPlugins: cmd.unloadPlugin( plugin ) #we need to unload the plugin so that it gets reloaded (it was flushed) - it *may* be nessecary to handle the plugin reload here, but we'll see how things go for now #lastly, close all windows managed by baseMelUI - otherwise callbacks may fail... for melUI in baseMelUI.BaseMelWindow.IterInstances(): melUI.delete() #determine the location of maya lib files - we don't want to flush them either mayaLibPath = Path( maya.__file__ ).up( 2 ) #flush all modules dependencies.flush( [ mayaLibPath ] ) if initialScene and not cmd.file( q=True, sn=True ): if Path( initialScene ).exists(): cmd.file( initialScene, o=True ) print "WARNING: You'll need to close and re-open any python based tools that are currently open..."
def on_browse(self, *a): curValue = self.getValue() ext = curValue.getExtension() or 'txt' if curValue.isFile(): curValue = curValue.up() elif not curValue.isDir(): curValue = Path(cmd.file(q=True, sn=True)).up(2) if not curValue.exists(): curValue = Path('') filepath = cmd.fileDialog(directoryMask=curValue / ("/*.%s" % ext)) if filepath: self.setValue(filepath, True)
def setupDagProcMenu(): ''' sets up the modifications to the dagProcMenu script ''' try: dagMenuScriptpath = findFirstInEnv('dagMenuProc.mel', 'MAYA_SCRIPT_PATH') except: MGlobal.displayWarning( "Cannot find the dagMenuProc.mel script - aborting auto-override!") return tmpScriptpath = Path( cmd.internalVar(usd=True)) / 'zoo_dagMenuProc_override.mel' def writeZooLines(fStream, parentVarStr, objectVarStr): fStream.write('\n/// ZOO TOOLBOX MODS ########################\n') fStream.write('\tsetParent -m $parent;\n') fStream.write('\tmenuItem -d 1;\n') fStream.write('\tpython( "from zooPyMaya import triggeredUI" );\n') fStream.write( """\tint $killState = python( "triggeredUI.buildMenuItems( '"+ %s +"', '"+ %s +"' )" );\n""" % (parentVarStr, objectVarStr)) fStream.write('\tif( $killState ) return;\n') fStream.write('/// END ZOO TOOLBOX MODS ####################\n\n') globalProcDefRex = re.compile( "^global +proc +dagMenuProc *\( *string *(\$[a-zA-Z0-9_]+), *string *(\$[a-zA-Z0-9_]+) *\)" ) with open(dagMenuScriptpath) as f: dagMenuScriptLineIter = iter(f) with open(tmpScriptpath, 'w') as f2: hasDagMenuProcBeenSetup = False for line in dagMenuScriptLineIter: f2.write(line) globalProcDefSearch = globalProcDefRex.search(line) if globalProcDefSearch: parentVarStr, objectVarStr = globalProcDefSearch.groups() selHierarchyRex = re.compile( 'uiRes *\( *"m_dagMenuProc.kSelectHierarchy" *\)') if '{' in line: writeZooLines(f2, parentVarStr, objectVarStr) hasDagMenuProcBeenSetup = True if not hasDagMenuProcBeenSetup: for line in dagMenuScriptLineIter: f2.write(line) if '{' in line: writeZooLines(f2, parentVarStr, objectVarStr) hasDagMenuProcBeenSetup = True break if not hasDagMenuProcBeenSetup: printErrorStr("Couldn't auto setup dagMenuProc! AWOOGA!") return evalMel('source "%s";' % tmpScriptpath) evalMel('source "%s";' % tmpScriptpath)
def on_buildRig(self, e=None): curScene = Path(cmd.file(q=True, sn=True)) referenceModel = self.UI_reference.getValue() if referenceModel: if not curScene: cmd.confirmDialog( t='Scene not saved!', m= "Looks like your current scene isn't saved\n\nPlease save it first so I know where to save the rig. thanks!", b=('OK', ), db='OK') return rigPrimitives.buildRigForModel(referenceModel=referenceModel, deletePlacers=False) #if the model is being referenced run populate to update the rig part instances - container names will have changed because they're now referenced if referenceModel: self.populate() #if we're not referencing the model however, its safe to just run the updateBuildRigButton method on all rig part UI instances else: for partUI in self.UI_partForms: partUI.updateBuildRigButton()
def writePresetToFile(presetFilepath): try: contents = generatePresetContents() except NoPartsError: print "No parts found in the scene!" return Path(presetFilepath).write(contents)
def on_dirChange(self, theDir=None): if theDir is None: theDir = self.getDir() theDir = Path(theDir) self.UI_files.setRootDir(theDir) self.populateFiles()
def loadMappingFile(self, filepath): mapping = Path(filepath).unpickle() mapping = Mapping.FromDict(mapping) if self.ALLOW_MULTI_SELECTION: self._srcToTgtDict = mapping.asDict() else: self._srcToTgtDict = mapping.asFlatDict() self.refresh()
def on_storeB( self, *a ): kw = {} if self.UI_file.getValue(): kw[ 'filepath' ] = Path( self.UI_file.getValue() ) joints = cmd.ls( type='joint', r=True ) jointMeshes = removeDupes( cmd.listRelatives( joints, ad=True, pa=True, type='mesh' ) ) skinWeights.saveWeights( jointMeshes, **kw )
def getFilepath( self, copyNumber=False ): ''' will return the filepath to the scene file this node comes from. If copyNumber=True then the "copy number" will be included in the filepath - see the docs for the referenceQuery mel command for more information ''' if not self._isReferenced: return None return Path( referenceQuery( self._node, filename=True, withoutCopyNumber=not copyNumber ) )
def IterAll( cls ): for referenceNode in ls( type='reference' ): try: referenceFilepath = Path( referenceQuery( referenceNode, filename=True ) ) #maya throws an exception on "shared" references - whatever the F they are. so catch and skip when this happens except RuntimeError: continue yield referenceFilepath
def on_loadMapping(self, *a): previous = presets.getPresetDirs(presets.LOCAL, TOOL_NAME)[0] if self._previousMappingFile is not None: previous = self._previousDir filename = cmd.fileDialog(directoryMask=("%s/*.%s" % (previous, EXT))) filepath = Path(filename) self._previousMappingFile = filepath.up() self.loadMappingFile(filepath)
class PoseSymLayout(MelVSingleStretchLayout): ICONS = ICON_SWAP, ICON_MIRROR, ICON_MATCH = ( Path(__file__).up() / 'poseSym_swap.png', Path(__file__).up() / 'poseSym_mirror.png', Path(__file__).up() / 'poseSym_match.png' ) def __init__( self, parent ): self.UI_swap = swap = MelIconButton( self, label='swap pose', style='iconAndTextCentered', align='left', h=30, c=self.on_swap ) swap.setImage( self.ICON_SWAP ) self.UI_mirror = mirror = MelIconButton( self, label='mirror pose', style='iconAndTextCentered', align='left', h=30, c=self.on_mirror ) mirror.setImage( self.ICON_MATCH ) spacer = MelSpacer( self ) hLayout = MelHLayout( self ) MelLabel( hLayout, l='mirror: ' ) self.UI_mirror_t = MelCheckBox( hLayout, l='translate', v=1 ) self.UI_mirror_r = MelCheckBox( hLayout, l='rotate', v=1 ) self.UI_mirror_other = MelCheckBox( hLayout, l='other', v=1 ) hLayout.layout() self.setStretchWidget( spacer ) self.layout() ### EVENT HANDLERS ### @mayaDecorators.d_unifyUndo def on_swap( self, *a ): cmdStack = poseSym.CommandStack() for pair, obj in poseSym.iterPairAndObj( cmd.ls( sl=True ) ): pair.swap( t=self.UI_mirror_t.getValue(), r=self.UI_mirror_r.getValue(), other=self.UI_mirror_other.getValue(), cmdStack=cmdStack ) cmdStack.execute() @mayaDecorators.d_unifyUndo def on_mirror( self, *a ): for pair, obj in poseSym.iterPairAndObj( cmd.ls( sl=True ) ): pair.mirror( obj==pair.controlA, t=self.UI_mirror_t.getValue(), r=self.UI_mirror_r.getValue(), other=self.UI_mirror_other.getValue() ) @mayaDecorators.d_unifyUndo def on_match( self, *a ): for pair, obj in poseSym.iterPairAndObj( cmd.ls( sl=True ) ): pair.match( obj==pair.controlA, t=self.UI_mirror_t.getValue(), r=self.UI_mirror_r.getValue(), other=self.UI_mirror_other.getValue() )
def addExploreToMenuItems( filepath ): if filepath is None: return filepath = Path( filepath ) if not filepath.exists(): filepath = filepath.getClosestExisting() if filepath is None: return cmd.menuItem(l="Explore to location...", c=lambda x: mel.zooExploreTo( filepath ), ann='open an explorer window to the location of this file/directory') cmd.menuItem(l="CMD prompt to location...", c=lambda x: mel.zooCmdTo( filepath ), ann='open a command prompt to the location of this directory')
def on_restore( self, *a ): filepath = None if self.UI_file.getValue(): filepath = Path( self.UI_file.getValue() ) skinWeights.loadWeights( cmd.ls( sl=True ), filepath, True, #not self.UI_restoreById.getValue(), self.UI_ratio.getValue(), (-1,) if self.UI_mirror.getValue() else None, averageVerts=self.UI_average.getValue(), doPreview=False, #self.UI_doPreview.getValue(), meshNameRemapDict=self.getMeshRemapDict(), jointNameRemapDict=self.getJointRemapDict() )
def setupZooPlugins(): thisFile = Path(__file__) thisPath = thisFile.up() existingPlugPathStr = maya.mel.eval('getenv MAYA_PLUG_IN_PATH;') existingPlugPaths = map(Path, existingPlugPathStr.split(os.pathsep)) existingPlugPathsSet = set(existingPlugPaths) zooPyPath = thisPath / 'zooPyMaya' if zooPyPath not in existingPlugPathsSet: existingPlugPaths.append(zooPyPath) existingPlugPaths = removeDupes(existingPlugPaths) newPlugPathStr = os.pathsep.join( [p.unresolved() for p in existingPlugPaths]) maya.mel.eval('putenv MAYA_PLUG_IN_PATH "%s";' % newPlugPathStr)
def setupZooScriptPaths(): thisFile = Path(__file__) thisPath = thisFile.up() mayaScriptPaths = map( Path, maya.mel.eval('getenv MAYA_SCRIPT_PATH').split(os.pathsep)) mayaScriptPathsSet = set(mayaScriptPaths) zooMelPath = thisPath / 'zooMel' if zooMelPath not in mayaScriptPathsSet: mayaScriptPaths.append(zooMelPath) mayaScriptPaths.extend(zooMelPath.dirs(recursive=True)) mayaScriptPaths = removeDupes(mayaScriptPaths) newScriptPath = os.pathsep.join( [p.unresolved() for p in mayaScriptPaths]) maya.mel.eval('putenv MAYA_SCRIPT_PATH "%s"' % newScriptPath)
def getRefFilepathDictForNodes(nodes): ''' returns a dictionary keyed by the referenced filename. Key values are dictionaries which are keyed by reference node (any file can be referenced multiple times) the value of which are the given nodes that are referenced. example: we have a scene with three references: refA comes from c:/someFile.ma refB comes from c:/someFile.ma refC comes from c:/anotherFile.ma we have 3 nodes: nodeA, nodeB and nodeC. nodeA comes from refA nodeB comes from refB nodeA comes from refC in this example running getRefFilepathDictForNodes( ('nodeA', 'nodeB', 'nodeC') ) would return: { 'c:/someFile.ma': { 'refA': [ 'nodeA' ], 'refB': [ 'nodeB' ], 'c:/anotherFile.ma': { 'refC': [ 'nodeC' ] } ''' refFileDict = {} #find the referenced files for the given meshes for node in nodes: isReferenced = referenceQuery(node, inr=True) if isReferenced: refNode = referenceQuery(node, referenceNode=True) refFile = Path( referenceQuery(node, filename=True, withoutCopyNumber=True)) if refFile in refFileDict: refNodeDict = refFileDict[refFile] else: refNodeDict = refFileDict[refFile] = {} refNodeDict.setdefault(refNode, []) refNodeDict[refNode].append(node) return refFileDict
def delete( self ): nodes = sets( self._container, q=True ) for node in nodes: cleanDelete( node ) if objExists( self._container ): delete( self._container ) #if the skeleton part is referenced, clean all reference edits off skeleton part joints skeletonPart = self.getSkeletonPart() if skeletonPart.isReferenced(): skeletonPartJoints = skeletonPart.items #now unload the reference partReferenceFile = Path( referenceQuery( skeletonPart.getContainer(), filename=True ) ) file( partReferenceFile, unloadReference=True ) #remove edits from each joint in the skeleton part for j in skeletonPartJoints: referenceEdit( j, removeEdits=True, successfulEdits=True, failedEdits=True ) #reload the referenced file file( partReferenceFile, loadReference=True )
def setRootDir(self, rootDir): self._rootDir = Path(rootDir) self.update()
def getValue(self): ''' return as an absolute path ''' return Path(cmd.file(q=True, sn=True)).up() / self.UI_filepath.getValue()
def getFile(cls): clsFile = Path(inspect.getfile(cls)) if clsFile.setExtension('py').exists(): return clsFile.setExtension('py') return clsFile
def on_notepad( self, filepath ): filepath = Path( filepath ) subprocess.Popen( 'notepad "%s"' % filepath.asNative(), cwd=filepath.up() )
def getSelectedPresetNames( self ): selected = cmd.textScrollList( self.UI_tsl_presets, q=True, si=True ) or [] return [ Path( s ).name() for s in selected ]
def itemAsStr(self, item): if self._displayRelativeToRoot and self._rootDir: return str(Path(item) - self._rootDir) return str(item)
def on_storeA(self, *a): kw = {} if self.UI_file.getValue(): kw['filepath'] = Path(self.UI_file.getValue()) skinWeights.saveWeights(cmd.ls(sl=True), **kw)
import meshUtils from apiExtensions import asMObject, MObject from melUtils import mel, printErrorStr SPACE_WORLD = rigUtils.SPACE_WORLD SPACE_LOCAL = rigUtils.SPACE_LOCAL SPACE_OBJECT = rigUtils.SPACE_OBJECT Axis = rigUtils.Axis CONTROL_DIRECTORY = None if CONTROL_DIRECTORY is None: #try to determine the directory that contains the control macros dirsToSearch = [ Path(__file__).up() ] + sys.path + os.environ['MAYA_SCRIPT_PATH'].split(os.pathsep) dirsToSearch = map(Path, dirsToSearch) dirsToSearch = removeDupes(dirsToSearch) for dirToSearch in dirsToSearch: if not dirToSearch.isDir(): continue foundControlDir = False for f in dirToSearch.files(recursive=True): if f.hasExtension('shape'): if f.name().startswith('control'): CONTROL_DIRECTORY = f.up() foundControlDir = True break