CG・コンテンツ制作
  1. CG・コンテンツ制作トップ
  2. DAIKIN CG Channel
  3. UsersNotes
  4. スクリプト
  5. Maya;Pythonで表の作成と書き込み/読み込みツール を作ろう!!(GTMF2015ネタ)
SUITE USERS NOTES
GTMF2015 ネタ
Maya;Pythonで表の作成と書き込み/読み込みツールを作ろう!!
Constraint Table

Maya; Let's Make a Table with Read/Write CSV Tool with Python
(Used Maya 2014, 2015 2016)
プロローグ;Prologue
GTMF2015 ネタConstraint Table
Maya で scriptTable というコマンドを使うと表を作ることが出来ます。
この表の内容をCSVというExcelでも読み書き出来るカンマ(、)で
区切られたファイルに書き込んだり、読み込んだりする仕組みをPythonで実現します。
この機能の活用としてコンストレイントのテーブルツールを作成します。

このツールはRig作成などでも便利で、あらかじめ決められたノード名に
決められたコンストレイントを一発で設定してくれます。
(ほとんど同じような構造体のキャラRigを何体も作るような時等々)
尚、GTMF2015での発表時よりも既に更新があり、Version2からの公開です。

Version2
スケールコンストレイントに対応しました。

なお、このサイトで掲載している事例の決まり事ですが、
使用に関しては自己責任でよろしくお願い申し上げます。
(Maya2014、2015、2016 で動作確認しています)

Please use it as your own risk
Windows7 Professional 64Bit、Intel Core i7-3930K(3.20GHz,6コア/12スレッド)
メモリ16GB、NVIDIA GeForce GTX560 Ti 2GB(メモリ2GB)
ConstraintTable_00s

ritaro_ml



最初は、表を作成するMayaのコマンド、scriptTableから見てみましょう。

scriptTable(Python) http://help.autodesk.com/cloudhelp/2015/JPN/Maya-Tech-Docs/CommandsPython/scriptTable.html おおまかなコマンドの説明は上記 ドキュメント が示しているので
まずは、以下のようなスクリプトからスタートしてみます。

import maya.cmds as cmds

def edit_cell(row, column, value):
    return 1

def add_row(*args):
    last_row_num = cmds.scriptTable('table', query=True, rows=True)
    cmds.scriptTable('table', edit=True,insertRow=last_row_num)

def delete_row(*args):
    last_row_num = cmds.scriptTable('table', query=True, rows=True)
    cmds.scriptTable('table', edit=True,deleteRow=last_row_num - 1)

window = cmds.window(widthHeight=(620, 300))

form = cmds.formLayout()
table =  cmds.scriptTable('table',rows=3, columns=7,columnWidth=([1,135],[2,145],[3,70],[4,45],[5,40],[6,40],[7,40]),
        label=[(1,"SourceNodeName"), (2,"DestinationNodeName"), (3,"Constrain"), (4,"Offset"), (5,"X"), (6,"Y"), (7,"Z")],
        cellChangedCmd=edit_cell)

addButton = cmds.button(label="Add Row",command=add_row)
deleteButton = cmds.button(label="Delete Row",command=delete_row)

cmds.formLayout(form, edit=True, 
    attachForm=[(table, 'top', 0), (table, 'left', 0), (table, 'right', 0), 
    (addButton, 'left', 0), (addButton, 'bottom', 0), 
    (deleteButton, 'bottom', 0), (deleteButton, 'right', 0)],
    attachControl=(table, 'bottom', 0, addButton), 
    attachNone=[(addButton, 'top'),(deleteButton, 'top')], 
    attachPosition=[(addButton, 'right', 0, 50), (deleteButton, 'left', 0, 50)]
    )

cmds.showWindow( window )
ConstraintTable_02
ドキュメントのPython例で

def edit_cell(row, column, value):
    return 1

という記述がありますが、これ必ず必要です。
これは、cmds.scriptTable(rows=4, columns=2, label=[(1,"Column 1"), (2,"Column 2")], cellChangedCmd=edit_cell)
とオフションの最後にedit_cell があり、”セルに変化が起こったら編集する”と設定しています。
この記述が無いと、あれ?セルに値を記入しても受け付けない、という状態になります。
ConstraintTable_03
window内の表示はformLayoutで作成しています。
表をtableとして、
また、2つの行追加と削除ボタンをaddButtondeleteButtonとしてformLayoutを使って並べます。

