もうちょっとだけなんとか
具体的には
前回は objectA から objectB だったんですけども、
objectA_left から objectB_right へ
ジョイント名は left_joint から right_joint へ
ただし前回のままだと、 left_joint right_joint を両方使用してる場合はおかしくなるので
ジョイント名は left_joint から right_joint へ
ジョイント名は right_joint から left_joint へ
基本的には前回のやつのインフルエンス書き換え部分を何とかすれば良いはず
改修
import maya.cmds as cmds
from xml.etree import ElementTree
def getSkinClusterNode(target):
history = cmds.listHistory(target,pruneDagObjects =True)
skinNode = cmds.ls(history,type = "skinCluster") or None
if skinNode != None:
return skinNode[0]
return None
def getBindInfo(filePath):
tree = ElementTree.parse(filePath)
root = tree.getroot()
skinBindDict = {}
##weights を見つける
for e in root.findall('weights'):
#それぞれのパラメーターを取得
inf = e.get("source")
shape = e.get("shape")
deformer = e.get("deformer")
if deformer in list(skinBindDict.keys()):
if inf not in skinBindDict[deformer]["inf"]:
skinBindDict[deformer]["inf"].append(inf)
else:
skinBindDict[deformer] = {
"inf":[inf],
"shape":shape
}
return skinBindDict
def importSkinWeight(filePath,fileName):
skinBindDict = getBindInfo(filePath+fileName)
for deformerNode in list(skinBindDict.keys()):
target = skinBindDict[deformerNode]["shape"]
infs = skinBindDict[deformerNode]["inf"]
#skinClusterの有無確認
targetSkinNode = getSkinClusterNode(target)
if targetSkinNode == None:
targetSkinNode = cmds.skinCluster(infs,target,normalizeWeights = 1,toSelectedBones =True,name = deformerNode)[0]
else:
#現在のインフルエンスを取得して、addInfするための差分を取る
curInfs = cmds.skinCluster(targetSkinNode, q =True, inf =True)
addInfs = list(set(infs) - set(curInfs))
for inf in addInfs:
cmds.skinCluster(targetSkinNode, e =True, ai = inf, weight = 0)
cmds.deformerWeights(fileName, path = filePath, deformer = targetSkinNode, method = "index",im = True)
cmds.skinCluster(targetSkinNode,e =True,forceNormalizeWeights = True)
##前回のはそのままにして別ものとして改修-------------------------------------------
def switchSkinWeight(source,target,leftString,rightString):
#sourceのスキニング情報を書き出す
sourceSkinNode = getSkinClusterNode(source)
if sourceSkinNode == None:
return
#書き出し場所はひとまずmayaのuserAppDir
tmpExportPath = cmds.internalVar(userAppDir=True) + 'temp/'
tmpFileName = "tempSkinWeight.xml"
cmds.deformerWeights(
tmpFileName,
path = tmpExportPath,
deformer = sourceSkinNode,
format ="XML",ex = True
)
targetShape = cmds.listRelatives(target,type = "shape")[0]
#sourceのXMLを読み込む
tree = ElementTree.parse(tmpExportPath+tmpFileName)
root = tree.getroot()
for e in root.findall('shape'):
e.set("name",targetShape)
for e in root.findall('weights'):
targetInf = e.get("source")
if leftString in targetInf:
#左なので右化
replaceInf = targetInf.replace(leftString,rightString)
elif rightString in targetInf:
#右なので左化
replaceInf = targetInf.replace(rightString,leftString)
else:
#右でも左でもないのでそのまま
replaceInf = targetInf
replaceInf = targetInf.replace(searchString,replaceString)
e.set("source",replaceInf)
e.set("shape",targetShape)
#skinCluster名も念のため調整
e.set("deformer",target + "_skinCluster")
#XMLファイルとして保存する(上書き)
tree.write(tmpExportPath + tmpFileName, encoding='UTF-8')
#XMLファイルを読み込ませる
importSkinWeight(tmpExportPath,tmpFileName)
#一応一時ファイルとしては削除
os.remove(tmpExportPath+tmpFileName)
制限事項と改修案
左右のjointを区別するためのネーミングルール必須
単純なネーミングでの識別ではなく、jointのラベルを使った入れ替えとかどうだろか
その為にはシーン内 or ツリー内のjointを全取得してラベルをkeyとしたdictつくるとか?
うん?これでヒトネタ書けそうな気もしますね