もうちょっと何とかしたくなりました。
具体的には
objectA がスキニングされてる状態で、
同一メッシュのobjectB,objectCにもjoint名を変えて
ウェイト情報を転送したい
考える
objectAのスキニング情報をXMLで書き出して、
XMLファイルをテキストデータとして扱って、中身をreplaceして読ませるとか?
ただ予期せぬ箇所のreplaceが発生すると困る。
ちゃんと?やるなら
- objectAのスキニング情報をXMLファイルで書き出して、
- XMLファイルをXMLのデータとしてパースして、
- 対象となるアトリビュートを書き換えて、
- 書き換えた内容をどこかにXMLとして保存して、
- 前回作った importSkinWeight に渡す。
とかかなぁ
雑に実装
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 substituteSkinWeight(source,target,searchString,replaceString):
#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()
#各アトリビュートを書き換える
#<shape> の name と
#<weights> の deformer / source / shape を最低限書き換えれば行けるかな?
for e in root.findall('shape'):
e.set("name",targetShape)
for e in root.findall('weights'):
targetInf = e.get("source")
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)
こんな感じのデータを用意して、pCube1 のスキンウェイトをpCube2へ
substituteSkinWeight("pCube1","pCube2","cubeA","cubeB")
# Exported deformer weights to 'C:/Users/kubo/Documents/maya/temp/tempSkinWeight.xml'. #