SHARE
TWEET

Proxy Skinning

snolan Oct 8th, 2016 (edited) 383 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. """
  2. Proxy Skinning Utilities
  3.    Example:
  4.  
  5.        # Select faces on a mesh
  6.        from proxy import extractFaces
  7.        newMesh = extractFaces()
  8.  
  9.        # Select Source Mesh and Destination Mesh
  10.        from proxy import skinTo
  11.        newSkinCluster = skinTo()
  12. """
  13. from maya import cmds
  14. from functools import wraps
  15.  
  16. __author__ = 'Sean.Nolan'
  17. __doc__ = 'Utility functions for Proxy skinning'
  18.  
  19.  
  20. def d_undo(func):
  21.     """
  22.    Undo Decorator
  23.    :param func: incoming function
  24.    :return:
  25.    """
  26.     @wraps(func)
  27.     def _undo_func(*args, **kwargs):
  28.         try:
  29.             cmds.undoInfo(ock=True)
  30.             return func(*args, **kwargs)
  31.         finally:
  32.             cmds.undoInfo(cck=False)
  33.             cmds.undo()
  34.  
  35.     return _undo_func
  36.  
  37.  
  38. @d_undo
  39. def extractFaces(faceList=None, newName=None, keepOriginal=False, copySkinning=False):
  40.     """
  41.    Extract faces from mesh and make a copy
  42.    :param faceList: List of faces to extract
  43.    :type : list
  44.    :param newName: New mesh name
  45.    :type: str
  46.    :param keepOriginal: Make a copy of mesh before extraction
  47.    :type: bool
  48.    :param copySkinning: Copy skin weights over to extracted mesh
  49.    :type: bool
  50.    :return: Extracted mesh name
  51.    """
  52.  
  53.     if not faceList:
  54.         selectedFaces = cmds.ls(sl=True)
  55.     else:
  56.         selectedFaces = faceList
  57.  
  58.     if not bool(cmds.filterExpand(selectedFaces, ex=True, sm=34)) or []:
  59.         raise RuntimeError("Must select one or more Faces")
  60.  
  61.     shape = cmds.listRelatives(p=1)
  62.     curMesh = cmds.listRelatives(shape, p=1)[0]
  63.  
  64.     cmds.select(curMesh + '.f[:]', tgl=1)
  65.     extractFaces = cmds.ls(sl=1)
  66.  
  67.     # Save current pose
  68.     infList = cmds.skinCluster(curMesh, q=True, wi=True)
  69.     curPose = cmds.dagPose(infList, save=True, name='extractInPose')
  70.  
  71.     # Go to bind pose before copying weights
  72.     bindPose = cmds.dagPose(infList, q=True, bindPose=True)
  73.     cmds.dagPose(bindPose, restore=True)
  74.  
  75.     newMesh = cmds.duplicate(curMesh)[0]
  76.  
  77.     # Rename mesh
  78.     if newName:
  79.         newMesh = cmds.rename(newMesh, newName)
  80.  
  81.     # Copy skin weights over to new mesh
  82.     if copySkinning:
  83.         skinTo(curMesh, newMesh)
  84.  
  85.     if not keepOriginal:
  86.         cmds.delete(selectedFaces)
  87.  
  88.     # Swap current mesh to new mesh
  89.     for i in range(len(extractFaces)):
  90.         extractFaces[i] = extractFaces[i].replace(curMesh, newMesh)
  91.  
  92.     cmds.delete(extractFaces)
  93.  
  94.     # Clean new mesh
  95.     if copySkinning:
  96.         cmds.bakePartialHistory(curMesh, prePostDeformers=True)
  97.         cmds.bakePartialHistory(newMesh, prePostDeformers=True)
  98.     else:
  99.         cmds.delete(newMesh, ch=1)
  100.  
  101.     cmds.dagPose(curPose, restore=True)
  102.     cmds.delete(curPose)
  103.     cmds.select(newMesh, r=1)
  104.     return newMesh
  105.  
  106.  
  107. def skinTo(srcMesh=None, destMesh=None):
  108.     """
  109.    Skin from source to destination mesh
  110.    :param srcMesh: Source mesh
  111.    :type : str
  112.    :param destMesh: Destination Mesh
  113.    :type: str
  114.    :return: New skinCluster name
  115.    """
  116.  
  117.     # Test for selection
  118.     if not srcMesh or not destMesh:
  119.         meshes = cmds.ls(sl=1)
  120.         if meshes:
  121.             if len(meshes) >= 2:
  122.                 srcMesh = meshes[0]
  123.                 destMesh = meshes[1]
  124.             else:
  125.                 raise RuntimeError("Two meshes need to be selected!")
  126.         else:
  127.             raise RuntimeError("Two meshes need to be selected!")
  128.  
  129.     # Get source skinCluster
  130.     srcSkin = cmds.ls(cmds.listHistory(srcMesh), type='skinCluster')
  131.     if not srcSkin:
  132.         raise RuntimeError("{} does not have a skinCluster".format(srcSkin))
  133.  
  134.     # Check destination skinCluster
  135.     dstSkin = cmds.ls(cmds.listHistory(destMesh), type='skinCluster')
  136.  
  137.     # Save current pose
  138.     infList = cmds.skinCluster(srcSkin, q=True, wi=True)
  139.     curPose = cmds.dagPose(infList, save=True, name='skinToPose')
  140.  
  141.     # Go to bind pose before copying weights
  142.     bindPose = cmds.dagPose(infList, q=True, bindPose=True)
  143.     cmds.dagPose(bindPose, restore=True)
  144.  
  145.     # Build destination skinCluster
  146.     if not dstSkin:
  147.         dstPrefix = destMesh.split(':')[-1]
  148.         srcInfList = cmds.skinCluster(srcSkin[0], q=True, inf=True)
  149.         dstSkin = cmds.skinCluster(srcInfList, destMesh,
  150.                                    toSelectedBones=True, rui=False, n=dstPrefix + '_skinCluster')
  151.  
  152.     # Copy skin weights
  153.     cmds.copySkinWeights(sourceSkin=str(srcSkin[0]),
  154.                          destinationSkin=str(dstSkin[0]),
  155.                          surfaceAssociation='closestPoint',
  156.                          influenceAssociation='name',
  157.                          noMirror=True)
  158.  
  159.     cmds.dagPose(curPose, restore=True)
  160.     cmds.delete(curPose)
  161.     cmds.select(cl=1)
  162.     # Return result
  163.     return dstSkin
RAW Paste Data
Top