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)
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 )