window = cmds.window(widthHeight=(620, 300))
form = cmds.formLayout()
table = cmds.scriptTable('table',rows=3, columns=7,columnWidth=([1,135],[2,145],[3,70],[4,45],[5,40],[6,40],[7,40]),
        label=[(1,"SourceNodeName"), (2,"DestinationNodeName"), (3,"Constrain"), (4,"Offset"), (5,"X"), (6,"Y"), (7,"Z")],
        cellChangedCmd=edit_cell)

addButton = cmds.button(label="Add Row",command=add_row)
deleteButton = cmds.button(label="Delete Row",command=delete_row)


こうすることによって、windowサイズの変更に応じて大きさが変化する2つのボタンをウィンドウ下部に配置します。
行をドンドン追加していくと、表示しているウィンドウのサイズ以上に表が増えた場合は、右側にスライダーを出現して表の追加を続行します。
ただ、気が付くのは、行の追加削除最後の行に対して動作することです。
そこで、こんな風に追加します。

import maya.cmds as cmds

def edit_cell(row, column, value):
    return 1

def add_row(*args):
    last_row_num = cmds.scriptTable('table', query=True, rows=True)
    cmds.scriptTable('table', edit=True,insertRow=last_row_num)

def delete_row(*args):
    last_row_num = cmds.scriptTable('table', query=True, rows=True)
    cmds.scriptTable('table', edit=True,deleteRow=last_row_num - 1)

def insert_add_row(*args):
    try:
        selected_row = cmds.scriptTable('table', query=True, selectedRows=True)[0]
        if selected_row == None:
            print 'Select Row to Insert'
        else:
            cmds.scriptTable('table', edit=True,insertRow=selected_row)
    except:
        print 'Select Row to Insert'

def delete_sel_row(*args):
    try:
        selected_row = cmds.scriptTable('table', query=True, selectedRows=True)[0]
        if selected_row == None:
            print 'Select Row to Delete'
        else:
            cmds.scriptTable('table', edit=True,deleteRow=selected_row)
    except:
        print 'Select Row to Delete'

window = cmds.window(widthHeight=(620, 300))
form = cmds.formLayout()
table = cmds.scriptTable('table',rows=3, columns=7,columnWidth=([1,135],[2,145],[3,70],[4,45],[5,40],[6,40],[7,40]),
        label=[(1,"SourceNodeName"), (2,"DestinationNodeName"), (3,"Constrain"), (4,"Offset"), (5,"X"), (6,"Y"), (7,"Z")],
        cellChangedCmd=edit_cell)

addButton = cmds.button(label="Add Row",command=add_row)
deleteButton = cmds.button(label="Delete Row",command=delete_row)
insertAddRowButton = cmds.button(label="Insert to Selected Row",command=insert_add_row)
deleteSelRowButton = cmds.button(label="Delete Selected Row",command=delete_sel_row)

cmds.formLayout(form, edit=True, 
    attachForm=[(table, 'top', 0), (table, 'left', 0), (table, 'right', 0), 
        (addButton, 'left', 0), (addButton, 'bottom', 0), 
        (deleteButton, 'bottom', 0), (deleteButton, 'right', 0),
        (insertAddRowButton, 'bottom', 0), (insertAddRowButton, 'right', 0),
        (deleteSelRowButton, 'bottom', 0), (deleteSelRowButton, 'right', 0)
        ],
    attachControl=(table, 'bottom', 0, addButton), 
    attachPosition=[(addButton, 'right', 0, 25),
        (deleteButton, 'left', 0, 25),(deleteButton, 'right', 0, 50),
        (insertAddRowButton, 'left', 0,50),(insertAddRowButton, 'right', 0, 75),
        (deleteSelRowButton, 'left', 0,75)], 
    attachNone=[(addButton, 'top'),(deleteButton, 'top'),(insertAddRowButton, 'top'),(deleteSelRowButton, 'top')]
    )

cmds.showWindow( window )

