#!/usr/bin/env python # -*- coding: utf-8 -*- from maya import cmds from maya import mel import os, json import pymel.core as pm from . import weight from . import common from . import qt import maya.api.OpenMaya as om import re def setSoftEdge(mesh, angle=120): # 法線のロック解除 cmds.polyNormalPerVertex(mesh + '.vtx[*]', unFreezeNormal=True) # アングルを設定 cmds.polySoftEdge(mesh+'.e[*]', a=angle) # Separate_Face,Duplicate_Faceから呼び出してくるモジュール def face_extraction(faces=None, deleteOrg=True, selectDuplicated=True, transferWeight=True): ''' メッシュを選択したフェイスで切り分ける deleteOrg 切り分け元のフェイスを削除するかどうかを指定デフォルトTrue faces → 外部ツールからフェイスのリストを渡して実行したい場合の引数 ''' if faces is None: selection = cmds.ls(sl=True) else: selection = faces selObjects = [] for sel in selection: objNameTemp = sel.split('.') if not objNameTemp[0] in selObjects: selObjects.append(objNameTemp[0]) cmds.select(cl=True) duplicated = [] # 最後の選択格納用 # ハイライトされているオブジェクト毎に処理 for selObj in selObjects: compTemp = [] # バラバラのコンポーネントをオブジェクト毎に格納するリスト # 選択されているコンポーネントを整理 for sel in selection: objNameTemp = sel.split('.') objName = objNameTemp[0] # コンポーネントのオブジェクト名 # オブジェクト名が一致且つフェイス選択ならリスト入り if selObj == objName and '.f[' in sel: compTemp.append(sel) # print 'compTemp ALL : '+str(compTemp) if len(compTemp) != 0: dupObj = cmds.duplicate(selObj, rr=True) # 子供のオブジェクト取得関数呼び出し children = cmds.listRelatives(dupObj[0], type='transform', ad=True) # 子供のオブジェクトがある場合は重複を避けるため削除 if children: cmds.delete(children) duplicated.append(dupObj[0]) if transferWeight: # ウェイト転送フラグが有効だったら weight.transfer_weight(selObj, dupObj, logTransfer=False) # ウェイトを転送 faces = ",".join(compTemp) # リストを括弧のない文字列に faces = faces.replace(selObj, dupObj[0]) # 名前置き換え delface = faces.split(',') cmds.selectMode(co=True) cmds.hilite(dupObj) cmds.select(delface, r=True) #print 'del face :',delface for obj in dupObj: face_count = str(len(common.conv_comp(obj, mode='face'))) cmds.select(obj+'.f[0:'+face_count+']', tgl=True) #mel.eval('InvertSelection;') # 選択の反転 deleter = cmds.ls(sl=True) cmds.delete(deleter) # 最初に選択されていなかったフェース部分のみ削除 # 削除フラグが立っていたら古いフェイス削除 if deleteOrg is True: cmds.delete(compTemp) if selectDuplicated: cmds.select(duplicated) return duplicated #クラスタデフォーマの書き戻し class ClusterCopy(): 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 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 duplicate_with_skin(nodes, parentNode=None): #親子付けがあってもエラーはかないように修正 #print nodes # リストタイプじゃなかったらリストに変換する if not isinstance(nodes, list): nodes = [nodes] dupObjs = [] for node in nodes: #子供のノード退避用ダミーペアレントを用意 dummy = common.TemporaryReparent().main(mode='create') common.TemporaryReparent().main(node,dummyParent=dummy, mode='cut') #複製 dup = cmds.duplicate(node)[0] #ウェイト転送メソッドをSimpleWeightコピペに変更 weight.SimpleWeightCopyPaste().main(node, mode='copy', saveName=__name__, weightFile=node) weight.SimpleWeightCopyPaste().main(dup, mode='paste', saveName=__name__, weightFile=node) #親子付けを戻す common.TemporaryReparent().main(node,dummyParent=dummy, mode='parent') #ダミーペアレントを削除 common.TemporaryReparent().main(dummyParent=dummy, mode='delete') if parentNode is not None: cmds.parent(dup, parentNode) dupObjs.append(dup) return dupObjs #シーン内、もしくは入力メッシュ内にゼロポリゴンオブジェクトがあるかどうか調べる関数 def cehck_zero_poly_object(mesh=None, pop_msg=True): #mesh 入力メッシュ #pop_msg 探索結果を表示するかどうか if mesh == None: polyMeshes = common.search_polygon_mesh(cmds.ls(tr=True)) else: polyMeshes = common.search_polygon_mesh(mesh) zeroPolyObj = [] if polyMeshes == None: if pop_msg: cmds.confirmDialog( title="Check",message='Zero Polygon Object Count : 0') return zeroPolyObj for p in polyMeshes: vtx = cmds.polyListComponentConversion(p, tv=True) if vtx == []: zeroPolyObj.append(p) if not pop_msg: return zeroPolyObj if zeroPolyObj == []: cmds.confirmDialog( title="Check",message='Zero Polygon Object Count : 0') else: msg = 'Zero Polygon Object Count : '+str(len(zeroPolyObj)) for p in zeroPolyObj: msg+='\n[ '+p+' ]' cmds.confirmDialog( title="Check",message=msg ) cmds.select(zeroPolyObj, r=True) return zeroPolyObj #スキニングを保ったままメッシュマージするクラス class MeshMarge(): def main(self, objects): self.objects= objects qt.Callback(self.marge_run()) return self.marged_mesh def marge_run(self): objects = common.search_polygon_mesh(self.objects, serchChildeNode=True, fullPath=True) #print 'marge target :', objects if len(objects) < 2: self.marged_mesh = objects return True skined_list = [] no_skin_list = [] parent_list = [cmds.listRelatives(obj, p=True, f=True) for obj in objects] for obj in objects: skin = cmds.ls(cmds.listHistory(obj), type='skinCluster') if skin: skined_list.append(obj) else: no_skin_list.append(obj) if no_skin_list and skined_list: skined_mesh = skined_list[0] for no_skin_mesh in no_skin_list: weight.transfer_weight(skined_mesh, no_skin_mesh, transferWeight=False, returnInfluences=False, logTransfer=False) if skined_list: marged_mesh = pm.polyUniteSkinned(objects)[0] pm.polyMergeVertex(marged_mesh, d=0.001) target_mesh = pm.duplicate(marged_mesh)[0] weight.transfer_weight(str(marged_mesh), str(target_mesh), transferWeight=True, returnInfluences=False, logTransfer=False) else: marged_mesh = pm.polyUnite(objects, o=True)[0] pm.polyMergeVertex(marged_mesh, d=0.001) target_mesh = pm.duplicate(marged_mesh)[0] #pm.delete(objects) for obj in objects: if pm.ls(obj): pm.delete(obj) pm.delete(marged_mesh) all_attr_list = [['.sx', '.sy', '.sz'], ['.rx', '.ry', '.rz'], ['.tx', '.ty', '.tz']] for p_node in parent_list: if cmds.ls(p_node, l=True): all_lock_list = [] for attr_list in all_attr_list: lock_list = [] for attr in attr_list: lock_list.append(pm.getAttr(target_mesh+attr, lock=True)) pm.setAttr(target_mesh+attr, lock=False) all_lock_list.append(lock_list) pm.parent(target_mesh, p_node[0]) for lock_list, attr_list in zip(all_lock_list, all_attr_list): for lock, attr in zip(lock_list, attr_list): #continue #print 'lock attr :', lock, target_mesh, attr pm.setAttr(target_mesh+attr, lock=lock) break pm.rename(target_mesh, objects[0]) pm.select(target_mesh) self.marged_mesh = str(target_mesh) return True