[maya] animationExportコマンドの罠 [pymel]

久々にMayaPymelネタ。

Mayaのコマンド Mel MayaCmds Pymel それぞれにAnimationExportコマンドは存在するのですが、こいつにはとんでもない罠があります。
Pymelコマンドの場合 exportSelectedAnim() というコマンド名です。
この関数名からしたら、どう考えても

『選択しているノードのキーフレームアニメーションを、ExportSelectionする』

もんだと。
ExportしたものをImportすればアニメーションが再読み込みできると思うでしょう。
私もそう思いましたよ。
しかし、それは大きな勘違い。
これは、アニメーションをExportするのではなく、
アニメーションノードをExportするコマンドなんです。
え、何が違うんよ?と思うでしょうが、違うんです!!

 

Read more

[mayaPython]バージョンを上げてシーンを保存する

Mayaに限らず、作業しているシーンを保存する場合は 前に保存したものを上書きするのではなく _v01 のようにバージョンをつけて保存する…というのを日常的にやってる人も多いかと思います。

そのとき、Windowsの仕様なのか FileDialogで バージョンナシのものをリネームして、ファイル名をバージョンなしに設定して保存する をすると リネームしたはずなのに、上書きしますか?と聞かれ

非常に ウザい

ので、バージョンをつけて保存してくれるコマンドを書いてみました。

[python] import os,os.path,re,glob
import maya.cmds as mc

#フォルダ内にあるバージョンファイルのバージョンに+1したファイル名を返すスクリプト

def incrementFileName(ST_path,ST_vName="_",IN_defIncrementNum=2):

if os.path.exists(ST_path):

basename = os.path.basename(ST_path)
fileName = os.path.splitext(basename)[0] fileNameNonVer = re.sub(ST_vName+"v[0-9]+$","",fileName)
fileExt = os.path.splitext(basename)[1] dirName = os.path.dirname(ST_path)

fileList = glob.glob(dirName+"/"+ fileNameNonVer + ST_vName + "v" + "*"+fileExt)

incrimentNum = 0

if len(fileList) == 0:

incrimentNum = 1

else:

maxNum = 1

for files in fileList:

buff = files.split(ST_vName + "v")

if maxNum < int(buff[len(buff) -1].strip(fileExt)):

maxNum = int(buff[len(buff) -1].strip(fileExt))

incrimentNum = maxNum + 1

return dirName + "/" + fileNameNonVer + ST_vName + "v" + str(incrimentNum).zfill(IN_defIncrementNum) + fileExt

#バージョンを残して保存するスクリプト本体
def incrementSaveFile():

ST_mayaScenes = mc.file(q=True,sceneName=True)

if ST_mayaScenes != "":

ST_IncrementFileName = incrementFileName(ST_mayaScenes)
os.rename(ST_mayaScenes,ST_IncrementFileName)
mc.file(save=True)
else:
#新規ファイルの場合は、ダイアログを出して新規保存
multipleFilters = "Maya ASCII (*.ma);;Maya Binary (*.mb);;All Files (*.*)"
saveFileName = mc.fileDialog2(fileFilter=multipleFilters, dialogStyle=1)
print saveFileName[0] ST_type = "mayaAscii"
if os.path.splitext(saveFileName[0])[1] == ".mb":

ST_type = "mayaBinary"

mc.file(rename=saveFileName[0])
mc.file(save=True,f=True,type=ST_type)

#実行
incrementSaveFile()

[/python]

新しいシーンの場合は、ダイアログを出してファイル名を指定して保存します。

上のコマンドの場合、バージョンは _v00 のように _ + v + 数字二桁 のバージョンがつきますが、それを変更したい場合は、

47行目の

ST_IncrementFileName = incrementFileName(ST_mayaScenes)

ST_IncrementFileName = incrementFileName(ST_mayaScenes,<区切る文字>,<桁数>)

ex: test.mb => incrementFileName(ST_mayaScenes,".",3) => test.v001.mb

に変更すると、桁数と区切る文字を変えられます。

 

これでバージョンをつけて保存する手間も減って楽チン☆ と、気楽に保存しまくって バージョンがすごいことになったりしなかったり。。。

[mayaPython] 選択しているカーブの色を変える にUIをつけてみた。

前に書いた 選択しているカーブの色を変える に、UIをつけてみました。

[python] import maya.cmds as mc

def selectPalette():

selectNum = mc.palettePort(palette,q=True,scc=True)
print selectNum
changeCurveColor(selectNum)

def changeCurveColor(colorNum):
selectNode = mc.ls(sl=True,fl=True)
if selectNode != None:
for node in selectNode:
shapeNode =mc.listRelatives(node,s=True)
if shapeNode != None:
for shape in shapeNode:
if mc.objectType(shape) == "nurbsCurve":
mc.setAttr(shape + ".overrideEnabled",1)
mc.setAttr(shape + ".overrideColor",int(colorNum))