ConstraintTable_05
すると、左端のボタンを使って選択状態にした行部分に新規の行を挿入したり削除したりが行えるようになります。
内容としては選択行番号をcmds.scriptTable('table', query=True, selectedRows=True)[0]で求め、
その番号行に対して以下を実行しています。
行の挿入cmds.scriptTable('table', edit=True,insertRow=selected_row)
行の削除cmds.scriptTable('table', edit=True,deleteRow=selected_row)



表への書き込み、取り出し
コマンドの説明順的には、まずは値の取得からいった方が簡単です。
では、出来たこの表に、今は適当な値を手で書き込んで、それを取り出したいと思います。
ConstraintTable_06
次のスクリプトを実行します。

print cmds.scriptTable('table', query=True, rows=True)

4

4という数値が返って来ます。縦に4行あって、1行目はヘッダーとして文字が入っています。

print cmds.scriptTable('table', query=True, columns=True)

8

8という数値が返って来ます。横に8列あって、1列目は行選択ボタンになっています。
つまり、上記例の”20”となっている縦2行目の横3列目の値を取得するには、
縦横の 0 から始まる数値で指定するので(1,2)となり、

print cmds.scriptTable('table', cellIndex=(1,2), query=True, cellValue=True)[0]

20

となります。
全体のデータを得るには、行数分、列の値を順に得るループを作成すればOKです。
ヘッダー部分はNoneで返って来るところだけは気をつけて・・・、

all_rows = cmds.scriptTable('table', query=True, rows=True)
for o_r in range(all_rows):
    all_colums = cmds.scriptTable('table', query=True, columns=True)
    data_list = []
    for o_c in range( all_colums):
        cell_list = cmds.scriptTable('table', cellIndex=(o_r,o_c), query=True, cellValue=True)
        if type(cell_list) == 'list':
            cell_text = "".join(cell_list)
        elif cell_list == None:
            cell_text = cell_list
        else:
            cell_text = cell_list[0]

        data_list.append(cell_text)
    print data_list

#結果
[None, None, None, None, None, None, None, None]
[None, u'1', u'20', u'30', u'1', u'10', u'20', u'30']
[None, u'2', u'', u'', u'', u'', u'', u'']
[None, u'3', u'', u'', u'', u'', u'', u'']


さて、値の記入はquery=True,をeditにしてcellValue=に値を入れてば良いと気が付きます。

cmds.scriptTable('table', cellIndex=(2,2), edit=True, cellValue=1000)
ConstraintTable_07
次に考えるのは、ワークフロー的にどのような操作で順に値を入れると良いか、となります。
ここでは、コンストレイントの表を作る予定なので、2列目・3列目はオブジェクトの名前、4列目はコンストレイントの種類の名前、オフセットの有無の0と1、座標値となります。
きっと、1つ設定は、1つの組み合せとして、1行毎に横に書いて行って、表を埋めると考えます。
表のどの部分に書き始めるかも自由なはずですから、選択された行に順々に書き込むと便利かなと想像します。

ウィンドーにボタンを配置し、選択されている行の決まった列に選択しているオブジェクトの名前を記入するです。

import maya.cmds as cmds

def edit_cell(row, column, value):
    return 1

def add_row(*args):
    last_row_num = cmds.scriptTable('table', query=True, rows=True)
    cmds.scriptTable('table', edit=True,insertRow=last_row_num)

def delete_row(*args):
    last_row_num = cmds.scriptTable('table', query=True, rows=True)
    cmds.scriptTable('table', edit=True,deleteRow=last_row_num - 1)

def insert_add_row(*args):
    try:
        selected_row = cmds.scriptTable('table', query=True, selectedRows=True)[0]
        if selected_row == None:
            print 'Select Row to Insert'
        else:
            cmds.scriptTable('table', edit=True,insertRow=selected_row)
    except:
        print 'Select Row to Insert'

def delete_sel_row(*args):
    try:
        selected_row = cmds.scriptTable('table', query=True, selectedRows=True)[0]
        if selected_row == None:
            print 'Select Row to Delete'
        else:
            cmds.scriptTable('table', edit=True,deleteRow=selected_row)
    except:
        print 'Select Row to Delete'

