def createBlendNode(self): files = cmds.getFileList(folder=PATH_OF_FILES, filespec="*.{}".format(FILE_TYPE)) if files: for x in files: cmds.file(PATH_OF_FILES + "/" + x, i=True, defaultNamespace=True) else: cmds.warning("No files found") print ("------------complete-faceShape-imports--------------") cmds.file(HEAD_PATH, i=True, defaultNamespace=True) pm.rename(NEUTRAL, "bsMan_fRig_PLY") fShapes = [] for x in files: item = x.split(".") fShapes.append(item[0]) pm.select(fShapes) pm.blendShape(fShapes, "bsMan_fRig_PLY", name="faceShapes_BSN") pm.delete(fShapes) print ("------------complete---blending-Of-faceShapes--------------") pm.select(clear=True) pm.select("bsMan_fRig_PLY") cmds.file(OUT_BLEND_PATH + "\\" + BSMAN_NAME, type="mayaAscii", force=True, exportSelected=True) print ("------------complete---exporting-Of-blendNode--------------") pm.delete("bsMan_fRig_PLY")
def save_as_BS() : print u"\n- - - 現在の形状をブレンドシェイプとして保存 - - -" start = time.time() blender2 = "blendLap" dup_name = "expression_" + str( int(pm.currentTime(q = 1)) ) base = pm.PyNode("base") base_dup = pm.duplicate(base, n = dup_name) # ブレンドシェイプとして追加:とりあえず別なセットに。 shape_initialization() # ここが重い if not pm.objExists(blender2) : pm.select(base_dup) pm.select(base, add = 1) pm.blendShape(n = blender2) else : print base_name print dup_name print blender2 index = len( pm.getAttr(pm.PyNode(blender2).w) ) pm.blendShape(blender2, e=True, t=(base_name, index+1, dup_name , 1),) pm.delete(base_dup) print "[time] ", time.time() - start
def addTargets(sourceObj=None, splittedTargets=list()): firstIndex = 0 bsNode = getBlendShapeNode(sourceObj) if bsNode: appliedTargetNames = pm.listAttr(bsNode.w, m=True) firstIndex = nextFreeIndex(bsNode) for i, target in enumerate(splittedTargets): if target.name() in appliedTargetNames: delete_blendshape_target(bsNode.name(), getIndexByName(bsNode, target.name())) pm.aliasAttr(bsNode.name() + '.' + target.name(), rm=True) pm.blendShape(bsNode, edit=True, t=(sourceObj.name(), i + firstIndex, target.name(), 1.0)) print('reapplying target{1} index {0}'.format( i + firstIndex, target.name())) pm.delete(splittedTargets) else: firstIndex = 0 pm.blendShape(splittedTargets, sourceObj) pm.delete(splittedTargets) return firstIndex
def _create_deformers_(self): # Setup missing geo shapes dictionary missing_shapes = {} # Build in the order of blendshapes for blendshape in libXml.list_persist(self.import_data["Order"]): # Check if the blendshapes exists. If so create one. shapes = libXml.list_persist(self.import_data["Data"][blendshape]) if not pm.objExists(blendshape): # Read info for each blendshape # select select the shapes. pm.select(cl=1) for shape in shapes: # Check the shape exists if pm.objExists(shape): # Add to the selection pm.select(shape, add=1) else: # If not then then add to error list dictionary if missing_shapes.has_key(blendshape): missing_shapes[blendshape].append(shape) else: missing_shapes[blendshape] = [shape] # Select the target geo and create blendshape pm.select(self.target, add=1) pm.blendShape(name=blendshape) if len(missing_shapes): print "#######The following blends had missing shapes#######" for key in missing_shapes.keys(): print key.upper() libUtilities.print_list(missing_shapes[key])
def cbsHookup(*args, **kwargs): base = kwargs.setdefault('base') #(string) The base mesh for the character bs = kwargs.setdefault('bs') #(string) The blendshape deformer to which the shape should be added (if blank, a new deformer will be created shape = kwargs.setdefault('shape') #(string) The new target to add to the blendshape driver = kwargs.setdefault('driver') #(string) Node and attribute to have drive the blendshape target weight driveRange = kwargs.setdefault('driveRange', [0, 1]) #(2 float list) The range of the driver to go from 0-1. [0]=target weight of 0, [1]=weight of 1 tan = kwargs.setdefault('tan', ['spline', 'spline']) # (2 string list) The tangent types for the set driven keys. [0]=start, [1]=end infinity = kwargs.setdefault('infinity', [False, False]) # (2 bool list) sets whether or not to give the set driven key pre or post infinity. [0]=pre, [1]=post #create a blendshape deformer if one hasn't been specified if not bs: bs = pm.blendShape(base, frontOfChain=True, n='%s_corrective_bs'%base)[0] #add the new target to the blendshape targs = pm.blendShape(bs, q=True, t=True) for targ in targs: if str(shape).split('|')[-1] == str(targ).split('|')[-1]: pm.error('It appears you already have a blendshape target named %s in the node %s. Please rename the new target with a unique name.'%(shape, bs)) pm.blendShape(bs, e=True, t=[base, len(targs), shape, 1]) #set up the set driven key to drive the blendshape pm.setDrivenKeyframe('%s.%s'%(bs, shape), cd=driver, dv=driveRange[0], v=0, itt=tan[0], ott=tan[0]) pm.setDrivenKeyframe('%s.%s'%(bs, shape), cd=driver, dv=driveRange[1], v=1, itt=tan[1], ott=tan[1]) #set up infinity if requested if infinity[0]: pm.setInfinity('%s.%s'%(bs, shape), pri='linear') if infinity[1]: pm.setInfinity('%s.%s'%(bs, shape), poi='linear') return bs
def connectWithBlendshape(mesh, bst, wgt=1.0): """Connect 2 geometries using blendshape node Args: mesh (PyNode): The Object to apply the blendshape target bst (PyNode): The Blendshape target wgt (float, optional): Description Returns: PyNode: The blenshape node """ if isinstance(mesh, string_types): mesh = pm.PyNode(mesh) if isinstance(bst, string_types): bst = pm.PyNode(bst) bsnode = getBlendShape(mesh) if bsnode: wc = pm.blendShape(bsnode, q=True, wc=True) pm.blendShape(bsnode, edit=True, t=(mesh, wc, bst, 1.0)) bsnode.attr(bst.name()).set(wgt) bs = bsnode else: bs = pm.blendShape(bst, mesh, name="_".join([mesh.name(), "blendShape"]), foc=True, w=[(0, 1.0)]) return bs
def add_upper_deformers(self, target, layers_to_add =[], ): """ Add lower layer deformation as blendshapes """ new_order = [] for layer in layers_to_add: get_vis = pm.PyNode(layer).v.get() pm.PyNode(layer).v.set(1) pm.blendShape(layer, target, o = 'local', w = [(0, 1.0)], foc = False) pm.PyNode(layer).v.set(get_vis) deformers_order = mel.eval('findRelatedDeformer("' + str(target) + '")') skin_deformer = [x for x in deformers_order if pm.PyNode(x).type()=='skinCluster'][0] bls_deformer = [x for x in deformers_order if pm.PyNode(x).type()=='blendShape'] new_order.append(skin_deformer) new_order.append(target) for bls in bls_deformer: new_order.insert(1,bls) pm.reorderDeformers(new_order) new_order.remove(bls) return bls_deformer
def add_target_on_corrective_blendshape(blendshape, target, base, values=None): ''' this is a simple function to add target on a blendshape ''' corrective_blendshape = pm.PyNode(blendshape) base = pm.PyNode(base) target = pm.PyNode(target) index = int(corrective_blendshape.inputTarget[0].inputTargetGroup.get( multiIndices=True)[-1] + 1) set_target_relative(corrective_blendshape, target, base) target.outMesh.get(type=True) # the target is created with "1.0" as weight. But it still created with # value set to 0.0. If the value is not set to 1.0, strange bug's appears # I have to set the target after if I want my value to 1.0 (life's strange) pm.blendShape(corrective_blendshape, edit=True, before=True, target=(base, index, target, 1.0)) pm.blendShape(corrective_blendshape, edit=True, weight=(index, 1.0)) apply_animation_template_on_blendshape_target_weight( blendshape=corrective_blendshape, target_index=index, values=values)
def _create_deformers_(self): # Setup missing geo shapes dictionary missing_shapes = {} # Build in the order of blendshapes for blendshape in self.import_data["Order"]: # Check if the blendshapes exists. If so create one. shapes = self.import_data["Data"][blendshape] if not pm.objExists(blendshape): # Read info for each blendshape # select select the shapes. pm.select(cl=1) for shape in shapes: # Check the shape exists if pm.objExists(shape): # Add to the selection pm.select(shape, add=1) else: # If not then then add to error list dictionary if missing_shapes.has_key(blendshape): missing_shapes[blendshape].append(shape) else: missing_shapes[blendshape] = [shape] # Select the target geo and create blendshape pm.select(self.target, add=1) pm.blendShape(name=blendshape) if missing_shapes: print "#######The following blends had missing shapes#######" for key in missing_shapes.keys(): print key.upper() libUtilities.print_list(missing_shapes[key])
def linkTheHooks(self): faceShapesGeo = "bsMan_fRig_PLY" faceGeo = "C_head_low_PLY" faceShapesGeoHis = pm.listHistory(faceShapesGeo) faceShapesBls = cmds.ls(faceShapesGeoHis, type="blendShape")[0] targetIndeces = pm.getAttr(faceShapesBls + ".weight", multiIndices=1) bsShapeNames = [ pm.aliasAttr("{0}.weight[{1}]".format(faceShapesBls, num), query=True) for num in targetIndeces ] faceBlendGRP = pm.group(empty=True, n="faceBlends_hooks") for x in bsShapeNames: pm.addAttr(faceBlendGRP, sn=x) hooks = pm.PyNode("faceBlends_hooks") # Check every blendshape for matching hook names. allBlends = pm.ls(type='blendShape') for newBlend in allBlends: for eachShape in newBlend.w: shapeName = eachShape.getAlias() if hooks.hasAttr(shapeName): hookAttr = hooks.attr(shapeName) try: hookAttr.connect(eachShape, force=True) except: continue pm.blendShape(faceShapesGeo, faceGeo, weight=[0, 1]) pm.setAttr(faceShapesGeo + ".visibility", 0)
def apply_animation_template_on_blendshape_target_weight( blendshape, target_index, values=None): """ this function will apply an animation on the blendshape target index given. the value is an float array. It represent a value at frame. the array middle value is the value set at the current frame. """ if values is None or not any(1 for v in values if v is not None): return blendshape = pm.PyNode(blendshape) startframe = int(pm.env.time - float(len(values) / 2) + .5) endframe = int(pm.env.time + float(len(values) / 2) + .5) frames = range(int(startframe), int(endframe)) decimal = pm.env.time - int(pm.env.time) frames_values = { f + decimal: values[i] for i, f in enumerate(frames) if values[i] is not None } for frame, value in frames_values.iteritems(): pm.setKeyframe(blendshape.weight[target_index], time=frame, value=value, inTangentType='linear', outTangentType='linear') # this force maya to refresh the current frame in evaluation # without those lines, maya does'nt refresh the current frame if a # key is set at this timing. if frames_values.get(pm.env.time) is not None: pm.blendShape(blendshape, edit=True, weight=(target_index, frames_values[pm.env.time]))
def connect_bls(source, target): """ This function connects input|source to output|target with a blendShape. If the source and target are of type list, it will blendShape each of those lists together. Else it will take the children of each and blendShape those together """ # Define Variable type if isinstance(source, list) and isinstance(target, list): inputs = [x for x in source] outputs = [x for x in target] else: # get all children in group inputs = pm.listRelatives(source, children=True, path=True) outputs = pm.listRelatives(target, children=True, path=True) for _input, _output in zip(inputs, outputs): blendShapeNode = ('{}_BLS'.format(_input)).split('|')[-1] if not mc.objExists(blendShapeNode): pm.blendShape(_input, _output, name=blendShapeNode, o="world", w=[(0, 1.0)], foc=False) else: pm.warning('{} already Exist'.format(blendShapeNode)) sys.stdout.write('// Result: Connection Done // \n ')
def copy_correctiveToBlend(base, corrective): '''Bakes a static mesh that can be used as a corrective to what you've posed Args: base (pm.PyNode): base object with bad shape from skinCluster or blendShapes corrective (pm.PyNode): sculpted fixed shape Returns: [pm.PyNode]: new corrected shape Usage: copy_correctiveToBlend(pm.ls(sl=True)[0], pm.ls(sl=True)[1]) ''' #Duplicate your deformed mesh twice, calling one positive and one negative. Move them a little away from your model positive = corrective negative = pm.duplicate(base, n=corrective.name()+"_negative")[0] inputs = pm.listConnections(base.getShape(), type=['skinCluster','blendShape']) for input in inputs: input.attr('envelope').set(0) corrected = pm.duplicate(base, n=corrective.name()+"_corrective")[0] #Make a new blend-shape node on your character containing the two duplicate meshes. This blend shape must use the parallel blending mode. blend = pm.blendShape(corrected, n='corrector_BS')[0] pm.blendShape(blend, e=True, t=(corrected, 0, positive, 1.0)) pm.blendShape(blend, e=True, t=(corrected, 1, negative, 1.0)) set=1 for alias in blend.listAliases(): alias[1].set(set) set=-1 #Move your character back to bind-pose and in the parallel blend-node, set the positive mesh to 1 and the negative to -1. This should blend your mesh so that you only have the deformations you made to the positive mesh, but now in a neutral pose. #bindPose #Duplicate this new mesh and call it something with the letters BS is the name because this is infinitely funny. This mesh can now be used as a corrective blend-shape #Delete the parallel blend-node and repeat these steps for all your shapes. Yes, really. #pm.delete(p_bs) #pm.delete(base) for input in inputs: input.attr('envelope').set(1) return corrected
def addWires(self): # adding wires self.w1 = pm.wire(self.upCrv, w=self.upBlink)[0] self.w2 = pm.wire(self.lowCrv, w=self.lowBlink)[0] self.w3 = pm.wire(self.upTarget, w=self.upCrv_ctl)[0] self.w4 = pm.wire(self.lowTarget, w=self.lowCrv_ctl)[0] # adding blendshapes self.bs_upBlink = pm.blendShape(self.upTarget, self.midTarget, self.upBlink, n=self.getName("blendShapeUpBlink")) self.bs_lowBlink = pm.blendShape(self.lowTarget, self.midTargetLower, self.lowBlink, n=self.getName("blendShapeLowBlink")) self.bs_mid = pm.blendShape(self.lowTarget, self.upTarget, self.midTarget, n=self.getName("blendShapeMidBlink")) self.bs_midLower = pm.blendShape(self.lowTarget, self.upTarget, self.midTargetLower, n=self.getName("blendShapeMidLowerBlink")) # setting blendshape reverse connections rev_node = pm.createNode("reverse") pm.connectAttr(self.bs_upBlink[0].attr(self.midTarget.name()), rev_node + ".inputX") pm.connectAttr(rev_node + ".outputX", self.bs_upBlink[0].attr(self.upTarget.name())) rev_node = pm.createNode("reverse") rev_nodeLower = pm.createNode("reverse") pm.connectAttr(self.bs_lowBlink[0].attr(self.midTargetLower.name()), rev_node + ".inputX") pm.connectAttr(rev_node + ".outputX", self.bs_lowBlink[0].attr(self.lowTarget.name())) rev_node = pm.createNode("reverse") pm.connectAttr(self.bs_mid[0].attr(self.upTarget.name()), rev_node + ".inputX") pm.connectAttr(self.bs_midLower[0].attr(self.upTarget.name()), rev_nodeLower + ".inputX") pm.connectAttr(rev_node + ".outputX", self.bs_mid[0].attr(self.lowTarget.name())) pm.connectAttr(rev_nodeLower + ".outputX", self.bs_midLower[0].attr(self.lowTarget.name())) # setting default values self.bs_mid[0].attr(self.upTarget.name()).set(self.blinkH) self.bs_midLower[0].attr(self.upTarget.name()).set(self.blinkH)
def transferAnimationByBlendshapes(self, namespace=''): #get SelectionList selectionList = pm.ls(sl=True, fl=True, type='transform') pm.select(cl=True) #check if objects are selected if not (selectionList): if (self.verbose): print( 'No objects selected, please select at least one object.') return None #Check if namespace is valid if not (namespace in self.getNamespaces()): if (self.verbose): print( 'Picked namespace does not exists anymore. Please refresh namespace list' ) return None #Transfer Animation by blendshapes #Iterate through selectionList and create blendshape deformer for equal base and target objects for masterTrans in selectionList: #getShape masterShape = masterTrans.getShape() ''' #SKIP ALEMBIC CONNECTION CHECK - NOT NECCESSARY FOR BLENDSHAPES #check if masterShape inMesh Attr connected to Alembic if not(pm.nodeType(pm.listConnections(masterShape.inMesh, s = True)[0]) == 'AlembicNode'): if(self.verbose): print(masterTrans.name() +' inMesh Attribute not connected to Alembic node. Continuing...') continue ''' #Check if namespace + masterTrans object exists if not (pm.objExists(namespace + ':' + masterTrans.name().split(':')[-1])): if (self.verbose): print(namespace + ':' + masterTrans.name().split(':')[-1] + ' does not exist. Continuing...') continue #create blendshape targetName = namespace + ':' + masterTrans.name().split(':')[-1] blendshapeDeformer = pm.blendShape(masterTrans.name(), targetName, foc=True) pm.select(cl=True) pm.blendShape(blendshapeDeformer, edit=True, w=(0, 1.0)) pm.select(cl=True) #Success Msg if (self.verbose): print( 'Successfully connected PaintFx Hair Geo to Alembic Cache Geo by blendshapes.' )
def connectTargets(self): 'Create blend shape node to all of the targets' # Create blend shape node with 1st target pm.blendShape(self.targetList[0], self.name, name = self.blendShape) # Add the remaining targets to the blend shape node for bIndex in range(1, len(self.targetList)): pm.blendShape(self.blendShape, edit=True, t=(self.name, bIndex, self.targetList[bIndex], 1.0))
def cbsHookup(*args, **kwargs): base = kwargs.setdefault('base') #(string) The base mesh for the character bs = kwargs.setdefault( 'bs' ) #(string) The blendshape deformer to which the shape should be added (if blank, a new deformer will be created shape = kwargs.setdefault( 'shape') #(string) The new target to add to the blendshape driver = kwargs.setdefault( 'driver' ) #(string) Node and attribute to have drive the blendshape target weight driveRange = kwargs.setdefault( 'driveRange', [0, 1] ) #(2 float list) The range of the driver to go from 0-1. [0]=target weight of 0, [1]=weight of 1 tan = kwargs.setdefault( 'tan', ['spline', 'spline'] ) # (2 string list) The tangent types for the set driven keys. [0]=start, [1]=end infinity = kwargs.setdefault( 'infinity', [False, False] ) # (2 bool list) sets whether or not to give the set driven key pre or post infinity. [0]=pre, [1]=post #create a blendshape deformer if one hasn't been specified if not bs: bs = pm.blendShape(base, frontOfChain=True, n='%s_corrective_bs' % base)[0] #add the new target to the blendshape targs = pm.blendShape(bs, q=True, t=True) for targ in targs: if str(shape).split('|')[-1] == str(targ).split('|')[-1]: pm.error( 'It appears you already have a blendshape target named %s in the node %s. Please rename the new target with a unique name.' % (shape, bs)) pm.blendShape(bs, e=True, t=[base, len(targs), shape, 1]) #set up the set driven key to drive the blendshape pm.setDrivenKeyframe('%s.%s' % (bs, shape), cd=driver, dv=driveRange[0], v=0, itt=tan[0], ott=tan[0]) pm.setDrivenKeyframe('%s.%s' % (bs, shape), cd=driver, dv=driveRange[1], v=1, itt=tan[1], ott=tan[1]) #set up infinity if requested if infinity[0]: pm.setInfinity('%s.%s' % (bs, shape), pri='linear') if infinity[1]: pm.setInfinity('%s.%s' % (bs, shape), poi='linear') return bs
def addObjMorphs(self): morphPath = os.path.join( os.path.split(self.fbxFile)[0], 'blendshapes/') morphFiles = [ f for f in os.listdir(morphPath) if f.endswith('.obj') and 'default' not in f ] meshesVtxCount = {} meshes = pm.ls(type='mesh') for m in meshes: if 'Orig' not in m.name() and 'rg' not in m.name(): meshesVtxCount[m.name()] = pm.polyEvaluate(m, v=1) print meshesVtxCount if morphFiles: self.hasMorphs = 1 bsNode = '' bsCreated = 0 bsEntry = 0 for obj in morphFiles: speakName = obj.split('.')[0] speakName = 'speak_' + speakName pm.importFile(morphPath + obj, namespace='morph') morph = pm.ls('morph:*', type='mesh')[0] morph.rename(speakName) morphVtxCount = pm.polyEvaluate(morph, v=1) for mesh, count in meshesVtxCount.iteritems(): print mesh, count if count == morphVtxCount: rigMesh = [pm.ls(mesh, type='mesh')[0].getParent()] skinCls = pm.listConnections('%s.inMesh' % rigMesh[0].getShape())[0] if not bsCreated: print 'creating blendshape' bsNode = pm.blendShape(rigMesh, name='speak_BS')[0].name() pm.reorderDeformers(skinCls.name(), bsNode, rigMesh[0].name()) pm.blendShape(bsNode, e=1, t=(rigMesh[0].name(), bsEntry, morph.name(), 1)) bsCreated = 1 else: print 'adding blendshape' pm.blendShape(bsNode, e=1, t=(rigMesh[0].name(), bsEntry, morph.name(), 1)) pm.delete(morph) bsEntry += 1 removeNamespace()
def add_sine(self): nurbs_sine = pm.duplicate(self.nurbs, name='geo_' + self.ribbon_name + '_sine') # create sine deformer dfm_sine, tfm_sine = pm.nonLinear(nurbs_sine, type='sine') tfm_sine.setRotation([0, 0, 90], space='world') dfm_sine.dropoff.set(1) pm.blendShape(nurbs_sine, self.nurbs, weight=[0, 1])
def create_skinDeform(ob, bsName='BodyBS'): if not ob.name().endswith('skinDeform'): dupOb = ob.duplicate(name="_".join([ob.name(), "skinDeform"])) for child in dupOb[0].listRelatives(ad=True): add_suffix(child) try: pm.delete(bsName) except pm.MayaNodeError: pass finally: pm.blendShape(ob, dupOb, name=bsName)
def connectBS(): try: if not pm.ls('RootBS') and not pm.ls('EyeDeformBS'): pm.select('facial',r=True) pm.select("*_face_grp_skinDeform",add=True) pm.blendShape(name='RootBS',w=[(0,1),], automatic=True) pm.select('eyeDeform',r=True) pm.select("*_eye_grp_skinDeform",add=True) pm.blendShape(name='EyeDeformBS',w=[(0,1),], ar=True) except: print 'Cant connect BS'
def create_renderMesh(ob, bsName='BodyBS'): if '_' in ul.get_name(ob): dupOb = ob.duplicate(name="_".join(ul.get_name(ob).split('_')[:-1])) for child in dupOb[0].listRelatives(ad=True): child.rename(name="_".join(ul.get_name(child).split('_')[:-1])) pm.reorder(dupOb[0], f=True) try: pm.delete(bsName) except pm.MayaNodeError: pass finally: pm.blendShape(ob, dupOb, name=bsName)
def addIntermidiateBlendShapes(blendShapeNode, baseMesh, mainShape, intermidiatePattern, intermidiateShapeList=list()): """ This adds the intermediate shapes to the baseMesh. Returns: """ blendShapeNode = pm.PyNode(blendShapeNode) weightCount = len(blendShapeNode.listAttr(m=True, k=True)) - 1 pm.blendShape(blendShapeNode,tc=0, e=1, t=(baseMesh, weightCount, mainShape, 1)) for each in intermidiateShapeList: ret = decompileNames(each, intermidiatePattern) pm.blendShape(blendShapeNode, e=1, ib=1, t=(baseMesh, weightCount, each, float(ret[1]['#value']) / 100), tc=0)
def transferAnimationByBlendshapes(self, namespace = '' ): #get SelectionList selectionList = pm.ls(sl = True, fl = True, type = 'transform') pm.select(cl = True) #check if objects are selected if not(selectionList): if(self.verbose): print('No objects selected, please select at least one object.') return None #Check if namespace is valid if not(namespace in self.getNamespaces()): if(self.verbose): print('Picked namespace does not exists anymore. Please refresh namespace list') return None #Transfer Animation by blendshapes #Iterate through selectionList and create blendshape deformer for equal base and target objects for masterTrans in selectionList: #getShape masterShape = masterTrans.getShape() ''' #SKIP ALEMBIC CONNECTION CHECK - NOT NECCESSARY FOR BLENDSHAPES #check if masterShape inMesh Attr connected to Alembic if not(pm.nodeType(pm.listConnections(masterShape.inMesh, s = True)[0]) == 'AlembicNode'): if(self.verbose): print(masterTrans.name() +' inMesh Attribute not connected to Alembic node. Continuing...') continue ''' #Check if namespace + masterTrans object exists if not(pm.objExists(namespace +':' +masterTrans.name().split(':')[-1])): if(self.verbose): print(namespace +':' +masterTrans.name().split(':')[-1] +' does not exist. Continuing...') continue #create blendshape targetName = namespace +':' +masterTrans.name().split(':')[-1] blendshapeDeformer = pm.blendShape(masterTrans.name(), targetName, foc = True) pm.select(cl = True) pm.blendShape(blendshapeDeformer, edit = True, w = (0, 1.0)) pm.select(cl = True) #Success Msg if(self.verbose): print('Successfully connected PaintFx Hair Geo to Alembic Cache Geo by blendshapes.')
def addFbxMorphs(self): morphPath = os.path.join(os.path.split(self.fbxFile)[0], 'blendshapes') morphFiles = [f for f in os.listdir(fbxPath) if f.endswith('.fbx')] if morphFiles: self.morphFiles = morphFiles else: pm.warning('No morph file found') return 0 if len(self.morphFiles) > 0: rigMesh = [pm.ls(type='mesh')[0].getParent()] skinCls = pm.listConnections('%s.inMesh' % rigMesh[0].getShape())[0] bsNode = pm.blendShape(rigMesh, name=self.name + '_BS')[0] print bsNode pm.reorderDeformers(skinCls.name(), bsNode, rigMesh[0].name()) for morph in self.morphFiles: print morph if 'open' in morph: pm.mel.eval('FBXImport -f "' + morphPath + '/' + morph + '"') meshes = set(mesh.getParent() for mesh in pm.ls(type='mesh')) newMesh = list(meshes - set(rigMesh)) newMesh[0].rename('Open') pm.blendShape(bsNode, e=1, t=(rigMesh[0].name(), 0, newMesh[0].name(), 1)) pm.delete(newMesh) elif 'blink' in morph: pm.mel.eval('FBXImport -f "' + morphPath + '/' + morph + '"') meshes = set(mesh.getParent() for mesh in pm.ls(type='mesh')) newMesh = list(meshes - set(rigMesh)) newMesh[0].rename('Blink') pm.blendShape(bsNode, e=1, t=(rigMesh[0].name(), 1, newMesh[0].name(), 1)) pm.delete(newMesh)
def linkTheHooks(self): conditionNode = [] multiplyNode = [] faceShapesGeoHis = pm.listHistory(FACE_SHAPES_GEO) faceShapesBls = pm.ls(faceShapesGeoHis, type="blendShape")[0] targetIndeces = pm.getAttr(faceShapesBls + ".weight", multiIndices=1) bsShapeNames = [pm.aliasAttr("{0}.weight[{1}]".format(faceShapesBls, num), query=True)for num in targetIndeces] faceBlendGRP = pm.group(empty=True, name="faceBlends_hooks") for x in bsShapeNames: pm.addAttr(faceBlendGRP, shortName=x) hooks = pm.PyNode("faceBlends_hooks") # Check every blendshape for matching hook names. allBlends = pm.ls(type='blendShape') for newBlend in allBlends: for eachShape in newBlend.w: shapeName = eachShape.getAlias() if hooks.hasAttr(shapeName): hookAttr = hooks.attr(shapeName) try: hookAttr.connect(eachShape, force=True) condition = pm.createNode("condition", name= "{0}".format(shapeName) + "_COND") pm.addAttr(condition, shortName=shapeName) pm.setAttr(condition + ".colorIfFalseR", 0) pm.setAttr(condition + ".operation", 2) multiply = pm.createNode("multiplyDivide", name= "{0}".format(shapeName) + "_MULT") pm.addAttr(multiply, shortName=shapeName) pm.setAttr(multiply + ".input2Y", -1) name = "l_pullDown", "r_pullDown", "l_frown", "r_frown", "l_lipsPullOut", "r_lipsPullsOut", "r_narrow" if multiply.startswith(name): pm.connectAttr(multiply + ".outputY", hookAttr) else: pm.connectAttr(multiply + ".outputX", hookAttr) conditionNode.append(condition) multiplyNode.append(multiply) except: pass for x, y in zip(conditionNode, multiplyNode): pm.connectAttr(x + ".outColorR", y + ".input1X", force=True) pm.connectAttr(x + ".outColorG", y + ".input1Y", force=True) pm.blendShape(FACE_SHAPES_GEO, FACE_GEO, weight=[0,1]) pm.setAttr(FACE_SHAPES_GEO + ".visibility", 0)
def blendshapeEnMasse(): for obj in pm.ls(sl=True): import pymel.core.nodetypes as nt if isinstance(obj, nt.Transform): if obj.getShape() and obj.visibility.get(): target = obj.name().replace('interpenetration_BLEND_GEO', 'GEO').replace('_inverted','') print target source = obj.name() blends = getMeshBlendshapes(target) if blends: pm.blendShape(blends[0], e=True, en=1) print 'Modifying blendshape: %s to target: %s from source %s' % (blends[0], target, source) pm.blendShape(blends[0], e=True, t=(target, 9, source, 1)) '''
def mirrorBlendShape(self, mapName, blendShapeHead, neutralHead): pm.blendShape(blendShapeHead, neutralHead, weight=([0, 1.0], [1, 1.0]), foc=True) pm.delete(blendShapeHead) pm.select(neutralHead, r=True) mel.eval("ArtPaintBlendShapeWeightsToolOptions();") mel.eval( 'artImportAttrMapCB artAttrCtx "{0}" "image";'.format(MAP_PATH + mapName)) pm.select(neutralHead, r=True) pm.delete(all=True, ch=True)
def insertShapes(cls, obj, shpGrp): obj = pym.PyNode(obj) shpGrp = pym.PyNode(shpGrp) shpGrpP = shpGrp.name().split("_") bsName = "_".join(shpGrpP[:-1]) bsNode = pym.listHistory(obj, type='blendShape') if bsNode: bsNode = bsNode[0] else: bsNode = pym.blendShape(obj, n=bsName) i = 0 for child in shpGrp.getChildren(type="transform"): pym.blendShape(bsNode, edit=True, t=(obj, i, child, 1.0)) i += 1 return obj
def duplicateSculptShape(obj): if obj.type() == "transform": transform = obj elif obj.type() == "mesh": transform = obj.getParent() else : return False closeDeformer(transform) sculptShape = pm.duplicate(transform, name = "%s_blendshape" %transform.name())[0] clearGeometry(sculptShape) openDeformer(transform) pm.blendShape(transform, sculptShape, origin = "local", w=(0,1)) tweak = sculptShape.getShape().inputs(type = "tweak")[0] pm.delete(tweak) return sculptShape
def create_static_geo(): static_geo = [u'venom_eye_goo_left_geo', u'venom_eye_left_geo', u'venom_body_geo', u'venom_eye_goo_right_geo', u'venom_eye_right_geo'] match_name = [u'L_eyeGoo_static_geo', u'L_eye_static_geo', u'C_body_static_geo', u'R_eyeGoo_static_geo', u'R_eye_static_geo'] static_geo_root = pm.ls('static_geo') if static_geo_root: static_geo_root = static_geo[0] else: static_geo_root = pm.group(empty=True, name='static_geo') for each_geo, static_geo in zip(static_geo, match_name): static_geo_duplicate = pm.duplicate(each_geo, name=static_geo)[0] static_geo_duplicate.setParent(static_geo_root) blend_shape_node = pm.blendShape(each_geo)[0] pm.blendShape(str(blend_shape_node), edit=True, target=[str(each_geo), 0, str(static_geo_duplicate), 1.0]) blend_shape_node.setWeight(0, 1.0)
def _buildMorphTargets(mesh_type, figure): pm.importFile(figure.files[mesh_type], namespace=mesh_type+'Geo') tgt_mesh = pm.ls(mesh_type+'Geo:Mesh')[0] # Transfer existing blendshapes on imported mesh if tgt_mesh.inMesh.listConnections(type='blendShape'): dup_mesh = duplicateClean(tgt_mesh, name='TMP_'+figure.mesh.name()) bs_node = tgt_mesh.inMesh.listConnections(type='blendShape')[0] # Transfer new shape to dup_mesh pm.transferAttributes( figure.mesh, dup_mesh, transferPositions=True, sampleSpace=3, targetUvSpace='UVOrig') pm.delete(dup_mesh, ch=True) # Add as target to tgt_mesh pm.blendShape(bs_node, edit=True, target=( tgt_mesh, len(bs_node.listAliases()), dup_mesh, 1.0)) # Set new shape and lock bs_node.setAttr(dup_mesh.name(), 1.0, lock=True) new_shapes = transferShapes( bs_node, dup_mesh, tgt_prefix=mesh_type+'Geo:NEW_') # Delete existing blendshape targets for shp in bs_node.inputTarget.listConnections(): pm.delete(shp) for shp in new_shapes: pm.rename(shp, shp.name().replace('NEW_', '')) pm.delete(tgt_mesh, ch=True) # Transfer new figure shape to base geo pm.transferAttributes( figure.mesh, tgt_mesh, transferPositions=True, sampleSpace=3, targetUvSpace='UVOrig') pm.delete(tgt_mesh, ch=True) target_lists = { 'Head': pm.ls(('POS_*', 'SHP_*'), type='transform') + pm.ls(['JCM*' + limb + '*' for limb in ['Collar', 'Neck', 'Shldr']], type='transform'), 'Body': pm.ls(('JCM_*', 'SHP_*'), type='transform') } # Create morph target meshes for src_mesh in target_lists[mesh_type]: new_mesh = duplicateClean( tgt_mesh, name=mesh_type+'Geo:'+src_mesh.name()) pm.transferAttributes( src_mesh, new_mesh, transferPositions=True, sampleSpace=3, targetUvSpace='UVOrig') pm.delete(new_mesh, ch=True)
def blend_search_and_create ( find_string, replace_string, blend_suffix = 'main_BS', double_namespace=False ): '''creates a blendshape between selected objects and targets based on find/replace strings and turns on :param find_string: string to find in the name of the transform.name() :type find_string: str or unicode :param replace_string: string to find in the name of the transform.name() :type find_string: str or unicode :param blend_suffix: suffix for blendshapes that are created :type double_namespace: str or unicode :param double_namespace: if we should search mpc style or not :type double_namespace: bool :rtype : list of pm.PyNode :usage : blend_search_and_create( 'INPUT', 'GEO', double_namespace=True ) ''' blends=[] for transform in pm.ls(sl=True): namespace = '' if double_namespace: namespace = '*:*:' target = pm.ls( '%s%s'%( namespace, transform.name().replace( find_string, replace_string ) ) ) blend_name = transform.name().replace( find_string, blend_suffix ) blend = pm.blendShape(transform, target, n=blend_name, frontOfChain=True)[0] blend_aliases = blend.listAliases() for blend_alias in blend_aliases: blend.attr(blend_alias[0]).set(1) blends.append( blend ) return blends
def getTargetShapes(self,*args): pm.textScrollList("targetShapeList",e=1,ra=1) self.bsNd = pm.textScrollList("blendshapeList",q=1,si=1) if len(self.bsNd) == 1: tgtShapes = pm.blendShape(self.bsNd[0],t=1,q=1) if len(tgtShapes)>0: listTarget = pm.textScrollList("targetShapeList",e=1,append=tgtShapes)
def mirrorShapes(self, obj): """ mirror Shapes from a _L or _R geometry to the other :obj object to apply mirrored shapes """ obj = pym.PyNode(obj) self.__reset__() mirrTM = pym.createNode("transform", n="mirror") lDups = [] for key, attr in self.__attrs__.iteritems(): attr.set(1.0) dup = pym.duplicate(self.defNode, n=mirrorLR(key)) lDups.append(dup) pym.parent(dup, mirrTM) attr.set(0.0) mirrTM.scaleX.set(-1.0) for dup in lDups: pym.parent(dup, w=1, a=1) pym.makeIdentity(dup, a=1, pn=1) pym.delete(mirrTM) shapes = lDups + [obj] bsN = pym.blendShape(*shapes)[0] bsN.rename(obj.name() + "_BS") pym.delete(*lDups) self.__restore__()
def __mirrorBlendShape(self,*args): pm.select(self.baseShape) baseShape = pm.ls(sl = 1)[0] pm.select(self.sculptedShape) sculptedShape = pm.ls(sl = 1)[0] baseWarp = pm.duplicate(baseShape,n = nameUtils.setUniqueName(baseShape + 'Warp','geo')) baseScaleNeg = pm.duplicate(baseShape,n = nameUtils.setUniqueName(baseShape + 'ScaleNeg','geo')) #flip scale pm.setAttr(baseScaleNeg[0] + '.scaleX', -1) tempBlend = pm.blendShape(sculptedShape,baseScaleNeg[0],n = nameUtils.setUniqueName(sculptedShape + 'TempBlend','geo')) #create warp between warp and neg pm.select(cl=True) pm.select(baseWarp) pm.select(baseScaleNeg,add = 1) pm.runtime.CreateWrap() pm.setAttr(tempBlend[0] + '.' + sculptedShape, 1) #Duplicate Wrapped shape for final result pm.duplicate(baseWarp) #Clean up setup pm.delete(baseWarp,baseScaleNeg)
def duplicateSculptShape(obj): if obj.type() == "transform": transform = obj elif obj.type() == "mesh": transform = obj.getParent() else: return False closeDeformer(transform) sculptShape = pm.duplicate(transform, name="%s_blendshape" % transform.name())[0] clearGeometry(sculptShape) openDeformer(transform) pm.blendShape(transform, sculptShape, origin="local", w=(0, 1)) tweak = sculptShape.getShape().inputs(type="tweak")[0] pm.delete(tweak) return sculptShape
def copyBlendShapes(blendShapeNode, targetMesh): """ Copy each target from blendShapeNode into targetMesh, using wrap modifier Args: blendShapeAttr: blend shape attribute to clone targetMesh: target mesh where apply the wrap modifier Return: BlendShapeNode: blend Shape node BSNames: List with blend shapes Names """ # check blendshapeNode type if not isinstance(blendShapeNode, pm.nodetypes.BlendShape): blendShapeNode = pm.PyNode(blendShapeNode) # Get BSWeights attributes. # BlendShape node can have a lot of unused index, so we store the name of each element attribute, # to avoid possible errors. BSElements = blendShapeNode.weight.elements() # list of unicode targetBShapes = [] for attr in BSElements: targetBShapes.append( CopyDeforms.copyBlendShape(blendShapeNode.attr(attr), targetMesh)) # create BlendShapeNode BlendShapeNode = pm.blendShape(targetBShapes, targetMesh)[0] # save blendShapeNames BSNames = [str(BSName) for BSName in targetBShapes] # delete Extracted BlendShapes, we don't need anymore pm.delete(targetBShapes) return BlendShapeNode, BSNames
def create_blendshape_corrective_on_mesh(base, target, values=None): """ this function's creating a new corrective blendshape on a mesh and add the first target """ base = pm.PyNode(base) target = pm.PyNode(target) name = base.name() + '_' + CORRECTIVE_BLENDSHAPE_NAME corrective_blendshape = pm.blendShape(target, base, name=name, before=True, weight=(0, 1))[0] pm.addAttr(corrective_blendshape, attributeType='message', longName=CORRECTIVE_BLENDSHAPE_ATTR, niceName=CORRECTIVE_BLENDSHAPE_ATTR.replace('_', ' ')) base.message >> corrective_blendshape.attr(CORRECTIVE_BLENDSHAPE_ATTR) if values is not None: apply_animation_template_on_blendshape_target_weight( blendshape=corrective_blendshape, target_index=0, values=values)
def addObjMorphs(self): morphPath = os.path.join(os.path.split(self.fbxFile)[0], 'blendshapes/') morphFiles = [f for f in os.listdir(morphPath) if f.endswith('.obj') and 'default' not in f ] meshesVtxCount = {} meshes = pm.ls(type='mesh') for m in meshes: if 'Orig' not in m.name() and 'rg' not in m.name(): meshesVtxCount[m.name()] = pm.polyEvaluate(m,v=1) print meshesVtxCount if morphFiles: self.hasMorphs = 1 bsNode = '' bsCreated = 0 bsEntry =0 for obj in morphFiles: speakName = obj.split('.')[0] speakName = 'speak_' + speakName pm.importFile(morphPath + obj,namespace= 'morph') morph = pm.ls('morph:*',type='mesh')[0] morph.rename(speakName) morphVtxCount = pm.polyEvaluate(morph,v=1) for mesh, count in meshesVtxCount.iteritems(): print mesh, count if count == morphVtxCount: rigMesh = [pm.ls(mesh,type='mesh')[0].getParent()] skinCls = pm.listConnections('%s.inMesh'%rigMesh[0].getShape())[0] if not bsCreated: print 'creating blendshape' bsNode = pm.blendShape(rigMesh,name='speak_BS')[0].name() pm.reorderDeformers(skinCls.name(),bsNode,rigMesh[0].name()) pm.blendShape(bsNode,e=1,t=(rigMesh[0].name(), bsEntry , morph.name(), 1)) bsCreated = 1 else: print 'adding blendshape' pm.blendShape(bsNode,e=1,t=(rigMesh[0].name(), bsEntry , morph.name(), 1)) pm.delete(morph) bsEntry += 1 removeNamespace()
def fill(self, times ): self.transform() selected = pm.ls(sl = 1) pm.select(cl = 1) if len(selected) >= 1: haircap = self.capName.getText() if len(selected) > 1: allNewHairs = [] for n in range(len(selected)-1): hair1 = selected[n] hair2 = selected[n+1] grp = pm.group(empty = True, name = 'HairGrp') selfMatrix = selected[n].getMatrix() hair2Matrix = selected[n+1].getMatrix() grpMatrix = (selfMatrix + hair2Matrix)/2 grpMatrix = grpMatrix.homogenize() grp.setMatrix(grpMatrix) pm.parent([hair1, hair2], grp) newHairs = [] for x in range(times-1): newHair = pm.duplicate(hair1)[0] newHair.setMatrix((selfMatrix*grpMatrix.inverse()).blend((hair2Matrix*grpMatrix.inverse()), weight = (x+1)*(1.0/times))) #set blendshapes connecting new hair with the original hair pm.blendShape( hair1 ,newHair , w = ( 0 , 1-( (x+1)*(1.0/times) ) ) ) #if hairs are the same connect the last one as well if pm.polyEvaluate(hair1, v=1) == pm.polyEvaluate(hair2, v=1): pm.blendShape( hair2 ,newHair , w = ( 0 , (x+1)*(1.0/times) ) ) if pm.objExists(haircap) and self.transferCheckBox.getValue() == 1 : pm.transferAttributes(haircap, newHair, sampleSpace=0,transferUVs=1, transferColors=0, sourceUvSet = 'map1',targetUvSet = 'map1') newHairs.append(newHair) pm.ungroup(grp) allNewHairs.append(newHairs) if self.randSliderT.getValue() or self.randSliderR.getValue() > 0: self.randomize(allNewHairs, transRot = 2) pm.select(allNewHairs) else: hair1 = selected[0] newHairs = [] for x in range(times-1): newHair = pm.duplicate(hair1)[0] selfTrans = newHair.getTranslation() selfRot = newHair.getRotation() newHairs.append(newHair) if self.randSliderT.getValue() or self.randSliderR.getValue() > 0: self.randomize(newHairs, transRot = 2) pm.select(newHairs) else: pm.error( "select something")
def build(name=None, crv=None, reg_node=None, log=False): """Create ine node deformer and attributes on given plane, and IK control connected to the reg_node. name -- Prefix name. Str crv -- Curve to add deformer to. nt.Transform reg_node -- registration node. nt.Transform """ general.check_type(name, "name", [str]) general.check_type(crv, "crv", [pm.nt.Transform]) general.check_type(reg_node, "reg_node", [pm.nt.Transform]) cnt_attr = "%s1_ik_cnt" % name if not hasattr(reg_node, cnt_attr): raise errors.InputError("reg_node", reg_node, "Missing attr: %s" % cnt_attr) attr = getattr(reg_node, cnt_attr) cnt = attr.listConnections()[0] if log: str_1 = "Cnt: ", cnt general.logging.debug(str_1) crv2 = crv.duplicate() sineDef, sineHndl = pm.nonLinear(crv2, typ="sine", name="%s_sineDeformer" % name) bs = pm.blendShape(crv2, crv, foc=True, name="%s_sineBlendShape" % name)[0] attr = getattr(bs, crv2[0].name()) attr.set(1) sineDef.rename("%s_sineDeformer" % name) sineHndl.rename("%s_sineDeformerHandle" % name) attrs = {"sineOffOn": [1, 0, 1], "amplitude": 0.3, "wavelength": 2, "offset": 0, "direction": 0} for attr in attrs.keys(): if isinstance(attrs[attr], list): pm.addAttr(cnt, ln=attr, dv=attrs[attr][0], min=attrs[attr][1], max=attrs[attr][2], k=1) else: pm.addAttr(cnt, ln=attr, dv=attrs[attr], k=1) cnt.sineOffOn >> sineDef.envelope cnt.amplitude >> sineDef.amplitude cnt.wavelength >> sineDef.wavelength cnt.offset >> sineDef.offset cnt.direction >> sineHndl.rotateY # Setup the handle hndl_grp = pm.group(name="%s_hndlGrp" % name, em=1) pm.parent(sineHndl, hndl_grp) sineHndl.rz.set(180) sineDef.dropoff.set(1) sineDef.lowBound.set(0) sineDef.highBound.set(2) control.register_object(reg_node, "sine_handle", sineHndl) return reg_node
def newWeight(self, *args): result = pm.promptDialog( title='Create BlendShape', message='Enter Shape Name:', button=['OK', 'Cancel'], defaultButton='OK', cancelButton='Cancel', dismissString='Cancel') if result == 'OK': name = pm.promptDialog(query=True, text=True) pm.setAttr(self.blendShapeNode + ".envelope", 0) dup = pm.duplicate(self.object, name=name)[0] pm.setAttr(self.blendShapeNode + ".envelope", 1) pm.blendShape(self.blendShapeNode, e=True, t=[self.object, len(self.targets), dup.name(), 1.0]) self.load_blendShapeNode()
def main(neutral=None, target=None): ''' Generate separated blendshapes ''' # Get shaders shaders = _getShaders() # Create sets sets = _createSets(shaders=shaders) # _createBlend blend = pm.blendShape( target, neutral )[0] pm.setAttr('%s.%s'%(blend,target),1) # Flood all weights to 0 pm.mel.eval("select -r %s.vtx[0:%s]"%(neutral.name(), (neutral.numVertices()-1))) _floodWeightsOnSelected(blendNode=blend, value=0) # Get vertex weight dictionary weights = _createVertShaderMap(mesh=neutral,sets=sets) # Setup progressbar gMainProgressBar = pm.mel.eval('$tmp = $gMainProgressBar') pm.progressBar( gMainProgressBar, edit=True, beginProgress=True, isInterruptable=True, status='Creating blendshape targets from shaders ...', maxValue=len(sets) ) # Generate target per set for s in sets: if pm.progressBar(gMainProgressBar, query=True, isCancelled=True ) : break # Select components pm.select(s,r=1) verts = pm.ls(sl=1,fl=1) # Flood blend deformer weights to 1 for v in verts: pm.select(v,r=1) num = int(v.split('[')[-1].split(']')[0]) w = float(1.0/weights[num]) _floodWeightsOnSelected(blendNode=blend, value=w) # Create target _createTarget(mesh=neutral, name=s.replace('_set','Morph')) # Flood all weights to 0 pm.mel.eval("select -r %s.vtx[0:%s]"%(neutral.name(), (neutral.numVertices()-1))) _floodWeightsOnSelected(blendNode=blend, value=0) pm.progressBar(gMainProgressBar, edit=True, step=1) pm.progressBar(gMainProgressBar, edit=True, endProgress=True)
def addFbxMorphs(self): morphPath = os.path.join(os.path.split(self.fbxFile)[0], 'blendshapes') morphFiles = [f for f in os.listdir(fbxPath) if f.endswith('.fbx')] if morphFiles: self.morphFiles = morphFiles else: pm.warning('No morph file found') return 0 if len(self.morphFiles) > 0: rigMesh = [pm.ls(type='mesh')[0].getParent()] skinCls = pm.listConnections('%s.inMesh'%rigMesh[0].getShape())[0] bsNode = pm.blendShape(rigMesh,name=self.name + '_BS')[0] print bsNode pm.reorderDeformers(skinCls.name(),bsNode,rigMesh[0].name()) for morph in self.morphFiles: print morph if 'open' in morph: pm.mel.eval( 'FBXImport -f "' + morphPath + '/' + morph + '"') meshes = set(mesh.getParent() for mesh in pm.ls(type='mesh')) newMesh = list(meshes - set(rigMesh)) newMesh[0].rename('Open') pm.blendShape(bsNode,e=1,t=(rigMesh[0].name(), 0 , newMesh[0].name(), 1)) pm.delete(newMesh) elif 'blink' in morph: pm.mel.eval( 'FBXImport -f "' + morphPath + '/' + morph + '"') meshes = set(mesh.getParent() for mesh in pm.ls(type='mesh')) newMesh = list(meshes - set(rigMesh)) newMesh[0].rename('Blink') pm.blendShape(bsNode,e=1,t=(rigMesh[0].name(), 1 , newMesh[0].name(), 1)) pm.delete(newMesh)
def updateShape(self,*args): newShapes = pm.textScrollList("newShapeList",q=1,ai=1) curShapes = pm.textScrollList("curShapeList",q=1,ai=1) if len(newShapes) == len(curShapes) and len(curShapes)>0: for i,x in enumerate(curShapes): bsNd = pm.blendShape(newShapes[i],x) pm.setAttr(bsNd[0]+'.'+newShapes[i],1) pm.select(x,r=1) pm.delete(x,ch=1) pm.textScrollList("newShapeList",e=1,ri=newShapes[i]) pm.setAttr('{0}.visibility'.format(newShapes[i]),0) #pm.delete(newShapes[i])
def __init__(self, control=None, name=None, curve=None, numJnts=None, fwdBackCrvs=None, sideToSideCrvs=None): pm.select(control, r=1) control = pm.ls(sl=1)[0] pm.select(curve, r=1) curve = pm.ls(sl=1)[0] joints = self.createJoints(name=name, curve=curve, num=numJnts) self.createFKControls(name=name, joints=joints) self.createAttrs(control=control, name=name) fwd_blendshape = pm.blendShape(fwdBackCrvs, curve, ib=1, name='fwd_%s_blendshape' % name)[0] side_blendshape = pm.blendShape(sideToSideCrvs, curve, ib=1, name='side_%s_blendshape' % name)[0] self.setupTimeSineExp(control=control) pm.connectAttr('%s.time_sine' % control, '%s.%s' % (fwd_blendshape, fwdBackCrvs[-1]), f=1) pm.connectAttr('%s.time_sine' % control, '%s.%s' % (side_blendshape, sideToSideCrvs[-1]), f=1) pm.connectAttr('%s.fwd_back' % control, '%s.envelope' % fwd_blendshape) pm.connectAttr('%s.side_to_side' % control, '%s.envelope' % side_blendshape)
def exportCmd(*args, **kwargs): ''' export models with animation ''' kx = kxTool.KXTool() kx.getSceneName() sceneName = kx.sceneName scenePath = kx.scenePath cachePath = "{path}/{name}/{name}_cloth.abc".format(path = scenePath.replace('scenes', 'cache/alembic'), name = sceneName) cacheFile = name.compileFileName(cachePath) fileName = name.compileFileName("{path}/{name}_cloth.mb".format(path = scenePath, name = sceneName)) geos = pm.PyNode('kx_cloth_export_layer').listMembers() exportGeos = [] for geo in geos: dup = pm.duplicate(geo, name = '{0}_toCloth'.format(geo.name()))[0] dup.setParent(w=1) shapes = dup.getShapes() pm.delete(shapes[1:]) pm.blendShape(geo, dup, o = 'world', w = (0,1)) exportGeos.append(dup) cache.exportAbcCache(exportGeos, cacheFile, useTimeline = True, verbose = True) pm.newFile(f=1) sourceGrp = pm.createNode('transform', name = 'source_Grp') abcNodeName = cache.importAbcCache(cacheFile) objs = pm.PyNode(abcNodeName).outputs() for obj in objs: obj.rename(obj.name().replace('_toCloth', '_anim')) obj.setParent(sourceGrp) pm.saveAs(fileName, f=1) return fileName
def add_corrective(mainGeo, left, right, preCorrective): ## ##Add a corrective blendshape for two blendshape, eg use a corrective middle smile for smile_L and smile_R. ## corrective = correcter.createCorrectiveBlendshape(mainGeo, left, right) pm.select(preCorrective, corrective) blend = pm.blendShape()[0] eval("blend.%s.set(1)" % preCorrective) pm.delete(corrective, ch=1) dummy_blendshape = correcter.applyBlendshapesToDummy(mainGeo, left, right, corrective) correcter.addDummyToMasterBlendshape(mainGeo, dummy_blendshape) correcter.addCorrectiveExpressionToMaster(mainGeo, dummy_blendshape, left, right) pm.delete(corrective, dummy_blendshape)
def build_surf_bShp(self, *args): """ builds a blendShape surface and blendShape node to add deformations Args: None Returns (None) """ surf_name = self.flexiPlaneNameField.getText() + '_flexiPlane_SURF' surf_wirebShp_name = self.flexiPlaneNameField.getText() + '_flexiPlane_wire_bShp_SURF' surf_bShpNode_name = self.flexiPlaneNameField.getText() + '_flexiPlane_bShpNode_SURF' surf_tweekNode_name = self.flexiPlaneNameField.getText() + '_flexiPlane_bShp_SURF_tweak01' surf_bShpGRP_name = self.flexiPlaneNameField.getText() + '_flexiPlane_bShp_GRP' pm.duplicate( surf_name, n = surf_wirebShp_name) pm.blendShape( surf_wirebShp_name, surf_name, n = surf_bShpNode_name, w = [(0, 1), (1,1)] ) list = pm.listConnections( surf_name + 'Shape' ) pm.rename( list[-1] , surf_tweekNode_name ) pm.group( em = True, name = surf_bShpGRP_name ) pm.parent(surf_wirebShp_name, surf_bShpGRP_name ) pm.setAttr( surf_bShpGRP_name + '.visibility', 0 )
def qClothCmd(*args, **kwargs): ''' create qCloth step 1: Select an anim geo step 2: Duplicate a cloth geo and a output geo from the anim geo step 3: Do blendshape both anim geo and cloth geo with output geo step 4: Create QCloth on cloth geo ''' try: pm.loadPlugin("qualoth-2014-x64.mll") except: pass sel = pm.ls(sl=1) outputGrpName = 'output_Grp' clothGrpName = 'cloth_Grp' if pm.objExists(outputGrpName): outputGrp = pm.PyNode(outputGrpName) else : outputGrp = pm.createNode('transform', name = outputGrpName) outputGrp.v.set(0) if pm.objExists(clothGrpName): clothGrp = pm.PyNode(clothGrpName) else : clothGrp = pm.createNode('transform', name = clothGrpName) outputGeos = [pm.duplicate(i, name = i.name().replace("_anim", "_output"))[0] for i in sel] [outputGeo.setParent(outputGrp) for outputGeo in outputGeos] [i.v.set(0) for i in sel] clothShape = [] for i in sel: pm.select(i) clothShape.append(pm.mel.qlCreateCloth()) clothGeos = [pm.PyNode(i).outputMesh.outputs(p=0)[0] for i in clothShape] [clothGeo.setParent(clothGrp) for clothGeo in clothGeos] blendNodes = [pm.blendShape(sel[i], clothGeos[i], outputGeos[i], w = [(0,0), (1,1)]) for i in range(len(sel))]
def buildDevSolver(self): super(SubControlSpine, self).buildSolver() # Blendshape self.controlCurve.select() self.ikCurve.select(add=True) # Give a temporary name as this interferes with the metaConnections currentName = self.controlCurve.shortName() self.ikDriveCurve.rename("SpineDriver") # Blendshape blendShape = pm.blendShape(name=utils.nameMe(self.side, self.part, "BlendShape"))[0] blendShape.setWeight(0, 1) # Rename the control back self.ikDriveCurve.rename(currentName) # Convert a blendnode to meta blendNodeMeta = core.MetaRig(blendShape.name()) self.controlCurve.addSupportNode(blendNodeMeta, "baseDriver") self.controlCurve.transferPropertiesToChild(blendNodeMeta, "BlendShape")
def bdHookGeo(): refHeadGeoGrp = pm.ls('Head:GEO',type='transform')[0] refHeadGeoGrpRelatives = pm.listRelatives(refHeadGeoGrp,ad=True,type='transform') refHeadGeo = [] for relative in refHeadGeoGrpRelatives: if relative.getShape(): if relative.getShape().type() == 'mesh': refHeadGeo.append(relative) print relative.name() pm.select(refHeadGeo) for obj in refHeadGeo: sourceStr = obj.name().split(':')[2] target = pm.ls(sourceStr,type='transform')[0] pm.select([obj,target]) blendshape = pm.blendShape(n=sourceStr + '_BS')
def nClothCmd(*args, **kwargs): ''' create nCloth step 1: Select an anim geo step 2: Duplicate a cloth geo and a output geo from the anim geo step 3: Do blendshape both anim geo and cloth geo with output geo step 4: Create NCloth on cloth geo ''' sel = pm.ls(sl=1) outputGrpName = 'output_Grp' clothGrpName = 'cloth_Grp' if pm.objExists(outputGrpName): outputGrp = pm.PyNode(outputGrpName) else : outputGrp = pm.createNode('transform', name = outputGrpName) outputGrp.v.set(0) if pm.objExists(clothGrpName): clothGrp = pm.PyNode(clothGrpName) else : clothGrp = pm.createNode('transform', name = clothGrpName) clothGeos = [pm.duplicate(i, name = i.name().replace("_anim", "_cloth"))[0] for i in sel] [clothGeo.setParent(clothGrp) for clothGeo in clothGeos] outputGeos = [pm.duplicate(i, name = i.name().replace("_anim", "_output"))[0] for i in sel] [outputGeo.setParent(outputGrp) for outputGeo in outputGeos] [i.v.set(0) for i in sel] pm.select(clothGeos) clothShape = pm.mel.createNCloth(0) blendNodes = [pm.blendShape(sel[i], clothGeos[i], outputGeos[i], w = [(0,0), (1,1)]) for i in range(len(sel))]
def cbsMirror(blend=None, base=None, *args): import maya.mel as mel if len(pm.ls(sl=True))==2: if not blend: blend = pm.ls(sl=True)[0] # (string) The mesh that is desired to be mirrored if not base: base = pm.ls(sl=True)[1] # (string) The mesh that serves as the base to mirror (the skinned mesh) #setting up the new blendshape newBase = pm.duplicate(base)[0] for at in 'trs': for vec in 'xyz': pm.setAttr('%s.%s%s'%(newBase, at, vec), l=False) #creating the new base mesh pm.delete(newBase.getShapes()[1:]) #deleting the second shape node pm.connectAttr(('%s.outMesh' %pm.listRelatives(base, s=True)[1]), ('%s.inMesh' %newBase.getShape())) #setting up mirror target mirShape = pm.duplicate(newBase)[0] mirShape.sx.set(-1) bs = pm.blendShape(blend, mirShape)[0] #creating a wrap deformer pm.select([newBase, mirShape], r=True) mel.eval('CreateWrap') #deforming blendshape to deform the new base pm.setAttr('%s.%s'%(bs, blend), 1) #duplicating the result to prevent any tag-alongs outShape = pm.duplicate(newBase, n='%s_mirrored'%blend)[0] pm.delete(outShape.getShapes()[1:]) outShape.tx.set(-outShape.boundingBoxSizeX.get()) #clean things up pm.delete(mirShape, newBase) #apply a texture to the new shape. pm.select(outShape, r=True) pm.sets('initialShadingGroup', e=True, forceElement=True) return outShape
import pymel.core as pm import maya.mel as mm # recup selection (modele defaut et modele a symetriser) sel = pm.ls(sl= True) ''' double duplication du modele defaut ''' source = pm.duplicate(sel[0]) target = pm.duplicate(sel[0]) '''' symetrisation de la premiere copie''' pm.setAttr(source[0] + ".scaleX", -1 ) pm.setAttr(source[0] + ".translate", [100,0,0]) ''' application du blendsahape a la premiere copie symetrisee ''' tempBS = pm.blendShape( sel[1], source[0]) pm.setAttr(target[0] + ".translate", [100,0,0]) pm.select( target[0], source[0] ) ''' application du wrap a la deuxieme copie ''' test = mm.eval('doWrapArgList "2" { "1","0","1" };') # blendshape a fond pm.setAttr(tempBS[0] +"." + sel[1], 1) BSFinal = pm.duplicate( target[0], rr = True) pm.delete(source[0], target[0])
def bdBuildRbnDT(self,name,start,end,segments): surfaceRbn = pm.nurbsPlane(ax = [0,0,22], d=3, u=1, v=segments , w=1, lr = segments)[0] surfaceRbn.rename(name) flcGrp = self.bdCreateFol(surfaceRbn,segments) surfaceRbn_BS = surfaceRbn.duplicate()[0] surfaceRbn_BS.rename(name + '_BS') surfaceRbn_BS.translateX.set(segments * 0.5 ) blendshapeNode = pm.blendShape(surfaceRbn_BS,surfaceRbn,name=surfaceRbn.name() + '_blendShape')[0] blendshapeNode.attr(surfaceRbn_BS.name()).set(1) locatorsRbn = [] topLocator = pm.spaceLocator() topLocator.rename(name + '_loc_top_CON') topLocator.translateY.set(segments * 0.5) pm.makeIdentity(topLocator,apply=True,t=True,r=True,s=True) midLocator = pm.spaceLocator() midLocator.rename(name + '_loc_mid_CON') midLocatorGrp = pm.group(midLocator,name=midLocator.name() + '_grp') pm.makeIdentity(midLocator,apply=True,t=True,r=True,s=True) botLocator = pm.spaceLocator() botLocator.rename(name + '_loc_bot_CON') botLocator.translateY.set(segments * -0.5) pm.makeIdentity(botLocator,apply=True,t=True,r=True,s=True) locatorsRbn.append(topLocator) locatorsRbn.append(midLocator) locatorsRbn.append(botLocator) pm.pointConstraint(topLocator,botLocator,midLocatorGrp) conGrp = pm.group([topLocator,midLocatorGrp,botLocator],n=name.replace('srf','CON_GRP')) curveDrv = pm.curve(d=2, p=[(0, segments * 0.5, 0), (0, 0, 0), (0, segments * -0.5, 0)],k=[0,0,1,1]) curveDrv.rename(name.replace('srf', 'wire_CRV')) curveDrv.translateX.set(segments * 0.5) wireDef = pm.wire(surfaceRbn_BS,w=curveDrv,en=1,gw=False,ce=0, li=0, dds = [0,20], n=name.replace('srf','wire')) #kind of a hack wireDefBase = wireDef[0].baseWire[0].listConnections(d=False,s=True) curveCLS,clsGrp = self.bdClustersOnCurve(curveDrv,segments) for i in range(3): locatorsRbn[i].translate.connect(curveCLS[i].translate) #organize a bit moveGrp = pm.group([conGrp,surfaceRbn],name=name.replace('srf','move_GRP')) extraGrp = pm.group([flcGrp,surfaceRbn_BS,clsGrp,curveDrv,wireDefBase],name = name.replace('srf','extra_GRP')) allGrp = pm.group([moveGrp,extraGrp],name = name.replace('srf','RBN')) self.bdFlcScaleCnstr(moveGrp,flcGrp) globalCon = pm.spaceLocator() globalCon.rename(name.replace("srf",'world_CON')) pm.parent(globalCon,allGrp) pm.parent(moveGrp,globalCon) self.bdCreateJoints(flcGrp) twistDef, twistDefTransform = self.bdAddTwist(surfaceRbn_BS) pm.parent(twistDefTransform, extraGrp) topLocator.rotateY.connect(twistDef.startAngle) botLocator.rotateY.connect(twistDef.endAngle) pm.reorderDeformers(wireDef[0],twistDef,surfaceRbn_BS)
import pymel.core as pm baseShape = pm.PyNode('bs_baseShape') blend50 = pm.PyNode('bs_baseShape_a_50') blend100 = pm.PyNode('bs_baseShape_a') #create 50offset shape dup = pm.duplicate(baseShape, name='temp_50offset')[0] pm.delete([x for x in dup.listRelatives() if x.name() != dup.getShape()]) bs = pm.blendShape(blend50, blend100, dup) pm.blendShape( bs, edit=True, w=[(0, 1), (1, -0.5)] ) blend50offset = pm.duplicate(dup, name = 'bs_baseShape_a_50offset')[0] pm.delete(dup) bs = pm.blendShape(blend100, blend50offset, baseShape)[0] dvr_attr = "%s.%s" %(bs.name(), blend100.name()) dvn_attr = "%s.%s" %(bs.name(), blend50offset.name()) pm.setDrivenKeyframe(dvn_attr, v=0.0, cd=dvr_attr, dv=0.0, itt='spline', ott='spline') pm.setDrivenKeyframe(dvn_attr, v=1.0, cd=dvr_attr, dv=0.5, itt='flat', ott='flat') pm.setDrivenKeyframe(dvn_attr, v=0.0, cd=dvr_attr, dv=1.0, itt='spline', ott='spline') pm.keyTangent('%s_%s'%(bs.name(), blend50offset), e=True, ow=1, index=[2], inAngle=-10) pm.keyTangent('%s_%s'%(bs.name(), blend50offset), e=True, ow=1, index=[0], outAngle=10)
""" With influences point constrained to curves setup: - Create duplicate of the curve - Name the duplicate based on prefix input by user - Crete blendshape named using prefix - SDK to multiAxis attr """ import pymel.core as pm multiAxisAttr = "rt_shoulder_jacket_inf_cnt.RtShldr_u" crv = pm.ls(sl=1)[0] name = crv.name().replace("_curve", "_back_crv") dup = pm.duplicate(crv)[0] dup.rename(name) bs = pm.blendShape(dup, crv, n="%sBS" % name)[0] # off pm.setDrivenKeyframe(bs, at="%s" % name, cd=multiAxisAttr, dv=0.5, v=0) # on pm.setDrivenKeyframe(bs, at="%s" % name, cd=multiAxisAttr, dv=1, v=1)
def build(self): self.curveIn.setAttr('inheritsTransform',False) # create a crv and ctrls to act as a manual driver for the sys self.manCrv = pm.duplicate(self.curveIn, returnRootsOnly=True, name = '%s_man_%s' % (self.name,d.CURVE)) self.manCrv[0].inheritsTransform = False self.manCrv[0].setAttr('visibility',False) linearSkin = LinearSkin( mesh = self.manCrv, startLoc = self.startLoc, endLoc = self.endLoc, numControls = self.numControls, name = self.name, controlColor = self.controlColor, controlRadius = self.controlRadius, controlShape = self.controlShape) self.driverJoints = linearSkin.drivers self.controls = linearSkin.controls self.dynInCrv = pm.duplicate(self.manCrv,returnRootsOnly=1, name = '%s_dynIn_%s' % (self.name, d.CURVE))[0] self.dynInCrv.setAttr('visibility',False) # drive the dynmanic input curve with the manual curve self.shapeBs = pm.blendShape(self.manCrv, self.dynInCrv, name = '%s_shape_%s' % (self.name, d.BLENDSHAPE)) pm.blendShape(self.shapeBs, edit=True, weight=[(0,1)]) # make a dynamic curve that is driven by a hairSystem self.dynOutCrv = pm.duplicate( self.dynInCrv, returnRootsOnly=1, name = '%s_dynOut_%s' % (self.name, d.CURVE))[0] self.dynOutCrv.inheritsTransform = False self.dynOutCrv.setAttr('visibility',False) self.follicle = pm.createNode('follicle', skipSelect=1, name = '%s_%sShape' % ( self.name,d.FOLLICLE)) self.follicle = pm.rename(self.follicle.getParent(), '%s_%s' % (self.name,d.FOLLICLE)) self.follicle.setAttr('visibility',False) self.follicle.restPose.set(1) if self.hairSystem == None or not pm.objExists(self.hairSystem): self.hairSystem = pm.createNode( 'hairSystem', skipSelect=1, name='%s_%sShape' % (self.name,d.HAIR_SYS)) self.hairSystem = pm.rename(self.hairSystem.getParent(), '%s_%s' % (self.name,d.HAIR_SYS)) pm.PyNode('time1').outTime >> \ self.hairSystem.getShape().currentTime self.hairSystem.setAttr('visibility',False) hairSystem = pm.PyNode(self.hairSystem) hairIndex=len(hairSystem.getShape().inputHair.listConnections()) pm.parent(self.dynInCrv, self.follicle) self.dynInCrv.getShape().worldSpace[0] >> \ self.follicle.getShape().startPosition self.follicle.getShape().outCurve >> \ self.dynOutCrv.getShape().create self.follicle.getShape().outHair >> \ hairSystem.getShape().inputHair[hairIndex] hairSystem.getShape().outputHair[hairIndex] >> \ self.follicle.getShape().currentPosition # drive the input curve with a blendshape to blend btwn # the manual and dynmanic curves self.manDynBs = pm.blendShape( self.manCrv, self.dynOutCrv, self.curveIn, name='%s_manDyn_%s' % (self.name, d.BLENDSHAPE))[0] pm.addAttr(self.controls[0], longName='manDynBlend', attributeType='float', minValue = 0.0, maxValue = 1.0, keyable=True) pma = pm.createNode('plusMinusAverage', skipSelect=1, name = '%s_%s' % (self.name, d.PMA)) pma.setAttr('operation','Subtract') pma.setAttr('input1D[0]',1) self.controls[0].manDynBlend >> self.manDynBs.weight[1] self.controls[0].manDynBlend >> pma.input1D[1] pma.output1D >> self.manDynBs.weight[0]