ON-BLOG

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

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

前回までで、選択したものの値などを外部に保存することまでできました。
今回は引き続きコードを書いていきたいと思います。

次は、まず前回までで、できたものを整理します。
始めに現状だと一個のオブジェクトしか対応していないので
それを対応する為
配列を用意して、その配列に対して処理を行うようにします。

こんな感じで整理してみました。
※まだまだ改良の余地がありますが
 シェイプの件などもあるので一旦これで

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

oSel = cmds.ls(sl=True,l=True,type='transform')
Select_Value = []
ImportText = "import maya.cmds as cmds"
Select_Value.append(ImportText)
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)"
        Select_Value.append("cmds.setAttr" + Value)
        
ScenePath = cmds.internalVar(uad = True) + 'SavePose'
if not os.path.exists(ScenePath): 
	os.makedirs(ScenePath)

TextOpen = codecs.open(ScenePath+"\SavePose.py","w","utf-8")
for val in Select_Value:
    TextOpen.write(val)
    TextOpen.write("\r\n")
TextOpen.close()


複数選択してから実行すると、以下の画像みたいになるはずです。
f:id:tommy_on:20160906155833p:plain
変更点は配列「Select_Value」を追加し、値を追加したものを
外部へ出力する際に、Forで繰り返し出力しただけです。


これである程度まとまりができたので、テストを行います。
まずはすべてのコントローラーを選択して、実行してみます。
すると‥

f:id:tommy_on:20160906160504p:plain

はい。エラーになります。
エラー文を読みと
「# エラー: line 1: ValueError: file line 15: 名前と一致するオブジェクトがありません: ALL.blendOrient1 # 」
はい。
これは15行目でエラーになってることが分かります。

gettype = cmds.getAttr(Tmpsel + "." + att,type=True)

もっと詳しくみていくと、エラーが発生するコントローラーがあります。
右手のUPVですね。
f:id:tommy_on:20160906161849p:plain
書いてる通りアトリビュートの「blendOrient1」で問題が出ていることが分かります。
が、ここで改めてエラー文を見ると
「名前と一致するオブジェクトがありません: ALL.blendOrient1 # 」

とあります。
ただ、Allには ALL.blendOrient1はなく、エラーが出ているのは右手のUPVです。

このコトから、スクリプトの記載順番や
構造に問題があるんじゃないか?と想定します。

そう!簡単なミスです。
15行目のコマンドがエラーしているということは
その記述が間違っていなかったら
原因はそのコマンドに渡している
引数ないし、値に問題あるんですね。

ここでいうと、「Tmpsel 」か「att」に絞られます。
経験者なら、読んだ瞬間間違いに気づいていると思いますが
私は10分は悩んでしまいましたw
原因はTmpsel の中身です。
ここでTmpsel = cmds.ls(sl=True)[0] と
一番始めに選択しているものを再度取得した為
Allにはブレンドがないのに!
とエラーで弾かれてたわけです。
正しくは以下の中身になります。

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

oSel = cmds.ls(sl=True,l=True,type='transform')
Select_Value = []
print oSel
ImportText = "import maya.cmds as cmds"
Select_Value.append(ImportText)
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:
        gettype = cmds.getAttr(i + "." + att,type=True)
        if gettype == "bool":
            getValue = cmds.getAttr(i + "." + att)
        else:
            getValue = cmds.getAttr(i + "." + att)
        AttrStr =  str(i) + "." + str(att)
        Value = "(¥'" + str(AttrStr) + "¥'," + str(getValue) + " , clamp = True)"
        Select_Value.append("cmds.setAttr" + Value)
        
ScenePath = cmds.internalVar(uad = True) + 'SavePose'
if not os.path.exists(ScenePath): 
	os.makedirs(ScenePath)

TextOpen = codecs.open(ScenePath+"\SavePose.py","w","utf-8")
for val in Select_Value:
    TextOpen.write(val)
    TextOpen.write("\r\n")
TextOpen.close()

はい実行するとこんな感じ。
f:id:tommy_on:20160906162612p:plain

無事通りました。
再度テストを込めて、保存したものを別フレームで実行してみます。
ただ、今は読み込みの機能をつけていないので
データを開いてスクリプトエディタに
直接ペーストして実行します。

f:id:tommy_on:20160906162821p:plain
この状態で実行すると

f:id:tommy_on:20160906162845p:plain
こうなりました。

という点から、とりあえず問題ないように思います。
※本当はいっぱいありますが…


では、続けて読み込みのコマンドを用意してみます。
読み込みはすでにPythonコードが用意されているので
やり方は複数あります。
1.execfileを使ってスクリプトを実行
2.Openで開いてから読み込むで実行
3.execで読み込んで実行

以上のパターンがありました。
※本当はもっとあると思います。
今回のスクリプトで、一番相性がいいのが
どれかと考えていたのですが
結局エラー処理も同時にしたいので
一行ずつ読み込むようにします。
簡単に用意しました。こんな感じ。

import maya.cmds as cmds
import codecs
import os.path
import sys

script_code = []
script_err = []
ScenePath = cmds.internalVar(uad = True) + 'SavePose\SavePose.py'
for line in open(ScenePath, 'r').xreadlines():
   line = line.rstrip()
   script_code.append(line)
   
for i in script_code:
    try:
        exec(i)
    except:
        print i+"は存在していない為、実行できませんでした。"
        script_err.append(i)

はい。これで読み込みまでいけたはずです。
ただ、細かいエラー処理などはまだ組み込んでないです。
それらは、UI実装時に合わせて行います。

とまた一旦ここらで切ります。
次回以降はコマンドを関数化し、UIを実装してみます。

では…