def set_sel1(*args):
    if not cmds.ls( selection=True ):
        print 'Select Object to List'
    else:
        selected_obj = cmds.ls( sl=True )[0]
        selected_row = cmds.scriptTable('table', query=True, selectedRows=True)
        if selected_row == None:
            print 'Select Row to List'
        else:
            selected_row = cmds.scriptTable('table', query=True, selectedRows=True)[0]
            cmds.scriptTable('table', edit=True, selectedCells=[selected_row,1])
            cmds.scriptTable('table', cellIndex=(selected_row,1), edit=True, cellValue=selected_obj)
            cmds.scriptTable('table', edit=True, selectedRows=selected_row)

def set_sel2(*args):
    if not cmds.ls( selection=True ):
        print 'Select Object to List'
    else:
        selected_obj = cmds.ls( sl=True )[0]
        selected_row = cmds.scriptTable('table', query=True, selectedRows=True)
        if selected_row == None:
            print 'Select Row to List'
        else:
            selected_row = cmds.scriptTable('table', query=True, selectedRows=True)[0]
            cmds.scriptTable('table', edit=True, selectedCells=[selected_row,2])
            cmds.scriptTable('table', cellIndex=(selected_row,2), edit=True, cellValue=selected_obj)
            cmds.scriptTable('table', edit=True, selectedRows=selected_row)

window = cmds.window(widthHeight=(620, 300))
form = cmds.formLayout(numberOfDivisions=100)

table1 = cmds.scriptTable('table',rows=3, columns=7,columnWidth=([1,135],[2,145],[3,70],[4,45],[5,40],[6,40],[7,40]),
    label=[(1,"SourceNodeName"), (2,"DestinationNodeName"), (3,"Constrain"), (4,"Offset"), (5,"X"), (6,"Y"), (7,"Z")],
    cellChangedCmd=edit_cell)

addButton = cmds.button(label="Add Row",command=add_row)
deleteButton = cmds.button(label="Delete Row",command=delete_row)
insertAddRowButton = cmds.button(label="Insert to Selected Row",command=insert_add_row)
deleteSelRowButton = cmds.button(label="Delete Selected Row",command=delete_sel_row)

column = cmds.columnLayout()

cmds.separator(height=10)
cmds.text(label='Select Row to Input',width=420,bgc=[0.2,0.2,0.2],align='center' )
cmds.rowLayout(numberOfColumns=2)
cmds.button('set_bot1',label='Select SourceNodeName',width=210,bgc=[0.6,0.5,0.5],command=set_sel1)
cmds.button('set_bot2',label='Select DestinationNodeName',width=210,bgc=[0.5,0.5,0.6],command=set_sel2)
cmds.setParent('..')


cmds.formLayout(form, edit=True,
    attachForm=[
        (table1, 'left', 5), (table1, 'top', 0), (table1, 'right', 5), (table1, 'bottom', 10),
        (column, 'top', 5), (column, 'left', 5),

        (addButton, 'left', 0), (addButton, 'bottom', 0), 
        (deleteButton, 'bottom', 0), (deleteButton, 'right', 0),
        (insertAddRowButton, 'bottom', 0), (insertAddRowButton, 'right', 0),
        (deleteSelRowButton, 'bottom', 0), (deleteSelRowButton, 'right', 0)
        ],
    attachControl=[(table1, 'top', 10,column ),(table1, 'bottom', 0, addButton)],
    attachPosition=[(column, 'right', 0, 100),
        (addButton, 'right', 0, 25),(deleteButton, 'left', 0, 25),(deleteButton, 'right', 0, 50),
        (insertAddRowButton, 'left', 0,50),(insertAddRowButton, 'right', 0, 75),(deleteSelRowButton, 'left', 0,75)],
    attachNone=[(addButton, 'top'),(deleteButton, 'top'),(insertAddRowButton, 'top'),(deleteSelRowButton, 'top')])

cmds.showWindow( window )
ConstraintTable_08
記入すべき行を選択していないと、行を選択してくれと表示されます。
あとは、これに従って記入用のボタンを増やしただけです。



