def iterateHistory(self, plugs=False, node_type=None): """ A generator that parses the history of the shape based on connections. As a result you get a depth-only history, without nodes that are connected as blendShape targets or other clutter. :param str node: deformable shape (or its transform) :param bool plugs: list tuples of (input, output) attributes instead of nodes :param str node_type: filter the history based on the node type :return generator: generator that iterates over history ex: skin_clusters = list(adbTransform.Transform(pm.selected()[0]).iterateHistory( node_type='skinCluster')) """ history_plug = (pm.listHistory( self.transform, q=True, historyAttr=True) or [None])[0] future_plug = None while True: if node_type is None or pm.objectType(self.transform, isAType=node_type): if plugs: yield history_plug, future_plug else: yield self.transform if history_plug is None: break future_plug = (pm.listConnections(history_plug, source=True, destination=False, shapes=True, skipConversionNodes=False, plugs=True) or [None])[0] if future_plug is None: break self.transform = future_plug.split('.')[0] future_attr = '.'.join(future_plug.split('.')[1:]) history_plug = None if pm.objectType(self.transform, isAType='geometryFilter'): if future_attr.startswith('outputGeometry['): history_plug = '{0}.{1}.inputGeometry'.format( self.transform, future_attr.replace('outputGeometry', 'input')) elif pm.objectType(self.transform, isAType='polyModifier'): if future_attr == 'output': history_plug = '{0}.inputPolymesh'.format(self.transform) elif pm.objectType(self.transform, isAType='deformableShape'): if future_plug in (pm.listHistory(self.transform, q=True, futureLocalAttr=True)[0], pm.listHistory(self.transform, q=True, futureWorldAttr=True)[0]): history_plug = pm.listHistory(self.transform, q=True, historyAttr=True)[0] elif future_attr == 'outputGeometry': if pm.objExists('{0}.inputGeometry'.format(self.transform)): history_plug = '{0}.inputGeometry'.format(self.transform)
def poly_soft_edge(self, target, prefix=True, suffix=False): if suffix: prefix = False if prefix: prefix = 'unlockNorm_' suffix = '' elif suffix: prefix = '' suffix = '_unlockNorm' target_list = target if not isinstance(target_list, list): target_list = [target_list] for target in target_list: target = pm.PyNode(target) target_shape = self.get_visible_shape(target) old_polySoftEdge_list = pm.listHistory(target_shape, type = 'polySoftEdge') pm.polySoftEdge(target, angle = 180, constructionHistory = True) new_polySoftEdge_list = pm.listHistory(target_shape, type = 'polySoftEdge') for polySoftEdge in new_polySoftEdge_list: if polySoftEdge not in old_polySoftEdge_list: polySoftEdge.rename(prefix + target.stripNamespace() + suffix)
def unlock_normal(self, target, prefix=True, suffix=False): if suffix: prefix = False if prefix: prefix = 'unlockNorm_' suffix = '' elif suffix: prefix = '' suffix = '_unlockNorm' target_list = target if not isinstance(target_list, list): target_list = [target_list] for target in target_list: target = pm.PyNode(target) target_shape = self.get_visible_shape(target) old_unlockNorm_list = pm.listHistory(target_shape, type = 'polyNormalPerVertex') pm.polyNormalPerVertex(target, unFreezeNormal = True) new_unlockNorm_list = pm.listHistory(target_shape, type = 'polyNormalPerVertex') for unlockNorm in new_unlockNorm_list: if unlockNorm not in old_unlockNorm_list: unlockNorm.rename(prefix + target.stripNamespace() + suffix)
def get_connected_attributes_in_node_tree(node_or_nodes, node_types=None): """ gets all attributes, its type, the node_type and data_type Args: node_or_nodes: all connected attributes belonging to the node or nodes node_types: if unspecified it will only add the node of the given node_types Returns: dict {attribute: {"node_type": "some_node_type", "data_type": "some_data_type", "type": "some_attribute_type" } } """ # find all nodes connected in tree and remove doubled tree_nodes = list(set(pmc.listHistory(node_or_nodes, f=True, ac=True) + pmc.listHistory(node_or_nodes, ac=True))) all_connected_attributes = [] # checks if the attribute is a relevant attribute by checking # the node types of the nodes connected to it def _check_node_type(attribute): if node_types: is_relevant = False if attribute.nodeType() in node_types: dependencies = attribute.connections(p=True) if dependencies: for dependency in dependencies: if not is_relevant and dependency.nodeType() in node_types: is_relevant = True if is_relevant: all_connected_attributes.append(attribute) else: all_connected_attributes.append(attribute) # based on all nodes in tree get all related attributes # do the filtering and check if the attribute is relevant for connection in pmc.listConnections(tree_nodes, c=True, p=True): source, destination = connection if source not in all_connected_attributes: _check_node_type(source) if destination not in all_connected_attributes: _check_node_type(destination) # subdict skeleton every keys value in attribute should have subdict = {"node_type": None, "data_type": None, "type": None} attribute_dict = {} for attribute in all_connected_attributes: _ = subdict.copy() _["node_type"] = attribute.nodeType() _["data_type"] = attribute.type() _["type"] = get_used_attribute_type(attribute) attribute_dict[attribute.name()] = _ return attribute_dict
def get_connections(node_or_nodes): """ gets all connections for a single or multiple nodes Args: node_or_nodes: node name or PyNode instance (list) Returns: dict {slot: slot} """ # find all nodes connected in tree and remove doubled tree_nodes = list(set(pmc.listHistory(node_or_nodes, f=True, ac=True) + pmc.listHistory(node_or_nodes, ac=True))) return {str(x): str(y) for x, y in pmc.listConnections(tree_nodes, c=True, p=True, s=False)}
def get_skin_cluster(ob): """ Find the first skinCluster on the object that actually effects it. When multiple deformers are layered, this means that the latest skin in the deform chain will be returned. In situations where multiple skins are layered through blendshapes, this function will only return the skin on the current mesh and not any of the blendshape sources. :param ob: The object whose skin you wish to return. :returns: A skinCluster object, or None. """ shape = get_deform_shape(ob) if shape is None: return (None) skins = pm.ls(pm.listHistory(shape), type='skinCluster') if len(skins): for skin in skins: # log( '\t+ Processing %s...' % skin ) groupId = skin.input[0].groupId.inputs(plugs=True)[0] outputs = groupId.outputs(plugs=True) for outp in outputs: node = outp.node() if node == shape or node == ob: ## force neighbors! skin.weightDistribution.set(1) ## neighbors return (skin) return (None)
def GetHistoryByType(_oObj, _sType): aHistory = pm.listHistory(_oObj) for pCurHistory in aHistory: pCurType = pm.nodeType(pCurHistory) if pCurType == _sType: return pCurHistory return None
def getSkinCluster(obj): """Get the skincluster of a given object Arguments: obj (dagNode): The object to get skincluster Returns: pyNode: The skin cluster pynode object """ skinCluster = None if isinstance(obj, basestring): obj = pm.PyNode(obj) try: if (pm.nodeType(obj.getShape()) in ["mesh", "nurbsSurface", "nurbsCurve"]): for shape in obj.getShapes(): try: for skC in pm.listHistory(shape, type="skinCluster"): try: if skC.getGeometry()[0] == shape: skinCluster = skC except Exception: pass except Exception: pass except Exception: pm.displayWarning("%s: is not supported." % obj.name()) return skinCluster
def get_key_range(obj, start_frame=None, end_frame=None): ''' Find the first and last keyed frame from an object that lies outside of the given start and end frame range Args: obj (PyNode): The object to query start_frame (float): The current lowest frame to compare against end_frame (float): The current highest frame to compare against Returns: (float, float). The lowest and highest frame ''' first_key = start_frame last_key = end_frame historyNodes = pm.listHistory(obj, pruneDagObjects=True, leaf=False) animCurves = pm.ls(historyNodes, type='animCurve') if animCurves: # Warning - pm.findKeyframe will return currentTime if it's given no anim curves first_key = pm.findKeyframe(animCurves, which='first') last_key = pm.findKeyframe(animCurves, which='last') # We use frame -10000 and -10001 as a special holder frame for keys used by tools start_frame = first_key if first_key < start_frame or start_frame == None else start_frame start_frame = None if start_frame == -10000 or start_frame == -10001 else start_frame end_frame = last_key if last_key > end_frame or end_frame == None else end_frame end_frame = None if end_frame == -10000 or end_frame == -10001 else end_frame return (start_frame, end_frame)
def test_clusterPlane(self): fr = FollowRibbon.FollowRibbon(name="blah") plane = pm.nurbsPlane(axis=[0, 1, 0], patchesU=8, patchesV=1, lengthRatio=0.1, ch=0)[0] ctrls = [] ctrls.append(pm.circle(n="blah_ctrl_01")[0].name()) ctrls.append(pm.circle(n="blah_ctrl_02")[0].name()) mainGrp = pm.group(em=1, name="main") result = fr._clusterPlane(plane=plane, controls=ctrls, mainGrp="main") self.testLib.assertListEqual(result, ["blah_cluster_01Handle", "blah_cluster_02Handle"]) self.assertTrue(pm.objExists("blah_cluster_01")) self.assertTrue(pm.objExists("blah_cluster_02")) self.assertTrue(pm.listRelatives(result[0], parent=True), "main") self.assertTrue(pm.listRelatives(result[1], parent=True), "main") self.assertTrue(pm.listRelatives(result[0], parent=1)[0], "blah_ctrlsGrp") self.assertTrue(pm.listRelatives(result[1], parent=1)[0], "blah_ctrlsGrp") hist = pm.listHistory(plane) hitA = 0 hitB = 0 for each in hist: if each.name() == "blah_cluster_01": hitA = 1 if each.name() == "blah_cluster_02": hitB = 1 self.assertTrue(hitA) self.assertTrue(hitB) self.assertTrue(pm.isConnected("blah_ctrl_01.translate", "blah_cluster_01Handle.translate")) self.assertTrue(pm.isConnected("blah_ctrl_02.translate", "blah_cluster_02Handle.translate"))
def findFileNodes(self, shape): print "shape:", shape def checkInputs(node): inputNodes = node.inputs() if len(inputNodes) == 0: return [] else: filteredNodes = [ x for x in inputNodes if x.type() != "renderLayer" ] return filteredNodes # geo = obj.getShape() # Get the shading group from the selected mesh try: sg = shape.outputs(type='shadingEngine') except: # if there is no sg, return en empty list return [] everyInput = [] for i in sg: everyInput += pm.listHistory(i) everyInput = self.makeUnique(everyInput) print "everyInput", everyInput fileNodes = pm.ls(everyInput, type="file") return fileNodes
def analyzeShader(shape): current = 0 for i in shape: if str(shape[current]).endswith("Shape") == True: # Check for a file texture in the shader shader = cmds.listConnections(shape[current], type='shadingEngine') print(shader) usedTextureNodes = (pm.listHistory(shader, type="file")) #check if list is empty if not usedTextureNodes: pass else: print(usedTextureNodes) try : mel.eval('generateUvTilePreview ' + usedTextureNodes[current]) except IndexError: pass current += 1 # select the actual shape cmds.ls(shape) children_nodes = cmds.listRelatives(allDescendents=True, type='shadingEngine')
def get_skin_cluster(obj): if isinstance(obj, pymel.nodetypes.SkinCluster): return obj for hist in pymel.listHistory(obj): if isinstance(hist, pymel.nodetypes.SkinCluster): return hist return None
def SJ_randomChoice(): sels = pm.ls(sl=1) for sel in sels: try: selshape = sel.getShape() except: selshape = None if selshape != None: sg = pm.listConnections(selshape, s=0, type="shadingEngine")[0] choicesels = pm.listHistory(sg, ac=1, type="choice") if choicesels != []: for choicesel in choicesels: filesel = pm.listConnections(choicesel, s=0, type="file") if filesel != []: num = len(filesel[0].listAttr(ud=1)) - 1 value = random.randint(0, num) conjudges = pm.listConnections(choicesel + ".selector", c=1) if conjudges == []: pm.setAttr(choicesel + ".selector", value) print str(sel) + ">>>>>" + str(value), else: pm.disconnectAttr(conjudges[0]) pm.setAttr(choicesel + ".selector", value) print str(sel) + ">>>>>" + str(value), else: pm.warning("no choiceFileNode!!") else: pm.warning("no choiceNode!!")
def findIKHandle( joints=[] ): ''' update : 2015-04-29 ''' if joints: pm.select(joints) joints = pm.ls(sl=True, type='joint') if not joints: raise TypeError(u'조인트 체인의 조인트이름을 명시하거나 선택하세요.') ikHandles = [] for joint in joints: print joint while joint: history = pm.listHistory( joint, future=True, type='ikHandle' ) if history: ikHandles.append( history[0] ) break else: joint = joint.getParent() if ikHandles: ikHandles = list(set(ikHandles)) # 중복 제거 pm.select(ikHandles) return ikHandles
def _get_vert_weight_dict(): sel = pm.ls(sl=True) if (len(sel) != 1): pm.error('Please select ONE mesh transform') mesh = sel[0] if (mesh.type() != 'transform'): pm.error('Please select a MESH TRANSFORM') # get the skincluster skinclusters = [] for node in pm.listHistory(mesh): if (type(node) == pm.nodetypes.SkinCluster): skinclusters.append(node) vertweightdict = {} for skincluster in skinclusters: for joint in skincluster.getWeightedInfluence(): verts, weights = skincluster.getPointsAffectedByInfluence(joint) for i, vert in enumerate(verts[0]): weight = weights[i] if (not vert in vertweightdict.keys()): vertweightdict[vert] = [] vertweightdict[vert].append((joint, weight)) return vertweightdict, skinclusters
def createSkinnedMesh(): """ Creates a skinned mesh node for each root joint found in the skin clusters Returns: (list): PyNodes of nodes created. """ selected = pm.selected() scene_name = pm.sceneName().namebase if selected: skin_clusters = set() skin_clusters.update(set(pm.listConnections(selected, type='skinCluster'))) skin_clusters.update(set(pm.listHistory(selected, type='skinCluster'))) else: skin_clusters = pm.ls(type='skinCluster') if not skin_clusters: pm.warning('No skin clusters found!') piper_skinned_mesh = create('piperSkinnedMesh', 'pink', name=pcfg.skinned_mesh_prefix + 'piperSkinnedMesh') return [piper_skinned_mesh] piper_skinned_meshes = [] skinned_meshes = myu.getSkinnedMeshes(skin_clusters) for root_joint, geometry in skinned_meshes.items(): name = '' if scene_name.startswith(pcfg.skinned_mesh_prefix) else pcfg.skinned_mesh_prefix name += scene_name if scene_name else next(iter(geometry)).nodeName() piper_skinned_mesh = create('piperSkinnedMesh', 'pink', name=name) piper_skinned_meshes.append(piper_skinned_mesh) geometry_parents = myu.getRootParents(geometry) pm.parent(root_joint, geometry_parents, piper_skinned_mesh) return piper_skinned_meshes
def copySkin(skinedMesh, mesh): """ Copy skin cluster from a skined mesh """ # Checks nodetypes if not isinstance(skinedMesh, pm.nodetypes.Transform): skinedMesh = pm.PyNode(skinedMesh) if not isinstance(mesh, pm.nodetypes.Transform): mesh = pm.PyNode(mesh) # get shape skinedMeshShape = skinedMesh.getShape() # loop since a skin cluster are found skinCluster = pm.listHistory(skinedMeshShape, type='skinCluster')[0] # skinCluster = pm.PyNode(skinCluster) skinInf = skinCluster.maxInfluences.get() # joint list jointList = skinCluster.influenceObjects() # create skinCluster copySkinCluster = pm.skinCluster(mesh, jointList, mi=skinInf) print copySkinCluster # copy skin weigths pm.copySkinWeights(ss=skinCluster, ds=copySkinCluster, noMirror=True, surfaceAssociation='closestPoint', influenceAssociation=('closestJoint', 'closestJoint'))
def FindDeformers ( shape=None , type=''): if shape==None: obj = pm.ls(sl=True)[0] shape = obj.getShape() if shape : # List Deformers history = pm.listHistory( shape, pruneDagObjects=True, interestLevel=2 ) deformers = [] for node in history : nodeTypes = pm.nodeType( node, inherited=True ) if 'geometryFilter' in nodeTypes: if type=='' and nodeTypes[1] != 'tweak' : deformers.append(node) elif nodeTypes[1] == type and nodeTypes[1] != 'tweak': deformers.append(node) return deformers else: pm.warning('No shape found.')
def connectLipSetup(self): if not _hierarchyChecker(self.namespaceName): pm.windows.confirmDialog( title='Hierarchy Error', message= 'Hierarchy has some error please\nplease opens script editor for details.', button=['Yes', 'No'], defaultButton='Yes', cancelButton='No', dismissString='No') ar_qui.ar_displayDialogue('error', 'Hierarchy is not proper.') ar_qui.ar_displayMessage('error', 'Hierarchy is not proper.') return False # connect all rivet to "self.face_geo" geometry. for each in self.lipCtrlGrps: allHist = pm.listHistory(each, pdo=True) for hist in allHist: if hist.nodeType() == 'pointOnCurveInfo': crvFrmMshEdg = hist.inputCurve.connections( )[0].create.connections()[0] inputShape = self.face_geo.getShapes(ni=True)[0] inputShape.worldMesh[0].connect(crvFrmMshEdg.inputMesh, f=True) # add blendshape. for each in self.lip_geos: ar_blendshape.ar_addBlendShape(each, self.face_geo, value=1)
def options_box_setup(self): self.optvars.add('zSplitBlendShapesBlendDistance', 'float', 2) self.optvars.add('zSplitBlendShapesPlane', 'int', 2) self.optvars.add('zSplitBlendShapesPlaneOrigin', 'float', 0) self.optvars.add('zSplitBlendShapesNamingPattern', 'string', '<name>_<L|R>') parent = pm.columnLayout(adjustableColumn=1) pm.optionMenuGrp('sbsList', label='Blend shape:', cc=self.fill_blend_target) self.fill_blend_shapes('sbsList|OptionMenu', False) pm.optionMenuGrp('sbsLeftOutput', label='Left output:') self.fill_blend_shapes('sbsLeftOutput|OptionMenu', True) pm.optionMenuGrp('sbsRightOutput', label='Right output:') self.fill_blend_shapes('sbsRightOutput|OptionMenu', True) # If something is selected, try to find a blend shape to select by default. selection = pm.ls(sl=True) if selection: history = pm.listHistory(selection) blend_shapes = pm.ls(history, type='blendShape') if blend_shapes: default_blend_shape = blend_shapes[0] self.select_blend_shape(default_blend_shape) pm.optionMenuGrp('sbsTargetList', label='Blend target:') self.fill_blend_target() pm.floatSliderGrp('sbsBlendDistance', label='Blend distance', field=True, min=0, max=10, fieldMinValue=0, fieldMaxValue=1000) pm.radioButtonGrp('sbsPlane', label='Plane:', numberOfRadioButtons=3, labelArray3=('XY', 'YZ', 'XZ')) pm.floatSliderGrp('sbsPlaneOrigin', label='Plane origin', v=0, min=0, max=1000) pm.textFieldGrp('sbsNamingPattern', label='Naming pattern')
def get_target_defomer(target, deformer, multiple=False): """ Query the name of deformer on a target geometery @param target (string/pynode) the geometery which contains the deformer @param deformer (string) the deformer which is queried @param multiple (bool) whether to query the first deformer found and return a list of deformer @return name / list of names of the target deformers @code import libUtilities #Query a single defomer libUtilities.get_target_defomer("myGeo","skinCluster") # Result: 'skinCluster1' # #Query multiple defomers libUtilities.get_target_defomer("myGeo","cluster",multiple=True) # Result: ['cluster1','cluster2','cluster3','cluster4']# @endcode """ allDeformers = pm.listHistory(target, pdo=1) if allDeformers: allTargetDeformers = [] for dfrm in allDeformers: if dfrm.type() == deformer: if multiple: allTargetDeformers.append(dfrm.name()) else: return dfrm.name() if allTargetDeformers: allTargetDeformers.reverse() return allTargetDeformers
def ar_getInfluenceJoint(sel=None): """ @ select influence objects from selected skinned object. Args: sel (list): single object but in list. Returns: infObj. """ if not sel: sel = pm.ls(sl=True) if len(sel) == 1: skc = list() [ skc.append(str(each)) for each in pm.listHistory(sel[0], pdo=True) if each.nodeType() == 'skinCluster' ] if len(skc) == 1: infObj = cmds.skinCluster(skc[0], q=True, inf=True) return infObj else: ar_qui.ar_displayMessage( 'error', 'selected object has found multiple skin clusters...') return False else: ar_qui.ar_displayMessage('warning', 'Please select one skinned object...') return False
def list_history(object, type): hist = pymel.listHistory(object, lv=1) nodes = [] for h in hist: if pymel.objectType(h) == type: nodes.append(h) return nodes
def get_skin_cluster(skined_geometry): for each in pm.listHistory(skined_geometry, interestLevel=2, pruneDagObjects=True): if each.__class__ == pm.nodetypes.SkinCluster: return each return None
def _get_vert_weight_dict() : sel = pm.ls( sl=True ) if( len( sel ) != 1 ) : pm.error( 'Please select ONE mesh transform' ) mesh = sel[0] if( mesh.type() != 'transform' ) : pm.error( 'Please select a MESH TRANSFORM' ) # get the skincluster skinclusters = [] for node in pm.listHistory( mesh ) : if( type( node ) == pm.nodetypes.SkinCluster ) : skinclusters.append( node ) vertweightdict = {} for skincluster in skinclusters : for joint in skincluster.getWeightedInfluence() : verts, weights = skincluster.getPointsAffectedByInfluence( joint ) for i, vert in enumerate( verts[0] ) : weight = weights[i] if( not vert in vertweightdict.keys() ) : vertweightdict[ vert ] = [] vertweightdict[ vert ].append( ( joint, weight ) ) return vertweightdict, skinclusters
def linkTheHooks(self): faceShapesGeo = "bsMan_fRig_PLY" faceGeo = "C_head_low_PLY" faceShapesGeoHis = pm.listHistory(faceShapesGeo) faceShapesBls = cmds.ls(faceShapesGeoHis, type="blendShape")[0] targetIndeces = pm.getAttr(faceShapesBls + ".weight", multiIndices=1) bsShapeNames = [ pm.aliasAttr("{0}.weight[{1}]".format(faceShapesBls, num), query=True) for num in targetIndeces ] faceBlendGRP = pm.group(empty=True, n="faceBlends_hooks") for x in bsShapeNames: pm.addAttr(faceBlendGRP, sn=x) hooks = pm.PyNode("faceBlends_hooks") # Check every blendshape for matching hook names. allBlends = pm.ls(type='blendShape') for newBlend in allBlends: for eachShape in newBlend.w: shapeName = eachShape.getAlias() if hooks.hasAttr(shapeName): hookAttr = hooks.attr(shapeName) try: hookAttr.connect(eachShape, force=True) except: continue pm.blendShape(faceShapesGeo, faceGeo, weight=[0, 1]) pm.setAttr(faceShapesGeo + ".visibility", 0)
def createManipulatorDynamic(self): pm.select(cl=True) #createTextCurves nurbsText = self.prefix + '_ctrl' textCurvesReturnList = pm.textCurves(f='arial', t=nurbsText, ch=True) textTopGrp = textCurvesReturnList[0] makeTextCurvesNode = textCurvesReturnList[1] pm.select(cl=True) #get future history of makeTextCurvesNode textHistoryList = pm.listHistory(makeTextCurvesNode, future=True, af=True) #get list of transforms and NurbsCurve nodes connected to makeTextCurvesNode textTransformList = [] textNurbsCurveList = [] for node in textHistoryList: if (pm.nodeType(node) == 'transform'): textTransformList.append(node) if (pm.nodeType(node) == 'nurbsCurve'): textNurbsCurveList.append(node) pm.select(cl=True) #delete makeTextCurvesNode pm.delete(makeTextCurvesNode) pm.select(cl=True) #iterate through transformList, move pivot to ws (0,0,0) and freeze all for transformNode in textTransformList: pm.xform(transformNode, ws=True, piv=(0, 0, 0)) pm.makeIdentity(transformNode, a=True) #create manip_dynamicGrp self.manip_dynamic = pm.group(n=self.prefix + '_manip_dynamic') pm.select(cl=True) #iterate through nurbsCurve list and parent shapes under manip ctrlCenter for nurbsCurveShape in textNurbsCurveList: pm.parent(nurbsCurveShape, self.manip_dynamic, r=True, s=True) pm.select(cl=True) #create manip_dynamic grp and translate correctly self.manip_dynamic_grp = pm.group(n=self.prefix + '_manip_dynamic_grp') pm.select(cl=True) pm.parent(self.manip_dynamic, self.manip_dynamic_grp) pm.select(cl=True) self.manip_dynamic_grp.translate.set(self.highResCurveCoordList[0]) #delete remaining text transform nodes pm.delete(textTopGrp) pm.select(cl=True)
def getSkin(node): skin = [ x for x in pmc.listHistory(node) if pmc.nodeType(x) == "skinCluster" ] if skin: return skin[0].name() else: return None
def getBlendShapeNode(sourceObj): history = pm.listHistory(sourceObj, il=2, pdo=1) blendNodes = [x for x in history if isinstance(x, pm.nodetypes.BlendShape)] if blendNodes: return blendNodes[ -1] # get last blendShape, if there is a predeform one. Need to check else: return None
def connectScale(obj, ctl): obj = pym.PyNode(obj) ctl = pym.PyNode(ctl) dmN = pym.listHistory(obj, type="deltaMush")[0] try: ctl.scale.connect(dmN.scale) except Exception as e: print "ERROR:", e
def getObjectJoints(): """returns list of joints on skinned geometry""" skinnedObject = pm.ls(sl=True) #when there is more than one skin connection it will throw an error (example skinned blendshape) objectConnections = pm.listHistory(skinnedObject[0], exactType="skinCluster") objectJoints = objectConnections[0].getWeightedInfluence() return objectJoints
def createManipCtrlCenter(self): pm.select(cl = True) #createTextCurves nurbsText = self.prefix + '_Ctrl' textCurvesReturnList = pm.textCurves(f = 'arial' , t = nurbsText, ch = True ) textTopGrp = textCurvesReturnList[0] makeTextCurvesNode = textCurvesReturnList[1] pm.select(cl = True) #get future history of makeTextCurvesNode textHistoryList = pm.listHistory(makeTextCurvesNode, future = True, af = True) #get list of transforms and NurbsCurve nodes connected to makeTextCurvesNode textTransformList = [] textNurbsCurveList = [] for node in textHistoryList: if(pm.nodeType(node) == 'transform'): textTransformList.append(node) if(pm.nodeType(node) == 'nurbsCurve'): textNurbsCurveList.append(node) pm.select(cl = True) #delete makeTextCurvesNode pm.delete(makeTextCurvesNode) pm.select(cl = True) #iterate through transformList, move pivot to ws (0,0,0) and freeze all for transformNode in textTransformList: pm.xform(transformNode, ws = True, piv = (0,0,0)) pm.makeIdentity(transformNode, a = True) #create manipCtrlGrp self.manip_CtrlCenter = pm.group(n = self.prefix + '_manip_ctrl_center') pm.select(cl = True) #iterate through nurbsCurve list and parent shapes under manip ctrlCenter for nurbsCurveShape in textNurbsCurveList: pm.parent(nurbsCurveShape, self.manip_CtrlCenter, r = True, s = True) pm.select(cl = True) #create manip_ctrlCenter grp and translate correctly self.manip_CtrlCenter_grp = pm.group(n = self.prefix + '_manip_ctrl_center_grp') pm.select(cl = True) pm.parent(self.manip_CtrlCenter, self.manip_CtrlCenter_grp) pm.select(cl = True) self.manip_CtrlCenter_grp.translate.set(self.jointPositionList[-1][0], self.jointPositionList[-1][1] + 2, self.jointPositionList[-1][2]) #delete remaining text transform nodes pm.delete(textTopGrp) pm.select(cl = True)
def delete_smooth_on_selected(cls): selection = pm.ls(sl=1) deleteList = [] for item in selection: hist = pm.listHistory(item) for i in range(0, len(hist)): if hist[i].type() == 'polySmoothFace': deleteList.append(hist[i]) pm.delete(deleteList)
def getColor(obj, attr): # get texture name from asigned material shadingGroup = pm.listConnections(obj, type='shadingEngine') if not pm.listHistory(shadingGroup, type='alSurface'): # GET TEXTURE FROM ALL SHADERS but alSurface if attr == 'mtoa_constant_mColor': imageFile = pm.listHistory(shadingGroup, type='file') else: imageDisp = pm.listHistory(shadingGroup, type='displacementShader') if imageDisp: imageFile = pm.listHistory(imageDisp, type='file') else: imageFile = None if imageFile: texture = imageFile[0].attr('fileTextureName').get().replace('\\','/') return texture else: # Get texture from alSurface shader = pm.listHistory(shadingGroup, type='alSurface') imf = pm.listConnections( shader[0].diffuseColor ) if imf: texture = imf[0].attr('fileTextureName').get().replace('\\','/') return texture
def getBlendShapes(self,*args): getSel = pm.ls(sl=1,fl=1) if len(getSel) == 1: self.meshWithBS = getSel[0] bsNd = pm.ls(pm.listHistory(getSel[0]) or [],type='blendShape') itemInList = pm.textScrollList("blendshapeList",q=1,ai=1) if len(itemInList)>0: for x in bsNd: if x not in itemInList: listItems = pm.textScrollList("blendshapeList",e=1,append=x) else: listItems = pm.textScrollList("blendshapeList",e=1,append=bsNd)
def cbsStart(*args, **kwargs): base = kwargs.setdefault('base', pm.ls(sl=True)[0]) # (string) The base model for the character shape = kwargs.setdefault('shape') # (string) The shape node of the base model tweak = kwargs.setdefault('tweak') # (string) The tweak node of the base model that is being skinned skin = kwargs.setdefault('skin') # (string) The skinCluster node that is driving the base model #gather some info base, shape, tweak, skin = gatherInfo(base, shape, tweak, skin) verts = pm.polyEvaluate(base, v=True) #do a quick check to make sure this part hasn't been done before if base.hasAttr('baseTransform'): pm.error('You have already run the "Start" function on this model, so it is already ready to go.' + 'If corrections have already been made, click "Extract Shape to finish the process"') for i in pm.listHistory(base, lv=1): if i.type() == 'polySmoothFace': pm.error('The selected shape is connected to a smooth modifier. This hinders the ability to track edits. %s must be deleted.' % i) #turn off a couple things that might mess with things pm.symmetricModelling(e=True, symmetry= False) pm.softSelect(e=True, softSelectEnabled=False) for i in range(verts): x = pm.getAttr(('%s.vlist[0].vertex[%i].xVertex'%(tweak, i))) y = pm.getAttr(('%s.vlist[0].vertex[%i].yVertex'%(tweak, i))) z = pm.getAttr(('%s.vlist[0].vertex[%i].zVertex'%(tweak, i))) if not (x+y+z) == 0: pm.error('You have used the tweak node. No me gusta. If you really wanna clear it, run clearTweaks and try again. It will save what you have') #ok, let's get started, first instance the original mesh sculptTrans = pm.instance(base, n=('%s_corrective_sculpt'%base))[0] pm.reorderDeformers(skin, tweak, base) pm.setAttr('%s.v'%base, False) #Here, we'll make a duplicate of the base to look back on later if need be (for instance, using sculpt geometry tends to not register on tweak) baseRef = pm.duplicate(base, n='%s_editReference'%base)[0] pm.connectAttr(('%s.outMesh' %baseRef.getShapes()[1]), ('%s.inMesh' %baseRef.getShape())) #We'll also hook up the original so we can get it later pm.addAttr(sculptTrans, ln='baseTransform', at='message') pm.addAttr(sculptTrans, ln='baseReference', at='message') pm.connectAttr('%s.message'%base, '%s.baseTransform'%sculptTrans) pm.connectAttr('%s.message'%baseRef, '%s.baseReference'%sculptTrans) #now to keep things from changing between functions, we'll lock the three nodes involved in the #other script so our pesky little user won't delete or rename anything pm.lockNode(base, l=True) pm.lockNode(sculptTrans, l=True)
def copySkin(cls, skin_from, skin_to): """ !@Brief Copy Skin with point of shape. CopySkin of maya doesn't really works with different shape. :type skin_from: pymel.core.nodetypes.Transform / shape / SkinCluster :param skin_from: Maya node reference for copy skin :type skin_to: pymel.core.nodetypes.Transform / shape / SkinCluster :param skin_to: Maya node to copy skin. :rtype: bool :return: True if copy skin is finish. """ # Get skin Cluster from_node = pmc.listHistory(skin_from, type="skinCluster")[0] to_node = pmc.listHistory(skin_to, type="skinCluster") # If to node is None add Skin cluster from from_node if not to_node: to_node = cls.skinFromOther(from_node, skin_to) else: to_node = to_node[0] # Check two skin in case cls.checkTwoSkin(from_node, to_node) # CopySkin pmc.copySkinWeights( node_utils.getPointName(skin_from), node_utils.getPointName(skin_to), sourceSkin=from_node.name(), destinationSkin=to_node.name(), noMirror=True, surfaceAssociation="closestComponent", influenceAssociation="oneToOne" )
def _ls_file_tex_node(mesh, tex_name_surfix): try: sg = pm.listConnections(mesh, s=0, d=1, type='shadingEngine')[0] except: return [] all_file_nodes = [] for file_node in pm.listHistory(sg, type='file'): try: for surfix in tex_name_surfix: if file_node.ftn.get()[:-4].endswith(surfix): all_file_nodes.append(file_node) break except: pass return all_file_nodes
def populateBsMen(*args): bs = [] #getting blendshapes for i in pm.listHistory(args[-1]): if pm.objectType(i, isType='blendShape'): bs.append(str(i)) print bs #clearing then re-populating the menu args[-2].clear() pm.menuItem(l='<Create New>', p=args[-2]) for i in bs: pm.menuItem(l=i, p=args[-2])
def findFollicle( joints=[] ): ''' update : 2015-04-29 ''' ikHandles = findIKHandle( joints ) follicles = [] for ikHandle in ikHandles: history = pm.listHistory( ikHandle, type='follicle' ) if history: follicles.append( history[0] ) if follicles: pm.select(follicles) return follicles
def findHairSystem( joints=[] ): ''' update : 2015-04-29 ''' ikHandles = findIKHandle( joints ) hairSystems = [] for ikHandle in ikHandles: history = pm.listHistory( ikHandle, type='hairSystem' ) if history: hairSystems.append( history[0] ) if hairSystems: pm.select(hairSystems) return hairSystems
def findNucleus( joints=[] ): ''' update : 2015-04-29 ''' hairSystems = findHairSystem( joints ) nucleus = [] for hairSystem in hairSystems: history = pm.listHistory( hairSystem, type='nucleus' ) if history: nucleus.append( history[0] ) if nucleus: pm.select(nucleus) return nucleus
def findSplineIKCrv(joints=[]): ''' update : 2015-05-08 ''' ikHandles = findIKHandle( joints ) ikCurves = [] for hdl in ikHandles: history = pm.listHistory( hdl, type='nurbsCurve', levels=1 ) if history: ikCurves.append( history[0].getParent() ) if ikCurves: pm.select(ikCurves) return ikCurves
def cMuscle_prepareRelax(mesh): hist = pm.listHistory(mesh, pdo=True, il=1) muscleSystems = pm.ls(hist, type='cMuscleSystem') muscleSystems = list(set(muscleSystems)) for ms in muscleSystems: deformed = pm.deformer(ms, q=True, geometry=True)[0] if deformed.type() in ['nurbsSurface', 'mesh', 'subdiv']: ms.envelope.set(0) a, size = 0, 0 for attr in ['smoothData.smoothEntry','smoothData.ptToPtEntry','relaxData.relaxSt','relaxData.relaxBd','relaxData.relaxTri']: for index in range(0, ms.attr(attr).get(size=True)-1): pm.removeMultiInstance(ms.attr(attr)[index]) pm.cMuscleRelaxSetup(ms, gen=True) ms.envelope.set(1)
def findDynamicCurve( joints=[] ): ''' update : 2015-04-29 ''' follicles = findFollicle( joints ) nurbsCurves = [] for follicle in follicles: history = pm.listHistory( follicle, future=True, type='nurbsCurve' ) if history: nurbsCurves.append( history[0] ) if nurbsCurves: nurbsCurves = [crv.getParent() for crv in nurbsCurves ] pm.select(nurbsCurves) return nurbsCurves
def changeTrailDivisions(*args): selection = pm.ls(sl=1) trail = '' if selection: trail = selection[0] else: pm.warning('Select a trail to change divisions') return try: extrudeNode = pm.listHistory(trail,exactType = 'polyExtrudeEdge')[0] divisions = pm.intSliderGrp('trailDivisions', q=1,v=1) pm.setAttr(extrudeNode + '.divisions',divisions) createTrailUv(trail) except: pm.warning('Couild not find an extrude in the history')
def getAOVsInNetwork(rootNode): ''' returns a map from PyNode to aovs the aov list contains all registered aovs for that node type, regardless of whether they are currently enabled in the globals ''' results = {} for node in pm.listHistory(rootNode, pruneDagObjects=True): # TODO: Create a general method to assign AOVs of hidden nodes # lambert shader has only translator registered so this is a Lambert Maya node and does not have an AOV tab if pm.nodeType(node) == "lambert": results[node] = [u'direct_diffuse', u'indirect_diffuse'] else: # TODO: cache this result results[node] = [node.attr(at).get() for (aov, at, type) in aovs.getNodeGlobalAOVData(node.type())] return results
def find_hierarchy_errors(topNode): """ Return a dictanary of lists with common hierarchy errors @param topNode (pynode, string) The top node of a group @return A dictionary of errors """ duplicateTransform = [] duplicateShapes = [] namespaceTransform = [] geoWithHistory = [] incorrectShapes = [] for mesh in pm.listRelatives(topNode, type="mesh", ad=1, ni=True): meshParent = mesh.getParent() # Check shapes with namespace if ":" in mesh.name(): namespaceTransform.append(meshParent) # Check duplicate shapes if "|" in mesh.name(): duplicateShapes.append(mesh) # Check the shape name is name correctly if ("%sShape" % meshParent.name()) != mesh.name(): incorrectShapes.append(mesh) # Check geo with history if pm.listHistory(meshParent, ha=1, pdo=1): geoWithHistory.append(meshParent) for transform in pm.listRelatives(topNode, type="transform", ad=1, ni=True): # Check duplicate transform names if "|" in transform.name(): duplicateTransform.append(transform) return {"Namespace Transform": namespaceTransform, "Duplicate Shapes": duplicateShapes, "Duplicate Transform": duplicateTransform, "Incorrect Shape Names": incorrectShapes, "History Geos": geoWithHistory }
def _detect_dominant_color(mesh, tex_name_surfix, sample_rate, max_auto_sample, default_shader, default_channel): """ Try to guess average color of all textures whose name surfix match tex_name_surfix. If there is no texture, copy value from default channel in default shader. """ sampled_pixels = [] sample_verts = _ls_sample_verts(mesh, sample_rate, max_auto_sample) for file_tex_node in _ls_file_tex_node(mesh, tex_name_surfix): for v in sample_verts: color = _tex_color_from_uv(file_tex_node, v.getUV()) if color: sampled_pixels.append(color) if not len(sampled_pixels): try: sg = pm.listConnections(mesh, s=0, d=1, type='shadingEngine')[0] sampled_pixels = [pm.getAttr(shader.name() + '.' + default_channel) for shader in pm.listHistory(sg, type=default_shader)] except: return None # dominant_color = _average_color(sampled_pixels) dominant_color = _most_frequent_color(sampled_pixels) return dominant_color
def gatherInfo(*args): base, shape, tweak, skin = args #weed out any mistakes if not base: pm.error('No objects are selected') #gather info if not shape: shape = pm.listRelatives(base, s=True)[0] if not pm.objectType(shape, isType='mesh'): pm.error('This script is only approved to work with polygons') shapeConns = pm.listHistory(shape) for i in shapeConns: if pm.objectType(i, isType='tweak') and not tweak: tweak = i elif pm.objectType(i, isType='skinCluster') and not skin: skin = i else: continue return base, shape, tweak, skin
def createHairSystemForDynamicCurve(self): #Select dynamicCurve pm.select(cl = True) pm.select(self.spline_ik_dynamic_curve, r = True) #makeCurveDynamic pm.runtime.MakeCurvesDynamic() pm.select(cl = True) #get Hairsystem and Follicle #---------------------------------------------------- futureListDynamicCurve = pm.listHistory(self.spline_ik_dynamic_curve.getShape(), future = True, af = True) #Iterate futureList and get Hairsystem and follicle for node in futureListDynamicCurve: #HairSys if(pm.nodeType(node) == 'hairSystem'): self.dynamicHairsystem = node pm.rename(self.dynamicHairsystem.getParent(), self.prefix + '_dynamic_hair_system') #Follicle if(pm.nodeType(node) == 'follicle'): #follicle self.dynamicHairsystemFollicle = node pm.rename(self.dynamicHairsystemFollicle.getParent(), self.prefix + '_dynamic_hair_system_follicle') #follicle_grp self.dynamicHairsystemFollicleGrp = self.dynamicHairsystemFollicle.getParent().getParent() pm.rename(self.dynamicHairsystemFollicleGrp, self.prefix + '_dynamic_hair_system_follicle_grp') pm.select(cl = True) #get dynamicOutputCurve #---------------------------------------------------- connectionsList = pm.listConnections(self.dynamicHairsystemFollicle.outCurve, d = True) #dynamicOutputCurve self.dynamicOutputCurve = connectionsList[0] pm.rename(self.dynamicOutputCurve, self.prefix + '_dynamic_output_curve') pm.select(cl = True) #dynamicOutputCurveGrp self.dynamicOutputCurveGrp = self.dynamicOutputCurve.getParent() pm.rename(self.dynamicOutputCurveGrp, self.prefix + '_dynamic_output_curve_grp') pm.select(cl = True) #group hairSystem nodes #---------------------------------------------------- self.hairsystemNodesGrp = pm.group(n = self.prefix + '_hairSys_nodes_grp') pm.select(cl = True) #parent pm.parent(self.dynamicOutputCurveGrp, self.dynamicHairsystem.getParent(), self.dynamicHairsystemFollicleGrp, self.hairsystemNodesGrp) pm.select(cl = True) #Initial hairSys and follicle adjustments #---------------------------------------------------- #Set Follicle point lock attr to lock base pm.setAttr(self.dynamicHairsystemFollicle.pointLock, 1)
def mirror_cluster_on_lattice(): # 最後に選択を復元するために保存する selected = pm.selected() # 選択しているノードから clusterHandle をリストアップする target_cluster_handles = pm.ls(selection=True, type=u'clusterHandle') # 選択している transform の shape を確認して clusterHandle なら格納する is_cluster_only = True for transform in pm.ls(selection=True, type=u'transform'): for shape in transform.getShapes(): if pm.nt.ClusterHandle == type(shape): target_cluster_handles.append(shape) else: is_cluster_only = False # 初めに選択していたリストと数が合わなかったら # clusterHandle 以外を選択していたとみなして終了 if is_cluster_only and len(selected) == len(target_cluster_handles): message = u'These are not clusterHandle. ' \ u'Please select the clusterHandle only.' OpenMaya.MGlobal.displayError(message) sys.exit() # clusterHandle を一つも選択していなければ終了 if 0 == len(target_cluster_handles): message = u'Not found clusterHandle from selection list, ' \ u'Please select more clusterHandle before execute.' OpenMaya.MGlobal.displayError(message) sys.exit() # clusterHandle のコネクションを追って cluster をリストアップする target_clusters = pm.listConnections(target_cluster_handles, destination=True, type=u'cluster') # いったん無効化するデフォーマのセットを格納する変数を宣言 deformers = set() # mesh か lattice 以外を対象にしている cluster があれば格納する ignore_deformers = [] for target_cluster in target_clusters: # cluster のデフォーム対象を getGeometry で取得: 名前の配列が返る output_geometries = target_cluster.getGeometry() # type を調べるために一度 PyNode にする output_geometries = [pm.PyNode(g) for g in output_geometries] # フィルタリングする前の数を保存 output_num = len(output_geometries) # デフォーム対象を mesh か lattice だけにする output_geometries = filter(lambda g: pm.nodetypes.Mesh == type(g) or pm.nodetypes.Lattice == type(g), output_geometries) # mesh か lattice 以外にもセットされてる cluster ならスキップする if output_num is not len(output_geometries): ignore_deformers.append(target_cluster) continue # デフォーム対象のヒストリをリストアップする histories = pm.listHistory(output_geometries) # 継承している nodeType を調べて geometryFilter が含まれていたらデフォーマと確定 [deformers.add(d) for d in histories if u'geometryFilter' in pm.nodeType(d, inherited=True)] # mesh か lattice 以外にアタッチしている cluster があれば選択して処理を止める if 0 < len(ignore_deformers): ignore_handles = [d.matrix.listConnections()[0] for d in ignore_deformers] pm.select(ignore_handles) message = u'These are the cluster that are not supported. ' \ u'It must be attached only to the mesh or lattice. => ' \ + ' '.join([c.name() for c in ignore_handles]) OpenMaya.MGlobal.displayError(message) sys.exit() # あとで復元する envelope を保存。デフォーマをキーにしつつ envelope を保存する envelopes = {d: d.getEnvelope() for d in deformers} # デフォーマを無効化し元の形状にする [d.setEnvelope(0) for d in deformers] for target_cluster in target_clusters: # target_cluster のデフォーム対象を格納する members = [] [members.extend(x) for x in pm.listSets(object=target_cluster)] # lattice1.pt[0:9][0:9][0:9] みたいにまとめられてる配列を全部バラバラに扱う members = pm.ls(members, flatten=True) # node をキーにして ポイント を値に格納する member_dict = {} # node の全ポイントの座標を pm.dt.Point 型で格納する all_points_dict = {} for member in members: # ポイントの node 部分を摘出する node = member.node() # すでに node がキーに存在するなら if node in member_dict: # ポイントを格納して次へ進む member_dict[node].append(member) continue # ポイントを list でラッピングして値を初期化 member_dict[node] = [member] # さらに mesh や lattice の全ポイント座標を格納する if pm.nt.Mesh == type(node): all_points_dict[node] = vtx2pointsDict(node.vtx) elif pm.nt.Lattice == type(node): all_points_dict[node] = pt2pointsDict(node.pt) mirror_point_and_weights = {} for node in member_dict.iterkeys(): all_points = all_points_dict[node] if pm.nt.Mesh == type(node): for member in member_dict[node]: # vtx の world 座標を取得する。pm.dt.Point 型で返ってくる p = member.getPosition(space='world') # x を反転して p = pm.dt.Point(p.x * -1, p.y, p.z) # p に一番近いポイントを摘出 v = distanceMin(p, all_points) # member のウェイトをコピーするため、保存している mirror_point_and_weights[v] = pm.percent(target_cluster, member, query=True, value=True)[0] elif pm.nt.Lattice == type(node): # ここでは負荷軽減のため . (ドットシンタックス)無しで、 # 関数を呼び出せるようにキャッシュしている xform = pm.xform point = pm.dt.Point for member in member_dict[node]: # pt の world 座標を取得する。list of double 型で返ってくる p = xform(member, query=True, translation=True, worldSpace=True) # x を反転しつつ pm.dt.Point 型にする p = point(p[0] * -1, p[1], p[2]) # p に一番近いポイントを摘出 v = distanceMin(p, all_points) # member のウェイトをコピーするため、保存している mirror_point_and_weights[v] = pm.percent(target_cluster, member, query=True, value=True)[0] # 反転した点を選択する pm.select(mirror_point_and_weights.keys()) # cluster を作成する new_cluster, new_cluster_handle = pm.cluster() # 新しい cluster に元のアトリビュートの値をセットする new_cluster.attr('relative') \ .set(target_cluster.attr('relative').get()) new_cluster.attr('usePartialResolution') \ .set(target_cluster.attr('usePartialResolution').get()) new_cluster.attr('angleInterpolation') \ .set(target_cluster.attr('angleInterpolation').get()) new_cluster.attr('percentResolution') \ .set(target_cluster.attr('percentResolution').get()) new_cluster.setEnvelope(envelopes[target_cluster]) # 処理が完了した時に選択するリストに新しい clusterHandle も含める selected.append(new_cluster_handle) # envelope を復元 [d.setEnvelope(envelopes[d]) for d in envelopes.iterkeys()] # 初めに選択していたリスト + 新たな clusterHandle リストを選択する pm.select(selected)
def SkinToClust ( joints=None, sourceGeometry=None, finalGeometry=None ): #============================================================================ # user inputs if sourceGeometry==None or finalGeometry==None or joints==None: geoAndJnts = pm.ls(sl=True) sourceGeometry = geoAndJnts[ len (geoAndJnts) -2 ] finalGeometry = geoAndJnts[ len (geoAndJnts) -1 ] joints = geoAndJnts[:len (geoAndJnts) -2 ] #============================================================================ # find the skinCluster node on given objects skinClust = pm.ls ( pm.listHistory (sourceGeometry ) , type = "skinCluster" )[0] if skinClust == []: pm.error( "Source Object is not skinned." ) #============================================================================ # create a list per selected influence containing # all the vertices and their weights # find shape of sourceShape sourceShape = sourceGeometry.getShape() # find shape of finalShape finalShape = finalGeometry.getShape() # find the number of vertices of sourceGeometry numOfVtxs = pm.polyEvaluate(finalGeometry) ["vertex"] jnt = joints[0] for jnt in joints: # start progress window amount = 0 pm.progressWindow( title= str(jnt), progress=0, status=(" find " + str(jnt) + " weights:"), isInterruptable=True ) # create a dictionary containing all the values #================== tempDic = {} zeroVtxs = [] # create counter for amount for status present if numOfVtxs != 0: counter = 100.0 / numOfVtxs vtx = 1 for vtx in range(numOfVtxs): # get values from skinCluster tempVal = pm.skinPercent ( skinClust , sourceShape.vtx[vtx] ,q =True , value=True , transform = jnt ) # if the value is not 0 then add it to dictionary if not ( tempVal == 0 ): tempDic [vtx] = tempVal # else create a list containing 0 valued vertices else: zeroVtxs.append ( finalGeometry.vtx[vtx] ) # change progress window # pm.progressWindow ( edit=True, progress= int (amount), status=(" find " + str(jnt) + " weights:") ) # change amount for status present amount += counter # end progress window pm.progressWindow(endProgress=1) # create a cluster in the position of the joint #================== currentClustAndHandle = pm.cluster( finalShape , rel=True , n = (str(jnt)+"clust") ) currentClust = pm.ls( currentClustAndHandle[0] )[0] currentClustHandle = pm.ls( currentClustAndHandle[1] )[0] # change membership of cluster #================== # start progress window amount = 0 pm.progressWindow( title= str(jnt), progress=0, status=(" change " + str(jnt) + " membership:"), isInterruptable=True ) # create counter for amount for status present if len(zeroVtxs) != 0: counter = 100.0 / len(zeroVtxs) pm.sets ( currentClust+"Set" , rm = zeroVtxs ) # end progress window pm.progressWindow(endProgress=1) # positioning the clusters #================== # get position from current joint clustPos = pm.xform (jnt , q =True , ws=True , t=True ) # set cluster origin values currentClustHandle.origin.set( clustPos ) # center pivot of cluster pm.xform( currentClustHandle , centerPivots=True) # start progress window #==================== # create a new progress window amount = 0 pm.progressWindow( title= str(jnt), progress=0, status=(" apply " + str(jnt) + " weights:") , isInterruptable=True ) # create counter for amount for status present if len(tempDic) != 0: counter = 100.0 / len(tempDic) # get the values from dictionary we've created and use them as cluster weights #================== for vtx in tempDic: # applying values pm.percent ( currentClust , finalShape.vtx[vtx] , v = tempDic [vtx] ) # change progress window #pm.progressWindow ( edit=True, progress= int (amount), status=(" apply " + str(jnt) + " weights:") ) # change amount for status present amount += counter # end progress window pm.progressWindow(endProgress=1)
def cMuscle_getDeformers(deformerType, items): defs=[] hist=pm.listHistory(items, pdo=True, il=1) defs = pm.ls(hist, type=deformerType) defs = list(set(defs)) return defs
def cMuscle_connectToSystem(systems): if len(systems) <= 0: pm.warning(mel.eval('uiRes("m_cMuscle.kMustSelectMuscleObjectsAndMuscleSystemDeformerOrGeometry")')) mOs = pm.listRelatives(systems, shapes=True, ni=True, type='cMuscleObject') hist = pm.listHistory(systems, il=1, pdo=True) muscleSystems = pm.ls(hist, type='cMuscleSystem') muscleSystems = list(set(muscleSystems)) if len(mOs) <= 0: pm.warning(mel.eval('uiRes("m_cMuscle.kMustSelectMuscleObject2")')) if len(muscleSystems) <= 0: pm.warning(mel.eval('uiRes("m_cMuscle.kMustSelectMuscleSystem2")')) maxDist, hasNurbs, avgDist = -1, 0, 0.0 for mo in mOs: if mo.type() == 1: avgDist += mel.eval('cMuscle_autoCalcStickyBindDistance(%s)'%mo) hasNurbs+=1 break distMode = 0 #Only query for Max Dist if adding NURBs in. if hasNurbs: avgDist = avgDist/hasNurbs labelAutoCalculate = mel.eval('uiRes("m_cMuscle.kAutoCalculate")') labelAvgValue = mel.eval('uiRes("m_cMuscle.kAvgValue")') labelAllPoints = mel.eval('uiRes("m_cMuscle.kAllPoints")') labelCancel = mel.eval('uiRes("m_cMuscle.kCancel2")') result = pm.promptDialog( title = mel.eval('uiRes("m_cMuscle.kStickyBindMaximumDistance")'), message = mel.eval('uiRes("m_cMuscle.kMaxDistanceFromCenterOfMuscle")'), text = avgDist, button = [labelAutoCalculate,labelAvgValue,labelAllPoints,labelCancel], defaultButton = labelAutoCalculate , cancelButton = labelCancel, dismissString = labelCancel) if result == labelCancel: return maxDist = pm.promptDialog(q=True, text=True) if result == labelAllPoints or maxDist == -1: distMode, maxDist = 0, -1 elif result == labelAutoCalculate or maxDist == 0: distMod, maxDist = 1, 0 elif result == lableAvgValue: distMode = 2 else: return for muscleSystem in muscleSystems: muscleSystem.envelope.set(0.0) for mo in mOs: parents = mo.listRelatives(p=True) xform = parents[0] if distMode == 1: maxDist = cMuscle_autoCalcStickyBindDistance(mo) for muscleSystem in muscleSystems: muscleSystem.envelope.set(0.0) existMuscles = pm.cMuscleQuery(system=muscleSystem, muscle=True) alreadyConnected=0 if existMuscles: for existMuscle in existMuscles: if mo==e: alreadyConnected=1 break if alreadyConnected: msg = mel.eval('uiRes("m_cMuscle.kMuscleObjectAlreadyConnectedToMuscleNode")') msg = pm.format( msg, stringArg=[mo, muscleSystem] ) pm.warning( msg, sl=0 ) break musIdxs = pm.cMuscleQuery(system=muscleSystem, muscle=True, index=True) musIdxs = sort(musIdxs) idx, done = 0,0 for index in musIdx: if index != musIdxs[index]: idx=index done=1 break cons = mo.worldMatrixStartBase.listConnections(s=True, d=False, p=0, scn=1) hasBase=0 if cons[0] != '': hasBase=1 pm.select(xform, r=True) mel.eval('cMuscle_resetBindPose(%s, 0)'%hasBase) mo.muscleData.connect(muscleSystem.muscleData[idx], f=True) mel.eval('cMuscle_bindSticky(%s, %s, %f)'%(mo,muscleSystem,maxDist))
def getSkinCluster(_oObj): for oCurHistory in pymel.listHistory(_oObj): if isinstance(oCurHistory, pymel.nodetypes.SkinCluster): return oCurHistory return None