Maya Script Python スキニングウェイト情報のコピペ その2

import maya.cmds as cmds
import re

f = lambda x : x.rsplit("|",1)[1] if x.find("|") != -1 else x
oDic = {}

def gkn_weight_paste() :
	if oDic != {} :
		oSel2 = cmds.ls( sl= 1, o= 1, fl= 1 )
		oVtx2 = cmds.filterExpand( sm= 31 )
		oOname = cmds.textField( "Original", q= 1, tx= 1 )
		oCname = cmds.textField( "Change", q= 1, tx= 1 )
		for s in oSel2 :
			oSkt2 = cmds.listHistory( s )
			oCls2 = cmds.ls( oSkt2, type= 'skinCluster' )[0]
			oDic2 = dict([ (x,0.0) for x in cmds.skinCluster( oCls2, q= 1,inf= 1 ) ])
			for v in oVtx2 :
				s = s.rsplit("|",1)[1] if s.find("|") != -1 else s
				v = v.rsplit("|",1)[1] if v.find("|") != -1 else v
				if v.split( "." )[0] == "".join( s.split( "Shape" ) ) :
					for j,val in oDic.items() :
						if oOname != "" and oCname != "" and oDic2.has_key(re.sub( oOname, oCname ,j ,1 )):
							oDic2[re.sub( oOname, oCname ,j ,1 )] = val
						else :
							oDic2[j] = val
					cmds.skinPercent( oCls2, v, nrm= 0 , transformValue= ( oDic2.items() ) )

if cmds.window( "weight_copy_pasteUI", q= 1, ex= 1 ) :
	cmds.deleteUI( "weight_copy_pasteUI" )
wtool = cmds.window( "weight_copy_pasteUI", title= "Gkn Weight Copy Paste", w= 100, h= 100 )
cmds.columnLayout( adjustableColumn= 1 )
cmds.frameLayout( mh= 10, mw= 10, lv= 0 )
cmds.rowLayout( nc= 5, adj= 3, cw5= ( 50, 50 , 10 , 50 , 50 ) )
cmds.text( l= "Original")
cmds.textField( "Original",w= 50 )
cmds.text( l= "" )
cmds.text( l= "Change")
cmds.textField( "Change",w= 50 )
cmds.setParent('..')
cmds.rowLayout( nc= 4, adj= 2, cw4= ( 50, 10 , 50 , 50 ) )
cmds.button( l= "Clear", w= 80, c= ("cmds.textField( 'Original', e= 1, tx= '' )\ncmds.textField( 'Change', e= 1, tx= '' )"))
cmds.text( l= "" )
cmds.button( l= "Copy", w= 80, c= (
"oSel = cmds.ls( sl= 1, o= 1 )[0]\n"+
"oSkt = cmds.listHistory( oSel )\n"+
"oCls = cmds.ls( oSkt, type= 'skinCluster' )[0]\n"+
"oVtx = cmds.filterExpand( sm= 31 )[0]\n"+
"oJnt = [ f(x) for x in cmds.skinPercent( oCls, oVtx, query= 1, transform= None ) ]\n"+
"oWei = cmds.skinPercent( oCls, oVtx, query= 1, value= 1 )\n"+
"oWei = [ x for x in oWei if x > 0.0 ]\n"+
"oDic = dict( zip( oJnt, oWei ) )"))
cmds.button( l= "Paste", w= 80, c= ("gkn_weight_paste()"))
cmds.setParent('..')
cmds.showWindow( wtool )

複数ある筒状のメッシュのウェイトを編集する際に、一つの筒を編集して、他のメッシュにコピーできたら楽だな。
という不精な思いで作りました。
スクリプトを実行すると、ウィンドウが表れます。「Original」と書かれている所にリネームしたい文字を入力します。例:「A」
「Change」と書かれている所にリネーム後の文字を入力します。例:「B」
ウェイト情報を持った単一の頂点を選択し、「Copy」ボタンを押します。
ペーストしたい単一、もしくは複数の頂点を選択し、「Paste」を押すとリネームされた情報がペーストされます。

 

リネームに正規表現を使ってみました。同じ単語には一度しか反応しません。
コピーする時はウェイト情報の入ったインフルエンスの名前しか取得しません。
ペーストする際は、選択されたメッシュのインフルエンスを参照し、同じインフルエンスもしくはリネームして同じ名前になるインフルエンスが
無い限りはペーストできません。
それ以外のインフルエンスには強制的にゼロが割り振られるので、1を超えることは無いかと思います。
コピー元のウェイト情報の合計が1以下の場合は問題があるかと思います。その場合はコピー前に丸めておいてください。

 

作っていて思ったのですが、ペーストはグローバルの変数を見ればいいのだから関数でも良いんじゃないか。ということで関数化しました。
その後、コピーも変数に関数を入れてしまえば、動作自体は関数でいいんじゃないか。と関数化してみましたが、出来ました。
しかしこのスクリプトではそれをしていません。
ボタンコマンドで、複数のコマンドを書くときには「\n」を書いてコマンドを列挙すると実行できる。ということを備忘録的に書いておきたかったためです。
ただ、それでは「for」文を回すことが出来なかったので、リスト内包表記とラムダ関数、三項演算子を使うことで同じことができました。
今まで長ったらしく書いていたものが簡単に書けました。

 

Python3では標準で辞書内包表記が出来るそうですが、それ以前ではできないが同じ事は出来る。ということも知りました。
それを使って、ペーストするメッシュのインフルエンスで新たな辞書を作成し、値にゼロを設定し、必要なところだけコピー元の辞書と
置き換えているので、合計が1を超えることが無くなった。
三項演算子、正しくは条件演算子というそうですが、便利ですねぇ、他の言語と書き方が違うようですが、自分はPythonしか知りません。
コピーもペーストも関数化出来たので、以前作ったエディタに組み込んでみました。
そのエディタですが、選択したメッシュに設定されているインフルエンスを参照してウィンドウの大きさが変わるのですが、
骨の数が多すぎると画面からはみ出てしまうことが判明し、その部分を修正中です。
インターフェイスは面倒臭い。

コメント/トラックバック (1件)

  1. 技研 | mel - Maya Script Python Gkn Weight Editor ウェイトエディタ のコメント:

    [...] ※追記2012/4/11 コピー・ペーストの機能を追加しました。 機能の説明については、こちらにあります。weight_editor [...]

コメントする

post date*

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

トラックバックする

トラックバック用URL:

アニメーションが親切に解説されております

レンダリング、ライティングの基本が分かります

図版が見やすい美術解剖書です