CSVファイルの読み込み/書き込み
CSV (Comma Separated Values、カンマ区切り値列)ファイルは、単に”、”(カンマ)で区切られたテキストファイルですが、
Excelでは表として開ける便利なファイル形式です。
また、Maya Pythonからも扱い易く、import csvと冒頭に書くだけで利用できるライブラリー対応です。

csvhttp://docs.python.jp/2/library/csv.html
ConstraintTable_09
サンプルファイル >> constraint_table_00.csv
このサンプルファイルをMayaのユーザーディレクトリー以下に置いたとして、以下を実行します。

import csv

o_file = open('C:/Users/ritaro/Documents/maya/2016/ja_JP/prefs/scripts/constraint_table_00.csv', 'r')
reader = csv.reader(o_file)
header = next(reader)

for row in reader:
    print row[0] + ',' + row[1] + ',' + row[2] + ',' + row[3] + ',' + row[4] + ',' + row[5] + ',' + row[6]
o_file.close()

#結果
pSphere1,pCube1,Point,1,,,
pCone1,locator1,Orient,1,,,
pCylinder1,pTorus1,Scale,0,2,2,2

このように、opencloseに挟んで reader で内容を上から行毎に文字どうり読むことが出来ます。

では次のステップとして、今は出来ている前章の表に上の値を一旦手で入力しておいて、
その内容をCSVファイルに書き込むということをしてみます。
まずは、表にconstraint_table_00.csvの値を記入します。(第1行はヘッダーの為、2行目からになります)
ConstraintTable_10
そして、以下のスクリプトでMayaユーザーディレクトリーにconstraint_table_01.csvとして保存してみます。

import maya.cmds as cmds
import csv

o_file = 'C:/Users/ritaro/Documents/maya/2016/ja_JP/prefs/scripts/constraint_table_01.csv'

if not (cmds.file(o_file,query=True, exists=True)):
    tmp_csv_file = open(o_file, 'w' ,os.O_CREAT)
else:
    tmp_csv_file = open(o_file, 'w')
writer = csv.writer(tmp_csv_file, lineterminator='\n')

all_rows = cmds.scriptTable('table', query=True, rows=True)
for o_r in range(all_rows):
        
    all_colums = cmds.scriptTable('table', query=True, columns=True)
    data_list = []
    for o_c in range( all_colums - 1):
        if o_r == 0:
            data_list = ["SourceNodeName", "DestinationNodeName", "Constrain","MaintainOffset"]
        else:
            cell_list = cmds.scriptTable('table', cellIndex=(o_r,o_c + 1), query=True, cellValue=True)
            if o_c == 0:
                if type(cell_list) == list:
                    cell_text = "".join(cell_list)
                    print cell_text
                elif cell_list == None:
                    cell_text = u''
                else:
                    cell_text = cell_list
                data_list.append(cell_text)
            elif o_c == 1:
                if type(cell_list) == list:
                    cell_text = "".join(cell_list)
                    print cell_text
                elif cell_list == None:
                    cell_text = u''
                else:
                    cell_text = cell_list
                data_list.append(cell_text)
            else:
                if type(cell_list) == list:
                    cell_text = "".join(cell_list)
                elif cell_list == None:
                    cell_text = u''
                else:
                    cell_text = cell_list
                data_list.append(cell_text)
    writer.writerow(data_list)
tmp_csv_file.close()

Mayaのユーザーディレクトリー以下に新しくconstraint_table_01.csv というファイルが作成されます。
最初の open 記述部分が if 文で分岐になっている部分は面白く、
その指定したファイル名の CSVファイルが無かった場合、つまり新規の場合は
tmp_csv_file = open(o_file, 'w' ,os.O_CREAT)でファイルを作って開けと設定しています。

中の記述も確認します。テキストとして開くと

SourceNodeName,DestinationNodeName,Constrain,MaintainOffset
pSphere1,pCube1,Point,1,,,
pCone1,locator1,Orient,1,,,
pCylinder1,pTorus1,Scale,0,2,2,2

となっています。
後は、この部分のスクリプトがボタンを押した時に動作すれば良いということになります。

残る動作対応としては、上記の逆、ですね。
手入力して表を埋めるのではなく、新しく作成したconstraint_table_01.csvファイルから表に書き込みをします。
もう一度表を作るスクリプトを実行して、表の中身が全て空のものを用意します。
そして、以下を実行します。

