maya skinWeight import をちょっと何とかする2


https://qiita.com/9boz/items/ed9575fee8d59b1c1831

もうちょっと何とかしたくなりました。

具体的には

**objectA がスキニングされてる状態で、
同一メッシュのobjectB,objectCにもjoint名を変えて
ウェイト情報を転送したい**

考える
-

objectAのスキニング情報をXMLで書き出して、
XMLファイルをテキストデータとして扱って、中身をreplaceして読ませるとか？

ただ予期せぬ箇所のreplaceが発生すると困る。

ちゃんと？やるなら
- objectAのスキニング情報をXMLファイルで書き出して、
- XMLファイルをXMLのデータとしてパースして、
- 対象となるアトリビュートを書き換えて、
- 書き換えた内容をどこかにXMLとして保存して、
- 前回作った　importSkinWeight　に渡す。

とかかなぁ

雑に実装
-

```python
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へ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/b950fdbc-524d-2be7-4eeb-fc0a90d52c0e.png)


```
substituteSkinWeight("pCube1","pCube2","cubeA","cubeB")
# Exported deformer weights to 'C:/Users/kubo/Documents/maya/temp/tempSkinWeight.xml'. # 
```

お、行けたっぽい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/c78636ff-9a30-e0bc-b291-a81b85663d88.png)