ON-BLOG

CGのこと、あれこれ書いてます。

スクリプト書いてみようかと

超久しぶりにブログ書きます。
というのも色々本当にありまして…


さておき
では今回は割とガッツリスクリプトを書いてみようかと思います。

はじめに仕様面を決めてみようかと思います。

お題:ポーズセーブスクリプト
制作理由:MAYAデフォルトでポーズだけ保存したり、外部に残しておける方法がないため。
実装方法:今回は選択した物と、その子ども以下の階層のSRTとアトリビュートの値を保存する。
     シェイプや、追加アトリビュートについては現状は無しで、完成後追加で実装できればする。
     できればカレントのシェリフにも追加したい。

ポーズ保存と実行なので、以下の注意点がある。
1.選択したオブジェクトはフルパスし、重複するオブジェクトはエラーで出力
2.実行する際は、階層の持ち方に注意する。
3.外部に保存するコマンドとそうではない、イテレーションが早いコマンドも必要。パスはドキュメントで
4.外部保存の形式はなんでもいいが、中身はPythonで実装。
5.できれば、複数フレームの一斉書き出しがほしい。



プロトタイプとして、まずは値の取得から行う。

# -*- coding: utf-8 -*-
import maya.cmds as cmds

oSel = cmds.ls(sl=True,l=True, type='transform')

for i in oSel:
  #name
  print i
  #Rotate
  ro = cmds.xform(i,q=True,ro=True)
  #Trans
  tr = cmds.xform(i,q=True,t=True)
  #Vis
  vis = cmds.getAttr(i+".visibility")
  #Scale
  sc = cmds.xform(i,q=True,s=True)
  print sc

これで値自体は取れた。
ただ、ロックしている値まで取ってきているので、処理的に問題にもなりそう。
ということで、ロック情報を取得するか、除外する方法を考える。
SDK等みていると、「listAttr」というコマンドが使えそう。
このコマンドのフラグにて、
unlocked(u) boolean create
ロックが解除されているアトリビュートのみがリストされます。

f:id:tommy_on:20160905233516p:plain


このフラグがそのまま使えそうですね。
しかもありがたい事に、keyableや、channelBoxなどもありますね。
ではこれを用いて、再度値の取得を書いてみました。

# -*- coding: utf-8 -*-
import maya.cmds as cmds
oSel = cmds.ls(sl=True,l=True,type='transform')
print oSel
for i in oSel:
    #name
    print i
    list = cmds.listAttr(i, unlocked = True , visible = True , keyable = True, connectable = True, scalar = True, write = True, hd = True)
    print list

で結果。

[u'visibility', u'translateX', u'translateY', u'translateZ', u'rotateX', u'rotateY', u'rotateZ', u'scaleX', u'scaleY', u'scaleZ']

あれ…値が。。。
そうなんです。このままだと値が取れないので、ここからさらにGetAttrをかまして値を取ってみます。

# -*- coding: utf-8 -*-
import maya.cmds as cmds
oSel = cmds.ls(sl=True,l=True,type='transform')
print oSel
for i in oSel:
    #name
    print i
    list = cmds.listAttr(i, unlocked = True , visible = True , keyable = True, connectable = True, scalar = True, write = True, hd = True)
    print list
    for att in list:
        Tmpsel = cmds.ls(sl=True)[0] 
        getValue = cmds.getAttr(Tmpsel + "." + att)
        print getValue

結果こんな感じ。
[-1.4327737,100.82367,-26.672975]

うん。取れました。


あとこれは余談ですが、個人的にアトリビュートのタイプは分けて処理したほうがいいので、以下の感じで
一回アトリビュートのタイプで篩をかけています。
※大きく意味はないのですが、一応。

# -*- coding: utf-8 -*-
import maya.cmds as cmds
oSel = cmds.ls(sl=True,l=True,type='transform')
print oSel
for i in oSel:
    #name
    print i
    list = cmds.listAttr(i, unlocked = True , visible = True , keyable = True, connectable = True, scalar = True, write = True, hd = True)
    print list
    for att in list:
        Tmpsel = cmds.ls(sl=True,type='transform')[0] 
        gettype = cmds.getAttr(Tmpsel + "." + att,type=True)
        if gettype == "bool":
            BoolValue = cmds.getAttr(Tmpsel + "." + att)
            print BoolValue
        else:
            getValue = cmds.getAttr(Tmpsel + "." + att)
            print getValue


