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 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 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_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)
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 )
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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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)
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 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 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 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 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 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 setRootDir(self, rootDir): self._rootDir = Path(rootDir) self.update()
def getFile(cls): clsFile = Path(inspect.getfile(cls)) if clsFile.setExtension("py").exists(): return clsFile.setExtension("py") return clsFile
def ensureCurrentFileIsCheckedOut(): curFile = Path( file( q=True, sn=True ) ) if not curFile.getWritable(): curFile.edit()
def importFile( filepath, silent=False ): filepath = Path( filepath ) ext = filepath.getExtension().lower() if ext == 'ma' or ext == 'mb': cmd.file( filepath, i=True, prompt=silent, rpr='__', type='mayaAscii', pr=True, loadReferenceDepth='all' )
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
def on_notepad(self, filepath): filepath = Path(filepath) subprocess.Popen('notepad "%s"' % filepath.asNative(), cwd=filepath.up())
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_storeA(self, *a): kw = {} if self.UI_file.getValue(): kw['filepath'] = Path(self.UI_file.getValue()) skinWeights.saveWeights(cmd.ls(sl=True), **kw)
def buildRigForModel( scene=None, referenceModel=True, deletePlacers=False ): ''' given a model scene whose skeleton is assumed to have been built by the skeletonBuilder tool, this function will create a rig scene by referencing in said model, creating the rig as best it knows how, saving the scene in the appropriate spot etc... ''' #if no scene was passed, assume we're acting on the current scene if scene is None: scene = Path( cmd.file( q=True, sn=True ) ) #if the scene WAS passed in, open the desired scene if it isn't already open else: scene = Path( scene ) curScene = Path( cmd.file( q=True, sn=True ) ) if curScene: if scene != curScene: mel.saveChanges( 'file -f -open "%s"' % scene ) else: cmd.file( scene, f=True, open=True ) #if the scene is still none bail... if not scene and referenceModel: raise SceneNotSavedError( "Uh oh, your scene hasn't been saved - Please save it somewhere on disk so I know where to put the rig. Thanks!" ) #backup the current state of the scene, just in case something goes south... if scene.exists(): backupFilename = scene.up() / ('%s_backup.%s' % (scene.name(), scene.getExtension())) if backupFilename.exists(): backupFilename.delete() cmd.file( rename=backupFilename ) cmd.file( save=True, force=True ) cmd.file( rename=scene ) #finalize failedParts = finalizeAllParts() if failedParts: confirmDialog( t='Finalization Failure', m='The following parts failed to finalize properly:\n\n%s' % '\n'.join( map( str, failedParts ) ), b='OK', db='OK' ) return #delete placers if desired - NOTE: this should be done after after finalization because placers are often used to define alignment for end joints if deletePlacers: for part in SkeletonPart.IterAllParts(): placers = part.getPlacers() if placers: delete( placers ) #if desired, create a new scene and reference in the model if referenceModel: #remove any unknown nodes in the scene - these cause maya to barf when trying to save unknownNodes = ls( type='unknown' ) if unknownNodes: delete( unknownNodes ) #scene.editoradd() cmd.file( f=True, save=True ) cmd.file( f=True, new=True ) referenceFile( scene, 'model' ) #rename the scene to the rig rigSceneName = '%s_rig.ma' % scene.name() rigScene = scene.up() / rigSceneName cmd.file( rename=rigScene ) cmd.file( f=True, save=True, typ='mayaAscii' ) else: rigScene = scene buildRigForAllParts() setupMirroring() return rigScene
def saveMappingToFile( self, filepath ): filepath = Path( filepath ).setExtension( EXT ) filedata = self.getMapping() filepath.pickle( filedata )
def openFile( filepath, silent=False ): filepath = Path( filepath ) ext = filepath.getExtension().lower() if ext == 'ma' or ext == 'mb': mel.saveChanges( 'file -f -prompt %d -o "%s"' % (silent, filepath) ) mel.addRecentFile( filepath, 'mayaAscii' if Path( filepath ).hasExtension( 'ma' ) else 'mayaBinary' )
def propagateWeightChangesToModel( meshes ): ''' Given a list of meshes to act on, this function will store the skin weights, remove any edits from the skin clusters that affect them, open the scene file the meshes come from and apply the weights to the geometry in that scene. This makes it possible to fix skinning problems while animating with minimal workflow changes ''' curFile = Path( file( q=True, sn=True ) ) referencedMeshes = getRefFilepathDictForNodes( meshes ) if not curFile.name(): printWarningStr( "The current scene isn't saved - please save the current scene first before proceeding!" ) return for refFilepath, refNodeMeshDict in referencedMeshes.iteritems(): referencesToUnload = [] #make sure we don't visit any of the meshes more than once meshesToUpdateWeightsOn = [] meshesToUpdateWeightsOn_withNS = [] for refNode, refMeshes in refNodeMeshDict.iteritems(): #get the maya filepath for the reference (with the "copy number") mayaFilepathForRef = referenceQuery( refNode, f=True ) #get the namespace for this reference refNodeNamespace = file( mayaFilepathForRef, q=True, namespace=True ) #check to see if there are any meshes in this reference that we need to store weights for for mesh_withNS in refMeshes: mesh = stripNamespaceFromNamePath( mesh_withNS, refNodeNamespace ) if mesh in meshesToUpdateWeightsOn: continue meshesToUpdateWeightsOn.append( mesh ) meshesToUpdateWeightsOn_withNS.append( (mesh_withNS, refNodeNamespace) ) #append the file to the list of reference files that we need to unload referencesToUnload.append( mayaFilepathForRef ) #get a list of skin cluster nodes - its actually the skin cluster nodes we want to remove edits from... nodesToCleanRefEditsFrom = [] for m, ns in meshesToUpdateWeightsOn_withNS: nodesToCleanRefEditsFrom.append( mel.findRelatedSkinCluster( m ) ) #now we want to store out the weighting from the referenced meshes weights = [] for mesh, meshNamespace in meshesToUpdateWeightsOn_withNS: weights.append( storeWeightsById( mesh, meshNamespace ) ) #also lets remove any ref edits from the mesh and all of its shape nodes - this isn't strictly nessecary, but I can't think of a reason to make edits to these nodes outside of their native file nodesToCleanRefEditsFrom.append( mesh ) nodesToCleanRefEditsFrom += listRelatives( mesh, s=True, pa=True ) or [] #remove the skinweights reference edits from the meshes in the current scene for f in referencesToUnload: file( f, unloadReference=True ) #remove ref edits from the shape node as well - this isn't strictly nessecary but there probably shouldn't be changes to the shape node anyway for node in nodesToCleanRefEditsFrom: referenceEdit( node, removeEdits=True, successfulEdits=True, failedEdits=True ) #re-load references for f in referencesToUnload: file( f, loadReference=True ) #save this scene now that we've removed ref edits ensureCurrentFileIsCheckedOut() file( save=True, f=True ) #load up the referenced file and apply the weighting to the meshes in that scene file( refFilepath, open=True, f=True ) for mesh, weightData in zip( meshesToUpdateWeightsOn, weights ): #if there is no weight data to store - keep loopin... if not weightData: continue skinCluster = mel.findRelatedSkinCluster( mesh ) if not skinCluster: printWarningStr( "Couldn't find a skin cluster driving %s - skipping this mesh" % mesh ) continue skinWeights.setSkinWeights( skinCluster, weightData ) #save the referenced scene now that we've applied the weights to it ensureCurrentFileIsCheckedOut() file( save=True, f=True ) #reload the original file file( curFile, o=True, f=True )