import maya.cmds as cmds
import csv

o_file = open('C:/Users/ritaro/Documents/maya/2016/ja_JP/prefs/scripts/constraint_table_01.csv', 'r')
reader = csv.reader(o_file)
header = next(reader)

row_no = 1
for row in reader:
    if row_no > 3:
        cmds.scriptTable('table', edit=True,insertRow=row_no)

    cmds.scriptTable('table', cellIndex=(row_no,1), edit=True, cellValue=row[0])
    cmds.scriptTable('table', cellIndex=(row_no,2), edit=True, cellValue=row[1])
    cmds.scriptTable('table', cellIndex=(row_no,3), edit=True, cellValue=row[2])
    cmds.scriptTable('table', cellIndex=(row_no,4), edit=True, cellValue=row[3])
    cmds.scriptTable('table', cellIndex=(row_no,5), edit=True, cellValue=row[4])
    cmds.scriptTable('table', cellIndex=(row_no,6), edit=True, cellValue=row[5])
    cmds.scriptTable('table', cellIndex=(row_no,7), edit=True, cellValue=row[6])
    row_no = 1 + row_no

o_file.close()

結果は
ConstraintTable_10
です。

このように、表とCSVファイルを利用したツール作成が簡単に出来ることがわかります。



表データに基づくコンストレイント
表のデータからの実行ですが、これはもう表を順に上から読み取って
データの種類によって異なるコンストレイントを設定しているだけです。

if o_conmodel == 'Point':
    o_conmodel_t = 'pointConstraint'
elif o_conmodel == 'Orient':
    o_conmodel_t = 'orientConstraint'
elif o_conmodel == 'Parent':
    o_conmodel_t = 'parentConstraint'
elif o_conmodel == 'Scale':
    o_conmodel_t = 'scaleConstraint'

追加の情報としては、キャラクターRigを作成することを前提に考えられているツールなので
コンストレイントの元と先にそれぞれ別のネームスペースが付けられるようになっています。
ConstraintTable_11
その部分のスクリプトです。(多少長いです。)