では、以上で値が取れたきた事を確認しました。
続いては、この情報を選択名とくっつけて、テキスト保存し拡張子を変更しましょう。
まずは、値を実行できるように、「SetAttr」としてまとめていきます。
現状取得できているのは、
「i」で選択物の名前
「att」でアトリビュート
「getValue」でその値
が取得できています。
ここまで取得できてると、setattr用に簡易にまとめれますね。
こんな感じでまとめました。

# -*- coding: utf-8 -*-
import maya.cmds as cmds
oSel = cmds.ls(sl=True,l=True,type='transform')
print oSel
for i in oSel:
    #name
    print i
    list = cmds.listAttr(i, unlocked = True , visible = True , keyable = True, connectable = True, scalar = True, write = True, hd = True)
    print list
    for att in list:
        Tmpsel = cmds.ls(sl=True,type='transform')[0] 
        gettype = cmds.getAttr(Tmpsel + "." + att,type=True)
        if gettype == "bool":
            getValue = cmds.getAttr(Tmpsel + "." + att)
            print getValue
        else:
            getValue = cmds.getAttr(Tmpsel + "." + att)
            print getValue
        AttrStr =  str(i) + "." + str(att)
        Value = "(¥'" + str(AttrStr) + "¥'," + str(getValue) + " , clamp = True)"
        SetValue = "cmds.setAttr" + Value
        #exec(SetValue)

こんな感じで値をまとめれました。
実行したらこんな感じに↓

cmds.setAttr('|Monster_Rig|ALL|COG|Stomach|Chest|Neck|Head.rotateX',-11.0883595763 , clamp = True)
cmds.setAttr('|Monster_Rig|ALL|COG|Stomach|Chest|Neck|Head.rotateY',0.0 , clamp = True)
cmds.setAttr('|Monster_Rig|ALL|COG|Stomach|Chest|Neck|Head.rotateZ',0.0 , clamp = True)

あとはこれをテキストに保存します。
保存の仕方はGoogle先生なんかでよくでてくる感じでまとました。↓
またその際に、保存するディレクトリーを作成し、配置させてます。
ディレクトリーがない場合は、作成する方向で

# -*- coding: utf-8 -*-
import maya.cmds as cmds
import codecs
import os.path

oSel = cmds.ls(sl=True,l=True,type='transform')
for i in oSel:
    #name
    list = cmds.listAttr(i, unlocked = True , visible = True , keyable = True, connectable = True, scalar = True, write = True, hd = True)
    for att in list:
        Tmpsel = cmds.ls(sl=True,type='transform')[0] 
        gettype = cmds.getAttr(Tmpsel + "." + att,type=True)
        if gettype == "bool":
            getValue = cmds.getAttr(Tmpsel + "." + att)
        else:
            getValue = cmds.getAttr(Tmpsel + "." + att)
        AttrStr =  str(i) + "." + str(att)
        Value = "(¥'" + str(AttrStr) + "¥'," + str(getValue) + " , clamp = True)"
        SetValue = "cmds.setAttr" + Value
        #exec(SetValue)

ScenePath = cmds.internalVar(uad = True) + 'SavePose'
ImportText = "import maya.cmds as cmds"
if not os.path.exists(ScenePath): 
	os.makedirs(ScenePath)

TextOpen = codecs.open(ScenePath+"\SavePose.py","w","utf-8")
TextOpen.write(ImportText)
TextOpen.write("\r\n")
TextOpen.write(SetValue)
TextOpen.write("\r\n")
TextOpen.close()



"""
使わないけど、拡張子変更する方法も記載。
file_path = ScenePath+"\SavePose.txt" 
basefile, ext = os.path.splitext(file_path)
basefile, ext = os.path.splitext( os.path.basename(file_path) )
print ScenePath + "\\" + basefile + ".py"
os.rename(file_path, ScenePath + "\\" + basefile + ".py")
"""


すげぇ汚いっすね。
今後スクラッチかけますわ‥
とりあえず、リグの頭を選んで実行すると、以下の画像みたくなります。
※拡張子がテキストになってますが、間違いです。。。
正式には、「.py」になってます。
f:id:tommy_on:20160906140906p:plain

はい。
これでテキスト出力までできました。
次はこれらを複数できるようにカスタムし、実行文とUIをやっていきます。

が、長くなったので一旦ここで切ります。

大体ここまでで2時間ぐらいでしょうか‥


それでは‥