def _set_channel_edit_target(chn, edit=True): """Set the blendshape target of a channel editable or not editable Args: chn (PyNode): Attribute channel to edit edit (bool, optional): Set ON or OFF the channel edit status """ attrs = chn.listConnections(d=True, s=False, p=True) for a in attrs: if edit: pm.sculptTarget(a.node(), e=True, t=a.index()) pm.inViewMessage(amg="{}: Edit mode is ON".format(chn.name()), pos='midCenterBot', fade=True) else: a.node().inputTarget[a.index()].sculptTargetIndex.set(-1) pm.mel.eval("updateBlendShapeEditHUD;") pm.inViewMessage(amg="{}: Edit mode is OFF".format(chn.name()), pos='midCenterBot', fade=True)
def rebuild_BS(self, main_index, bsNode='', inBetArray=[]): BS_targets = {} inBetweens = [] to_parent = [] target = pm.sculptTarget(bsNode, target=main_index, edit=True, regenerate=True) if target is not None: py_targ = pm.PyNode(target[0]) pm.addAttr(py_targ, ln='value', at='float', defaultValue=1.000) to_parent.append(py_targ) if len(inBetArray) > 0: for value in inBetArray: inBet = pm.sculptTarget(bsNode, target=main_index, edit=True, regenerate=True, ibw=value) py_inBet = pm.PyNode(inBet[0]) newInBet = pm.rename( py_inBet, str(py_targ.name() + '_InBet_%s' % ''.join(str(value).split('.')))) inBetweens.append([newInBet, value]) to_parent.append(py_inBet) self.tag_for_inbetween(py_targ, py_inBet, value) # print(py_inBet) # BS_targets[py_targ] = inBetweens # parent to main group pm.parent(to_parent, self.mainGroup) return
def getRebuildTargetFromShapeEditor(): ''' 쉐입 에디터에서 선택된 타겟 목록 얻어옴. Result: [u'blendShape1.2', u'blendShape1.3'] [블렌드쉐입노드.타겟ID] 형식으로 리턴됨. split(".")으로 블렌드쉐입 노드와, 타겟 ID를 얻어옴. getShapeEditorTreeviewSelection() 명령어는 C:\Program Files\Autodesk\Maya2017\scripts\others\createShapePanelMenu.mel 파일에 있는 스크립트 임. ''' # 쉐입 에디터에서 선택한 타겟 목록 리턴 selectedTargetL = pm.mel.getShapeEditorTreeviewSelection( 24) # @UndefinedVariable # selectedTargetL = [u'blendShape2.0', u'blendShape2.1'] # 이런 형식으로 들어옴. resultMesh = [] for item in selectedTargetL: # .으로 분리 blendShapeNode, targetID = item.split( '.') # blendShape1.1 => blendShape1 1 # int형으로 변환 targetID = int(targetID) # pynode로 변환 blendShapeNode = pm.PyNode(blendShapeNode) # 타겟명을 알아야 함. attrs = blendShapeNode.listAliases() targetName = attrs[targetID][0] # sculptTarget명령어는 타겟이름과 같은 이름의 오브젝트가 존재하면 작동 안함. # 타겟이름과 같은 오브젝트가 씬에 있는지 체크 if pm.objExists(targetName): print u' "%s" 타겟과 같은이름의 오브젝트가 이미 존재합니다.' % targetName continue # 타겟 분리 mesh = pm.sculptTarget(blendShapeNode, e=True, regenerate=True, target=targetID) # 분리된 메쉬 resultMesh.append(mesh) return resultMesh
def rebuild_targets(obj): """Simple rebuild targets using pymel builtin function""" if len(obj) == 0: pymel.warning('Nothing in selection') return None blend_shape_node = obj[0].listHistory(type='blendShape') if len(blend_shape_node) == 0: pymel.warning('Could not find Blendshape node on selected mesh') return None blend_aliases = blend_shape_node[0].listAliases() for alias in blend_aliases: target_name = alias[0] target = pymel.sculptTarget(blend_shape_node, e=True, r=True, t=alias[1].index()) pymel.rename(target, target_name)
def add_frame_sculpt(layer_node, anim=False, keyf=[1, 0, 0, 1]): """Add a sculpt frame to each selected layer Args: layer_node (dagNode list): ist of Crank layer node to add the sculpt frame anim (bool, optional): if True, will keyframe the sculpt frame in the specified range. keyf (list, optional): Keyframe range configuration. EaseIn, pre hold, post hold and ease out """ objs = layer_node.layer_objects.inputs() bs_node = layer_node.layer_blendshape_node.inputs() # ensure other targets are set to false the edit flag # get current frame cframe = int(pm.currentTime(query=True)) # get valid name. Check if frame is ducplicated in layer frame_name = "frame_{}".format(str(cframe)) i = 1 while layer_node.hasAttr(frame_name): frame_name = "frame_{}_v{}".format(str(cframe), str(i)) i += 1 # create frame master channel master_chn = attribute.addAttribute(layer_node, frame_name, "float", value=1, minValue=0, maxValue=1) # keyframe in range the master channel if anim: # current frame pm.setKeyframe(master_chn, t=[cframe], v=1, inTangentType="linear", outTangentType="linear") # pre and post hold pre_hold = keyf[1] if pre_hold: pm.setKeyframe(master_chn, t=[cframe - pre_hold], v=1, inTangentType="linear", outTangentType="linear") post_hold = keyf[2] if post_hold: pm.setKeyframe(master_chn, t=[cframe + post_hold], v=1, inTangentType="linear", outTangentType="linear") # ease in and out if keyf[0]: ei = pre_hold + keyf[0] pm.setKeyframe(master_chn, t=[cframe - ei], v=0, inTangentType="linear", outTangentType="linear") if keyf[3]: eo = post_hold + keyf[3] pm.setKeyframe(master_chn, t=[cframe + eo], v=0, inTangentType="linear", outTangentType="linear") for obj, bsn in zip(objs, bs_node): dup = pm.duplicate(obj)[0] bst_name = "_".join([obj.name(), frame_name]) pm.rename(dup, bst_name) indx = bsn.weight.getNumElements() pm.blendShape(bsn, edit=True, t=(obj, indx, dup, 1.0), ts=True, tc=True, w=(indx, 1)) pm.delete(dup) pm.blendShape(bsn, e=True, rtd=(0, indx)) # is same as: bs.inputTarget[0].sculptTargetIndex.set(3) pm.sculptTarget(bsn, e=True, t=indx) # connect target to master channel pm.connectAttr(master_chn, bsn.attr(bst_name))
def rebuild_targets_match(obj): """ Regenerate Blendshape targets with deformers masks applied. If you have masked out a portion of a blendshape that mask will now be baked into the generated target. :param obj: Node that has blendshapes applied. :return: Regenerated targets. """ # Disable skin an tweak nodes. if not obj: print "Need to select object with blendshape" return try: skin_node = obj.listHistory(type='skinCluster')[0] except: skin_node = None pass try: tweak_node = obj.listHistory(type='tweak')[0] except: tweak_node = None pass if skin_node: skin_node.envelope.set(0) if tweak_node: tweak_node.envelope.set(0) # Get blendshape blend_shape_node = obj.listHistory(type='blendShape')[0] blend_aliases = blend_shape_node.listAliases() connection_dict = {} # Store connections, going to break them and reconnect later. for alias in blend_aliases: attribute = '{}.{}'.format(blend_shape_node, alias[0]) connection = pymel.listConnections(attribute, destination=True, plugs=True) if connection: connection_dict[attribute] = connection[0] pymel.disconnectAttr(connection[0], attribute) pymel.setAttr(attribute, 0) for alias in blend_aliases: target_name = alias[0] target = pymel.sculptTarget(blend_shape_node, e=True, r=True, t=alias[1].index()) pymel.rename(target, target_name) # Set blendshape value to 1 attribute = '{}.{}'.format(blend_shape_node, alias[0]) pymel.setAttr(attribute, 1) # todo: forget why this is re finding the pynode and not just using target. pynode_target = pymel.PyNode(target_name) print target print pynode_target # Baking vertex position from masking pos = match_vertex_position.get_vtx_pos(obj) match_vertex_position.set_vtx_pos(pynode_target, pos) # Set blendshape value to 0 pymel.setAttr(attribute, 0) if attribute in connection_dict.keys(): pymel.connectAttr(connection_dict[attribute], attribute) # Re-enable skin and tweak nodes if skin_node: skin_node.envelope.set(1) if tweak_node: tweak_node.envelope.set(1)
def rebuild_target(self, target_index): return pm.sculptTarget(self.bs_node, e=1, r=1, t=target_index) or []