def do_constraint(*args):

    try:
        o_namespace = cmds.textField('c_namespace',q=True,text=True)
        n_namespace = ""
        if o_namespace != "":
            n_namespace = o_namespace + ':'

        s_namespace = cmds.textField('d_namespace',q=True,text=True)
        m_namespace = ""
        if s_namespace != "":
            m_namespace = s_namespace + ':'

        last_row_num = cmds.scriptTable('table', query=True, rows=True)
        row_no = 1
        for row in range( last_row_num - 1):
            o_sname = cmds.scriptTable('table', cellIndex=(row_no,1), q=True, cellValue=True)[0]
            o_dname = cmds.scriptTable('table', cellIndex=(row_no,2), q=True, cellValue=True)[0]
            o_conmodel = cmds.scriptTable('table', cellIndex=(row_no,3), q=True, cellValue=True)[0]
            o_offmodel = cmds.scriptTable('table', cellIndex=(row_no,4), q=True, cellValue=True)[0]

            if o_sname == "" or o_dname == "" or o_conmodel == "" or o_offmodel == "":
                cmds.confirmDialog( title='ERROR', message='No Node Name to Set !_! ')
                break
            else:
                if o_conmodel == 'Point':
                    o_conmodel_t = 'pointConstraint'
                elif o_conmodel == 'Orient':
                    o_conmodel_t = 'orientConstraint'
                elif o_conmodel == 'Parent':
                    o_conmodel_t = 'parentConstraint'
                elif o_conmodel == 'Scale':
                    o_conmodel_t = 'scaleConstraint'

                if o_offmodel == '0':
                    o_offmodel_t = 'False'
                    if o_conmodel == 'Parent':
                        if cmds.pointConstraint(m_namespace + o_dname,q=True) != None:
                            cmds.pointConstraint(n_namespace + o_sname,m_namespace + o_dname,edit=True,remove=True)
                        if cmds.orientConstraint(m_namespace + o_dname,q=True) != None:
                            cmds.orientConstraint(n_namespace + o_sname,m_namespace + o_dname,edit=True,remove=True)

                        do_const = "cmds." + o_conmodel_t + "('"+ n_namespace + o_sname +"','" + m_namespace + o_dname + "',maintainOffset=False)"
                        exec do_const

                    elif o_conmodel == 'Point':
                        if cmds.orientConstraint(m_namespace + o_dname,q=True) != None:
                            cmds.orientConstraint(n_namespace + o_sname,m_namespace + o_dname,edit=True,remove=True)
                        if cmds.parentConstraint(m_namespace + o_dname,q=True) != None:
                            cmds.parentConstraint(n_namespace + o_sname,m_namespace + o_dname,edit=True,remove=True)

                        o_off_x = cmds.scriptTable('table', cellIndex=(row_no,5), q=True, cellValue=True)[0]
                        if o_off_x == '':
                            o_off_x_t = '0.0000'
                        else:
                            o_off_x_t = str(o_off_x)

                        o_off_y = cmds.scriptTable('table', cellIndex=(row_no,6), q=True, cellValue=True)[0]
                        if o_off_y == '':
                            o_off_y_t = '0.0000'
                        else:
                            o_off_y_t = str(o_off_y)

                        o_off_z = cmds.scriptTable('table', cellIndex=(row_no,7), q=True, cellValue=True)[0]
                        if o_off_z == '':
                            o_off_z_t = '0.0000'
                        else:
                            o_off_z_t = str(o_off_z)

                        do_const = "cmds." + o_conmodel_t + "('" + n_namespace + o_sname +"','" + m_namespace + o_dname + "',maintainOffset=False,offset=[" + o_off_x_t + "," + o_off_y_t + "," +  o_off_z_t + "])"
                        exec do_const

                    elif o_conmodel == 'Orient':
                        if cmds.pointConstraint(m_namespace + o_dname,q=True) != None:
                            cmds.pointConstraint(n_namespace + o_sname,m_namespace + o_dname,edit=True,remove=True)
                        if cmds.parentConstraint(m_namespace + o_dname,q=True) != None:
                            cmds.parentConstraint(n_namespace + o_sname,m_namespace + o_dname,edit=True,remove=True)

                        o_off_x = cmds.scriptTable('table', cellIndex=(row_no,5), q=True, cellValue=True)[0]
                        if o_off_x == '':
                            o_off_x_t = '0.0000'
                        else:
                            o_off_x_t = str(o_off_x)

                        o_off_y = cmds.scriptTable('table', cellIndex=(row_no,6), q=True, cellValue=True)[0]
                        if o_off_y == '':
                            o_off_y_t = '0.0000'
                        else:
                            o_off_y_t = str(o_off_y)

                        o_off_z = cmds.scriptTable('table', cellIndex=(row_no,7), q=True, cellValue=True)[0]
                        if o_off_z == '':
                            o_off_z_t = '0.0000'
                        else:
                            o_off_z_t = str(o_off_z)

                        do_const = "cmds." + o_conmodel_t + "('" + n_namespace + o_sname +"','" + m_namespace + o_dname + "',maintainOffset=False,offset=[" + o_off_x_t + "," + o_off_y_t + "," +  o_off_z_t + "])"
                        exec do_const

                    elif o_conmodel == 'Scale':
                        if cmds.orientConstraint(m_namespace + o_dname,q=True) != None:
                            cmds.orientConstraint(n_namespace + o_sname,m_namespace + o_dname,edit=True,remove=True)
                        if cmds.parentConstraint(m_namespace + o_dname,q=True) != None:
                            cmds.parentConstraint(n_namespace + o_sname,m_namespace + o_dname,edit=True,remove=True)

                        o_off_x = cmds.scriptTable('table', cellIndex=(row_no,5), q=True, cellValue=True)[0]
                        if o_off_x == '':
                            o_off_x_t = '1.0000'
                        else:
                            o_off_x_t = str(o_off_x)

                        o_off_y = cmds.scriptTable('table', cellIndex=(row_no,6), q=True, cellValue=True)[0]
                        if o_off_y == '':
                            o_off_y_t = '1.0000'
                        else:
                            o_off_y_t = str(o_off_y)

                        o_off_z = cmds.scriptTable('table', cellIndex=(row_no,7), q=True, cellValue=True)[0]
                        if o_off_z == '':
                            o_off_z_t = '1.0000'
                        else:
                            o_off_z_t = str(o_off_z)

                        do_const = "cmds." + o_conmodel_t + "('" + n_namespace + o_sname +"','" + m_namespace + o_dname + "',maintainOffset=False,offset=[" + o_off_x_t + "," + o_off_y_t + "," +  o_off_z_t + "])"
                        exec do_const

                else:
                    o_offmodel_t = 'True'
                    if o_conmodel == 'Parent':
                        if cmds.pointConstraint(m_namespace + o_dname,q=True) != None:
                            cmds.pointConstraint(n_namespace + o_sname,m_namespace + o_dname,edit=True,remove=True)
                        if cmds.orientConstraint(m_namespace + o_dname,q=True) != None:
                            cmds.orientConstraint(n_namespace + o_sname,m_namespace + o_dname,edit=True,remove=True)
                    elif o_conmodel == 'Point':
                        if cmds.orientConstraint(m_namespace + o_dname,q=True) != None:
                            cmds.orientConstraint(n_namespace + o_sname,m_namespace + o_dname,edit=True,remove=True)
                        if cmds.parentConstraint(m_namespace + o_dname,q=True) != None:
                            cmds.parentConstraint(n_namespace + o_sname,m_namespace + o_dname,edit=True,remove=True)
                    elif o_conmodel == 'Orient':
                        if cmds.pointConstraint(m_namespace + o_dname,q=True) != None:
                            cmds.pointConstraint(n_namespace + o_sname,m_namespace + o_dname,edit=True,remove=True)
                        if cmds.parentConstraint(m_namespace + o_dname,q=True) != None:
                            cmds.parentConstraint(n_namespace + o_sname,m_namespace + o_dname,edit=True,remove=True)

                    do_const = "cmds." + o_conmodel_t + "('" + n_namespace + o_sname +"','" + m_namespace + o_dname + "',maintainOffset=True)"
                    exec do_const

            row_no += 1

    except:
        cmds.confirmDialog( title='Name ERROR', message=' No Node Name to Constraint !! ')

