我们从Python开源项目中,提取了以下20个代码示例,用于说明如何使用maya.cmds.skinCluster()。
def get_skin_clusters(nodes): """Get the skinClusters attached to the specified node and all nodes in descendents. :param nodes: List of dag nodes. @return A list of the skinClusters in the hierarchy of the specified root node. """ if isinstance(nodes, basestring): nodes = [nodes, ] all_skins = [] for node in nodes: relatives = cmds.listRelatives(node, ad=True, path=True) or [] relatives.insert(0, node) relatives = [shortcuts.get_shape(node) for node in relatives] for relative in relatives: history = cmds.listHistory(relative, pruneDagObjects=True, il=2) or [] skins = [x for x in history if cmds.nodeType(x) == 'skinCluster'] if skins: all_skins.append(skins[0]) return list(set(all_skins))
def copy_skin(source, destination): '''Duplicate the selected mesh with skinning''' joints = utils.get_history(source, 'joint') history = utils.get_history(destination, 'skinCluster') if history: skincluster = history[0] for joint in joints: try: cmds.skinCluster(skincluster, edit=True, lw=True, ai=joint) except RuntimeError as e: if 'is already attached' not in str(e): raise else: skincluster = cmds.skinCluster(*(joints + [destination]), tsb=True) cmds.copySkinWeights( source, destination, noMirror=True, surfaceAssociation='closestPoint', influenceAssociation='closestJoint' )
def copySkinInfluences(source, dest): sourceSkin = getSkinCluster(source) if not sourceSkin: return False joints = mc.skinCluster(sourceSkin, query=True, influence=True) destSkin = getSkinCluster(dest) if not destSkin: destSkin = mc.skinCluster(joints, dest, toSelectedBones=True)[0] else: destJoints = mc.skinCluster(destSkin, query=True, influence=True) for joint in [x for x in joints if x not in destJoints]: mc.skinCluster(destSkin, edit=True, addInfluence=joint, lockWeights=False, weight=0) return destSkin
def copySkinComponents(source, destinationVerts): if not mc.listRelatives(source, shapes=True): raise RuntimeError('Source object must be geometry.') sourceSkin = getSkinCluster(source) if not sourceSkin: raise RuntimeError("Source mesh doesn't have a skinCluster to copy from.") destMesh = mc.ls(destinationVerts[0], o=True)[0] destMesh = mc.listRelatives(destMesh, parent=True)[0] destSkin = copySkinInfluences(source, destMesh) tempSet = mc.sets(destinationVerts) mc.select(source, tempSet) mc.copySkinWeights(noMirror=True, surfaceAssociation='closestPoint', influenceAssociation='closestJoint', normalize=True) mc.delete(tempSet) mc.select(destinationVerts)
def export_skin(file_path=None, shapes=None): """Exports the skinClusters of the given shapes to disk in a pickled list of skinCluster data. :param file_path: Path to export the data. :param shapes: Optional list of dag nodes to export skins from. All descendent nodes will be searched for skinClusters also. """ if shapes is None: shapes = cmds.ls(sl=True) or [] # If no shapes were selected, export all skins skins = get_skin_clusters(shapes) if shapes else cmds.ls(type='skinCluster') if not skins: raise RuntimeError('No skins to export.') if file_path is None: file_path = cmds.fileDialog2(dialogStyle=2, fileMode=0, fileFilter='Skin Files (*{0})'.format(EXTENSION)) if file_path: file_path = file_path[0] if not file_path: return if not file_path.endswith(EXTENSION): file_path += EXTENSION all_data = [] for skin in skins: skin = SkinCluster(skin) data = skin.gather_data() all_data.append(data) logging.info('Exporting skinCluster %s on %s (%d influences, %d vertices)', skin.node, skin.shape, len(data['weights'].keys()), len(data['blendWeights'])) fh = open(file_path, 'wb') json.dump(all_data, fh) fh.close()
def __init__(self, skin_cluster): """Constructor""" self.node = skin_cluster self.shape = cmds.listRelatives(cmds.deformer(skin_cluster, q=True, g=True)[0], parent=True, path=True)[0] # Get the skinCluster MObject self.mobject = shortcuts.get_mobject(self.node) self.fn = OpenMayaAnim.MFnSkinCluster(self.mobject) self.data = { 'weights': {}, 'blendWeights': [], 'name': self.node, 'shape': self.shape }
def gather_data(self): """Gather all the skinCluster data into a dictionary so it can be serialized. :return: The data dictionary containing all the skinCluster data. """ dag_path, components = self.__get_geometry_components() self.gather_influence_weights(dag_path, components) self.gather_blend_weights(dag_path, components) for attr in SkinCluster.attributes: self.data[attr] = cmds.getAttr('%s.%s' % (self.node, attr)) return self.data
def setUp(self): self.joint1 = cmds.joint(p=(-0.5, -0.5, 0)) self.joint2 = cmds.joint(p=(0, 0.0, 0)) self.joint3 = cmds.joint(p=(0.5, 0.5, 0)) self.shape = cmds.polyCube()[0] cmds.delete(self.shape, ch=True) self.skin = cmds.skinCluster(self.joint1, self.joint2, self.joint3, self.shape)[0] self.expected = { 'bindMethod': 1, 'blendWeights': [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], 'dropoffRate': 4.0, 'heatmapFalloff': 0.0, 'maintainMaxInfluences': False, 'maxInfluences': 2, 'name': u'skinCluster1', 'normalizeWeights': 1, 'shape': u'pCube1', 'skinningMethod': 0, 'useComponents': False, 'weightDistribution': 0, 'weights': { u'joint1': [0.9, 0.5, 0.5, 0.0, 0.5, 0.0, 0.9, 0.5], u'joint2': [0.10000000000000002, 0.5, 0.5, 0.5, 0.5, 0.5, 0.10000000000000002, 0.5], u'joint3': [0.0, 0.0, 0.0, 0.5, 0.0, 0.5, 0.0, 0.0]} }
def dm2skin_getLargestInfluenceOnVert(vertex, skinCluster=None): """Given a vertex returns the largest influence in the provided skin cluster that acts upon it.""" if not skinCluster: return False vertInfs = cmds.skinCluster(skinCluster, q=True, inf=True) vertVals = cmds.skinPercent(skinCluster, vertex, q=True, value=True) return vertInfs[vertVals.index(max(vertVals))]
def dm2skin_getNeighbouringJoints(joint, vertexString=None, cluster=None, influences=3): """This gets a list of nearby joints in the skin cluster to joint up to the number of influences. These will be the ones we use in our minimization later""" if not cmds.objExists(joint): return False if influences < 3: return False if not cluster: return False clusterJoints = cmds.skinCluster(cluster, q=True, inf=True) pos1 = cmds.xform(vertexString, q=True, ws=True, t=True) parentJoint = cmds.listRelatives(joint, parent=True) subtract = 1 # add the main joint resultList = [joint] # i've found it works best to always include the parent if parentJoint and parentJoint in clusterJoints: resultList.insert(0, parentJoint[0]) subtract = 2 # for the rest of the available influences get a list of nearby joints in space measureList = [] for measureJnt in clusterJoints: if measureJnt not in resultList: jntPos2 = cmds.xform(measureJnt, q=True, ws=True, t=True) #this just gets the length of the vector between the two joints dist = math.sqrt(reduce(lambda x, y: x + y, [math.pow(jntPos2[i] - pos1[i], 2) for i in range(len(pos1))])) measureList.append((measureJnt, dist)) # sort the list in ascending order so we get the closest joints first measureList.sort(key=lambda dist: dist[1]) ascendingList = [entry[0] for entry in measureList[0:influences - subtract]] return resultList + ascendingList
def dm2skin_getMaxInfluences(mesh): """Finds a skin cluster on the given mesh and returns the number of influences it is set to have.""" skinClusterStr = 'findRelatedSkinCluster("' + mesh + '")' skinCluster = mel.eval(skinClusterStr) if not skinCluster: return 0 allInfluences = cmds.skinCluster(skinCluster, q=True, inf=True) return len(allInfluences)
def copySkinning(*args): """select the orig bound mesh, then the new unbound target mesh and run""" sel = cmds.ls(sl=True) orig = sel[0] target = sel[1] #get orig obj joints try: jnts = cmds.skinCluster(orig, q=True, influence = True) except: cmds.warning("couldn't get skin weights from {}".format(orig)) #bind the target with the jnts try: targetClus = cmds.skinCluster(jnts, target, bindMethod=0, skinMethod=0, normalizeWeights=1, maximumInfluences = 3, obeyMaxInfluences=False, tsb=True)[0] print targetClus except: cmds.warning("couln't bind to {}".format(target)) #get skin clusters origClus = mel.eval("findRelatedSkinCluster " + orig) #copy skin weights from orig to target try: cmds.copySkinWeights(ss=origClus, ds=targetClus, noMirror=True, sa="closestPoint", ia="closestJoint") except: cmds.warning("couldn't copy skin weights from {0} to {1}".format(orig, target))
def new_joint_bind_at_center(tform, *args): """ create a new joint at the boudnign box center of pts and bind all pts to 1 :param tform - string - the geo to bind :param args: :return: string - skinCluster """ cmds.select(cl=True) jnt = cmds.joint(name="{0}_base_JNT".format(tform)) center = bounding_box_center(tform) cmds.xform(jnt, ws=True, t=center) skinCl = cmds.skinCluster(jnt, tform, normalizeWeights=1)[0] return(jnt, skinCl)
def main(): sel = mc.ls(sl=True) for each in sel: shapes = mc.listRelatives(each, shapes=True) for shape in shapes: #get skin cluster history = mc.listHistory(shape, groupLevels=True, pruneDagObjects=True) skins = mc.ls(history, type='skinCluster') for skin in skins: joints = mc.skinCluster(skin, query=True, influence=True) mc.setAttr(skin+'.envelope', 0) mc.skinCluster(skin, edit=True, unbindKeepHistory=True) #delete bindPose dagPose = mc.dagPose(each, query=True, bindPose=True) if dagPose: mc.delete(dagPose) dagPose = mc.listConnections(skin+'.bindPose', d=False, type='dagPose') if dagPose: mc.delete(dagPose) mc.skinCluster(joints, shape, toSelectedBones=True) mc.setAttr(skin+'.envelope', 1) if sel: mc.select(sel)
def getSkinCluster(mesh): shapes = mc.listRelatives(mesh, shapes=True, path=True) for shape in shapes: history = mc.listHistory(shape, groupLevels=True, pruneDagObjects=True) if not history: continue skins = mc.ls(history, type='skinCluster') if skins: return skins[0] return None
def softSelectionSkinWeights(*args): model = mc.ls(sl=True, o=True) joints = mc.ls(model, type='joint') mc.select(joints, deselect=True) weights = getSoftSelectionWeights() if not model or not joints or not weights: raise RuntimeError('Select vertices followed by a joint') if len(joints) > 1: raise RuntimeError('Only one joint can be selected at a time') joint = joints[0] skin = utl.getSkinCluster(model[0]) if not skin: raise RuntimeError('Mesh must have an existing skinCluster') influences = mc.skinCluster(skin, query=True, influence=True) if joint not in influences: mc.skinCluster(skin, edit=True, addInfluence=joint, lockWeights=False, weight=0) for influence in influences: mc.skinCluster(skin, edit=True, influence=influence, lockWeights=False) for vertex, weight in weights.items(): mc.skinPercent(skin, vertex, transformValue=(joint, weight)) mc.select(joint) # ______________________ # - -/__ Revision History __/- - - - - - - - - - - - - - - - - - - - - - - - # # Revision 1: 2016-12-31 : Initial publish
def create_spine(start_joint, end_joint, lower_control, upper_control, name='spine'): spline_chain, original_chain = shortcuts.duplicate_chain(start_joint, end_joint, prefix='ikSpine_') # Create the spline ik ikh, effector, curve = cmds.ikHandle( name='{0}_ikh'.format(name), solver='ikSplineSolver', startJoint=spline_chain[0], endEffector=spline_chain[-1], parentCurve=False, simplifyCurve=False) effector = cmds.rename(effector, '{0}_eff'.format(name)) curve = cmds.rename(curve, '{0}_crv'.format(name)) # Create the joints to skin the curve curve_start_joint = cmds.duplicate(start_joint, parentOnly=True, name='{0}CurveStart_jnt'.format(name)) cmds.parent(curve_start_joint, lower_control) curve_end_joint = cmds.duplicate(end_joint, parentOnly=True, name='{0}CurveEnd_jnt'.format(name)) cmds.parent(curve_end_joint, upper_control) # Skin curve cmds.skinCluster(curve_start_joint, curve_end_joint, curve, name='{0}_scl'.format(name), tsb=True) # Create stretch network curve_info = cmds.arclen(curve, constructionHistory=True) mdn = cmds.createNode('multiplyDivide', name='{0}Stretch_mdn'.format(name)) cmds.connectAttr('{0}.arcLength'.format(curve_info), '{0}.input1X'.format(mdn)) cmds.setAttr('{0}.input2X'.format(mdn), cmds.getAttr('{0}.arcLength'.format(curve_info))) cmds.setAttr('{0}.operation'.format(mdn), 2) # Divide # Connect to joints for joint in spline_chain[1:]: tx = cmds.getAttr('{0}.translateX'.format(joint)) mdl = cmds.createNode('multDoubleLinear', name='{0}Stretch_mdl'.format(joint)) cmds.setAttr('{0}.input1'.format(mdl), tx) cmds.connectAttr('{0}.outputX'.format(mdn), '{0}.input2'.format(mdl)) cmds.connectAttr('{0}.output'.format(mdl), '{0}.translateX'.format(joint)) # Setup advanced twist cmds.setAttr('{0}.dTwistControlEnable'.format(ikh), True) cmds.setAttr('{0}.dWorldUpType'.format(ikh), 4) # Object up cmds.setAttr('{0}.dWorldUpAxis'.format(ikh), 0) # Positive Y Up cmds.setAttr('{0}.dWorldUpVectorX'.format(ikh), 0) cmds.setAttr('{0}.dWorldUpVectorY'.format(ikh), 1) cmds.setAttr('{0}.dWorldUpVectorZ'.format(ikh), 0) cmds.setAttr('{0}.dWorldUpVectorEndX'.format(ikh), 0) cmds.setAttr('{0}.dWorldUpVectorEndY'.format(ikh), 1) cmds.setAttr('{0}.dWorldUpVectorEndZ'.format(ikh), 0) cmds.connectAttr('{0}.worldMatrix[0]'.format(lower_control), '{0}.dWorldUpMatrix'.format(ikh)) cmds.connectAttr('{0}.worldMatrix[0]'.format(upper_control), '{0}.dWorldUpMatrixEnd'.format(ikh)) # Constrain original chain back to spline chain for ik_joint, joint in zip(spline_chain, original_chain): if joint == end_joint: cmds.pointConstraint(ik_joint, joint, mo=True) cmds.orientConstraint(upper_control, joint, mo=True) else: cmds.parentConstraint(ik_joint, joint)
def create_joint(cvs, wts): tform = cvs[0].partition(".")[0] curve = cmds.listRelatives(tform, f=True, s=True)[0] ps = [] center = [] for cv in cvs: ps.append(cmds.pointPosition(cv)) center = [sum(y)/len(y) for y in zip(*ps)] #create joint at location # ----------- should get closest point on surface cmds.select(cl=True) jnt = cmds.joint() cmds.xform(jnt, ws=True, t=center) #---------------- orient the joint along the curve? #---------------- here create the ctrl set up for the joint ctrl = rig.createControl(name="{0}Ctrl".format(jnt), type="sphere", color="red") grp = cmds.group(name="{0}Grp".format(ctrl), em=True) cmds.parent(ctrl, grp) cmds.xform(grp, ws=True, t=center) cmds.parent(jnt, ctrl) # scale the control comps = cmds.ls("{0}.cv[*]".format(ctrl)) cmds.select(comps, r=True) cmds.scale(.2,.2,.2) #add influence to skin Cluster cmds.select(tform, r=True) cmds.skinCluster(e=True, ai=jnt, wt=0) cmds.setAttr("{0}.v".format(jnt), 0) #apply weights to that joint cls = mel.eval("findRelatedSkinCluster " + tform) for v in range(len(cvs)): cmds.skinPercent(cls, cvs[v], transformValue=[jnt, wts[v]]) return(jnt, ctrl, grp)
def soft_selection_to_joint(*args): """ takes a soft selection of verts and creates a joint to bind & wieght them in that proportion :param args: :return: string - name of the soft sel joint we've created """ # TODO - check for selection of verts! selVtx = cmds.ls(sl=True, fl=True) # to get center for joint vtxs, wts = rig.get_soft_selection() # to get weights for jnt tform = vtxs[0].partition(".")[0] mesh = cmds.listRelatives(tform, s=True)[0] ptOnSurface = cmds.checkBoxGrp(widgets["jntCPOMCBG"], q=True, v1=True) auto = cmds.checkBoxGrp(widgets["jntAutoCBG"], q=True, v1=True) jntName = cmds.textFieldGrp(widgets["jntNameTFG"], q=True, tx=True) rotOnSurface = cmds.checkBoxGrp(widgets["jntRotCBG"], q=True, v1=True) cls = mel.eval("findRelatedSkinCluster " + tform) if not cls: if auto: baseJnt, cls = rig.new_joint_bind_at_center(tform) else: cmds.warning("There isn't an initial bind on this geometry. Either create one or check 'auto'") return() center = rig.average_point_positions(selVtx) rot = (0,0,0) if ptOnSurface: center = rig.closest_pt_on_mesh_position(center, mesh) if rotOnSurface: rot = rig.closest_pt_on_mesh_rotation(center, mesh) cmds.select(cl=True) jnt = cmds.joint(name = jntName) cmds.xform(jnt, ws=True, t=center) cmds.xform(jnt, ws=True, ro=rot) # add influence to skin Cluster cmds.select(tform, r=True) cmds.skinCluster(e=True, ai=jnt, wt=0) # apply weights to that joint for v in range(len(vtxs)): cmds.skinPercent(cls, vtxs[v], transformValue=[jnt, wts[v]]) newName = rig.increment_name(jntName) cmds.textFieldGrp(widgets["jntNameTFG"], tx=newName, e=True) return(jnt)
def createCenterOfMass(*args): ''' Create a center of mass node, and constrain it to the character based on the selected root node. ''' sel = mc.ls(sl=True) if not len(sel) == 1: raise RuntimeError('Please select the root control of your puppet.') print 'Create Center Of Mass Node' print '--------------------------' meshes = meshesFromReference(sel[0]) or meshesFromHistory(sel[0]) if not meshes: raise RuntimeError('Could not determine geomerty from selected control. Make sure geo is visible.') mc.select(meshes) mc.refresh() print 'Discovered Meshes:' for mesh in meshes: print '\t',mesh skinnedMeshes = [] for mesh in meshes: if utl.getSkinCluster(mesh): skinnedMeshes.append(mesh) continue hist = mc.listHistory(mesh, breadthFirst=True) skins = mc.ls(hist, type='skinCluster') if not skins: warnings.warn('Could not find a skinned mesh affecting {}'.format(mesh)) continue outGeo = mc.listConnections(skins[0]+'.outputGeometry[0]', source=False) outGeo = mc.ls(outGeo, type=['mesh','transform']) if not outGeo: warnings.warn('Could not find a skinned mesh affecting {}'.format(mesh)) continue skinnedMeshes.append(outGeo[0]) if not skinnedMeshes: raise RuntimeError('Could not determine skinned geometry from selected control. This tool will only work if geo is skinned.') locator = centerOfMassLocator(skinnedMeshes) mc.addAttr(locator, longName=COM_ATTR, attributeType='message') mc.connectAttr('.'.join((sel[0],'message')), '.'.join((locator,COM_ATTR))) mc.select(sel) return locator