windowName = "changeCurveColorUI"
if mc.window(windowName,exists=True) == True:
mc.deleteUI(windowName)
paletteWindow = mc.window(windowName,title=windowName)
paletteLayout = mc.frameLayout(labelVisible=0)
palette = mc.palettePort( dimensions=(16,2),width=16 * 20,height= 2 * 20,transparent = 0,topDown=True,colorEditable=False,cc=selectPalette)

for i in range(1,31):

col = mc.colorIndex(i,q=True)
mc.palettePort(palette,e=True,rgbValue=(i,col[0],col[1],col[2]))

mc.showWindow(paletteWindow)

[/python]

ベタ書きであれですが、colorIndexとpalettePortのお陰でわりと簡単にかけました。

palettePortを知らなかった時は、

optionMenuとかtextScrollListの後ろを、Colorの色にして選択出来るようにして~とか、

colorIndexを知らなかったときは、

1こ1こ色をピッカーでとって、31パターンの色を取得して~とか、

とてつもなくアナログな手段を駆使してつくろうと思ってたわけですが、さすがにそんな事しなくても手段はあったようです。

HAHAHA…はは…orz

[mayaPython] blendShapeに追加・削除するScripts

[python] import maya.cmds as mc

def deleteBlendShape(blendShapeNode,geo):

if mc.objExists(blendShapeNode) == True:

blendShapeTaget = mc.blendShape(blendShapeNode,q=True,g=True)

targetNodeList = mc.blendShape(blendShapeNode,q=True,t=True)

if geo in targetNodeList:

taget_index = targetNodeList.index(geo)

mc.blendShape(blendShapeNode,e=True,rm=True,t=(blendShapeTaget[0],taget_index,geo,1))

def addBlendShape(blendShapeNode,geo,weight=1):

if mc.objExists(blendShapeNode) == True:

blendShapeTarget = mc.blendShape(blendShapeNode,q=True,g=True)

targetNodeList = mc.blendShape(blendShapeNode,q=True,t=True)

if (geo in targetNodeList) != True:

mc.blendShape(blendShapeNode,e=True,t=(blendShapeTarget[0],len(targetNodeList),geo,weight))
[/python]

blendShapeコマンドでBlendShapeのシェイプターゲット追加・削除 ができるのですが、このコマンドを使ってやろうとすると非常にわかりにくいので

自分でコマンドを書いてみました。

引数の blendShape には、追加したいBlendShapeNodeの名前 geo には、追加したいメッシュノードの名前を入れます。

blendShapeコマンドの、 target(t)には、

  1. string: ベース オブジェクト
  2. int: インデックス
  3. string: ターゲット オブジェクト
  4. double: ターゲット値

を、タプル形式でセットして指定する必要があり、これが非常にややこしいのでそれを毎度かくのがメンドクサイ。。。

 

はじめ、shapeをDeleteするために使うアトリビュートが rm と geometry だとばかり思って、コマンドでは消せないのか?とか頭をよぎったりしましたが。

だって、Helpの書き方が

-rm フラグも指定していない限り、指定したオブジェクトは、このデフォーマ オブジェクトによって変形されるオブジェクトのリストに追加されます

とか、どうみても rm=True,g=ShapeNode にしろとしか見えないですって(‘A`)

と、地味にターゲットの消し方がわからずしばらくあたふたしたものの、消せるようになったのでメモがてら書き起こしておきます。

MayaのCurveの色を変える おまけ

ノードの奥深くにあっていちいち色変更するのも面倒なので、簡単なスクリプトを書いてみた。

[python] def changeCurveColor(colorNum):
selectNode = mc.ls(sl=True,fl=True)
if selectNode != None:
for node in selectNode:
shapeNode =mc.listRelatives(node,s=True)
if shapeNode != None:
for shape in shapeNode:
if mc.objectType(shape) == "nurbsCurve":
mc.setAttr(shape + ".overrideEnabled",1)
mc.setAttr(shape + ".overrideColor",int(colorNum))
[/python]

changeCurveColor() 

UIあるとさらに便利そうだけど、UI書くのは面倒なのでまた今度。いい加減寝るんだ自分! 

おまけの追記。
setAttrのときに、Transformノードの名前だとダメかなと思って、ShapeノードをListしてきてListしたノードのうち、nurbsCurveノードにSetAttrするように書いたけど、

[python] def changeCurveColor(colorNum):
selectNode = mc.ls(sl=True,fl=True)
if selectNode != None:
for node in selectNode:
mc.setAttr(node + ".overrideEnabled",1)
mc.setAttr(node + ".overrideColor",int(colorNum))
[/python]

のように、transformノードの名前でSetAttrしても大丈夫なようです。
(ちゃんと確認したわけじゃないからアレだけど、CameraShapeとかもtransfromノードの名前で大丈夫だし そのへんは良きに計らってくれてるのか) 
まぁ、curveノード以外のものが選択されてても うえのほうがエラー吐かないしいい…のかな。