ここでは、exec を使って、得たテキスト内容を実行しています。おもしろいですね。



constraint_table
ツールの説明です。
まずは、表を記入するを左側のボタンを使って選択状態にします。
ConstraintTable_12
コンストレイントのソースオブジェクト;[Select SourceNodeName]、影響を受けるオブジェクト;[Select DestinationNodeName]
コンストレイントの種類、オフセットの有無、オフセット無しを選んだ場合のカスタム値(無記入は0,0,0になる)
の順に、次々と行を埋めていきます。

その表を保存したい場合は、[SAVE LIST to .CSV] ボタンで、一番上に書かれているファイルに記入されます。
別名にしておけば、新規ファイルとして保存されます。

ネームスペースを新たに追加したい場合は[SourceNamespace] / [DestinationNamespace] の下の空欄に記入します。

[Do All Constraint] を押すと、表に書かれているものに従って全てのコンストレイントが実行されます。
ConstraintTable_13
利用例は、色々あるのですが、
例えば、Rig作成時に、いつも決まった骨名同士に付ける各種コンストレイントはCSVとしてデータ化しておいて、
いざMayaでRigを組む時は一発で設定を完了させたり、
ネームスペースの有る無しでも同じコンストレイント設定を一発で実現したり、
或いは、Maya上でアニメーションベイクをするとコンストレイントが外れてしまう場合、
一発で元のコンストレイントを復活できるようにする・・・等々です。

色々とカスタマイズすると、更に良いかも知れません。

以上です。



constraint_table.py
という訳でconstraint_table.pyを公開します。
( Pyファイルは シェルフにボタン登録するか、プルダウンメニューに登録して実行します。)
あくまでも自己責任でお使いください。 use as your own risk.


constraint_table
(Maya2014,2015,2016)

constraint_table.zip 5.65 KB2015/11/8 現在



という訳で、次回は... What's Next ...
乞う、ご期待!!Stay tuned ..
戻る 次へ

Twitter

ページの先頭へ