def softSelectionClusterWeights(*args): sel = mc.ls(sl=True, o=True) if not sel: raise RuntimeError('Please select some vertices.') weights = getSoftSelectionWeights() if not weights: raise RuntimeError('Please select some vertices.') #get manipulator position for pivot mc.setToolTo('Move') moveMode = mc.manipMoveContext('Move', query=True, mode=True) mc.manipMoveContext('Move', edit=True, mode=0) position = mc.manipMoveContext('Move', query=True, position=True) mc.manipMoveContext('Move', edit=True, mode=moveMode) clusterNode, clusterHandle = mc.cluster(sel[0]) for vert in mc.ls(sel[0]+'.vtx[*]', fl=True, l=True): weight = 0.0 if vert in weights.keys(): weight = weights[vert] mc.percent(clusterNode, vert, v=weight) #set cluster pivot mc.xform(clusterHandle, a=True, ws=True, piv=(position[0], position[1], position[2])) clusterShape = mc.listRelatives(clusterHandle, c=True, s=True) mc.setAttr(clusterShape[0] + '.origin', position[0], position[1], position[2])
def softModToCluster(): softTransform = rig.ls(sl = True)[0] solftMod = rig.listConnections(softTransform,s = False,d = True,type = 'softMod')[0] modifModel = rig.listConnections(solftMod,s = False,d = True,type = 'mesh') if modifModel: origPos = rig.xform(softTransform,q = True,t = True,wd = True) for mesh in modifModel: prePos = [] curPos = [] weights = [] vtxs = rig.ls(mesh+'.vtx[*]',fl = True) rig.xform(softTransform,t = (0,0,0),wd = True) for vtx in vtxs: pos = rig.xform(vtx,q = True,t = True,wd = True) prePos.append(pos) rig.xform(softTransform,t = (0,1,0),wd = True) for vtx in vtxs: pos = rig.xform(vtx,q = True,t = True,wd = True) curPos.append(pos) weights = [math.pow(math.pow(pos[0]-curPos[i][0],2)+math.pow(pos[1]-curPos[i][1],2)+math.pow(pos[2]-curPos[i][2],2),0.5) for i,pos in enumerate(prePos)] rig.xform(softTransform,t = (0,0,0),wd = True) CLS = rig.cluster(mesh,n = mesh+'_CLS') for i,vtx in enumerate(vtxs): rig.percent(CLS[0],vtx,v = weights[i]) rig.xform(softTransform,t = origPos,wd = True)
def copy(self, mesh): self.cluster_list = [] self.point_dict = {} self.cls_weight_dict = {} dummy = common.TemporaryReparent().main(mode='create') common.TemporaryReparent().main(mesh, dummyParent=dummy, mode='cut') cluster = cmds.ls(cmds.listHistory(mesh), type='cluster', l=True) for cls in cluster: set_node = cmds.ls(cmds.listHistory(cls, f=True), type='objectSet', l=True)[0] cmds.select(set_node) vertices = cmds.ls(sl=True) vertices = cmds.filterExpand(vertices, sm=31) cmds.select(vertices, r=True) try: weights = cmds.percent(cls, q=True, v=True) print weights #値が取れないときアンドゥするとなぜか直ることがある except Exception as e: print e.message cmds.delete(cls) cmds.undo() set_node = cmds.ls(cmds.listHistory(cls, f=True), type='objectSet', l=True)[0] vertices = cmds.ls(sl=True) vertices = cmds.filterExpand(vertices, sm=31) cmds.select(vertices, r=True) weights = cmds.percent(cls, q=True, v=True) self.cluster_list.append(cls) self.cls_weight_dict[cls] = weights self.point_dict[cls] = vertices common.TemporaryReparent().main(mesh, dummyParent=dummy, mode='parent')#コピーのおわったメッシュの子供を元に戻す common.TemporaryReparent().main(dummyParent=dummy, mode='delete')#ダミー親削除 return self.point_dict, self.cls_weight_dict
def setWeights(mode, *args): """mode: "zero" to zero all weights or "selection" to apply weights to selection""" #---------------- if current selection is a transform then do the whole thing by this mult value. . . . deformers = cmds.textScrollList(widgets["defTSL"], q=True, selectItem=True) if mode == "selection": c, w = getWeights() if not c or not w: cmds.warning("zbw_deformerWeights(line 85): Couldn't get the components.") return() mult = cmds.floatFieldGrp(widgets["weightFFG"], q=True, v1=True) for d in deformers: for each in zip(c, w): cmds.percent(d, each[0], v=(each[1]*mult)) if mode == "zero": t = cmds.textFieldGrp(widgets["objTFG"], q=True, tx=True) sel = [] if rig.isType(t, "mesh"): sel = cmds.ls("{0}.vtx[*]".format(t), fl=True) elif rig.isType(t, "nurbsCurve") or rig.isType(t, "nurbsSurface"): sel = cmds.ls("{0}.cv[*]".format(t), fl=True) for d in deformers: if sel: for each in sel: cmds.percent(d, each, v=0)
def createCluster(selection_list): target_point_weight = {} for dag_path, point_weight_list in selection_list.items(): _getConvertedData(dag_path, point_weight_list, target_point_weight) cmds.softSelect(e=True, sse=False) cmds.select(target_point_weight.keys()) cluster_node = cmds.cluster() for point, weight in target_point_weight.items(): cmds.percent(cluster_node[0], point, v=weight)
def createSoftCluster(): softElementData = softSelection() selection = ["%s.vtx[%d]" % (el[0], el[1]) for el in softElementData] mc.select(selection, r=True) cluster = mc.cluster(relative=True) for i in range(len(softElementData)): mc.percent(cluster[0], selection[i], v=softElementData[i][2]) mc.select(cluster[1], r=True)
def importDeformer(dagnode, j): if dagnode not in j: rigUtils.log('Dagnode not found in json file: %s' % dagnode) return # temporarily disable deleteComponent nodes for delComp in cmds.ls('deleteComponent*'): cmds.setAttr('%s.nodeState' % delComp, 1) skincluster = rigUtils.findSkinClusterOnNode(dagnode) dict = j[dagnode] for deformer in dict: if deformer == 'skinCluster': continue if not cmds.objExists(deformer): continue pointdata = dict[deformer] set = '%sSet' % deformer existingdeformers = mel.eval('findRelatedDeformer "%s"' % dagnode) # ffd if cmds.objectType(deformer, isType='ffd'): i = 0 while(True): if i == len(pointdata): break if pointdata[i] == '1' and cmds.objExists(set): cmds.sets('%s.vtx[%s]' % (dagnode, i), add=set) i = i + 1 if skincluster: cmds.reorderDeformers(skincluster,deformer,dagnode) continue # all other deformers if not deformer in existingdeformers: if cmds.objExists(set): cmds.sets(dagnode, add=set) i = 0 while(True): if i == len(pointdata): break value = pointdata[i] cmds.percent(deformer, '%s.vtx[%s]' % (dagnode, i), v=float(value)) i = i + 1 if skincluster: cmds.reorderDeformers(skincluster, deformer, dagnode) rigUtils.log('Deformer weighting updated: %s' % deformer) # turn deleteComponent nodes back on for delComp in cmds.ls('deleteComponent*'): cmds.setAttr('%s.nodeState' % delComp, 0)
def paste(self, mesh): if not self.cluster_list: return for cls in self.cluster_list: weights = self.cls_weight_dict[cls] print 'paste cls :', cls cmds.select(cl=True) points = self.point_dict[cls] newcls = cmds.cluster(points, n=cls) for i, v in enumerate(points): cmds.percent(newcls[0], v, v=(weights[i])) return newcls
def deformerMirror(node, handle_list, axis, search, replace): if not isinstance(handle_list, (list, tuple, set)): handle_list = [handle_list] with OptimiseContext(): for handle in handle_list: if not mc.listRelatives(handle, shapes=True, type='clusterHandle'): log.warning('Current version only supports Cluster deformers.') continue shapes = mc.listRelatives(node, shapes=True) current_data = get_deformer_info_by_node(node, handle) closest_point_node = mc.createNode('closestPointOnMesh') for data in current_data: point_pos = mc.pointPosition(data[0], local=True) inv_pos = point_pos inv_pos[axis] *= -1 mc.setAttr(node + '.inPosition', *inv_pos) mc.connectAttr(shapes[0] + '.outMesh', closest_point_node + '.inMesh', force=True) closest_index = mc.getAttr(closest_point_node + '.closestVertexIndex') data[0] = node + '.vtx[{}]'.format(closest_index) mc.delete(closest_point_node) amount = len(current_data) new_points = [current_data[x][0] for x in range(amount)] deformer = mc.listConnections(handle + '.worldMatrix[0]', type='cluster', d=True) new_cluster = mc.cluster(new_points, rel=mc.getAttr(deformer + '.relative')) for x in range(amount): mc.percent(new_cluster[0], current_data[x][0], v=current_data[x][1]) # Mirror deformer pivot a_pos = mc.xform(node, q=True, ws=True, rp=True) pos = b_pos = mc.xform(handle, q=True, ws=True, rp=True) pos[axis - 1] = b_pos[axis - 1] - ( (b_pos[axis - 1] - a_pos[axis - 1]) * 2) mc.xform(new_cluster[1], a=True, ws=True, piv=(pos[0], pos[1], pos[2])) mc.setAttr(new_cluster[0] + '.origin', pos[0], pos[1], pos[2]) mc.rename(new_cluster[1], handle.replace(search, replace))
def use_weight_set(): cmds.select(cmds.cluster(cmds.textScrollList('UI_cluster_list', q=True, si=True)[0], q=True, g=True)[0]) mel.eval("ConvertSelectionToVertices;") weights = cmds.percent (cmds.textScrollList('UI_cluster_list', q=True, si=True)[0], q=True, v=True) cmds.filterExpand( ex=True, sm=31 ) elements = cmds.ls(sl=True, fl=True) return elements, weights
def get_cluster_verticies_on_mesh(mesh_transform, cluster_handle): cluster_deformer_node = cmds.listConnections( (cluster_handle + ".worldMatrix[0]"), type="cluster", destination=1) cluster_set = cmds.listConnections(cluster_deformer_node[0], type="objectSet") extracted_verts = cmds.sets(cluster_set[0], q=1) # 28: Control Vertices (CVs) # 31: Polygon Vertices # 36: Subdivision Mesh Points # 46: Lattice Points extracted_verts = cmds.filterExpand( extracted_verts, selectionMask=(28, 31, 36, 46)) # Filter Points Only # Isolate vertices on mesh verticies_on_mesh = [] for vertex in extracted_verts: name = vertex.encode('utf-8') if name.startswith(mesh_transform): verticies_on_mesh.append(vertex) # Pair Verticies with their weights verticies_with_weights = [] for vertex in verticies_on_mesh: vertex_weight_pair = [vertex] valueW = cmds.percent(cluster_deformer_node[0], vertex, q=1, v=1) vertex_weight_pair.append(valueW[0]) verticies_with_weights.append(vertex_weight_pair) return verticies_with_weights
def createClusterDeformers(self): # Create clusters on the top, middle, and bottom of our wire deformer curve. topCluster = cmds.cluster("%s.cv[1:2]" % self.wireDeformerCurve, name="%s_TOP_CLS" % self.name, relative=True) midCluster = cmds.cluster("%s.cv[1]" % self.wireDeformerCurve, name="%s_MID_CLS" % self.name, relative=True) bottomCluster = cmds.cluster("%s.cv[0:1]" % self.wireDeformerCurve, name="%s_BOT_CLS" % self.name, relative=True) clusters = [topCluster, midCluster, bottomCluster] # Shift the pivots to the controls on the base plane. cmds.setAttr("%sShape.originY" % str(topCluster[1]), (self.distance / 2) * -1) cmds.setAttr("%sShape.originY" % str(bottomCluster[1]), (self.distance / 2)) cmds.move(0, (self.distance / 2) * -1, 0, "%s.rotatePivot" % str(topCluster[1]), "%s.scalePivot" % str(topCluster[1])) cmds.move(0, 0, 0, "%s.rotatePivot" % str(midCluster[1]), "%s.scalePivot" % str(midCluster[1])) cmds.move(self.distance / 2, 0, 0, "%s.rotatePivot" % str(bottomCluster[1]), "%s.scalePivot" % str(bottomCluster[1])) # Adjust the weight towards the end points. cmds.percent(topCluster[0], "%s.cv[1]" % self.wireDeformerCurve, value=0.5) cmds.percent(bottomCluster[0], "%s.cv[1]" % self.wireDeformerCurve, value=0.5) # Group the clusters and connect them to their respective controls. group = cmds.group(name="%s_CLS_GRP" % self.name, empty=True) for index in range(len(clusters)): cmds.connectAttr("%s.translate" % str(self.controlCurves[index]), "%s.translate" % str(clusters[index][1])) self.parentObject(clusters[index][1], group) self.parentObject(group, self.noMoveGroup) self.hideObject(group) return clusters
def TransWeightToCluster(): ModelName = mc.textField('ClusterModelFLD', q=True, tx=True) SkinModel = mc.textField('SkinModelFLD', q=True, tx=True) ClusterName = mc.textField('ClusterNameFLD', q=True, tx=True) JointName = mc.textField('JointNameFLD', q=True, tx=True) #- get the cluster Node Name.. if mc.nodeType(ClusterName) == 'transform': ClusterName = mc.listConnections(ClusterName, t='cluster')[0] else: pass #- get SkinNode Name SkinClusterNode = mel.eval('findRelatedSkinCluster ' + SkinModel) #- set Value ModelVts = mc.polyEvaluate(SkinModel, v=True) JointID = mc.skinCluster(SkinClusterNode, q=True, inf=True).index(JointName) for i in range(ModelVts): SkinWeight = mc.skinPercent(SkinClusterNode, '%s.vtx[%s]'%(SkinModel, i), q=True, v=True)[JointID] mc.percent(ClusterName, '%s.vtx[%s]'%(ModelName, i), v=SkinWeight)
def Transfer(self): sel = cmds.ls(sl=True) curves = [] joints = [] wires = [] obj = None for obj in sel: if cmds.nodeType(cmds.listRelatives(obj, shapes=True)) == 'nurbsCurve': curves.append(obj) elif cmds.joint(obj, exists=obj): joints.append(obj) else: obj = obj if obj is not None: verts = cmds.ls(obj + '.vtx[0: ]', fl=True) clusters = cmds.listConnections(cmds.listRelatives(object, shapes=True)[0], t='skinCluster')[0] i = 1 for curve in curves: wires.append(cmds.wire(object, dds=[i, 999999999], w=curve)[0]) i = 0 for jnt in joints: for vert in verts: skinWeight = cmds.skinPercent(clusters, vert, transform=jnt, q=True, value=True) cmds.percent(wires[i], vert, v=skinWeight) i += 1 else: cmds.warning('Tool requires an object to be selected')
def createSoftCluster(excludeObjs=None, supportTypes=None): # determind select objects initSel = cmd.ls(sl=1, ap=1, st=1) firstSelObj, firstSelType = initSel[0], initSel[1] if firstSelType == 'transform': object = firstSelObj elif firstSelType in ['float3', 'double3']: object = cmd.listRelatives(cmd.listRelatives(p=True, f=1), p=True, f=1)[0] else: cmd.error('Selected objects Unsupported!') return # query manipulator's position cmd.setToolTo('Move') currentMoveMode = cmd.manipMoveContext('Move', q=True, m=True) cmd.manipMoveContext('Move', e=True, m=0) position = cmd.manipMoveContext('Move', q=True, p=True) cmd.manipMoveContext('Move', e=True, m=currentMoveMode) # query influenced elements and correspond weights elements = cmd.softSelectionQuery(cmp=1, exo=excludeObjs, t=supportTypes) weights = cmd.softSelectionQuery(w=1, exo=excludeObjs, t=supportTypes) # create cluster with elements and set weights try: clusterNode, clusterHandle = cmd.cluster(elements, n='%s_softCluster' % object.split('|')[-1]) except: cmd.error('Selected objects Unsupported!') return for i in xrange(len(elements)): cmd.percent(clusterNode, elements[i], v=weights[i]) repositionCluster(clusterHandle, position) return clusterNode, clusterHandle
def softCluster(): selectionVrts = cmds.ls(selection=True, flatten=True) if selectionVrts: posVtx = _getAverage(selectionVrts) cmds.softSelect(sse=True) softElementData = _softSelection() selection = ["%s.vtx[%d]" % (el[0], el[1]) for el in softElementData] model = selectionVrts[0].split('.')[0] cmds.select(model, r=True) cluster = cmds.cluster(name='%s_cls' % model, relative=False, bindState=True) clusterGrp = cmds.createNode('transform', name='%s_grp' % cluster[1]) cmds.xform(cluster, rotatePivot=posVtx, scalePivot=posVtx, objectSpace=True) cmds.xform(clusterGrp, rotatePivot=posVtx, scalePivot=posVtx, objectSpace=True) cmds.parent(cluster[1], clusterGrp) cmds.connectAttr('%s.worldInverseMatrix' % clusterGrp, '%s.bindPreMatrix' % cluster[0]) weight = [0.0] zero = 0.0 VertexNb = cmds.polyEvaluate(model, v=1) - 1 for x in range(VertexNb): weight.append(zero) cmds.setAttr('{0}.weightList[0].weights[0:{1}]'.format( cluster[0], VertexNb), *weight, size=len(weight)) shape = cmds.listRelatives(cluster[1], shapes=True)[0] cmds.setAttr('%s.originX' % shape, posVtx[0]) cmds.setAttr('%s.originY' % shape, posVtx[1]) cmds.setAttr('%s.originZ' % shape, posVtx[2]) for i in range(len(softElementData)): cmds.percent(cluster[0], selection[i], v=softElementData[i][2]) cmds.select(cluster[1], r=True)
def deformerMirror(object, deformerHandle, axis, search, replace): if not mc.objectType(mc.listRelatives(deformerHandle, c=1, s=1)[0], isType='clusterHandle'): mc.warning('Current version only supports cluster deformers') return shapes = mc.listRelatives(object, s=1, c=1) oldList = filterDeformer(object, deformerHandle) for pair in oldList: pointPos = mc.pointPosition(pair[0], l=1) node = mc.createNode('closestPointOnMesh') mc.setAttr(('%s.inPosition' % node), *invertValue(pointPos, axis)) try: mc.connectAttr('%s.outMesh' % shapes[0], '%s.inMesh' % node, f=1) except: pass else: pair[0] = '%s.vtx[%s]' % ( object, mc.getAttr('%s.closestVertexIndex' % node)) mc.delete(node) amount = len(oldList) newPoints = [oldList[x][0] for x in range(amount)] clusDeformer = mc.listConnections('%s.worldMatrix[0]' % deformerHandle, type='cluster', d=1) newClus = mc.cluster(newPoints, rel=mc.getAttr('%s.relative' % clusDeformer[0])) for x in range(amount): mc.percent(newClus[0], oldList[x][0], v=oldList[x][1]) aPos = mc.xform(object, q=1, ws=1, rp=1) pos = bPos = mc.xform(deformerHandle, q=1, ws=1, rp=1) pos[axis - 1] = bPos[(axis - 1)] - (bPos[(axis - 1)] - aPos[(axis - 1)]) * 2 mc.xform(newClus, a=1, ws=1, piv=(pos[0], pos[1], pos[2])) mc.setAttr( mc.listRelatives(newClus, c=1, s=1)[0] + '.origin', pos[0], pos[1], pos[2]) mc.rename(newClus[1], deformerHandle.replace(search, replace))
def __copyClusterWeight(*args): srcCluName,srcShape = cmds.button(widgets["bt_srcCluster"],q=True,l=True).split(" ") dstCluName,dstShape = cmds.button(widgets["bt_dstCluster"],q=True,l=True).split(" ") srcCluName = srcCluName.split(":")[-1][:-1] srcShape = srcShape.split(":")[-1][:-1] dstCluName = dstCluName.split(":")[-1][:-1] dstShape = dstShape.split(":")[-1][:-1] wd = __getBarycentricCoordsWeights(srcShape,dstShape) mult = cmds.floatField(widgets["ff_mult"],q=True,v=True) for i,j in zip(wd["srcVtxs"],wd["tgtVtxs"]): v1 = cmds.percent(srcCluName,i[0][0],q=True,v=True)[0] * i[1][0] v2 = cmds.percent(srcCluName,i[0][1],q=True,v=True)[0] * i[1][1] v3 = cmds.percent(srcCluName,i[0][2],q=True,v=True)[0] * i[1][2] cVal = (v1 + v2 + v3) * mult cmds.percent(dstCluName,j,v=cVal) om.MGlobal.displayInfo("Done!") __buttonInit()
def create_soft_cluster(): """ Create a Cluster deformer using the current soft selection. :return: New cluster deformer. :rtype: str """ elements, weights = _get_soft_selection() # Get the average position from the move manipulator mc.setToolTo('Move') current_mode = mc.manipMoveContext('Move', q=True, m=True) mc.manipMoveContext('Move', e=True, m=0) position = mc.manipMoveContext('Move', q=True, p=True) mc.manipMoveContext('Move', e=True, m=current_mode) obj = mc.listRelatives(mc.listRelatives(parent=True), parent=True) new_cluster = mc.cluster(elements, n=obj[0] + '_softCluster') for i in range(len(elements)): mc.percent(new_cluster[0], elements[i], v=weights[i]) _reposition_cluster_deformer(new_cluster[1], position)
def create_cluster(): cluster_name = cmds.textField('UI_cluster_clusterPrefix', q=True, tx=True) + cmds.textField('UI_cluster_clusterName', q=True, tx=True) cluster_name = cluster_name.replace (" ", "_") # cluster soft selections # Use Weight Set Override if cmds.checkBox('UI_useWeights_CheckBox', q=True, value=True) is True: elements, weights = use_weight_set() else: elements, weights = softSelection() cmds.softSelect( sse=0) mel.eval("polyConvertToShell;") vertex_count = cmds.ls(sl=True, fl=True) if cmds.objExists("loc_guide_deformer") is True: parent_cluster(cluster_name) else: cmds.cluster (name = cluster_name, bs = True) for vertex in vertex_count: cmds.percent (cluster_name, vertex, value = 0) for x in range(len(elements)): cmds.percent (cluster_name, elements[x], value = weights[x])
def getInfoDeformer(deformerHandle): results = [] cDeformer = mc.listConnections(deformerHandle + '.worldMatrix[0]', type='cluster', d=1) cSet = mc.listConnections(cDeformer[0], type='objectSet') components = mc.filterExpand(mc.sets(cSet[0], q=1), sm=(28, 31, 36, 46)) for vertex in components: vert = [vertex] vertWeight = mc.percent(cDeformer[0], vertex, q=1, v=1) vert.append(vertWeight[0]) results.append(vert) return results
def TransWeightToCluster(): ModelName = mc.textField('ClusterModelFLD', q=True, tx=True) SkinModel = mc.textField('SkinModelFLD', q=True, tx=True) ClusterName = mc.textField('ClusterNameFLD', q=True, tx=True) JointName = mc.textField('JointNameFLD', q=True, tx=True) #- get the cluster Node Name.. if mc.nodeType(ClusterName) == 'transform': ClusterName = mc.listConnections(ClusterName, t='cluster')[0] else: pass #- get SkinNode Name SkinClusterNode = mel.eval('findRelatedSkinCluster ' + SkinModel) #- set Value ModelVts = mc.polyEvaluate(SkinModel, v=True) JointID = mc.skinCluster(SkinClusterNode, q=True, inf=True).index(JointName) for i in range(ModelVts): SkinWeight = mc.skinPercent(SkinClusterNode, '%s.vtx[%s]' % (SkinModel, i), q=True, v=True)[JointID] mc.percent(ClusterName, '%s.vtx[%s]' % (ModelName, i), v=SkinWeight)
def setWeight(self, *a): fc = cmds.radioCollection('rc_awwFc', q=1, select=1) et = cmds.radioCollection('rc_awwEt', q=1, select=1) sv = cmds.floatSliderGrp('fs_awwA', q=1, value=1) ev = cmds.floatSliderGrp('fs_awwB', q=1, value=1) sl = cmds.ls(selection=1, long=1) sls = cmds.ls(selection=1) selList = [] for i, x in enumerate(sl): sn = sls[i] sp = cmds.listRelatives(x, shapes=1)[0] w = cmds.listConnections(sp, type='wire')[0] if w is not None: sd = cmds.getAttr(x + '.spans') + cmds.getAttr(x + '.degree') for j in range(sd): r = float(j) / float(sd - 1) wt = mel.eval('linstep(' + str(sv) + ',' + str(ev) + ',' + str(r) + ')') if fc == 'rb_awwSc': wt = mel.eval('smoothstep(' + str(sv) + ',' + str(ev) + ',' + str(r) + ')') print wt cmds.percent(w, x + '.cv[' + str(j) + ']', v=wt)
def TransWeightToJoint(): ModelName = mc.textField('ClusterModelFLD', q=True, tx=True) SkinModel = mc.textField('SkinModelFLD', q=True, tx=True) ClusterName = mc.textField('ClusterNameFLD', q=True, tx=True) JointName = mc.textField('JointNameFLD', q=True, tx=True) #- get the cluster Node Name.. if mc.nodeType(ClusterName) == 'transform': ClusterName = mc.listConnections(ClusterName, t='cluster')[0] else: pass #- get the Model Id and connect groupparts ModeID = mc.listRelatives(mc.cluster(ClusterName, q=True, g=True), p=True).index(ModelName) GroupParts = mc.connectionInfo(ClusterName + '.input[%d].inputGeometry' % ModeID, sfd=True).split('.')[0] #- get Inflution Vts Points = [ '%s.%s' % (ModelName, Vtx) for Vtx in mc.getAttr(GroupParts + '.inputComponents') ] #- get Cluster Value WeightDT = {} for VVtx in mc.ls(Points, fl=True): VtxID = re.search('(?<=\[)\d+(?=\])', VVtx).group() WeightValue = mc.percent(ClusterName, VVtx, q=True, v=True) WeightDT[VtxID] = WeightValue[0] #- get SkinNode Name SkinClusterNode = mel.eval('findRelatedSkinCluster ' + SkinModel) #- Remove Joint weights ModelVts = mc.polyEvaluate(SkinModel, v=True) mc.skinPercent(SkinClusterNode, '%s.vtx[0:%s]' % (SkinModel, ModelVts), tv=(JointName, 0)) #- set Weight Value for VtxID, WeightV in WeightDT.iteritems(): mc.skinPercent(SkinClusterNode, '%s.vtx[%s]' % (SkinModel, VtxID), tv=(JointName, WeightV))
def get_deformer_info(handle): """ Return the vertices and weights for the deformer. :param handle: Deformer handle object. :type handle: str :return: list(list(str, float)) """ deformer = mc.listConnections(handle + '.worldMatrix[0]', type='cluster', d=True)[0] obj_set = mc.listConnections(deformer, type='objectSet')[0] components = mc.filterExpand(mc.sets(obj_set, q=True), sm=(28, 31, 36, 46)) results = [[vertex, mc.percent(deformer, vertex, q=True, v=True)[0]] for vertex in components] return results
def TransWeightToJoint(): ModelName = mc.textField('ClusterModelFLD', q=True, tx=True) SkinModel = mc.textField('SkinModelFLD', q=True, tx=True) ClusterName = mc.textField('ClusterNameFLD', q=True, tx=True) JointName = mc.textField('JointNameFLD', q=True, tx=True) #- get the cluster Node Name.. if mc.nodeType(ClusterName) == 'transform': ClusterName = mc.listConnections(ClusterName, t='cluster')[0] else: pass #- get the Model Id and connect groupparts ModeID = mc.listRelatives(mc.cluster(ClusterName, q=True, g=True), p=True).index(ModelName) GroupParts = mc.connectionInfo(ClusterName + '.input[%d].inputGeometry'%ModeID, sfd=True).split('.')[0] #- get Inflution Vts Points = ['%s.%s'%(ModelName,Vtx) for Vtx in mc.getAttr(GroupParts + '.inputComponents')] #- get Cluster Value WeightDT = {} for VVtx in mc.ls(Points, fl=True): VtxID = re.search('(?<=\[)\d+(?=\])', VVtx).group() WeightValue = mc.percent(ClusterName, VVtx, q=True, v=True) WeightDT[VtxID] = WeightValue[0] #- get SkinNode Name SkinClusterNode = mel.eval('findRelatedSkinCluster ' + SkinModel) #- Remove Joint weights ModelVts = mc.polyEvaluate(SkinModel, v=True) mc.skinPercent(SkinClusterNode, '%s.vtx[0:%s]'%(SkinModel, ModelVts), tv=(JointName, 0)) #- set Weight Value for VtxID, WeightV in WeightDT.iteritems(): mc.skinPercent(SkinClusterNode, '%s.vtx[%s]'%(SkinModel, VtxID), tv=(JointName, WeightV))
def ss_deformerWeight(*args): #args: deformer name #method deformedGeometryNode = cmds.listRelatives(cmds.ls(selection=True), parent=True)[0] deformer = str(args[0]) method = args[1] elements, weights = softSelection() for e in range(len(elements)): if method == 0: cmds.percent(deformer, deformedGeometryNode + '.vtx[{}]'.format(elements[e]), addPercent=weights[e]) elif method == 1: cmds.percent(deformer, deformedGeometryNode + '.vtx[{}]'.format(elements[e]), multiplyPercent=weights[e]) elif method == 2: cmds.percent(deformer, deformedGeometryNode + '.vtx[{}]'.format(elements[e]), value=weights[e])
def cluster(self, character = None, mod = None, side = None, name = None, suffix = None, geometry = None, origin = [0,0,0], weightObj = None, weightValue = 1, parent = None, show = True, lockAttr = None, ihi = True): #--- this method creates a cluster deformer #--- select the specified geometry cmds.select(geometry) #--- create a cluster deformer node = cmds.cluster() filter_name = (name + node[0].split('Handle')[0][0].upper() + node[0].split('Handle')[0][1:]) #--- rename the cluster deformer node = self.__rename_node(mod = mod, side = side, name = filter_name, suffix = suffix, obj = node) #--- get the cluster deform node node.append(cmds.listConnections(node[0])[0]) #--- create a group on top and parent the deformer under the group node_grp = cmds.createNode('transform') cmds.parent(node[0], node_grp) #--- rename the node group node_grp = self.__rename_node(mod = mod, side = side, name = filter_name, suffix = 'GRP', obj = node_grp)[0] #--- take care of the node's settings #--- origin ori_x= cmds.getAttr(node[1] + '.originX') ori_y= cmds.getAttr(node[1] + '.originY') ori_z= cmds.getAttr(node[1] + '.originZ') new_origin = [ori_x + origin[0], ori_y + origin[1], ori_z + origin[2]] cmds.setAttr(node[1] + '.origin', new_origin[0], new_origin[1], new_origin[2]) cmds.xform(node[0], pivots = new_origin, worldSpace = True) #--- reposition the pivot of the group to the location of the cluster cmds.xform(node_grp, pivots = new_origin, worldSpace = True) #--- weightValue if weightObj: if isinstance(weightObj, list): if isinstance(weightValue, list): for obj, val in zip(weightObj, weightValue): cmds.percent(node[-1], obj, value = val) else: for obj in weightObj: cmds.percent(node[-1], obj, value = weightValue) else: cmds.percent(node[-1], weightObj, value = weightValue) #--- parent the group under the specified parent if parent: if not isinstance(parent, list): cmds.parent(node_grp, parent) else: raise Exception("Specified parent: " + parent + 'is not a valid') #--- show or hide transform if not show: if isinstance(target, list): for t in target: cmds.setAttr(t + '.v', 0) else: cmds.setAttr(target + '.v', 0) #--- lock specified attributes if lockAttr: if node: cmds.setAttr(node + '.' + lockAttr, lock = True) #--- set isHistoricalInteresting attribute if not ihi: cmds.setAttr(node + '.ihi', 0) #--- return node return node
def buildDeformers(self, ribbonPlane, controls=(), folGrp=()): # Create a target blendshape controlled by deformers flexiBlend = cmds.duplicate(ribbonPlane, n='flexiPlaneSetup_bShp_surface01') flexiBlendNode = cmds.blendShape(flexiBlend, ribbonPlane, n='%s_bShpNode_surface01' % self.name) # Turn blendshape on cmds.setAttr('%s.%s' % (flexiBlendNode[0], flexiBlend[0]), 1) # Create a wire deformer controled by ribbon controls wireCurve = cmds.curve( n='%s_wire_surface01' % self.name, d=2, p=[(-self.numJnts, 0, 0), (0, 0, 0), (self.numJnts, 0, 0)]) topClstr = cmds.cluster('%s.cv[0:1]' % wireCurve, rel=1, n='%s_cl_a01' % self.name) midClstr = cmds.cluster('%s.cv[1]' % wireCurve, rel=1, n='%s_cl_mid01' % self.name) botClstr = cmds.cluster('%s.cv[1:2]' % wireCurve, rel=1, n='%s_cl_b01' % self.name) clsGrp = cmds.group(topClstr, midClstr, botClstr, n='%s_cls01' % self.name) for attr in ['scalePivot', 'rotatePivot']: cmds.setAttr('%s.%s' % (topClstr[1], attr), -self.numJnts, 0, 0) for attr in ['scalePivot', 'rotatePivot']: cmds.setAttr('%s.%s' % (botClstr[1], attr), self.numJnts, 0, 0) cmds.setAttr('%sShape.originX' % topClstr[1], (-self.numJnts)) cmds.setAttr('%sShape.originX' % botClstr[1], (self.numJnts)) cmds.percent(topClstr[0], '%s.cv[1]' % wireCurve, v=0.5) cmds.percent(botClstr[0], '%s.cv[1]' % wireCurve, v=0.5) # Create twist and wire blend shape deformers twistNode = cmds.nonLinear(flexiBlend, type='twist') cmds.wire(flexiBlend, w=wireCurve, dds=[0, 20], foc=0, n='%s_wireAttrs_surface01' % self.name) cmds.xform(twistNode, ro=(0, 0, 90)) twistNode[0] = cmds.rename(twistNode[0], '%s_twistAttrs_surface01' % self.name) twistNode[1] = cmds.rename(twistNode[1], '%s_twist_surface01' % self.name) # Setup squash and stretch via utilitiy nodes arcLen = cmds.arclen(wireCurve, ch=1) arcLen = cmds.rename(arcLen, '%s_curveInfo01' % self.name) arcLenValue = cmds.getAttr('%s.arcLength' % arcLen) squashDivNode = cmds.createNode('multiplyDivide', n='%s_div_squashStretch_length01' % self.name) volDivNode = cmds.createNode('multiplyDivide', n='%s_div_volume01' % self.name) squashCondNode = cmds.createNode('condition', n='%s_cond_volume01' % self.name) cmds.setAttr('%s.operation' % squashDivNode, 2) cmds.setAttr('%s.input2X' % squashDivNode, arcLenValue) cmds.setAttr('%s.operation' % volDivNode, 2) cmds.setAttr('%s.input1X' % volDivNode, 1) cmds.setAttr('%s.secondTerm' % squashCondNode, 1) cmds.connectAttr('%s.arcLength' % arcLen, '%s.input1X' % squashDivNode) cmds.connectAttr('%s.outputX' % squashDivNode, '%s.input2X' % volDivNode) cmds.connectAttr('%s.outputX' % volDivNode, '%s.colorIfTrueR' % squashCondNode) # Set visibility options for obj in [flexiBlend[0], wireCurve, twistNode[1], clsGrp]: cmds.setAttr('%s.visibility' % obj, 0) # Connect controls to cluster deformers if they exist if len(controls) > 1: topCon = controls[0][0] botCon = controls[0][1] midCon = controls[0][2] for con, clstr in zip([topCon, botCon], [topClstr[1], botClstr[1]]): cmds.connectAttr('%s.translate' % con, '%s.translate' % clstr) cmds.connectAttr('%s.translate' % midCon, '%s.translate' % midClstr[1]) # Connect controls to twist deformer cmds.connectAttr('%s.rotateX' % topCon, '%s.endAngle' % twistNode[0]) cmds.connectAttr('%s.rotateX' % botCon, '%s.startAngle' % twistNode[0]) cmds.connectAttr('%s.volEnable' % controls[1], '%s.firstTerm' % squashCondNode) # Scale contraint each follicle to global move group for fol in cmds.listRelatives(folGrp, c=1): cmds.scaleConstraint(self.moveGrp, fol, mo=0) for shape in cmds.listRelatives(fol, s=1): cmds.setAttr('%s.visibility' % shape, 0) # Parent nodes cmds.parent(flexiBlend, wireCurve, clsGrp, twistNode[1], '%s_wire_surface01BaseWire' % self.name, self.extrasGrp)
def createRibbon(*args): #Gather information width = cmds.floatField('widthField', query=True, value=True) numJoints = cmds.intField('jointsField', query=True, value=True) prefix = cmds.textField('prefixField', query=True, text=True) scaleGrp = cmds.textField('scaleGrpField', query=True, text=True) topPoint = (width / 2) endPoint = (width / 2 * -1) #Create the main groups grpNoTransform = cmds.group(empty=True, name=(prefix + 'noTransform_grp')) grpTransform = cmds.group(empty=True, name=(prefix + 'transform_grp')) grpCtrl = cmds.group(empty=True, name=(prefix + 'ctrl_grp'), parent=grpTransform) grpSurface = cmds.group(empty=True, name=(prefix + 'surface_grp'), parent=grpTransform) grpSurfaces = cmds.group(empty=True, name=(prefix + 'surfaces_grp'), parent=grpNoTransform) grpDeformers = cmds.group(empty=True, name=(prefix + 'deformer_grp'), parent=grpNoTransform) grpFollMain = cmds.group(empty=True, name=(prefix + 'follicles_skin_grp'), parent=grpNoTransform) grpFollVolume = cmds.group(empty=True, name=(prefix + 'follicles_volume_grp'), parent=grpNoTransform) grpCluster = cmds.group(empty=True, name=(prefix + 'cluster_grp'), parent=grpNoTransform) grpMisc = cmds.group(empty=True, name=(prefix + 'misc_grp'), parent=grpNoTransform) #Create a NURBS-plane to use as a base tmpPlane = cmds.nurbsPlane(axis=(0, 1, 0), width=width, lengthRatio=(1.0 / width), u=numJoints, v=1, degree=3, ch=0)[0] #Create the NURBS-planes to use in the setup geoPlane = cmds.duplicate(tmpPlane, name=(prefix + 'geo')) geoPlaneTwist = cmds.duplicate(tmpPlane, name=(prefix + 'twist_blnd_geo')) geoPlaneSine = cmds.duplicate(tmpPlane, name=(prefix + 'sine_blnd_geo')) geoPlaneWire = cmds.duplicate(tmpPlane, name=(prefix + 'wire_blnd_geo')) geoPlaneVolume = cmds.duplicate(tmpPlane, name=(prefix + 'volume_geo')) #Offset the volume-plane cmds.setAttr((geoPlaneVolume[0] + '.translateZ'), -0.5) #Delete the base surface cmds.delete(tmpPlane) #Create the controllers ctrlTop = createCurveCtrl(name=(prefix + 'top_ctrl'), freezeTransforms=1, color=9, pos=(topPoint, 0, 0)) ctrlMid = createCurveCtrl(name=(prefix + 'mid_ctrl'), freezeTransforms=1, color=9, pos=(0, 0, 0)) ctrlEnd = createCurveCtrl(name=(prefix + 'end_ctrl'), freezeTransforms=1, color=9, pos=(endPoint, 0, 0)) #Group the controllers grpTop = grpObject(objects=[ctrlTop], snapTrans=1, keepTransforms=0, keepHi=1, empty=0, suffix='_grp')[0] grpMid = grpObject(objects=[ctrlMid], snapTrans=1, keepTransforms=0, keepHi=1, empty=0, suffix='_grp')[0] grpEnd = grpObject(objects=[ctrlEnd], snapTrans=1, keepTransforms=0, keepHi=1, empty=0, suffix='_grp')[0] #PointConstraint the midCtrl between the top/end midConst = cmds.pointConstraint(ctrlTop, ctrlEnd, grpMid) #Add attributes: Twist/Roll attributes addAttribute(objects=[ctrlTop, ctrlMid, ctrlEnd], longName=['twistSep'], niceName=['---------------'], at="enum", en='Twist', lock=1, k=True) addAttribute(objects=[ctrlTop, ctrlEnd], longName=['twist'], at="float", k=True) addAttribute(objects=[ctrlTop, ctrlEnd], longName=['twistOffset'], at="float", k=True) addAttribute(objects=[ctrlTop, ctrlEnd], longName=['affectToMid'], at="float", min=0, max=10, dv=10, k=True) addAttribute(objects=[ctrlMid], longName=['roll'], at="float", k=True) addAttribute(objects=[ctrlMid], longName=['rollOffset'], at="float", k=True) #Add attributes: Volume attributes addAttribute(objects=[ctrlMid], longName=['volumeSep'], niceName=['---------------'], at="enum", en='Volume', lock=1, k=True) addAttribute(objects=[ctrlMid], longName=['volume'], at="float", min=-1, max=1, k=True) addAttribute(objects=[ctrlMid], longName=['volumeMultiplier'], at="float", min=1, dv=3, k=True) addAttribute(objects=[ctrlMid], longName=['startDropoff'], at="float", min=0, max=1, dv=1, k=True) addAttribute(objects=[ctrlMid], longName=['endDropoff'], at="float", min=0, max=1, dv=1, k=True) addAttribute(objects=[ctrlMid], longName=['volumeScale'], at="float", min=endPoint * 0.9, max=topPoint * 2, k=True) addAttribute(objects=[ctrlMid], longName=['volumePosition'], min=endPoint, max=topPoint, at="float", k=True) #Add attributes: Sine attributes addAttribute(objects=[ctrlMid], longName=['sineSep'], niceName=['---------------'], attributeType='enum', en="Sine:", keyable=True, lock=1) addAttribute(objects=[ctrlMid], longName=['amplitude'], attributeType="float", keyable=True) addAttribute(objects=[ctrlMid], longName=['offset'], attributeType="float", keyable=True) addAttribute(objects=[ctrlMid], longName=['twist'], attributeType="float", keyable=True) addAttribute(objects=[ctrlMid], longName=['sineLength'], min=0.1, dv=2, attributeType="float", keyable=True) #Add attributes: Extra attributes addAttribute(objects=[ctrlMid], longName=['extraSep'], niceName=['---------------'], at="enum", en='Extra', lock=1, k=True) addAttribute(objects=[ctrlMid], longName=['showExtraCtrl'], at="enum", en='Hide:Show:', k=True) cmds.setAttr((ctrlMid + '.showExtraCtrl'), 1) #Create deformers: Twist deformer, Sine deformer, Squash deformer twistDef = nonlinearDeformer(objects=[geoPlaneTwist[0]], defType='twist', name=geoPlaneTwist[0], lowBound=-1, highBound=1, rotate=(0, 0, 90)) sineDef = nonlinearDeformer(objects=[geoPlaneSine[0]], defType='sine', name=geoPlaneSine[0], lowBound=-1, highBound=1, rotate=(0, 0, 90)) squashDef = nonlinearDeformer(objects=[geoPlaneVolume[0]], defType='squash', name=geoPlaneVolume[0], lowBound=-1, highBound=1, rotate=(0, 0, 90)) cmds.setAttr((sineDef[0] + '.dropoff'), 1) #Create deformers: Wire deformer deformCrv = cmds.curve(p=[(topPoint, 0, 0), (0, 0, 0), (endPoint, 0, 0)], degree=2) deformCrv = cmds.rename(deformCrv, (prefix + 'ribbon_wire_crv')) wireDef = cmds.wire(geoPlaneWire, dds=(0, 15), wire=deformCrv) wireDef[0] = cmds.rename(wireDef[0], (geoPlaneWire[0] + '_wire')) #Create deformers: Clusters clsTop = cmds.cluster((deformCrv + '.cv[0:1]'), relative=1) clsMid = cmds.cluster((deformCrv + '.cv[1]'), relative=1) clsEnd = cmds.cluster((deformCrv + '.cv[1:2]'), relative=1) clsTop[0] = cmds.rename(clsTop[0], (ctrlTop + '_top_cluster')) clsTop[1] = cmds.rename(clsTop[1], (ctrlTop + '_top_clusterHandle')) clsMid[0] = cmds.rename(clsMid[0], (ctrlMid + '_mid_cluster')) clsMid[1] = cmds.rename(clsMid[1], (ctrlMid + '_mid_clusterHandle')) clsEnd[0] = cmds.rename(clsEnd[0], (ctrlEnd + '_end_cluster')) clsEnd[1] = cmds.rename(clsEnd[1], (ctrlEnd + '_end_clusterHandle')) cmds.setAttr((cmds.listRelatives(clsTop[1], type="shape")[0] + '.originX'), topPoint) cmds.setAttr((cmds.listRelatives(clsEnd[1], type="shape")[0] + '.originX'), endPoint) setPivot(objects=[clsTop[1]], rotatePivot=1, scalePivot=1, pivot=(topPoint, 0, 0)) setPivot(objects=[clsEnd[1]], rotatePivot=1, scalePivot=1, pivot=(endPoint, 0, 0)) cmds.percent(clsTop[0], (deformCrv + '.cv[1]'), v=0.5) cmds.percent(clsEnd[0], (deformCrv + '.cv[1]'), v=0.5) posTopPma = cmds.shadingNode('plusMinusAverage', asUtility=1, name=(prefix + 'top_ctrl_pos_pma')) cmds.connectAttr((ctrlTop + '.translate'), (posTopPma + '.input3D[0]')) cmds.connectAttr((grpTop + '.translate'), (posTopPma + '.input3D[1]')) posEndPma = cmds.shadingNode('plusMinusAverage', asUtility=1, name=(prefix + 'end_ctrl_pos_pma')) cmds.connectAttr((ctrlEnd + '.translate'), (posEndPma + '.input3D[0]')) cmds.connectAttr((grpEnd + '.translate'), (posEndPma + '.input3D[1]')) cmds.connectAttr((posTopPma + '.output3D'), (clsTop[1] + '.translate')) cmds.connectAttr((ctrlMid + '.translate'), (clsMid[1] + '.translate')) cmds.connectAttr((posEndPma + '.output3D'), (clsEnd[1] + '.translate')) #Create deformers: Blendshape blndDef = cmds.blendShape(geoPlaneWire[0], geoPlaneTwist[0], geoPlaneSine[0], geoPlane[0], name=(prefix + 'blendShape'), weight=[(0, 1), (1, 1), (2, 1)]) #Twist deformer: Sum the twist and the roll sumTopPma = cmds.shadingNode('plusMinusAverage', asUtility=1, name=(prefix + 'twist_top_sum_pma')) cmds.connectAttr((ctrlTop + '.twist'), (sumTopPma + '.input1D[0]')) cmds.connectAttr((ctrlTop + '.twistOffset'), (sumTopPma + '.input1D[1]')) cmds.connectAttr((ctrlMid + '.roll'), (sumTopPma + '.input1D[2]')) cmds.connectAttr((ctrlMid + '.rollOffset'), (sumTopPma + '.input1D[3]')) cmds.connectAttr((sumTopPma + '.output1D'), (twistDef[0] + '.startAngle')) sumEndPma = cmds.shadingNode('plusMinusAverage', asUtility=1, name=(prefix + 'twist_low_sum_pma')) cmds.connectAttr((ctrlEnd + '.twist'), (sumEndPma + '.input1D[0]')) cmds.connectAttr((ctrlEnd + '.twistOffset'), (sumEndPma + '.input1D[1]')) cmds.connectAttr((ctrlMid + '.roll'), (sumEndPma + '.input1D[2]')) cmds.connectAttr((ctrlMid + '.rollOffset'), (sumEndPma + '.input1D[3]')) cmds.connectAttr((sumEndPma + '.output1D'), (twistDef[0] + '.endAngle')) #Twist deformer: Set up the affect of the deformer topAffMdl = cmds.shadingNode('multDoubleLinear', asUtility=1, name=(prefix + 'twist_top_affect_mdl')) cmds.setAttr((topAffMdl + '.input1'), -0.1) cmds.connectAttr((ctrlTop + '.affectToMid'), (topAffMdl + '.input2')) cmds.connectAttr((topAffMdl + '.output'), (twistDef[0] + '.lowBound')) endAffMdl = cmds.shadingNode('multDoubleLinear', asUtility=1, name=(prefix + 'twist_end_affect_mdl')) cmds.setAttr((endAffMdl + '.input1'), 0.1) cmds.connectAttr((ctrlEnd + '.affectToMid'), (endAffMdl + '.input2')) cmds.connectAttr((endAffMdl + '.output'), (twistDef[0] + '.highBound')) #Squash deformer: Set up the connections for the volume control volumeRevfMdl = cmds.shadingNode('multDoubleLinear', asUtility=1, name=(prefix + 'volume_reverse_mdl')) cmds.setAttr((volumeRevfMdl + '.input1'), -1) cmds.connectAttr((ctrlMid + '.volume'), (volumeRevfMdl + '.input2')) cmds.connectAttr((volumeRevfMdl + '.output'), (squashDef[0] + '.factor')) cmds.connectAttr((ctrlMid + '.startDropoff'), (squashDef[0] + '.startSmoothness')) cmds.connectAttr((ctrlMid + '.endDropoff'), (squashDef[0] + '.endSmoothness')) cmds.connectAttr((ctrlMid + '.volumePosition'), (squashDef[1] + '.translateX')) #Squash deformer: Set up the volume scaling sumScalePma = cmds.shadingNode('plusMinusAverage', asUtility=1, name=(prefix + 'volume_scale_sum_pma')) cmds.setAttr((sumScalePma + '.input1D[0]'), topPoint) cmds.connectAttr((ctrlMid + '.volumeScale'), (sumScalePma + '.input1D[1]')) cmds.connectAttr((sumScalePma + '.output1D'), (squashDef[1] + '.scaleY')) #Sine deformer: Set up the connections for the sine cmds.connectAttr((ctrlMid + '.amplitude'), (sineDef[0] + '.amplitude')) cmds.connectAttr((ctrlMid + '.offset'), (sineDef[0] + '.offset')) cmds.connectAttr((ctrlMid + '.twist'), (sineDef[1] + '.rotateY')) cmds.connectAttr((ctrlMid + '.sineLength'), (sineDef[0] + '.wavelength')) #Cleanup: Hierarchy cmds.parent(geoPlaneWire[0], geoPlaneTwist[0], geoPlaneSine[0], geoPlaneVolume[0], grpSurfaces) cmds.parent(twistDef[1], sineDef[1], squashDef[1], grpDeformers) cmds.parent(clsTop[1], clsMid[1], clsEnd[1], grpCluster) cmds.parent(grpTop, grpMid, grpEnd, grpCtrl) cmds.parent(geoPlane[0], grpSurface) cmds.parent(deformCrv, (cmds.listConnections(wireDef[0] + '.baseWire[0]')[0]), grpMisc) #Cleanup: Visibility cmds.hide(grpSurfaces, grpDeformers, grpCluster, grpMisc) for x in cmds.listConnections(ctrlMid): cmds.setAttr((x + '.isHistoricallyInteresting'), 0) for y in cmds.listConnections(x): cmds.setAttr((y + '.isHistoricallyInteresting'), 0) #Update the scale-group scaleGrp = scaleGrp if scaleGrp else grpTransform #Create follicles: The main-surface and the volume-surface for x in range(0, numJoints): #Declare a variable for the current index num = str(x + 1) #Get the normalized position of where to place the current follicle uVal = ((0.5 / numJoints) * (x + 1) * 2) - ((0.5 / (numJoints * 2)) * 2) #Create a follicle for the bind-plane and the volume-plane follicleS = createFollicle(scaleGrp=scaleGrp, inputSurface=cmds.listRelatives( geoPlane[0], type="shape"), uVal=uVal, name=(prefix + num + '_follicle')) follicleV = createFollicle(scaleGrp=None, inputSurface=cmds.listRelatives( geoPlaneVolume[0], type="shape"), uVal=uVal, vVal=0, name=(prefix + num + '_volume_follicle')) cmds.parent(follicleS[0], grpFollMain) cmds.parent(follicleV[0], grpFollVolume) #Create a joint, controller and a group for the current skin-follicle cmds.select(clear=True) follicleJoint = cmds.joint(name=(prefix + num + '_jnt'), radius=0.1) follicleCtrl = cmds.circle(name=(prefix + num + '_ctrl'), c=(0, 0, 0), nr=(1, 0, 0), sw=360, r=0.5, d=3, s=8, ch=0)[0] follicleXform = cmds.group(name=(prefix + num + '_xform_grp'), empty=True) cmds.parent(follicleXform, follicleS[0]) cmds.parent(follicleCtrl, follicleXform) cmds.parent(follicleJoint, follicleCtrl) cmds.delete(cmds.parentConstraint(follicleS[0], follicleXform)) #Set the color and connect the visibility-switch for the controller cmds.setAttr((cmds.listRelatives(follicleCtrl, shapes=True)[0] + '.overrideEnabled'), 1) cmds.setAttr((cmds.listRelatives(follicleCtrl, shapes=True)[0] + '.overrideColor'), 12) cmds.connectAttr( (ctrlMid + '.showExtraCtrl'), (cmds.listRelatives(follicleCtrl, shapes=True)[0] + '.visibility')) #Make the connections for the volume multMpd = cmds.shadingNode('multiplyDivide', asUtility=1, name=(prefix + num + '_multiplier_mpd')) cmds.connectAttr((ctrlMid + '.volumeMultiplier'), (multMpd + '.input1Z')) cmds.connectAttr((follicleV[0] + '.translate'), (multMpd + '.input2')) sumPma = cmds.shadingNode('plusMinusAverage', asUtility=1, name=(prefix + num + '_volume_sum_pma')) cmds.connectAttr((multMpd + '.outputZ'), (sumPma + '.input1D[0]')) cmds.setAttr((sumPma + '.input1D[1]'), 1) cmds.connectAttr((sumPma + '.output1D'), (follicleXform + '.scaleY')) cmds.connectAttr((sumPma + '.output1D'), (follicleXform + '.scaleZ'))
def mirrorWeightsCmd(rbsNode, upperIdx): destIdx = upperIdx # get destination prefix destPrfx = _getTargetNameFromIdx(rbsNode, destIdx)[0] # ask for the source srcPrfx = cmds.layoutDialog(t='Mirror bulge weights', ui=lambda *x: _mirrorWeightsDialog(rbsNode, destPrfx)) if len(srcPrfx) > 1: return # find the source index idxPrfxList = _getEyeIdxPrfxList(rbsNode) srcIdx = -1 for lowerIdx, prfx in idxPrfxList: if prfx == srcPrfx: srcIdx = lowerIdx + 1 break if srcIdx < 0: raise Exception, 'Cannot find the index of target %s' % srcPrfx # membership set objSetNode = _getMembershipSet(rbsNode) affectedVtxList = cmds.ls(cmds.sets(objSetNode, q=True) or [], fl=True) # find original shape obj = cmds.listRelatives(cmds.deformer(rbsNode, q=True, g=True), p=True, pa=True)[0] origShape = [s for s in cmds.listRelatives(obj, s=True, pa=True) if cmds.getAttr('%s.intermediateObject' % s)][0] # get the original point position origAffectedVtxList = ['%s%s' % (origShape, vtx[vtx.rindex('.'):]) for vtx in affectedVtxList] vtxCount = len(origAffectedVtxList) posList = cmds.xform(origAffectedVtxList, q=True, os=True, t=True) posList = [posList[i:i+3] for i in xrange(0, len(posList), 3)] # create a symmetry map (it stores the indices of the opposite vertices) cmds.progressBar('mainProgressBar', e=True, beginProgress=True, isInterruptable=False, status='Generating symmetry map...', maxValue=vtxCount) symmMap = [-1]*len(affectedVtxList) for i, pos in enumerate(posList): cmds.progressBar('mainProgressBar', e=True, step=1) # avoid doing the test twice for the opposite vertex if symmMap[i] != -1: continue oppIdx = -1 minDistance = 1000000.0 for j, otherPos in enumerate(posList): dist = (otherPos[0]+pos[0])**2 + (otherPos[1]-pos[1])**2 + (otherPos[2]-pos[2])**2 if dist < minDistance: minDistance = dist oppIdx = j symmMap[i] = oppIdx symmMap[oppIdx] = i cmds.progressBar('mainProgressBar', e=True, endProgress=True) # disconnect paint weights _disconnectPaintWeights(rbsNode) srcAttr = '%s.it[%d].%s' % (rbsNode, srcIdx, _wAttr) destAttr = '%s.it[%d].%s' % (rbsNode, destIdx, _wAttr) pAttr = '%s.weightList[0].weights' % rbsNode # copy weights from source to paint cmds.connectAttr(srcAttr, pAttr, f=True) cmds.getAttr(pAttr, mi=True) cmds.disconnectAttr(srcAttr, pAttr) # connect paint to destination weights cmds.connectAttr(pAttr, destAttr, f=True) affectedWeightList = cmds.percent(rbsNode, affectedVtxList, q=True, v=True) # set weights cmds.progressBar('mainProgressBar', e=True, beginProgress=True, isInterruptable=False, status='Setting weights...', maxValue=vtxCount) for i, vtx in enumerate(affectedVtxList): cmds.progressBar('mainProgressBar', e=True, step=1) cmds.percent(rbsNode, vtx, v=affectedWeightList[symmMap[i]]) cmds.progressBar('mainProgressBar', e=True, endProgress=True) # show the paint tool cmds.select(obj) cmds.setToolTo(cmds.artAttrCtx(oaa='%s.%s.weights' % (_rbsNodeName, rbsNode)))
def softSelectDef(*args): """calls on getSoftSelection() to get the weights of the softSelect and then puts it all under a cluster and a control""" ssDefName = cmds.textFieldGrp(widgets["ssdTFG"], q=True, tx=True) if not cmds.objExists("%s_CLS"%ssDefName): ssScale = cmds.floatFieldGrp(widgets["ssScaleFFG"], q=True, v1=True) ssIncrement = cmds.checkBoxGrp(widgets["ssIncrCBG"], q=True, v1=True) ssCheck = cmds.checkBoxGrp(widgets["ssCheckCBG"], q=True, v1=True) ssParent = cmds.checkBoxGrp(widgets["ssParentCBG"], q=True, v1=True) ssCPOM = cmds.checkBoxGrp(widgets["ssCPOMCBG"], q=True, v1=True) #this gets the verts selected and their respective weights in the soft selection elements,weights = getSoftSelection() #get transform and mesh xform = elements[0].partition(".")[0] #maybe here I should check for "orig", etc and exclude them? mesh = cmds.listRelatives(xform, f=True, s=True)[0] #check if there are other deformers on the obj if ssCheck: deformers = [] deformers = getDeformers(xform) if deformers: cmds.confirmDialog( title='Deformer Alert!', message='Found some deformers on %s.\nYou may want to put the softmod\n early in the input list'%xform, button=['OK'], defaultButton='OK', cancelButton='OK', dismissString='OK' ) #select each of the points from the list and create a cluster cmds.select(cl=True) for elem in elements: cmds.select(elem, add=True) clus = cmds.cluster(relative=True, name="%s_CLS"%ssDefName) for i in range(len(elements)): element = elements[i] value = weights[i] #percent -v 0.5 thisCluster pSphere1.vtx[241] ; cmds.percent(clus[0], element, v=value, ) #get cluster position clusPos = cmds.xform(clus[1], ws=True, q=True, rp=True) if ssCPOM: #create closest point on mesh (surface?) node cpomNode = cmds.shadingNode("closestPointOnMesh", asUtility=True, n="%s_CPOM"%ssDefName) #-------------------- #inputs and outputs for "closestPointOnMesh": #inputs: #"mesh"->"inputMesh" (mesh node of transform) #"clusPos"->"inPosition" #"worldMatrix"(transform of object)->"inputMatrix" #outputs: #"position"->surfacepoint in space #"u"->parameter u #"v"->parameter v #"normal"->normal vector #--------------------- #connect up object to cpom cmds.connectAttr("%s.outMesh"%mesh, "%s.inMesh"%cpomNode) cmds.setAttr("%s.inPosition"%cpomNode, clusPos[0], clusPos[1], clusPos[2]) cmds.connectAttr("%s.worldMatrix"%mesh, "%s.inputMatrix"%cpomNode) cpomPos = cmds.getAttr("%s.position"%cpomNode)[0] #delete cpom node cmds.delete(cpomNode) else: cpomPos = avgElementPos(elements) #TO-DO----------------see if you can't orient things to the verts (maybe only with cpom?) #now create a control control = "%s_CTRL"%ssDefName cmds.curve(n=control, d=1, p=[[0.0, 1.0, 0.0], [-0.382683, 0.92388000000000003, 0.0], [-0.70710700000000004, 0.70710700000000004, 0.0], [-0.92388000000000003, 0.382683, 0.0], [-1.0, 0.0, 0.0], [-0.92388000000000003, -0.382683, 0.0], [-0.70710700000000004, -0.70710700000000004, 0.0], [-0.382683, -0.92388000000000003, 0.0], [0.0, -1.0, 0.0], [0.382683, -0.92388000000000003, 0.0], [0.70710700000000004, -0.70710700000000004, 0.0], [0.92388000000000003, -0.382683, 0.0], [1.0, 0.0, 0.0], [0.92388000000000003, 0.382683, 0.0], [0.70710700000000004, 0.70710700000000004, 0.0], [0.382683, 0.92388000000000003, 0.0], [0.0, 1.0, 0.0], [0.0, 0.92388000000000003, 0.382683], [0.0, 0.70710700000000004, 0.70710700000000004], [0.0, 0.382683, 0.92388000000000003], [0.0, 0.0, 1.0], [0.0, -0.382683, 0.92388000000000003], [0.0, -0.70710700000000004, 0.70710700000000004], [0.0, -0.92388000000000003, 0.382683], [0.0, -1.0, 0.0], [0.0, -0.92388000000000003, -0.382683], [0.0, -0.70710700000000004, -0.70710700000000004], [0.0, -0.382683, -0.92388000000000003], [0.0, 0.0, -1.0], [0.0, 0.382683, -0.92388000000000003], [0.0, 0.70710700000000004, -0.70710700000000004], [0.0, 0.92388000000000003, -0.382683], [0.0, 1.0, 0.0], [-0.382683, 0.92388000000000003, 0.0], [-0.70710700000000004, 0.70710700000000004, 0.0], [-0.92388000000000003, 0.382683, 0.0], [-1.0, 0.0, 0.0], [-0.92388000000000003, 0.0, 0.382683], [-0.70710700000000004, 0.0, 0.70710700000000004], [-0.382683, 0.0, 0.92388000000000003], [0.0, 0.0, 1.0], [0.382683, 0.0, 0.92388000000000003], [0.70710700000000004, 0.0, 0.70710700000000004], [0.92388000000000003, 0.0, 0.382683], [1.0, 0.0, 0.0], [0.92388000000000003, 0.0, -0.382683], [0.70710700000000004, 0.0, -0.70710700000000004], [0.382683, 0.0, -0.92388000000000003], [0.0, 0.0, -1.0], [-0.382683, 0.0, -0.92388000000000003], [-0.70710700000000004, 0.0, -0.70710700000000004], [-0.92388000000000003, 0.0, -0.382683], [-1.0, 0.0, 0.0]]) cmds.select(cl=True) #scale the control scaleCtrl([control], ssScale) shapes = cmds.listRelatives(control, shapes=True) for shape in shapes: cmds.setAttr("%s.overrideEnabled"%shape, 1) cmds.setAttr("%s.overrideColor"%shape, 14) controlGrp = cmds.group(control, n="%s_GRP"%control) #put the control at the cpomPos cmds.xform(controlGrp, ws=True, t=(cpomPos[0],cpomPos[1],cpomPos[2])) clusHandShape = cmds.listRelatives(clus[1], s=True) # #move the cluster control to the control space (weighted node) cmds.cluster(clus[0], e=True, bs=1, wn=(control, control)) cmds.setAttr("%s.originX"%clusHandShape[0], 0.0) cmds.setAttr("%s.originY"%clusHandShape[0], 0.0) cmds.setAttr("%s.originZ"%clusHandShape[0], 0.0) cmds.delete(clus[1]) cmds.setAttr("%s.visibility"%clusHandShape[0], 0) if ssParent: cmds.parent(controlGrp, xform) cmds.select(control, r=True) if ssIncrement == 1: print "trying to rename" split = ssDefName.rpartition("_") end = split[2] isInt = integerTest(end) if isInt: newNum = int(end) + 1 newName = "%s%s%02d"%(split[0], split[1], newNum) cmds.textFieldGrp(widgets["ssdTFG"], tx=newName, e=True) else: newName = "%s_01"%ssDefName cmds.textFieldGrp(widgets["ssdTFG"], tx=newName, e=True) else: cmds.warning("An object/cluster of that name already exists! Please choose another name!")
def flexiPlaneSetup(prefix='flexiPlane', numJoints=5): width = numJoints * 2 # Create Nurbs surface flexiPlane = cmds.nurbsPlane(w=width, lr=0.1, u=width / 2, v=1, ax=[0, 1, 0]) flexiPlane = cmds.rename(flexiPlane[0], '%s_surface01' % prefix) cmds.delete(flexiPlane, constructionHistory=1) # Create plane follicles mel.eval('createHair %s 1 2 0 0 0 0 1 0 1 1 1;' % str(width / 2)) for obj in ['hairSystem1', 'pfxHair1', 'nucleus1']: cmds.delete(obj) folChildren = cmds.listRelatives('hairSystem1Follicles', ad=1) cmds.delete([i for i in folChildren if 'curve' in i]) folGrp = cmds.rename('hairSystem1Follicles', '%s_flcs01' % prefix) alphabetList = map(chr, range(97, 123)) folChildren = cmds.listRelatives(str(folGrp), c=1) for obj, letter in zip(folChildren, alphabetList): folJnt = cmds.joint(p=cmds.xform(obj, t=1, q=1), n='%s_bind_%s01' % (prefix, letter)) cmds.parent(folJnt, obj) cmds.rename(obj, '%s_flc_%s01' % (prefix, letter)) # Add controls squareCons = ['%s_cnt_a01' % prefix, '%s_cnt_b01' % prefix, '%s_midBend01' % prefix] for squareCon in squareCons: squareCon = cmds.curve(n=squareCon, d=1, p=[(-1, 0, -1), (1, 0, -1), (1, 0, 1), (-1, 0, 1), (-1, 0, -1)]) cmds.scale(.75, .75, .75, squareCon, r=1) cmds.setAttr('%s.overrideEnabled' % squareCon, 1) cmds.setAttr('%s.overrideColor' % squareCon, 17) cmds.xform(squareCon, roo='xzy') cmds.xform(squareCons[0], t=(-width / 2, 0, 0), ws=1) cmds.xform(squareCons[1], t=(width / 2, 0, 0), ws=1) cmds.xform(squareCons[2], t=(0, 0, 0), ws=1) cmds.makeIdentity(squareCons, a=1) squareConGrp = cmds.group(squareCons[0], squareCons[1], n='%s_cnts01' % prefix) midConGrp = cmds.group(squareCons[2], n='%s_midCnt01' % prefix) cmds.parent(midConGrp, squareConGrp) cmds.pointConstraint(squareCons[1], squareCons[0], midConGrp, mo=0) # Create a target blendshape controlled by deformers flexiBlend = cmds.duplicate(flexiPlane, n='flexiPlaneSetup_bShp_surface01') flexiBlendNode = cmds.blendShape(flexiBlend, flexiPlane, n='%s_bShpNode_surface01' % prefix) cmds.setAttr('%s.%s' % (flexiBlendNode[0], flexiBlend[0]), 1) wireCurve = cmds.curve(n='%s_wire_surface01' % prefix, d=2, p=[(-width / 2, 0, 0), (0, 0, 0), (width / 2, 0, 0)]) topClstr = cmds.cluster('%s.cv[0:1]' % wireCurve, rel=1, n='%s_cl_a01' % prefix) midClstr = cmds.cluster('%s.cv[1]' % wireCurve, rel=1, n='%s_cl_mid01' % prefix) botClstr = cmds.cluster('%s.cv[1:2]' % wireCurve, rel=1, n='%s_cl_b01' % prefix) clsGrp = cmds.group(topClstr, midClstr, botClstr, n='%s_cls01' % prefix) for attr in ['scalePivot', 'rotatePivot']: cmds.setAttr('%s.%s' % (topClstr[1], attr), -width / 2, 0, 0) for attr in ['scalePivot', 'rotatePivot']: cmds.setAttr('%s.%s' % (botClstr[1], attr), width / 2, 0, 0) cmds.setAttr('%sShape.originX' % topClstr[1], (-width / 2)) cmds.setAttr('%sShape.originX' % botClstr[1], (width / 2)) cmds.percent(topClstr[0], '%s.cv[1]' % wireCurve, v=0.5) cmds.percent(botClstr[0], '%s.cv[1]' % wireCurve, v=0.5) # Create twist and wire blend shape deformers twistNode = cmds.nonLinear(flexiBlend, type='twist') cmds.wire(flexiBlend, w=wireCurve, dds=[0, 20], foc=0, n='%s_wireAttrs_surface01' % prefix) cmds.xform(twistNode, ro=(0, 0, 90)) twistNode[0] = cmds.rename(twistNode[0], '%s_twistAttrs_surface01' % prefix) twistNode[1] = cmds.rename(twistNode[1], '%s_twist_surface01' % prefix) # Connect controls to cluster deformers cmds.connectAttr('%s.translate' % squareCons[0], '%s.translate' % topClstr[1]) cmds.connectAttr('%s.translate' % squareCons[1], '%s.translate' % botClstr[1]) cmds.connectAttr('%s.translate' % squareCons[2], '%s.translate' % midClstr[1]) # Connect controls to twist deformer cmds.connectAttr('%s.rotateX' % squareCons[0], '%s.endAngle' % twistNode[0]) cmds.connectAttr('%s.rotateX' % squareCons[1], '%s.startAngle' % twistNode[0]) # Organize hiearchy nodes and groups rootGrp = cmds.group(em=1, n='%s01' % prefix) moveGrp = cmds.group(em=1, n='%s_globalMove01' % prefix) extrasGrp = cmds.group(em=1, n='%s_extraNodes01' % prefix) cmds.parent(flexiBlend, folGrp, wireCurve, twistNode[1], clsGrp, '%s_wire_surface01BaseWire' % prefix, extrasGrp) cmds.parent(flexiPlane, squareConGrp, moveGrp) cmds.parent(moveGrp, extrasGrp, rootGrp) # Scale contraint each follicle to global move group for fol in cmds.listRelatives(folGrp, c=1): cmds.scaleConstraint(moveGrp, fol, mo=0)
def cluster(self, character=None, mod=None, side=None, name=None, suffix=None, geometry=None, origin=[0, 0, 0], weightObj=None, weightValue=1, parent=None, show=True, lockAttr=None, ihi=True): #--- this method creates a cluster deformer #--- select the specified geometry cmds.select(geometry) #--- create a cluster deformer node = cmds.cluster() filter_name = (name + node[0].split('Handle')[0][0].upper() + node[0].split('Handle')[0][1:]) #--- rename the cluster deformer node = self.__rename_node(mod=mod, side=side, name=filter_name, suffix=suffix, obj=node) #--- get the cluster deform node node.append(cmds.listConnections(node[0])[0]) #--- create a group on top and parent the deformer under the group node_grp = cmds.createNode('transform') cmds.parent(node[0], node_grp) #--- rename the node group node_grp = self.__rename_node(mod=mod, side=side, name=filter_name, suffix='GRP', obj=node_grp)[0] #--- take care of the node's settings #--- origin ori_x = cmds.getAttr(node[1] + '.originX') ori_y = cmds.getAttr(node[1] + '.originY') ori_z = cmds.getAttr(node[1] + '.originZ') new_origin = [ori_x + origin[0], ori_y + origin[1], ori_z + origin[2]] cmds.setAttr(node[1] + '.origin', new_origin[0], new_origin[1], new_origin[2]) cmds.xform(node[0], pivots=new_origin, worldSpace=True) #--- reposition the pivot of the group to the location of the cluster cmds.xform(node_grp, pivots=new_origin, worldSpace=True) #--- weightValue if weightObj: if isinstance(weightObj, list): if isinstance(weightValue, list): for obj, val in zip(weightObj, weightValue): cmds.percent(node[-1], obj, value=val) else: for obj in weightObj: cmds.percent(node[-1], obj, value=weightValue) else: cmds.percent(node[-1], weightObj, value=weightValue) #--- parent the group under the specified parent if parent: if not isinstance(parent, list): cmds.parent(node_grp, parent) else: raise Exception("Specified parent: " + parent + 'is not a valid') #--- show or hide transform if not show: if isinstance(target, list): for t in target: cmds.setAttr(t + '.v', 0) else: cmds.setAttr(target + '.v', 0) #--- lock specified attributes if lockAttr: if node: cmds.setAttr(node + '.' + lockAttr, lock=True) #--- set isHistoricalInteresting attribute if not ihi: cmds.setAttr(node + '.ihi', 0) #--- return node return node
def __init__(self, name='felxi', amount=5, width=10, side=Position.left, debug=False): """ :param name: Name of component. :param amount: Amount of follicles to be created. :param width: Total length of the plane. """ # Global Node globalGrp = cmds.group(name='{}_global_grp'.format(name), em=True) masterGrp = cmds.group(globalGrp, name='{}_grp'.format(name)) # Nurbs Plane axis = [0, 1, 0] plane = cmds.nurbsPlane(name='{}_plane'.format(name), ax=axis, w=width, lr=0.1, d=3, u=amount, v=1, ch=0)[0] planeShape = cmds.listRelatives(plane, shapes=True)[0] cmds.parent(plane, globalGrp) # BlendShape dup = cmds.duplicate(plane, name='{}_twist_blend'.format(plane)) blendshape = cmds.blendShape(dup, plane, name='{}_blendShape0'.format(name), weight=[0, 1]) step = 1.0 / float(amount - 1) uPos = 0 vPos = 0.5 posList = [] for x in range(amount): posList.append(uPos) uPos += step if side == Position.right: posList = list(reversed(posList)) # Follicles follicleList = [] follicleScale = [] for x in range(amount): follicle = createFollicle('{}_{}_follicle'.format(name, x), debug=debug) follicleTransform = follicle[0] follicleShape = follicle[1] cmds.connectAttr('{}.local'.format(planeShape), '{}.inputSurface'.format(follicleShape)) cmds.connectAttr('{}.worldMatrix[0]'.format(planeShape), '{}.inputWorldMatrix'.format(follicleShape)) cmds.setAttr('{}.parameterU'.format(follicleShape), posList[x]) cmds.setAttr('{}.parameterV'.format(follicleShape), vPos) cmds.setAttr('{}.v'.format(follicleShape), 0) follicleScale.append( cmds.scaleConstraint(globalGrp, follicleTransform, mo=True)[0]) follicleList.append(follicleTransform) # Locators pos = [width / 2 * -1, 0, width / 2] if side == Position.right: pos = list(reversed(pos)) locList = [] locGrpList = [] i = 0 for x in pos: loc = cmds.spaceLocator(name='{}_{}_locator'.format(name, i))[0] cmds.xform(loc, ws=True, t=[x, 0, 0]) freezeTransform(loc) cmds.parent(loc, globalGrp) locList.append(loc) i += 1 # Curve clusterList = [] clusterGrp = cmds.group(name='{}_cluster_grp'.format(name), em=True) curve = makeNurbsCurve(locList, n='{}_curve'.format(name), d=2) i = 0 for x in ['0:1', '1', '1:2']: cluster = cmds.cluster('{}.cv[{}]'.format(curve, x), rel=True, name='{}_{}_cluster'.format(name, i)) clusterShape = cluster[0] cluster = cluster[1] cmds.xform(cluster, ws=True, rp=[pos[i], 0, 0]) cmds.setAttr('{}.v'.format(cluster), 0) cmds.connectAttr('{}.t'.format(locList[i]), '{}.t'.format(cluster)) cmds.parent(cluster, clusterGrp) clusterList.append(clusterShape) i += 1 cmds.percent(clusterList[0], '{}.cv[1]'.format(curve), v=.5) cmds.percent(clusterList[-1], '{}.cv[1]'.format(curve), v=.5) # TwistDeformer twist = cmds.nonLinear(dup, type='twist', name='{}_twist'.format(name)) twistShape = cmds.rename(twist[0], '{}_twist'.format(name)) twistTransform = cmds.rename(twist[1], '{}_twistHandle'.format(name)) cmds.setAttr('{}.rz'.format(twistTransform), -90 if side == Position.left else 90) rangeNode = cmds.createNode('setRange', name='{}_twist_setRange0'.format(name)) addList = [] for axis in ['x', 'y', 'z']: cmds.setAttr('{}.oldMax{}'.format(rangeNode, axis.upper()), 1) cmds.addAttr(globalGrp, ln='startTwist', min=0, max=1, dv=1, k=True) cmds.addAttr(globalGrp, ln='endTwist', min=0, max=1, dv=1, k=True) cmds.addAttr(globalGrp, ln='startTwistAmount', k=True, at='doubleAngle') cmds.addAttr(globalGrp, ln='endTwistAmount', k=True, at='doubleAngle') cmds.addAttr(globalGrp, ln='startTwistAdd', k=True, at='doubleAngle') cmds.addAttr(globalGrp, ln='endTwistAdd', k=True, at='doubleAngle') cmds.addAttr( globalGrp, ln='twistSide', min=-1, max=1, dv=-1 if side == Position.left else 1, k=True, ) mirror = cmds.createNode('multiplyDivide', name='{}_mirror_mult0'.format(name)) axis = 'X' for attr in ['start', 'end']: add = cmds.createNode('addDoubleLinear', name='{}_{}_add0'.format(name, attr)) cmds.connectAttr('{}.{}TwistAmount'.format(globalGrp, attr), '{}.input1'.format(add)) cmds.connectAttr('{}.{}TwistAdd'.format(globalGrp, attr), '{}.input2'.format(add)) cmds.connectAttr('{}.output'.format(add), '{}.max{}'.format(rangeNode, axis)) cmds.connectAttr('{}.{}Twist'.format(globalGrp, attr), '{}.value{}'.format(rangeNode, axis)) cmds.connectAttr('{}.twistSide'.format(globalGrp), '{}.input1{}'.format(mirror, axis)) cmds.connectAttr('{}.outValue{}'.format(rangeNode, axis), '{}.input2{}'.format(mirror, axis)) cmds.connectAttr('{}.output{}'.format(mirror, axis), '{}.{}Angle'.format(twistShape, attr)) axis = 'Y' # Wire Deformer wire = cmds.wire(dup, wire=curve, name='{}_wire0'.format(name)) wireShape = wire[0] wireBaseTransform = cmds.listConnections( '{}.baseWire[0]'.format(wireShape))[0] cmds.setAttr('{}.dropoffDistance[0]'.format(wire[0]), 20) # SnS cmds.addAttr(globalGrp, ln='sns', min=0, max=1, dv=1, k=True) cmds.addAttr(globalGrp, ln='snsAdd', k=True) # cmds.addAttr(globalGrp, ln='snsHighBound', k=True, min=0, max=1, dv=1) # cmds.addAttr(globalGrp, ln='snsLowBound', k=True, min=0, max=1, dv=1) curveInfo = createCurveInfo(curve) divideA = cmds.createNode('multiplyDivide', name='{}_divide0'.format(name)) cmds.setAttr('{}.operation'.format(divideA), 2) cmds.setAttr('{}.input2X'.format(divideA), width) divideB = cmds.createNode('multiplyDivide', name='{}_divide0'.format(name)) cmds.setAttr('{}.operation'.format(divideB), 2) cmds.setAttr('{}.input1X'.format(divideB), 1) cmds.connectAttr('{}.arcLength'.format(curveInfo), '{}.input1X'.format(divideA)) cmds.connectAttr('{}.outputX'.format(divideA), '{}.input2X'.format(divideB)) setRange = cmds.createNode('setRange', name='{}_sns_setRange0'.format(name)) cmds.setAttr('{}.minX'.format(setRange), 1) cmds.setAttr('{}.oldMaxX'.format(setRange), 1) cmds.connectAttr('{}.sns'.format(globalGrp), '{}.valueX'.format(setRange)) cmds.connectAttr('{}.outputX'.format(divideB), '{}.maxX'.format(setRange)) add = cmds.createNode('addDoubleLinear', name='{}_add0'.format(name)) cmds.connectAttr('{}.outValueX'.format(setRange), '{}.input1'.format(add)) cmds.connectAttr('{}.snsAdd'.format(globalGrp), '{}.input2'.format(add)) var = 0 step = 1.0 / float(amount - 1) stepRangePos = [] for x in range(amount): if x == 0: stepRangePos.append(.1) else: stepRangePos.append(var) var += step stepRangeNeg = list(reversed(stepRangePos)) for scale in follicleScale: i = follicleScale.index(scale) for axis in ['y', 'z']: cmds.connectAttr('{}.output'.format(add), '{}.offset{}'.format(scale, axis.upper())) # Hierarchy extrasGrp = cmds.group(clusterGrp, curve, twistTransform, dup, wireBaseTransform, name='{}_extras_grp'.format(name)) cmds.setAttr('{}.v'.format(extrasGrp), 0) cmds.setAttr('{}.inheritsTransform'.format(extrasGrp), 0) follicleGrp = cmds.group(follicleList, name='{}_follicle_grp'.format(name)) cmds.setAttr('{}.inheritsTransform'.format(follicleGrp), 0) cmds.parent(extrasGrp, follicleGrp, masterGrp) for x in [follicleGrp, clusterGrp, extrasGrp, plane]: lockKeyableAttributes(x) setVisibility(globalGrp) lockScale(globalGrp) # Return self.plane = plane self.planeShape = planeShape self.planeBlend = dup self.planeBlendShape = blendshape self.follicle = follicleList self.curve = curve self.twist = twistTransform self.twistShape = twistShape self.wire = wire self.wireBase = wireBaseTransform self.control = locList self.group = locGrpList self.parent = globalGrp self.masterGroup = masterGrp self.extra = extrasGrp
def Cas_convertRigidToSmooth_cmd(object): def getObjectVertices(ob, verts): ov = cmds.polyListComponentConversion(ob, tv=1) ov = cmds.filterExpand(ov, ex=1, fp=1, sm=31) verts = cmds.filterExpand(verts, ex=1, fp=1, sm=31) # print ov # print verts com = [] for v in verts: if v in ov: com.append(v) return com """ """ warningCount = 0 num = 0 objects = object[:] # objects.append(object) allClusters = [] # get all the joint cluster names jCluster = cmds.ls(typ="jointCluster") # print cmds.cluster(jCluster,q=1,g=1) # print jCluster # return if jCluster == None: return [num, warningCount] for objT in objects: obj = cmds.listRelatives(objT, s=1, pa=1) # full path!!! if obj == None: continue # print obj # objShape = obj[0] # iterate through to see if any clusters are connected to the object joint = [] cluster = [] jointSet = [] # find related clusters jointsets and joints for c in jCluster: jc = [] jc = cmds.cluster(c, q=1, g=1) # print obj[0] if obj[0] in jc: # print "deformer found" # print jc deformer = Cas_CRTS_getJointDeformer(c) if deformer != None: joint.append(deformer) jointSet.append(Cas_CRTS_getJointSet(c)) cluster.append(c) if c not in allClusters: allClusters.append(c) # check if any jointcluster exists for this object if cluster == []: # print "No jointCluster found for node : %s" %objT continue # now joint should contain all the joints names which i need to bind my new object to # bind skin # print joint # print objT # return newClusterName = [] try: newClusterName = cmds.skinCluster(joint, objT, tst=True)[0] except Exception, msg: Cas_IO.Cas_printWarning("Failed to assign skinCluster. skinCluster may exist already for node : %s" % objT) warningCount = warningCount + 1 continue else: print "jointCluster found for node : %s" % objT # setAttr "skinCluster4.normalizeWeights" 1; # cmds.setAttr(newClusterName+".normalizeWeights",0) # now needs to copy weights over. index = 0 for c in cluster: jSet = jointSet[index] jsetName = jSet[0].split(".") # print jsetName vertices = cmds.sets(jsetName[0], q=1) vertices = getObjectVertices(objT, vertices) # print vertices if (vertices == None) or (vertices == []): # print "skip" index = index + 1 continue deformer = joint[index] parentDeformer = cmds.listRelatives(deformer, p=1) # print parentDeformer # vertices = cmds.filterExpand(vertices,ex=1,fp=1,sm=31) cmds.select(vertices) value = cmds.percent(c, q=1, v=1) # print len(value) # print len(vertices) if not parentDeformer == None: cmds.skinPercent(newClusterName, vertices, tv=([parentDeformer[0], 1])) # for j in joint: # cmds.skinPercent(newClusterName,vertices,tv=([j,0])) i = 0 for v in value: cmds.skinPercent(newClusterName, vertices[i], tv=([deformer, v])) # if not parentDeformer == None: # cmds.skinPercent(newClusterName,vertices[i],tv=([parentDeformer[0],(1-v)])) # print i i += 1 cmds.percent(c, vertices, v=0) index = index + 1 num = num + 1
def mirrorWeightsCmd(rbsNode, upperIdx): destIdx = upperIdx # get destination prefix destPrfx = _getTargetNameFromIdx(rbsNode, destIdx)[0] # ask for the source srcPrfx = cmds.layoutDialog( t='Mirror bulge weights', ui=lambda *x: _mirrorWeightsDialog(rbsNode, destPrfx)) if len(srcPrfx) > 1: return # find the source index idxPrfxList = _getEyeIdxPrfxList(rbsNode) srcIdx = -1 for lowerIdx, prfx in idxPrfxList: if prfx == srcPrfx: srcIdx = lowerIdx + 1 break if srcIdx < 0: raise Exception, 'Cannot find the index of target %s' % srcPrfx # membership set objSetNode = _getMembershipSet(rbsNode) affectedVtxList = cmds.ls(cmds.sets(objSetNode, q=True) or [], fl=True) # find original shape obj = cmds.listRelatives(cmds.deformer(rbsNode, q=True, g=True), p=True, pa=True)[0] origShape = [ s for s in cmds.listRelatives(obj, s=True, pa=True) if cmds.getAttr('%s.intermediateObject' % s) ][0] # get the original point position origAffectedVtxList = [ '%s%s' % (origShape, vtx[vtx.rindex('.'):]) for vtx in affectedVtxList ] vtxCount = len(origAffectedVtxList) posList = cmds.xform(origAffectedVtxList, q=True, os=True, t=True) posList = [posList[i:i + 3] for i in xrange(0, len(posList), 3)] # create a symmetry map (it stores the indices of the opposite vertices) cmds.progressBar('mainProgressBar', e=True, beginProgress=True, isInterruptable=False, status='Generating symmetry map...', maxValue=vtxCount) symmMap = [-1] * len(affectedVtxList) for i, pos in enumerate(posList): cmds.progressBar('mainProgressBar', e=True, step=1) # avoid doing the test twice for the opposite vertex if symmMap[i] != -1: continue oppIdx = -1 minDistance = 1000000.0 for j, otherPos in enumerate(posList): dist = (otherPos[0] + pos[0])**2 + (otherPos[1] - pos[1])**2 + ( otherPos[2] - pos[2])**2 if dist < minDistance: minDistance = dist oppIdx = j symmMap[i] = oppIdx symmMap[oppIdx] = i cmds.progressBar('mainProgressBar', e=True, endProgress=True) # disconnect paint weights _disconnectPaintWeights(rbsNode) srcAttr = '%s.it[%d].%s' % (rbsNode, srcIdx, _wAttr) destAttr = '%s.it[%d].%s' % (rbsNode, destIdx, _wAttr) pAttr = '%s.weightList[0].weights' % rbsNode # copy weights from source to paint cmds.connectAttr(srcAttr, pAttr, f=True) cmds.getAttr(pAttr, mi=True) cmds.disconnectAttr(srcAttr, pAttr) # connect paint to destination weights cmds.connectAttr(pAttr, destAttr, f=True) affectedWeightList = cmds.percent(rbsNode, affectedVtxList, q=True, v=True) # set weights cmds.progressBar('mainProgressBar', e=True, beginProgress=True, isInterruptable=False, status='Setting weights...', maxValue=vtxCount) for i, vtx in enumerate(affectedVtxList): cmds.progressBar('mainProgressBar', e=True, step=1) cmds.percent(rbsNode, vtx, v=affectedWeightList[symmMap[i]]) cmds.progressBar('mainProgressBar', e=True, endProgress=True) # show the paint tool cmds.select(obj) cmds.setToolTo( cmds.artAttrCtx(oaa='%s.%s.weights' % (_rbsNodeName, rbsNode)))
def softSelectDef(*args): """calls on getSoftSelection() to get the weights of the softSelect and then puts it all under a cluster and a control""" elements,weights = getSoftSelection() print elements print weights #get transform and mesh xform = elements[0].partition(".")[0] #maybe here I should check for "orig", etc and exclude them? mesh = cmds.listRelatives(xform, f=True, s=True)[0] #select each of the points from the list and create a cluster cmds.select(cl=True) for elem in elements: cmds.select(elem, add=True) clus = cmds.cluster(relative=True, name="thisCluster") for i in range(len(elements)): element = elements[i] value = weights[i] #percent -v 0.5 thisCluster pSphere1.vtx[241] ; cmds.percent(clus[0], element, v=value, ) #get cluster position clusPos = cmds.xform(clus[1], ws=True, q=True, rp=True) #create closest point on mesh (surface?) node cpomNode = cmds.shadingNode("closestPointOnMesh", asUtility=True, n="tempCPOM") #-------------------- #inputs and outputs for "closestPointOnMesh": #inputs: #"mesh"->"inputMesh" (mesh node of transform) #"clusPos"->"inPosition" #"worldMatrix"(transform of object)->"inputMatrix" #outputs: #"position"->surfacepoint in space #"u"->parameter u #"v"->parameter v #"normal"->normal vector #--------------------- #connect up object to cpom cmds.connectAttr("%s.outMesh"%mesh, "%s.inMesh"%cpomNode) cmds.setAttr("%s.inPosition"%cpomNode, clusPos[0], clusPos[1], clusPos[2]) cmds.connectAttr("%s.worldMatrix"%mesh, "%s.inputMatrix"%cpomNode) cpomPos = cmds.getAttr("%s.position"%cpomNode)[0] #delete cpom node cmds.delete(cpomNode) #now create a control, orient it to the follicle control = "controlName" cmds.curve(n=control, d=1, p=[[0.0, 1.0, 0.0], [-0.382683, 0.92388000000000003, 0.0], [-0.70710700000000004, 0.70710700000000004, 0.0], [-0.92388000000000003, 0.382683, 0.0], [-1.0, 0.0, 0.0], [-0.92388000000000003, -0.382683, 0.0], [-0.70710700000000004, -0.70710700000000004, 0.0], [-0.382683, -0.92388000000000003, 0.0], [0.0, -1.0, 0.0], [0.382683, -0.92388000000000003, 0.0], [0.70710700000000004, -0.70710700000000004, 0.0], [0.92388000000000003, -0.382683, 0.0], [1.0, 0.0, 0.0], [0.92388000000000003, 0.382683, 0.0], [0.70710700000000004, 0.70710700000000004, 0.0], [0.382683, 0.92388000000000003, 0.0], [0.0, 1.0, 0.0], [0.0, 0.92388000000000003, 0.382683], [0.0, 0.70710700000000004, 0.70710700000000004], [0.0, 0.382683, 0.92388000000000003], [0.0, 0.0, 1.0], [0.0, -0.382683, 0.92388000000000003], [0.0, -0.70710700000000004, 0.70710700000000004], [0.0, -0.92388000000000003, 0.382683], [0.0, -1.0, 0.0], [0.0, -0.92388000000000003, -0.382683], [0.0, -0.70710700000000004, -0.70710700000000004], [0.0, -0.382683, -0.92388000000000003], [0.0, 0.0, -1.0], [0.0, 0.382683, -0.92388000000000003], [0.0, 0.70710700000000004, -0.70710700000000004], [0.0, 0.92388000000000003, -0.382683], [0.0, 1.0, 0.0], [-0.382683, 0.92388000000000003, 0.0], [-0.70710700000000004, 0.70710700000000004, 0.0], [-0.92388000000000003, 0.382683, 0.0], [-1.0, 0.0, 0.0], [-0.92388000000000003, 0.0, 0.382683], [-0.70710700000000004, 0.0, 0.70710700000000004], [-0.382683, 0.0, 0.92388000000000003], [0.0, 0.0, 1.0], [0.382683, 0.0, 0.92388000000000003], [0.70710700000000004, 0.0, 0.70710700000000004], [0.92388000000000003, 0.0, 0.382683], [1.0, 0.0, 0.0], [0.92388000000000003, 0.0, -0.382683], [0.70710700000000004, 0.0, -0.70710700000000004], [0.382683, 0.0, -0.92388000000000003], [0.0, 0.0, -1.0], [-0.382683, 0.0, -0.92388000000000003], [-0.70710700000000004, 0.0, -0.70710700000000004], [-0.92388000000000003, 0.0, -0.382683], [-1.0, 0.0, 0.0]]) cmds.select(cl=True) shapes = cmds.listRelatives(control, shapes=True) for shape in shapes: cmds.setAttr("%s.overrideEnabled"%shape, 1) cmds.setAttr("%s.overrideColor"%shape, 14) controlGrp = cmds.group(control, n="%s_GRP"%control) #put the control at the cpomPos cmds.xform(controlGrp, ws=True, t=(cpomPos[0],cpomPos[1],cpomPos[2])) clusHandShape = cmds.listRelatives(clus[1], s=True) # #move the cluster control to the control space (weighted node) cmds.cluster(clus[0], e=True, bs=1, wn=(control, control)) cmds.setAttr("%s.originX"%clusHandShape[0], 0.0) cmds.setAttr("%s.originY"%clusHandShape[0], 0.0) cmds.setAttr("%s.originZ"%clusHandShape[0], 0.0) cmds.delete(clus[1]) cmds.setAttr("%s.visibility"%clusHandShape[0], 0)
class analyticGPUClusters(BaseAnalytic): """ Analyze the usage mode of cluster node. """ def run(self): """ Examine animated cluster nodes and check how they are used. It checks whether they are used for fixed rigid transform, weighted rigid transform or per-vertex-weighted transform. When the 'details' option is set the CSV columns are: ClusterNode : Name of the animated cluster node envelope_is_static : True if the envelope is not animated and its value is 1 uses_weights : True if weights are used in the node uses_same_weight : True if weight is the same for all vertices Mode : Mode for this node supported_geometry : True if the geometry processed by animated cluster node is supported by deformer evaluator otherwise the CSV columns are: ClusterMode : Description of the usage for the animated cluster node Mode : Mode for animated cluster nodes meeting this criteria supported_geometry : True if the geometry processed by animated cluster nodes meeting this criteria is supported by deformer evaluator Count : Number of animated cluster nodes in this mode See is_supported_geometry() for what criteria a geometry must meet to be supported. One row is output for every animated cluster node. The "Mode" is an integer value with the following meaning: - 1 => Rigid transform : cluster node only performs a rigid transform - 2 => Weighted rigid transform : cluster node performs a rigid transform, but it is weighted down by a factor - 3 => Per-vertex transform : cluster node computes a different transform for each individually-weighted vertex Return True if the analysis succeeded, else False """ with emModeManager() as em_manager: em_manager.setMode('ems') em_manager.rebuild() # Get all animated nodes. try: json_nodes = json.loads( cmds.dbpeek(op='graph', eg=True, all=True, a='nodes')) animated_nodes = set(json_nodes['nodes']) except Exception, ex: self.error('Graph examination failure ({0:s})'.format(str(ex))) return if not animated_nodes: self.warning('No GPU animation to examine') return # Loop and process only cluster nodes. cluster_nodes = [] for node in animated_nodes: if cmds.nodeType(node) == 'cluster': # Check the envelope attribute. envelope_source = cmds.listConnections(node + '.envelope', source=True, destination=False) if envelope_source and len(envelope_source) > 0: envelope_is_static = False else: envelope = cmds.getAttr(node + '.envelope') if envelope == 1: envelope_is_static = True else: envelope_is_static = False # Now loop over each output geometry as separate usage of this node. geometries = cmds.cluster(node, query=True, geometry=True) geometry_indices = cmds.cluster(node, query=True, geometryIndices=True) if geometries == None or geometry_indices == None: continue cluster_geometry = dict(zip(geometry_indices, geometries)) for index, geometry in cluster_geometry.items(): # Check if the deformed geometry is supported. supported_geometry = analyticGPUDeformers.is_supported_geometry( geometry) # Check if weights are used. uses_weights = False weight_plug = '%s.weightList[%d]' % (node, index) weights_source = cmds.listConnections(weight_plug, source=True, destination=False) if weights_source and len(weights_source) > 0: # If they are animated, we consider they don't have default value. uses_weights = True uses_same_weight = False common_value = None if not uses_weights: uses_same_weight = True # Check if the weights have non default value. weights = cmds.percent(node, geometry, query=True, value=True) for weight in weights: if common_value == None: common_value = weight else: if common_value != weight: uses_same_weight = False break if (not uses_same_weight) or (common_value != 1): uses_weights = True # Determine the mode. if uses_weights: mode = 3 else: if envelope_is_static: mode = 1 else: mode = 2 # Append the info. nodeName = '%s[%d]' % (self._node_name(node), index) cluster_nodes.append( (nodeName, envelope_is_static, uses_weights, uses_same_weight, mode, supported_geometry)) if not cluster_nodes: self.warning('No GPU clusters to examine') return # Output to CSV. if self.option(OPTION_DETAILS): self._output_csv([ 'ClusterNode', 'EnvelopeIsStatic', 'UsesWeights', 'UsesSameWeight', 'Mode', 'SupportedGeometry' ]) output_rows = cluster_nodes else: self._output_csv( ['ClusterType', 'Mode', 'SupportedGeometry', 'Count']) # Build the summary using different categories. categories = [ ('Rigid_Supported', (1, True)), ('Weighted_Supported', (2, True)), ('PerVertex_Supported', (3, True)), ('Rigid_NotSupported', (1, False)), ('Weighted_NotSupported', (2, False)), ('PerVertex_NotSupported', (3, False)), ] # Loop over each "category" and count the number of collected nodes (in cluster_nodes) # meeting the criteria for each category. # # Here, the criteria to know whether or not a node belongs to a category is: # - The "mode" (see help above for description of the modes) # - Whether or not the cluster node drives a supported mesh (vs another type of geometry) summary = [] for category in categories: name = category[0] criteria = category[1] tester = lambda x, criteria_to_check=criteria: x[ 4:] == criteria_to_check count = len([node for node in cluster_nodes if tester(node)]) summary.append((name, criteria[0], criteria[1], count)) output_rows = summary for row in output_rows: self._output_csv(list(row))
def Cas_convertRigidToSmooth_cmd(object): def getObjectVertices(ob, verts): ov = cmds.polyListComponentConversion(ob, tv=1) ov = cmds.filterExpand(ov, ex=1, fp=1, sm=31) verts = cmds.filterExpand(verts, ex=1, fp=1, sm=31) #print ov #print verts com = [] for v in verts: if v in ov: com.append(v) return com """ """ warningCount = 0 num = 0 objects = object[:] #objects.append(object) allClusters = [] #get all the joint cluster names jCluster = cmds.ls(typ="jointCluster") #print cmds.cluster(jCluster,q=1,g=1) #print jCluster #return if jCluster == None: return [num, warningCount] for objT in objects: obj = cmds.listRelatives(objT, s=1, pa=1) #full path!!! if obj == None: continue #print obj #objShape = obj[0] #iterate through to see if any clusters are connected to the object joint = [] cluster = [] jointSet = [] #find related clusters jointsets and joints for c in jCluster: jc = [] jc = cmds.cluster(c, q=1, g=1) #print obj[0] if obj[0] in jc: #print "deformer found" #print jc deformer = Cas_CRTS_getJointDeformer(c) if deformer != None: joint.append(deformer) jointSet.append(Cas_CRTS_getJointSet(c)) cluster.append(c) if c not in allClusters: allClusters.append(c) #check if any jointcluster exists for this object if cluster == []: #print "No jointCluster found for node : %s" %objT continue #now joint should contain all the joints names which i need to bind my new object to #bind skin #print joint #print objT #return newClusterName = [] try: newClusterName = cmds.skinCluster(joint, objT, tst=True)[0] except Exception, msg: Cas_IO.Cas_printWarning( "Failed to assign skinCluster. skinCluster may exist already for node : %s" % objT) warningCount = warningCount + 1 continue else: print "jointCluster found for node : %s" % objT #setAttr "skinCluster4.normalizeWeights" 1; #cmds.setAttr(newClusterName+".normalizeWeights",0) #now needs to copy weights over. index = 0 for c in cluster: jSet = jointSet[index] jsetName = jSet[0].split(".") #print jsetName vertices = cmds.sets(jsetName[0], q=1) vertices = getObjectVertices(objT, vertices) #print vertices if (vertices == None) or (vertices == []): #print "skip" index = index + 1 continue deformer = joint[index] parentDeformer = cmds.listRelatives(deformer, p=1) #print parentDeformer #vertices = cmds.filterExpand(vertices,ex=1,fp=1,sm=31) cmds.select(vertices) value = cmds.percent(c, q=1, v=1) #print len(value) #print len(vertices) if not parentDeformer == None: cmds.skinPercent(newClusterName, vertices, tv=([parentDeformer[0], 1])) #for j in joint: # cmds.skinPercent(newClusterName,vertices,tv=([j,0])) i = 0 for v in value: cmds.skinPercent(newClusterName, vertices[i], tv=([deformer, v])) #if not parentDeformer == None: # cmds.skinPercent(newClusterName,vertices[i],tv=([parentDeformer[0],(1-v)])) #print i i += 1 cmds.percent(c, vertices, v=0) index = index + 1 num = num + 1
def mirror_cluster(): is_current_setup_valid = True mesh_transform = global_settings.get("loaded_mesh") cluster_handle = global_settings.get("loaded_cluster_handle") mirror_axis = cmds.radioButtonGrp("mirror_axis_btn_grp", q=1, sl=1) if cmds.objExists(mesh_transform) == True: if cmds.objectType( cmds.listRelatives(mesh_transform, children=True)[0]) != "mesh": is_current_setup_valid = False else: is_current_setup_valid = False if cmds.objExists(cluster_handle) == True: if cmds.objectType( cmds.listRelatives(cluster_handle, children=True)[0]) != "clusterHandle": is_current_setup_valid = False else: is_current_setup_valid = False if is_current_setup_valid: mesh_shape = cmds.listRelatives(mesh_transform, s=1, c=1) verticies_selected_mesh = get_cluster_verticies_on_mesh( mesh_transform, cluster_handle) mirrored_vertices = [] for vertex in verticies_selected_mesh: vertex_position = cmds.pointPosition(vertex[0], local=1) # Utility node used to collect information about the other side of the mesh closest_point_node = cmds.createNode('closestPointOnMesh') if mirror_axis == 1: cmds.setAttr((closest_point_node + ".inPosition"), -vertex_position[0], vertex_position[1], vertex_position[2]) elif mirror_axis == 2: cmds.setAttr((closest_point_node + ".inPosition"), vertex_position[0], -vertex_position[1], vertex_position[2]) else: cmds.setAttr((closest_point_node + ".inPosition"), vertex_position[0], vertex_position[1], -vertex_position[2]) try: cmds.connectAttr((mesh_shape[0] + ".outMesh"), (closest_point_node + ".inMesh"), force=1) except: pass mirrored_vertex = ( mesh_transform + ".vtx[" + str(cmds.getAttr( (closest_point_node + ".closestVertexIndex"))) + "]" ) # Find mirrored vertex vertex[ 0] = mirrored_vertex # Replace previous pair vertex with new found one mirrored_vertices.append(mirrored_vertex) cmds.delete(closest_point_node) # Delete utility node cluster_deformer_node = cmds.listConnections( (cluster_handle + ".worldMatrix[0]"), type="cluster", destination=1) is_relative = cmds.getAttr((cluster_deformer_node[0] + ".relative")) new_cluster_name = cluster_handle.replace( cmds.textField("search_text_field", q=True, text=True), cmds.textField("replace_text_field", q=True, text=True)) new_cluster = cmds.cluster(mirrored_vertices, rel=is_relative) #Transfer weight back to new cluster for num in range(len(verticies_selected_mesh)): cmds.percent(new_cluster[0], verticies_selected_mesh[num][0], v=verticies_selected_mesh[num][1]) cmds.rename(new_cluster_name) else: cmds.warning( "Something went wrong. Please try loading the objects again.")
def ribbonBuild(): # check for matrixNodes.mll plug (comes with Maya, but might be off) if cmds.pluginInfo('matrixNodes.mll', q=True) == False: cmds.loadPlugin('matixNodes.mll') max = 3 rstats = ["castsShadows", "receiveShadows", "motionBlur", "primaryVisibility", "smoothShading", "smoothShading", "visibleInReflections", "visibleInRefractions"] locGrp = cmds.group( em=True, n="ribbon_grp_#" ) # set primary vector (down the chain, i.e: x, y or z) and other default values jointDown = 'x' divisions = 3 planeW = divisions * 2 posIncr = 0 increment = 0.5 v = 0.5 # create the ribbon nurb surface nameFP = cmds.nurbsPlane( ch=False, u=divisions, v=1, ax=[0,1,0], p=[0,0,0], lr=0.2, w=planeW, n="ribbonPlane1" )[0] # diag print print( increment ) print( posIncr ) for i in xrange(0, divisions): posNode = cmds.pointOnSurface( nameFP, ch=True, top=1, u=posIncr, v=0.5 ) posLoc = cmds.group(em=True, n='posNode_'+ str(i)) cmds.connectAttr( '{0}.position'.format(posNode), '{0}.translate'.format(posLoc) ) posIncr += 0.5 posX = cmds.getAttr( '{0}.positionX'.format(posNode) ) posY = cmds.getAttr( '{0}.positionY'.format(posNode) ) posZ = cmds.getAttr( '{0}.positionZ'.format(posNode) ) newJoint = cmds.joint(p=[posX, posY, posZ], n='ribbon_jnt_bn') # set-up parent rotations for joints to follow surface correctly # this follows a process similar to Michael Bazhutkin's river script aimCon = cmds.createNode('aimConstraint') cmds.connectAttr( '{0}.normal'.format(posNode), '{0}.target[0].targetTranslate'.format(aimCon), f=True ) cmds.connectAttr( '{0}.tangentV'.format(posNode), '{0}.worldUpVector'.format(aimCon), f=True ) cmds.connectAttr( '{0}.constraintRotate'.format(aimCon), '{0}.rotate'.format(posLoc), f=True ) cmds.parent(aimCon, posLoc) cmds.parent(posLoc, locGrp) # switch statement look-alike for py.. for case in switch(jointDown): if case('x'): cmds.setAttr( '{0}.aimVector'.format(aimCon), type='double3', *list( (0,1,0) ) ) cmds.setAttr( '{0}.upVector'.format(aimCon), type='double3', *list( (0,0,1) ) ) break if case('y'): cmds.setAttr( '{0}.aimVector'.format(aimCon), type='double3', *list( (0,1,0) ) ) cmds.setAttr( '{0}.upVector'.format(aimCon), type='double3', *list( (0,0,1) ) ) break if case('z'): cmds.setAttr( '{0}.aimVector'.format(aimCon), type='double3', *list( (0,1,0) ) ) cmds.setAttr( '{0}.upVector'.format(aimCon), type='double3', *list( (0,0,1) ) ) break if case(): #default print("Couldn't found a valid joint down value (x, y, z") #print 'lol' topCtrl = cmds.circle( n='ribbon1_top_ctrl', ch=False )[0] botCtrl = cmds.circle( n='ribbon1_bottom_ctrl', ch=False )[0] midCtrl = cmds.circle( n='ribbon1_mid_ctrl', ch=False )[0] # set to origin (creation points were recorded away from origin, otherwise this would be unnecessary) setToOrigin(topCtrl) setToOrigin(botCtrl) # two more curves that will serve as the god ctrl leftMainCurve = cmds.circle( n='pHolder_1', ch=False, r=0.3)[0] rightMainCurve = cmds.circle( n='pHolder_2',ch=False, r=0.3)[0] setToOrigin(leftMainCurve) setToOrigin(rightMainCurve) # groupFreeze stuff topOffset = grpFreeze(topCtrl) botOffset = grpFreeze(botCtrl) midOffset = grpFreeze(midCtrl) # position things topCtrlPOS = cmds.pointOnSurface(nameFP, ch=False, p=True, u=1, v=0.5) midCtrlPOS = cmds.pointOnSurface(nameFP, ch=False, p=True, u=0.5, v=0.5) botCtrlPOS = cmds.pointOnSurface(nameFP, ch=False, p=True, u=0, v=0.5) cmds.setAttr('{0}.translate'.format(topOffset), *topCtrlPOS ) cmds.setAttr('{0}.translate'.format(midOffset), *midCtrlPOS ) cmds.setAttr('{0}.translate'.format(botOffset), *botCtrlPOS ) midCtrlPOS[2] -= 1.5 cmds.setAttr('{0}.translate'.format(rightMainCurve), *midCtrlPOS ) midCtrlPOS[2] += 3.0 cmds.setAttr('{0}.translate'.format(leftMainCurve), *midCtrlPOS ) midCtrlPOS[2] -= 1.5 # create god ctrl for ribbon mainCtrl = cmds.group(em=True, n='ribbon_main_ctrl') parentShape(rightMainCurve, mainCtrl) parentShape(leftMainCurve, mainCtrl) mainCtrlOffset = grpFreeze(mainCtrl) # point constraint god ctrl freeze grp between top and bot midCtrlPC = cmds.pointConstraint( topCtrl, botCtrl, midOffset, mo=False, w=1) # create bShape for surface bShape = cmds.duplicate(nameFP, n='ribbon_bShape_1')[0] cmds.xform(bShape, ws=True, t=[0,0,5]) bShapeNode = cmds.blendShape(bShape, nameFP, en=1, n='ribbon_blendNode_1') cmds.setAttr('{0}.{1}'.format(bShapeNode[0],bShape), 1) # get POSI position of 0%, 50% and 100% of surface to get wire curve positions cInitPOS = cmds.pointOnSurface(bShape, p=True, top=1, u=0.0, v=0.5) cMidPOS = cmds.pointOnSurface(bShape, p=True, top=1, u=0.5, v=0.5) cEndPOS = cmds.pointOnSurface(bShape, p=True, top=1, u=1, v=0.5) # wire, clusters rWireCurve = cmds.curve( n='ribbon_wire_curve_1', p=[ cInitPOS, cMidPOS, cEndPOS ], d=2, k=[0,0,1,1] ) wireCIn = cmds.cluster('{0}.cv[0:1]'.format(rWireCurve), rel=True, en=1, n='ribbon_wireCL_init_1') wireCMid = cmds.cluster('{0}.cv[1]'.format(rWireCurve), rel=True, en=1, n='ribbon_wireCL_mid_1') wireCEnd = cmds.cluster('{0}.cv[1:2]'.format(rWireCurve), rel=True, en=1, n='ribbon_wireCL_end_1') # cluster pivots and origins cDict = { wireCIn[1] : cInitPOS, wireCMid[1] : cMidPOS, wireCEnd[1] : cEndPOS } for cl, pos in cDict.items(): #print pos cmds.xform(cl, pivots= pos) cmds.setAttr('{0}Shape.origin'.format(cl), *pos) # cluster weights cmds.percent(wireCIn[0], '{0}.cv[1]'.format(rWireCurve), v=0.5 ) cmds.percent(wireCEnd[0], '{0}.cv[1]'.format(rWireCurve), v=0.5 ) # bShape deformers [could also just skin surface to previously created joints..] wireDeformer = cmds.wire(bShape, dds=[(1,25), (0,25)], en=1, ce=0, li=0, w=rWireCurve, n='ribbon_bShape_wireNode_1') twistDeformer = cmds.nonLinear( bShape, type='twist', foc=1, n='ribbon_bShape_twistNode_1') cmds.setAttr('{0}.rotateZ'.format(twistDeformer[1]), 90) cmds.hide(twistDeformer[1]) for attr in rstats: cmds.setAttr('{0}Shape.{1}'.format(bShape, attr), 0) cmds.setAttr('{0}Shape.{1}'.format(nameFP, attr), 0) # connect controls to cluster handles ctrlDict = {topCtrl : wireCEnd[1], midCtrl : wireCMid[1], botCtrl : wireCIn[1] } for ctrl, cl in ctrlDict.items(): cmds.connectAttr('{0}.translate'.format(ctrl), '{0}.translate'.format(cl), f=True ) cmds.connectAttr('{0}.rotateX'.format(botCtrl), '{0}.endAngle'.format(twistDeformer[0]) ) cmds.connectAttr('{0}.rotateX'.format(topCtrl), '{0}.startAngle'.format(twistDeformer[0]) ) # group stuff controlsGrp = cmds.group(em=True, n='ribbon_controls_grp_1') cmds.parent( topOffset, midOffset, botOffset, controlsGrp ) clustersGrp = cmds.group(em=True, n='ribbon_clusters_grp_1') cmds.parent( wireCIn[1], wireCMid[1], wireCEnd[1], clustersGrp ) moveGrp = cmds.group(em=True, n='ribbon_move_grp_1') cmds.parent(controlsGrp, nameFP, moveGrp) extraGrp = cmds.group(em=True, n='ribbon_extras_grp_1') cmds.parent( clustersGrp, locGrp, rWireCurve, '{0}BaseWire'.format(rWireCurve), bShape, twistDeformer[1], extraGrp) godGrp = cmds.group(em=True, n='ribbon_main_grp_1') cmds.parent( extraGrp, mainCtrlOffset, godGrp ) cmds.parent( moveGrp, mainCtrl ) toHideList = [ bShape, rWireCurve, clustersGrp ] for object in toHideList: cmds.hide(object) locators = cmds.listRelatives(locGrp, c=True) for loc in locators: cmds.scaleConstraint(moveGrp, loc, offset=[1,1,1])
def buildDeformers(self, ribbonPlane, controls=(), folGrp=()): # Create a target blendshape controlled by deformers flexiBlend = cmds.duplicate(ribbonPlane, n='flexiPlaneSetup_bShp_surface01') flexiBlendNode = cmds.blendShape(flexiBlend, ribbonPlane, n='%s_bShpNode_surface01' % self.name) # Turn blendshape on cmds.setAttr('%s.%s' % (flexiBlendNode[0], flexiBlend[0]), 1) # Create a wire deformer controled by ribbon controls wireCurve = cmds.curve(n='%s_wire_surface01' % self.name, d=2, p=[(-self.numJnts, 0, 0), (0, 0, 0), (self.numJnts, 0, 0)]) topClstr = cmds.cluster('%s.cv[0:1]' % wireCurve, rel=1, n='%s_cl_a01' % self.name) midClstr = cmds.cluster('%s.cv[1]' % wireCurve, rel=1, n='%s_cl_mid01' % self.name) botClstr = cmds.cluster('%s.cv[1:2]' % wireCurve, rel=1, n='%s_cl_b01' % self.name) clsGrp = cmds.group(topClstr, midClstr, botClstr, n='%s_cls01' % self.name) for attr in ['scalePivot', 'rotatePivot']: cmds.setAttr('%s.%s' % (topClstr[1], attr), -self.numJnts, 0, 0) for attr in ['scalePivot', 'rotatePivot']: cmds.setAttr('%s.%s' % (botClstr[1], attr), self.numJnts, 0, 0) cmds.setAttr('%sShape.originX' % topClstr[1], (-self.numJnts)) cmds.setAttr('%sShape.originX' % botClstr[1], (self.numJnts)) cmds.percent(topClstr[0], '%s.cv[1]' % wireCurve, v=0.5) cmds.percent(botClstr[0], '%s.cv[1]' % wireCurve, v=0.5) # Create twist and wire blend shape deformers twistNode = cmds.nonLinear(flexiBlend, type='twist') cmds.wire(flexiBlend, w=wireCurve, dds=[0, 20], foc=0, n='%s_wireAttrs_surface01' % self.name) cmds.xform(twistNode, ro=(0, 0, 90)) twistNode[0] = cmds.rename(twistNode[0], '%s_twistAttrs_surface01' % self.name) twistNode[1] = cmds.rename(twistNode[1], '%s_twist_surface01' % self.name) # Setup squash and stretch via utilitiy nodes arcLen = cmds.arclen(wireCurve, ch=1) arcLen = cmds.rename(arcLen, '%s_curveInfo01' % self.name) arcLenValue = cmds.getAttr('%s.arcLength' % arcLen) squashDivNode = cmds.createNode('multiplyDivide', n='%s_div_squashStretch_length01' % self.name) volDivNode = cmds.createNode('multiplyDivide', n='%s_div_volume01' % self.name) squashCondNode = cmds.createNode('condition', n='%s_cond_volume01' % self.name) cmds.setAttr('%s.operation' % squashDivNode, 2) cmds.setAttr('%s.input2X' % squashDivNode, arcLenValue) cmds.setAttr('%s.operation' % volDivNode, 2) cmds.setAttr('%s.input1X' % volDivNode, 1) cmds.setAttr('%s.secondTerm' % squashCondNode, 1) cmds.connectAttr('%s.arcLength' % arcLen, '%s.input1X' % squashDivNode) cmds.connectAttr('%s.outputX' % squashDivNode, '%s.input2X' % volDivNode) cmds.connectAttr('%s.outputX' % volDivNode, '%s.colorIfTrueR' % squashCondNode) # Set visibility options for obj in [flexiBlend[0], wireCurve, twistNode[1], clsGrp]: cmds.setAttr('%s.visibility' % obj, 0) # Connect controls to cluster deformers if they exist if len(controls) > 1: topCon = controls[0][0] botCon = controls[0][1] midCon = controls[0][2] for con, clstr in zip([topCon, botCon], [topClstr[1], botClstr[1]]): cmds.connectAttr('%s.translate' % con, '%s.translate' % clstr) cmds.connectAttr('%s.translate' % midCon, '%s.translate' % midClstr[1]) # Connect controls to twist deformer cmds.connectAttr('%s.rotateX' % topCon, '%s.endAngle' % twistNode[0]) cmds.connectAttr('%s.rotateX' % botCon, '%s.startAngle' % twistNode[0]) cmds.connectAttr('%s.volEnable' % controls[1], '%s.firstTerm' % squashCondNode) # Scale contraint each follicle to global move group for fol in cmds.listRelatives(folGrp, c=1): cmds.scaleConstraint(self.moveGrp, fol, mo=0) for shape in cmds.listRelatives(fol, s=1): cmds.setAttr('%s.visibility' % shape, 0) # Parent nodes cmds.parent(flexiBlend, wireCurve, clsGrp, twistNode[1], '%s_wire_surface01BaseWire' % self.name, self.extrasGrp)
def importDeformersByMirroredObject(dagnode, file): # look for the mapping if not os.path.exists(file): rigUtils.log('Skin file not found - skipping: %s' % file) return rigUtils.log('Reading file: %s' % file) f = open(file, 'r') j = json.loads(f.read()) f.close() # get the mirrored object buffer = dagnode.split('_') locus = buffer[0][-1] if locus == 'R': buffer[0] = '%sL' % buffer[0][:-1] mirror = string.join(buffer, '_') elif locus == 'L': buffer[0] = '%sR' % buffer[0][:-1] mirror = string.join(buffer, '_') else: rigUtils.log('Select a valid mesh') return if mirror not in j: rigUtils.log('Mirror object not found in json file: %s' % mirror) return # get the skin cluster on the target object skincluster = rigUtils.findSkinClusterOnNode(dagnode) # step through the deformers of the mirrored object dict = j[mirror] for mirrorDeformer in dict: if mirrorDeformer == 'skinCluster': continue if not cmds.objExists(mirrorDeformer): continue # get the corresponding deformer on the target object buffer = mirrorDeformer.split('_') locus = buffer[0][-1] if locus == 'R': buffer[0] = '%sL' % buffer[0][:-1] deformer = string.join(buffer, '_') elif locus == 'L': buffer[0] = '%sR' % buffer[0][:-1] deformer = string.join(buffer, '_') else: deformer = mirrorDeformer pointdata = dict[mirrorDeformer] set = '%sSet' % deformer # ffd if cmds.objectType(deformer, isType='ffd'): i = 0 while(True): if i == len(pointdata): break if pointdata[i] == '1' and cmds.objExists(set): cmds.sets('%s.vtx[%s]' % (dagnode, i), add=set) i = i + 1 continue # if the corresponding deformer isn't influencing the target object, make it so existingdeformers = mel.eval('findRelatedDeformer "%s"' % dagnode) if not deformer in existingdeformers: if cmds.objExists(set): cmds.sets(dagnode, add=set) # step through each vert and update the weights for the target objects deformer i = 0 while(True): if i == len(pointdata): break value = pointdata[i] cmds.percent(deformer, '%s.vtx[%s]' % (dagnode, i), v=float(value)) i = i + 1 # rearrange the deformers to come before any skincluster if skincluster: cmds.reorderDeformers(skincluster, deformer, dagnode) rigUtils.log('Deformer weighting updated: %s' % deformer)
def __createPanelCtrls(self, baseJnts): """ create controller for panel """ if not(self.lEyeLoc): print "create the face locators" if not cmds.objExists(self.eyelidCrvGrpName): eyeLidCrvGrp = cmds.group(em =1, n = self.eyelidCrvGrpName, p = self.crvGrp) allLidsCtlGrp = [] for ud in self.uploPrefix: for lr in self.prefix: #- left right + upper lower prefix uploPrefix = lr + ud ctlP = uploPrefix + "Ctrl0" kids = cmds.listRelatives(ctlP, ad=True, type ='transform') if kids: cmds.delete(kids) lidJnts = cmds.ls(uploPrefix + self.blinkJntName + "*" + self.jntSuffix, type = 'joint') lidJntsLen = len(lidJnts) #- making lids Ctrl group lidsCtrlGrp = cmds.group(em=True, w =True, n = uploPrefix + self.eyelidName + self.ctlSuffix + self.grpSuffix) cmds.parent(lidsCtrlGrp, ctlP) allLidsCtlGrp.append(lidsCtrlGrp) cntPos = cmds.xform(ctlP, q=1, ws =1, t = 1) #- creating controller if lr == self.prefix[0]: cColor = 6 else: cColor = 17 for pos in ['Center', 'InCorner', 'OutCorner']: lidCtl, lidCtlP = self.circleController(uploPrefix + pos + self.ctlSuffix, 'xy', self.ctlSize * 0.1, color = cColor, lockAttr = ['tz', 'sc', 'ro', 'vi']) cmds.xform(lidCtlP, ws = True, t =(cntPos[0], cntPos[1], cntPos[2])) cmds.parent(lidCtlP, lidsCtrlGrp) if pos == 'InCorner': cmds.setAttr(lidCtl +'.tx', -1) elif pos == 'OutCorner': cmds.setAttr(lidCtl +'.tx', 1) details = [] for i in range(1, lidJntsLen+1): detailCtl = self.circleController(uploPrefix + 'Detail'+ str(i).zfill(2) + self.ctlSuffix, 'xy', self.ctlSize * 0.05, color = cColor, lockAttr = ['tz', 'sc', 'ro', 'vi']) details.append(detailCtl[0]) detailCtlP = detailCtl[1] cmds.parent(detailCtlP, ctlP) increment = 2.0 /(lidJntsLen+1) cmds.setAttr(detailCtlP + ".tx", increment*i - 1.0) cmds.setAttr(detailCtlP + ".ty", 0) cmds.setAttr(detailCtlP + ".tz", 0) #- eyelids controller curve shape(different number of points) tempCtlCrv = cmds.curve(d = 3, p =([0,0,0],[0.33,0,0],[0.66,0,0],[1,0,0])) cmds.rebuildCurve(tempCtlCrv, rt = 0, d = 3, kr = 0, s = 2) lidCtlCrv = cmds.rename(tempCtlCrv, uploPrefix +'Ctl' + self.crvSuffix) cmds.parent(lidCtlCrv, self.eyelidCrvGrpName) ctlCrvCv = cmds.ls(lidCtlCrv + '.cv[*]', fl =True)#!!check same curve exist if Error : list index out of range #- corner twist curves setup(curves for corner Adjust 06/23/2016) cornerCrv = cmds.duplicate(lidCtlCrv, n = uploPrefix +'Corner' + self.crvSuffix) cornerCrvCv = cmds.ls(cornerCrv[0] + '.cv[*]', fl =True) if self.uploPrefix[0] in uploPrefix: inCls = cmds.cluster(cornerCrvCv[0:2], n = uploPrefix[:2] +'inTwistCls') cmds.percent(inCls[0], cornerCrvCv[1], v = 0.3) cmds.parent(inCls, self.eyelidClsGrpName) outCls = cmds.cluster(cornerCrvCv[3:5], n = uploPrefix[:2] +'outTwistCls') cmds.percent(outCls[0], cornerCrvCv[3], v = 0.3) cmds.parent(outCls, self.eyelidClsGrpName) elif self.uploPrefix[1] in uploPrefix: cmds.sets(cornerCrvCv[0:2], add = uploPrefix[:2] +'inTwistClsSet') cmds.percent(uploPrefix[:2] +'inTwistCls', cornerCrvCv[1], v = 0.3) cmds.sets(cornerCrvCv[3:5], add = uploPrefix[:2] +'outTwistClsSet') cmds.percent(uploPrefix[:2] +'outTwistCls', cornerCrvCv[3], v = 0.3) #- corner twist setup(no need to use ClsHandle.rotateZ) cmds.connectAttr(uploPrefix[:2] + self.innerOuter[0] + "LidTwist.tx" , uploPrefix[:2] +'inTwistClsHandle.tx') cmds.connectAttr(uploPrefix[:2] + self.innerOuter[0] + "LidTwist.ty" , uploPrefix[:2] +'inTwistClsHandle.ty') cmds.connectAttr(uploPrefix[:2] + self.innerOuter[1] + "LidTwist.tx" , uploPrefix[:2] +'outTwistClsHandle.tx') cmds.connectAttr(uploPrefix[:2] + self.innerOuter[1] + "LidTwist.ty" , uploPrefix[:2] +'outTwistClsHandle.ty') #- lidCtl drive the center controlPoints on ctlCrv #corner ctls setup cmds.connectAttr(uploPrefix + "InCorner" + self.ctlSuffix + ".ty" , ctlCrvCv[0] + ".yValue") cmds.connectAttr(uploPrefix + "InCorner" + self.ctlSuffix + ".ty" , ctlCrvCv[1] + ".yValue") cmds.setAttr(ctlCrvCv[0] + ".xValue" , lock = True) cmds.setAttr(ctlCrvCv[1] + ".xValue" , lock = True) cmds.connectAttr(uploPrefix + "OutCorner" + self.ctlSuffix + ".ty" , ctlCrvCv[3] + ".yValue") cmds.connectAttr(uploPrefix + "OutCorner" + self.ctlSuffix + ".ty" , ctlCrvCv[4] + ".yValue") cmds.setAttr(ctlCrvCv[3] + ".xValue", lock = True) cmds.setAttr(ctlCrvCv[4] + ".xValue", lock = True) cntAddD = cmds.shadingNode('addDoubleLinear', asUtility=True, n= uploPrefix + "Cnt_AddD") if self.prefix[0] in uploPrefix: #left #- center ctrl.tx drives center point(lidCtl_crv) lCntMult = cmds.shadingNode('multiplyDivide', asUtility=True, n = uploPrefix +'Cnt_mult') cmds.connectAttr(uploPrefix + "Center" + self.ctlSuffix + ".tx", cntAddD + ".input1") cmds.setAttr(cntAddD + ".input2", 0.5) cmds.connectAttr(cntAddD + ".output" , ctlCrvCv[2] + ".xValue") #- center ctrl.ty drives ctlCrv center cv[2].yValue cmds.connectAttr(uploPrefix + "Center" + self.ctlSuffix + ".ty" , lCntMult + ".input1Y") cmds.setAttr(lCntMult + ".input2Y", 2) cmds.connectAttr(lCntMult + ".outputY", ctlCrvCv[2] + ".yValue") if self.prefix[1] in uploPrefix: #right #- center ctrl.tx drives ctlCrv center cv[2].xValue rCntMult = cmds.shadingNode('multiplyDivide', asUtility=True, n = uploPrefix +'Cnt_mult') cmds.connectAttr(uploPrefix + "Center" + self.ctlSuffix + ".tx" , rCntMult + ".input1X") cmds.setAttr(rCntMult + ".input2X", -1) cmds.connectAttr(rCntMult + ".outputX", cntAddD + ".input1") cmds.setAttr(cntAddD + ".input2", 0.5) cmds.connectAttr(cntAddD + ".output" , ctlCrvCv[2] + ".xValue") #center ctrl.ty drives ctlCrv center cv[2].yValue cmds.connectAttr(uploPrefix + "Center" + self.ctlSuffix + ".ty" , rCntMult + ".input1Y") cmds.setAttr(rCntMult + ".input2Y", 2) cmds.connectAttr(rCntMult + ".outputY", ctlCrvCv[2] + ".yValue") detailPCtls = cmds.ls(uploPrefix + "Detail*" + self.grpSuffix, type = 'transform') incrementYPoc = 1.0/(lidJntsLen +1) incrementXPoc = 1.0/(lidJntsLen -1) for i in range(1, lidJntsLen+1): #- POC for positionX on the eyelids ctl curve ctlXPOC = cmds.shadingNode('pointOnCurveInfo', asUtility=True, n = uploPrefix + 'CtlXPoc' + str(i).zfill(2)) cmds.connectAttr(uploPrefix + "Ctl_crvShape.worldSpace", ctlXPOC + '.inputCurve') cmds.setAttr(ctlXPOC + '.turnOnPercentage', 1) cmds.setAttr(ctlXPOC + '.parameter', incrementXPoc *(i-1)) #- POC for positionY on the eyelids ctl curve ctlYPOC = cmds.shadingNode('pointOnCurveInfo', asUtility=True, n = uploPrefix + 'CtlYPoc' + str(i).zfill(2)) cmds.connectAttr(uploPrefix + "Ctl_crvShape.worldSpace", ctlYPOC + '.inputCurve') cmds.setAttr(ctlYPOC + '.turnOnPercentage', 1) cmds.setAttr(ctlYPOC + '.parameter', incrementYPoc *i) #- POC on ctlCrv drive detail control parent cntRemoveX = cmds.shadingNode('addDoubleLinear', asUtility=True, n= uploPrefix +"RemoveX"+ str(i).zfill(2)) momMult = cmds.shadingNode('multiplyDivide', asUtility=True, n = uploPrefix +'Mom'+ str(i).zfill(2)+'_mult') cmds.connectAttr(ctlYPOC +".positionY", detailPCtls[i-1] + ".ty") #- Xvalue match between POC and CtrlP(detailPCtls[i] = 2*ctlPoc -1) cmds.connectAttr(ctlXPOC +".positionX", momMult + ".input1X") cmds.setAttr(momMult + ".input2X", 2) cmds.connectAttr(momMult + ".outputX", cntRemoveX + ".input1") cmds.setAttr(cntRemoveX + ".input2", -1) cmds.connectAttr(cntRemoveX +".output", detailPCtls[i-1] + ".tx") #- curves for corner Adjust 06/23/2016 cornerPOC = cmds.shadingNode('pointOnCurveInfo', asUtility=True, n = uploPrefix + 'CornerPoc' + str(i).zfill(2)) cmds.connectAttr(uploPrefix +"Corner" + self.crvSuffix + ".worldSpace", cornerPOC + '.inputCurve') cmds.setAttr(cornerPOC + '.turnOnPercentage', 1) cmds.setAttr(cornerPOC + '.parameter', incrementXPoc*(i-1))
def nmpWrapToJoints(): ''' Main Function for Extracting the Wrap Weights to Each Joint ''' # Query Selected Geo with Wrap Deformer --- Get Geo Verts objects = cmds.ls(sl=True, flatten=True) if not objects: raise Exception, 'Please Select Geometry' sourceVerts = [] geoNames = [] # Separate SourceVerts from Wrapped Geos for obj in objects: if '.vtx' in obj: sourceVerts.append(obj) else: geoNames.append(obj) #---------------------------------------------------------------------------------------- # Check for Wrap Deformer --- Retrieve Source Geo from Wrap wraps = [] for geoName in geoNames: geoHistory = cmds.listHistory(geoName) wrap = cmds.ls(geoHistory, type='wrap') destSkinCluster = nmpGetSkinFromGeo(geoName) if destSkinCluster: cmds.delete(destSkinCluster) if wrap: wraps.append(wrap[0]) else: raise Exception, 'No Wrap Deformer Found on ' + geoName sourceGeo = cmds.connectionInfo(wraps[0] + '.inflType[0]', sfd=True).split('.')[0] # If SourceGeo Wasn't Found Try Nurbs Surface Connection if not sourceGeo: sourceGeoShape = cmds.connectionInfo(wraps[0] + '.driverPoints[0]', sfd=True).split('.')[0] sourceGeo = cmds.listRelatives(sourceGeoShape, p=True)[0] sourceVerts = cmds.ls(sourceGeo + '.cv[*]', flatten=True) #---------------------------------------------------------------------------------------- # Get SkinCluster + Joints of SourceGeo indexes = [] joints = [] sourceSkinCluster = '' try: sourceSkinCluster = nmpGetSkinFromGeo(sourceGeo) except: raise Exception, 'No SkinCluster Found on Source Geometry' nmpHoldUnholdInfluences(sourceSkinCluster) joints = cmds.skinCluster(sourceSkinCluster, q=True, inf=True) # If Source Verts Were Selected -> Find Out Which Joints are Affecting those Verts Only to Increase Speed if sourceVerts: weightedJoints = [] for vert in sourceVerts: valuesAll = cmds.skinPercent(sourceSkinCluster, vert, q=True, v=True) values = cmds.skinPercent(sourceSkinCluster, vert, q=True, v=True, ib=.0001) indexes = [ valuesAll.index(value) for value in values if value ] for i in indexes: if joints[i] not in weightedJoints: weightedJoints.append( joints[i] ) #print 'Weighted Joints = ' + str(weightedJoints) indexes = [ joints.index(joint) for joint in weightedJoints ] joints = weightedJoints else: sourceVerts = cmds.ls(sourceGeo + '.vtx[*]', flatten=True) indexes = [ i for i in range(len(joints)) ] # Create A Cluster for Every Joint/Influence Object clusters, clusterHandles = [], [] for joint in joints: cluster, clusterHan = cmds.cluster(sourceVerts) worldPos = cmds.xform(joint, q=True, ws=True, rp=True) cmds.xform(clusterHan, ws=True, rp=worldPos) cmds.setAttr(clusterHan + '.origin', worldPos[0],worldPos[1], worldPos[2]) clusters.append(cluster) clusterHandles.append(clusterHan) length = len(sourceVerts) amount = 0 cmds.progressWindow(title='Transferring Wrap Weights', progress=amount, status='Retrieving Joint Weights', isInterruptable=True ) #---------------------------------------------------------------------------------------- # Retrieve Joint Weights for Each Vert --> apply Those to each corresponding Cluster for a,vert in enumerate(sourceVerts): values = cmds.skinPercent(sourceSkinCluster, vert, q=True, v=True) for i,cluster in enumerate(clusters): cmds.percent(cluster, vert, v=values[indexes[i]]) if cmds.progressWindow( query=True, isCancelled=True ) : break amount = int( str( a/float(length) * 100 ).split('.')[0] ) cmds.progressWindow( edit=True, progress=amount, status=('Retrieving Joint Weights: ' + `amount` + '%' ) ) #---------------------------------------------------------------------------------------- # Check Each Joint in Source SkinCluster ---> Separate by type Joints and Influence Objects bindJoints = [] influenceObjects = [] for joint in joints: if cmds.nodeType(joint) == 'joint': bindJoints.append(joint) else: influenceObjects.append(joint) if not bindJoints: bindJoints.append( cmds.joint(p=[0,0,0], n='nmpTempJoint') ) # Iterate Through Each Piece of Wrapped Geo --> Assign Skin Weights for i,geoName in enumerate(geoNames): destSkinCluster = cmds.skinCluster(bindJoints, geoName)[0] # Add Influence Objects To SkinCluster if They Exist in sourceSkinCluster if influenceObjects: cmds.skinCluster(destSkinCluster, e=True, ai=influenceObjects) # Get Weights for Each Joint - Return Value Per Cluster = [ [joint, distance], [joint, distance], ....... ] length = len(clusterHandles) amount = 0 cmds.progressWindow(e=True, progress=amount, status= 'Calculating Wrap Weights...', isInterruptable=True ) values = [] for i,clusterHan in enumerate(clusterHandles): values.append( nmpExtractWeights(clusterHan, joints[i], destSkinCluster, geoName) ) if cmds.progressWindow( query=True, isCancelled=True ) : break amount = int( str( i/float(length) * 100 ).split('.')[0] ) cmds.progressWindow( edit=True, progress=amount, status=('Calculating Wrap Weights : %s...' % geoName + `amount` + '%' ) ) #---------------------------------------------------------------------------------------- # Create List of Lists of Each Verts weights --- [ [transform, value] ] --- Reduces Amount of skinPercent Calls vertWeights = [ ] verts = cmds.ls(geoName + '.vtx[*]', flatten=True) for i in range( len(verts) ): appendObj = [] for i2 in range( len(values) ): appendObj.append( [ values[i2][0][0], values[i2][i][1] ]) vertWeights.append(appendObj) length = len(verts) amount = 0 cmds.progressWindow(e=True, progress=amount, status='Assigning Weights: ' + geoName, isInterruptable=True ) # Clear All Weights to Avoid "Greater Than 1.0 Weight" Error cmds.setAttr(destSkinCluster + '.normalizeWeights', 0) cmds.skinPercent(destSkinCluster, geoName, pruneWeights=1.0 ) #---------------------------------------------------------------------------------------- # Assign SkinWeights for i,vert in enumerate(verts): cmds.skinPercent(destSkinCluster, vert, tv=vertWeights[i] ) if cmds.progressWindow( query=True, isCancelled=True ) : break amount = int( str( i/float(length) * 100 ).split('.')[0] ) cmds.progressWindow( edit=True, progress=amount, status=('Assigning Weights: ' + geoName + ' ' + `amount` + '%' ) ) # Prune off any small excess weighting that normalizeing missed cmds.setAttr(destSkinCluster + '.normalizeWeights', 1) cmds.skinPercent(destSkinCluster, geoName, pruneWeights=.005 ) cmds.delete(clusters, clusterHandles, wraps) try: cmds.delete('nmpTempJoint') except: pass cmds.progressWindow(endProgress=1) #---------------------------------------------------------------------------------------- print 'Wrap Weights Transfered !!!',
def buildStickyLips(cls, *args): ''' Main method. ''' # Duplicate geometry oriGeo = cls.upperLipEdges[0].rsplit('.e')[0] logger.debug('Geometry Name: %s' % oriGeo) dupGeo = cmds.duplicate(oriGeo, n=oriGeo + '_stickyLipsSrcCrv_geo')[0] cmds.select(dupGeo, r=True) tak_cleanUpModel.delHis() tak_cleanUpModel.delInterMediObj() cmds.select(oriGeo, dupGeo, r=True) tak_misc.TransSkinWeights() # Convert polygon edges to curves dupGeoUpperEdges = cls.rplcStrInList(cls.upperLipEdges, oriGeo, dupGeo) cmds.select(dupGeoUpperEdges, r=True) upperLipCrv = mel.eval('polyToCurve -form 2 -degree 3;') upperLipCrv = cmds.rename(upperLipCrv[0], 'upper_lip_sticky_crv') dupGeoLowerEdges = cls.rplcStrInList(cls.lowerLipEdges, oriGeo, dupGeo) cmds.select(dupGeoLowerEdges, r=True) lowerLipCrv = mel.eval('polyToCurve -form 2 -degree 3;') lowerLipCrv = cmds.rename(lowerLipCrv[0], 'lower_lip_sticky_crv') # Create sticky lips curve stickyLipsCrv = cmds.duplicate(upperLipCrv, n='stickyLips_crv')[0] stickyLipsCrvShp = cmds.listRelatives(stickyLipsCrv, s=True)[0] upperLipCrvShp = cmds.listRelatives(upperLipCrv, s=True)[0] lowerLipCrvShp = cmds.listRelatives(lowerLipCrv, s=True)[0] avgCrvNode = cmds.createNode('avgCurves', n='stickyLips_avgCurve') cmds.setAttr('%s.automaticWeight' % avgCrvNode, 0) cmds.setAttr('%s.normalizeWeights' % avgCrvNode, 0) cmds.connectAttr('%s.worldSpace[0]' % upperLipCrvShp, '%s.inputCurve1' % avgCrvNode) cmds.connectAttr('%s.worldSpace[0]' % lowerLipCrvShp, '%s.inputCurve2' % avgCrvNode) cmds.connectAttr('%s.outputCurve' % avgCrvNode, '%s.create' % stickyLipsCrvShp) # Grouping stklGrp = cmds.createNode('transform', n='stickyLips_grp') cmds.parent(dupGeo, upperLipCrv, lowerLipCrv, stickyLipsCrv, stklGrp) cmds.setAttr('%s.visibility' % stklGrp, 0) # Assign wire deformer to the geometry wire = cmds.wire(oriGeo, w=stickyLipsCrv)[0] cmds.setAttr('%s.scale[0]' % wire, 0) cmds.setAttr('%s.envelope' % wire, 2) cmds.setAttr('%s.envelope' % wire, lock=True) cmds.connectAttr('%s.outputCurve' % avgCrvNode, '%sBaseWireShape.create' % stickyLipsCrv) # Weighting vtxNumber = cmds.polyEvaluate(oriGeo, vertex=True) cmds.percent(wire, '%s.vtx[0:%d]' % (oriGeo, vtxNumber - 1), v=0) wireVtxList = cmds.polyListComponentConversion(cls.upperLipEdges, cls.lowerLipEdges, tv=True) cmds.percent(wire, wireVtxList, v=1)
def createRibbon(*args): #Gather information width = cmds.floatField('widthField', query=True, value=True) numJoints = cmds.intField('jointsField', query=True, value=True) prefix = cmds.textField('prefixField', query=True, text=True) scaleGrp = cmds.textField('scaleGrpField', query=True, text=True) topPoint = (width/2) endPoint = (width/2*-1) #Create the main groups grpNoTransform = cmds.group(empty=True, name=(prefix + 'noTransform_grp')) grpTransform = cmds.group(empty=True, name=(prefix + 'transform_grp')) grpCtrl = cmds.group(empty=True, name=(prefix + 'ctrl_grp'), parent=grpTransform) grpSurface = cmds.group(empty=True, name=(prefix + 'surface_grp'), parent=grpTransform) grpSurfaces = cmds.group(empty=True, name=(prefix + 'surfaces_grp'), parent=grpNoTransform) grpDeformers = cmds.group(empty=True, name=(prefix + 'deformer_grp'), parent=grpNoTransform) grpFollMain = cmds.group(empty=True, name=(prefix + 'follicles_skin_grp'), parent=grpNoTransform) grpFollVolume = cmds.group(empty=True, name=(prefix + 'follicles_volume_grp'), parent=grpNoTransform) grpCluster = cmds.group(empty=True, name=(prefix + 'cluster_grp'), parent=grpNoTransform) grpMisc = cmds.group(empty=True, name=(prefix + 'misc_grp'), parent=grpNoTransform) #Create a NURBS-plane to use as a base tmpPlane = cmds.nurbsPlane(axis=(0,1,0), width=width, lengthRatio=(1.0 / width), u=numJoints, v=1, degree=3, ch=0)[0] #Create the NURBS-planes to use in the setup geoPlane = cmds.duplicate(tmpPlane, name=(prefix + 'geo')) geoPlaneTwist = cmds.duplicate(tmpPlane, name=(prefix + 'twist_blnd_geo')) geoPlaneSine = cmds.duplicate(tmpPlane, name=(prefix + 'sine_blnd_geo')) geoPlaneWire = cmds.duplicate(tmpPlane, name=(prefix + 'wire_blnd_geo')) geoPlaneVolume = cmds.duplicate(tmpPlane, name=(prefix + 'volume_geo')) #Offset the volume-plane cmds.setAttr((geoPlaneVolume[0] + '.translateZ'), -0.5) #Delete the base surface cmds.delete(tmpPlane) #Create the controllers ctrlTop = createCurveCtrl(name=(prefix + 'top_ctrl'), freezeTransforms=1, color=9, pos=(topPoint,0,0)) ctrlMid = createCurveCtrl(name=(prefix + 'mid_ctrl'), freezeTransforms=1, color=9, pos=(0,0,0)) ctrlEnd = createCurveCtrl(name=(prefix + 'end_ctrl'), freezeTransforms=1, color=9, pos=(endPoint,0,0)) #Group the controllers grpTop = grpObject(objects=[ctrlTop], snapTrans=1, keepTransforms=0, keepHi=1, empty=0, suffix='_grp')[0] grpMid = grpObject(objects=[ctrlMid], snapTrans=1, keepTransforms=0, keepHi=1, empty=0, suffix='_grp')[0] grpEnd = grpObject(objects=[ctrlEnd], snapTrans=1, keepTransforms=0, keepHi=1, empty=0, suffix='_grp')[0] #PointConstraint the midCtrl between the top/end midConst = cmds.pointConstraint(ctrlTop, ctrlEnd, grpMid) #Add attributes: Twist/Roll attributes addAttribute(objects=[ctrlTop,ctrlMid,ctrlEnd],longName=['twistSep'],niceName=['---------------'],at="enum",en='Twist',lock=1,k=True) addAttribute(objects=[ctrlTop,ctrlEnd],longName=['twist'],at="float",k=True) addAttribute(objects=[ctrlTop,ctrlEnd],longName=['twistOffset'],at="float",k=True) addAttribute(objects=[ctrlTop,ctrlEnd],longName=['affectToMid'],at="float",min=0, max=10,dv=10,k=True) addAttribute(objects=[ctrlMid],longName=['roll'],at="float",k=True) addAttribute(objects=[ctrlMid],longName=['rollOffset'],at="float",k=True) #Add attributes: Volume attributes addAttribute(objects=[ctrlMid],longName=['volumeSep'],niceName=['---------------'],at="enum",en='Volume',lock=1,k=True) addAttribute(objects=[ctrlMid],longName=['volume'],at="float",min=-1,max=1,k=True) addAttribute(objects=[ctrlMid],longName=['volumeMultiplier'],at="float",min=1,dv=3,k=True) addAttribute(objects=[ctrlMid],longName=['startDropoff'],at="float",min=0, max=1, dv=1,k=True) addAttribute(objects=[ctrlMid],longName=['endDropoff'],at="float",min=0, max=1, dv=1, k=True) addAttribute(objects=[ctrlMid],longName=['volumeScale'],at="float",min=endPoint*0.9, max=topPoint*2,k=True) addAttribute(objects=[ctrlMid],longName=['volumePosition'],min=endPoint,max=topPoint,at="float",k=True) #Add attributes: Sine attributes addAttribute(objects=[ctrlMid], longName=['sineSep'], niceName=['---------------'], attributeType='enum', en="Sine:", keyable=True, lock=1) addAttribute(objects=[ctrlMid], longName=['amplitude'], attributeType="float", keyable=True) addAttribute(objects=[ctrlMid], longName=['offset'], attributeType="float", keyable=True) addAttribute(objects=[ctrlMid], longName=['twist'], attributeType="float", keyable=True) addAttribute(objects=[ctrlMid], longName=['sineLength'], min=0.1, dv=2, attributeType="float", keyable=True) #Add attributes: Extra attributes addAttribute(objects=[ctrlMid],longName=['extraSep'],niceName=['---------------'],at="enum",en='Extra',lock=1,k=True) addAttribute(objects=[ctrlMid],longName=['showExtraCtrl'],at="enum",en='Hide:Show:',k=True) cmds.setAttr((ctrlMid + '.showExtraCtrl'), 1) #Create deformers: Twist deformer, Sine deformer, Squash deformer twistDef = nonlinearDeformer(objects=[geoPlaneTwist[0]], defType='twist', name=geoPlaneTwist[0], lowBound=-1, highBound=1, rotate=(0,0,90)) sineDef = nonlinearDeformer(objects=[geoPlaneSine[0]], defType='sine', name=geoPlaneSine[0], lowBound=-1, highBound=1, rotate=(0,0,90)) squashDef = nonlinearDeformer(objects=[geoPlaneVolume[0]], defType='squash', name=geoPlaneVolume[0], lowBound=-1, highBound=1, rotate=(0,0,90)) cmds.setAttr((sineDef[0] + '.dropoff'), 1) #Create deformers: Wire deformer deformCrv = cmds.curve(p=[(topPoint,0,0),(0,0,0),(endPoint,0,0)], degree=2) deformCrv = cmds.rename(deformCrv, (prefix + 'ribbon_wire_crv')) wireDef = cmds.wire(geoPlaneWire, dds=(0,15), wire=deformCrv) wireDef[0] = cmds.rename(wireDef[0], (geoPlaneWire[0] + '_wire')) #Create deformers: Clusters clsTop = cmds.cluster((deformCrv + '.cv[0:1]'), relative=1) clsMid = cmds.cluster((deformCrv + '.cv[1]'), relative=1) clsEnd = cmds.cluster((deformCrv + '.cv[1:2]'), relative=1) clsTop[0] = cmds.rename(clsTop[0], (ctrlTop + '_top_cluster')) clsTop[1] = cmds.rename(clsTop[1], (ctrlTop + '_top_clusterHandle')) clsMid[0] = cmds.rename(clsMid[0], (ctrlMid + '_mid_cluster')) clsMid[1] = cmds.rename(clsMid[1], (ctrlMid + '_mid_clusterHandle')) clsEnd[0] = cmds.rename(clsEnd[0], (ctrlEnd + '_end_cluster')) clsEnd[1] = cmds.rename(clsEnd[1], (ctrlEnd + '_end_clusterHandle')) cmds.setAttr((cmds.listRelatives(clsTop[1], type="shape")[0] + '.originX'), topPoint) cmds.setAttr((cmds.listRelatives(clsEnd[1], type="shape")[0] + '.originX'), endPoint) setPivot(objects=[clsTop[1]], rotatePivot=1, scalePivot=1, pivot=(topPoint,0,0)) setPivot(objects=[clsEnd[1]], rotatePivot=1, scalePivot=1, pivot=(endPoint,0,0)) cmds.percent(clsTop[0], (deformCrv + '.cv[1]'), v=0.5) cmds.percent(clsEnd[0], (deformCrv + '.cv[1]'), v=0.5) posTopPma = cmds.shadingNode('plusMinusAverage', asUtility=1, name = (prefix + 'top_ctrl_pos_pma')) cmds.connectAttr((ctrlTop + '.translate'), (posTopPma + '.input3D[0]')) cmds.connectAttr((grpTop + '.translate'), (posTopPma + '.input3D[1]')) posEndPma = cmds.shadingNode('plusMinusAverage', asUtility=1, name = (prefix + 'end_ctrl_pos_pma')) cmds.connectAttr((ctrlEnd + '.translate'), (posEndPma + '.input3D[0]')) cmds.connectAttr((grpEnd + '.translate'), (posEndPma + '.input3D[1]')) cmds.connectAttr((posTopPma + '.output3D'), (clsTop[1] + '.translate')) cmds.connectAttr((ctrlMid + '.translate'), (clsMid[1] + '.translate')) cmds.connectAttr((posEndPma + '.output3D'), (clsEnd[1] + '.translate')) #Create deformers: Blendshape blndDef = cmds.blendShape(geoPlaneWire[0], geoPlaneTwist[0], geoPlaneSine[0], geoPlane[0], name=(prefix + 'blendShape'),weight=[(0,1),(1,1),(2,1)]) #Twist deformer: Sum the twist and the roll sumTopPma = cmds.shadingNode('plusMinusAverage', asUtility=1, name = (prefix + 'twist_top_sum_pma')) cmds.connectAttr((ctrlTop + '.twist'), (sumTopPma + '.input1D[0]')) cmds.connectAttr((ctrlTop + '.twistOffset'), (sumTopPma + '.input1D[1]')) cmds.connectAttr((ctrlMid + '.roll'), (sumTopPma + '.input1D[2]')) cmds.connectAttr((ctrlMid + '.rollOffset'), (sumTopPma + '.input1D[3]')) cmds.connectAttr((sumTopPma + '.output1D'), (twistDef[0] + '.startAngle')) sumEndPma = cmds.shadingNode('plusMinusAverage', asUtility=1, name = (prefix + 'twist_low_sum_pma')) cmds.connectAttr((ctrlEnd + '.twist'), (sumEndPma + '.input1D[0]')) cmds.connectAttr((ctrlEnd + '.twistOffset'), (sumEndPma + '.input1D[1]')) cmds.connectAttr((ctrlMid + '.roll'), (sumEndPma + '.input1D[2]')) cmds.connectAttr((ctrlMid + '.rollOffset'), (sumEndPma + '.input1D[3]')) cmds.connectAttr((sumEndPma + '.output1D'), (twistDef[0] + '.endAngle')) #Twist deformer: Set up the affect of the deformer topAffMdl = cmds.shadingNode('multDoubleLinear', asUtility=1, name = (prefix + 'twist_top_affect_mdl')) cmds.setAttr((topAffMdl + '.input1'), -0.1) cmds.connectAttr((ctrlTop + '.affectToMid'), (topAffMdl + '.input2')) cmds.connectAttr((topAffMdl + '.output'), (twistDef[0] + '.lowBound')) endAffMdl = cmds.shadingNode('multDoubleLinear', asUtility=1, name = (prefix + 'twist_end_affect_mdl')) cmds.setAttr((endAffMdl + '.input1'), 0.1) cmds.connectAttr((ctrlEnd + '.affectToMid'), (endAffMdl + '.input2')) cmds.connectAttr((endAffMdl + '.output'), (twistDef[0] + '.highBound')) #Squash deformer: Set up the connections for the volume control volumeRevfMdl = cmds.shadingNode('multDoubleLinear', asUtility=1, name = (prefix + 'volume_reverse_mdl')) cmds.setAttr((volumeRevfMdl + '.input1'), -1) cmds.connectAttr((ctrlMid + '.volume'), (volumeRevfMdl + '.input2')) cmds.connectAttr((volumeRevfMdl + '.output'), (squashDef[0] + '.factor')) cmds.connectAttr((ctrlMid + '.startDropoff'), (squashDef[0] + '.startSmoothness')) cmds.connectAttr((ctrlMid + '.endDropoff'), (squashDef[0] + '.endSmoothness')) cmds.connectAttr((ctrlMid + '.volumePosition'), (squashDef[1] + '.translateX')) #Squash deformer: Set up the volume scaling sumScalePma = cmds.shadingNode('plusMinusAverage', asUtility=1, name = (prefix + 'volume_scale_sum_pma')) cmds.setAttr((sumScalePma + '.input1D[0]'), topPoint) cmds.connectAttr((ctrlMid + '.volumeScale'), (sumScalePma + '.input1D[1]')) cmds.connectAttr((sumScalePma + '.output1D'), (squashDef[1] + '.scaleY')) #Sine deformer: Set up the connections for the sine cmds.connectAttr((ctrlMid + '.amplitude'), (sineDef[0] + '.amplitude')) cmds.connectAttr((ctrlMid + '.offset'), (sineDef[0] + '.offset')) cmds.connectAttr((ctrlMid + '.twist'), (sineDef[1] + '.rotateY')) cmds.connectAttr((ctrlMid + '.sineLength'), (sineDef[0] + '.wavelength')) #Cleanup: Hierarchy cmds.parent(geoPlaneWire[0], geoPlaneTwist[0], geoPlaneSine[0], geoPlaneVolume[0], grpSurfaces) cmds.parent(twistDef[1], sineDef[1], squashDef[1], grpDeformers) cmds.parent(clsTop[1], clsMid[1], clsEnd[1], grpCluster) cmds.parent(grpTop, grpMid, grpEnd, grpCtrl) cmds.parent(geoPlane[0], grpSurface) cmds.parent(deformCrv, (cmds.listConnections(wireDef[0] + '.baseWire[0]')[0]), grpMisc) #Cleanup: Visibility cmds.hide(grpSurfaces, grpDeformers, grpCluster, grpMisc) for x in cmds.listConnections(ctrlMid): cmds.setAttr((x + '.isHistoricallyInteresting'), 0) for y in cmds.listConnections(x): cmds.setAttr((y + '.isHistoricallyInteresting'), 0) #Update the scale-group scaleGrp = scaleGrp if scaleGrp else grpTransform #Create follicles: The main-surface and the volume-surface for x in range(0, numJoints): #Declare a variable for the current index num = str(x + 1) #Get the normalized position of where to place the current follicle uVal = ((0.5 / numJoints) * (x + 1) * 2) - ((0.5 / (numJoints * 2)) * 2) #Create a follicle for the bind-plane and the volume-plane follicleS = createFollicle(scaleGrp=scaleGrp, inputSurface=cmds.listRelatives(geoPlane[0], type="shape"), uVal=uVal, name=(prefix + num + '_follicle')) follicleV = createFollicle(scaleGrp=None, inputSurface=cmds.listRelatives(geoPlaneVolume[0], type="shape"), uVal=uVal, vVal=0, name=(prefix + num + '_volume_follicle')) cmds.parent(follicleS[0], grpFollMain) cmds.parent(follicleV[0], grpFollVolume) #Create a joint, controller and a group for the current skin-follicle cmds.select(clear=True) follicleJoint = cmds.joint(name=(prefix + num + '_jnt'), radius=0.1) follicleCtrl = cmds.circle(name=(prefix + num + '_ctrl'), c=(0,0,0), nr=(1,0,0), sw=360, r=0.5, d=3, s=8, ch=0)[0] follicleXform = cmds.group(name=(prefix + num + '_xform_grp'), empty=True) cmds.parent(follicleXform, follicleS[0]) cmds.parent(follicleCtrl, follicleXform) cmds.parent(follicleJoint, follicleCtrl) cmds.delete(cmds.parentConstraint(follicleS[0], follicleXform)) #Set the color and connect the visibility-switch for the controller cmds.setAttr((cmds.listRelatives(follicleCtrl, shapes=True)[0] + '.overrideEnabled'), 1) cmds.setAttr((cmds.listRelatives(follicleCtrl, shapes=True)[0] + '.overrideColor'), 12) cmds.connectAttr((ctrlMid + '.showExtraCtrl'), (cmds.listRelatives(follicleCtrl, shapes=True)[0] + '.visibility')) #Make the connections for the volume multMpd = cmds.shadingNode('multiplyDivide', asUtility=1, name = (prefix + num + '_multiplier_mpd')) cmds.connectAttr((ctrlMid + '.volumeMultiplier'), (multMpd + '.input1Z')) cmds.connectAttr((follicleV[0] + '.translate'), (multMpd + '.input2')) sumPma = cmds.shadingNode('plusMinusAverage', asUtility=1, name = (prefix + num + '_volume_sum_pma')) cmds.connectAttr((multMpd + '.outputZ'), (sumPma + '.input1D[0]')) cmds.setAttr((sumPma + '.input1D[1]'), 1) cmds.connectAttr((sumPma + '.output1D'), (follicleXform + '.scaleY')) cmds.connectAttr((sumPma + '.output1D'), (follicleXform + '.scaleZ'))