チュートリアル / 読んで触ってよくわかる!Mayaを使いこなす為のAtoZ
第103回:コマンドの#1引数の謎を解き明かそう!
- Maya
- ゲーム
- コラム
- スクリプト・API
- チュートリアル
- 初心者・学生
Mayaでコマンドを使ってスクリプトを書いていると、時々サンプルの中で引数に「#1」が登場します。
optionMenuコマンドのMEL例にも次のコードがあります。
実行してみるとドロップダウンのメニューが出てきます。
選択項目を変えるごとに、選んだメニューのラベルがスクリプトエディタに出力されます。
ということは「#1」はラベル名が来ているわけです。
optionMenuコマンドのドキュメントは丁寧で、changeCommandフラグの説明に「#1」に入る値が紹介されています。
この「#1」は他のコントロールでも使う事ができます。うまく使うとコードが簡潔になります。
というわけで今回は引数の「#1」がどういうものか見ていきましょう!
「#1」を使うとコードが簡潔になる!
もし「#1」を使わないなら、次のようにコントロール名を指定してoptionMenuコマンドを照会モードで呼び出します。
今回は決め打ちのコントロール名にしていますが、自動的につく名前をもとにする場合は更に複雑になります。
「#1」を利用できるなら、なるべく使ったほうがコードを読みやすくなりますし、不具合も少なくなります。
まあ、知っている人は「#1」が何をしているのかという挙動がわかりますが、仕組みを知らない人がコードを見てもチンプンカンプンになる可能性もあるので、そのあたりのメンテナンス上のさじ加減は必要でしょうけれど…。
実は#の引数に関するドキュメントがある!
コードが複雑になるから「#1」を使いましょうと言われても、他のどのコントロールで使えて、どういう値が来るのか手探りだと使うに使えません。
実はヘルプドキュメントの中に、ちょっとだけ説明があります。
「UI 要素にコマンドをアタッチする」のページの下部に、こんなことが書かれています。
実行されるコマンドのパラメータとして、コントロールの値が必要なことがよくあります。状態が変わるたびにコントロールを照会しなくても済むように、コントロールの値を文字列「#1」としてコマンドに埋め込むことができます。コントロールの値が変わると、そのコマンドを送るときに「#1」がコントロールの実際の値に置き換えられます。複数の値を持つグループは異なるコンポーネントの値に対して、「#2」、「#3」などを使用します。たとえば、3 つのフィールドがある float フィールド グループは、「#1」、「#2」、「#3」を使用して、コマンドで各フィールドの値を表すことができます。
要は引数に「#1」「#2」「#3」などがあれば、コントロールの値を流し込んでくれるようです。
先程のoptionMenuでは-valueの結果が「#1」に入っていました。もしユーザが欲しいのが-select [int] だとすれば、残念ながら「#1」は使えません。
何の値が来るかは、実際のところ実装して動かしてみるしか無いです…。
というわけで、もう少し詳しく挙動を調べてみました。
使えるのは「#1~#5」まで!
改めてMayaの実装を見てみると、「#1~#5」まで値を流し込める仕様になっていました。
例えばfloatFieldGrpコマンドで-numberOfFields 4 にすれば「#1~#4」まで使われます。
(コマンドを実行できるコントロールで、値を返せるフィールドなどを5つ設定できるコントロールは存在しない気がしますが・・・)
次のMELで、色々なコントロールのテストを行なえます。
global proc testFuncArg1(string $arg1){
print("testFuncArg1:" + $arg1 + "\n");
}
global proc testFuncArg2(string $arg1, string $arg2){
print("testFuncArg1:" + $arg1 + ", " + $arg2 + "\n");
}
global proc testFuncArg3(string $arg1, string $arg2, string $arg3){
print("testFuncArg1:" + $arg1 + ", " + $arg2 + ", " + $arg3 + "\n");
}
global proc testFuncArg4(string $arg1, string $arg2, string $arg3, string $arg4){
print("testFuncArg1:" + $arg1 + ", " + $arg2 + ", " + $arg3 + ", " + $arg4 + "\n");
}
global proc testFuncArg5(string $arg1, string $arg2, string $arg3, string $arg4, string $arg5){
print("testFuncArg1:" + $arg1 + ", " + $arg2 + ", " + $arg3 + ", " + $arg4 + ", " + $arg5 + "\n");
}
window;
columnLayout;
// #1 は 0 (NULL)となります。ボタンに使っても意味がなさそう。
button -c "testFuncArg1 #1";
// #1 はフィールドの文字列。
textField -changeCommand "testFuncArg1 #1";
// #1 はフィールドの数値。
floatSliderGrp -field true -changeCommand "testFuncArg1 #1";
// #1~#4 にはそれぞれのフィールドの値
floatFieldGrp -numberOfFields 4 -changeCommand "testFuncArg4 #1 #2 #3 #4";
// #1はチェックのvalue。指定している"-changeCommand番号"目のチェックのvalue。
checkBoxGrp -numberOfCheckBoxes 2 -changeCommand1 "testFuncArg1 #1" -changeCommand2 "testFuncArg1 #1";
// -changeCommandでは、変更したチェックのvalueが来るものの、何番目のチェックのvalueかは分からず。
//checkBoxGrp -numberOfCheckBoxes 2 -changeCommand "testFuncArg1 #1";
// #1 には選んだmenuItemのラベル名
optionMenuGrp -label "Colors" -changeCommand "testFuncArg1 #1";
menuItem -label "Red";
menuItem -label "Green";
// #1 にはアイコンのvalue値。onCommand/offCommandのどちらでも、#1にはアイコンのvalue値。
// onCommandは常に1、offCommandは常に0となってしまうので、
// changeCommandに使わないと#1の意味がない。
iconTextCheckBox -style "iconAndTextHorizontal" -image1 "cone.png" -label "cone" -changeCommand "testFuncArg1 #1";
// #1はどのコマンドでも使われない・・・。
textScrollList -numberOfRows 3 -allowMultiSelection true
-append "one" -append "two" -append "three"
-showIndexedItem 3
-selectCommand "testFuncArg1 #1"; // error!
// radioButtonGrpは使い所が難しいです。
// -changeCommandに設定すると、ラジオボタンを選んだときと、選択が外れる(他に移る)ときの二回で、それぞれ1と0が#1に設定されます。
// -shareCollectionに設定された先のradioButtonGrpは無関係なため、下記の例では"Yellow" "Orange" "Purple"には反応しません。
string $group1 = `radioButtonGrp -numberOfRadioButtons 3
-label "Colors" -labelArray3 "Red" "Blue" "Green"
-changeCommand "testFuncArg1 #1"`;
radioButtonGrp -numberOfRadioButtons 3 -shareCollection $group1
-label "" -labelArray3 "Yellow" "Orange" "Purple";
showWindow;
実行すると次のウインドウが表示されますので、値を変えたりチェックしたりしてみてください。
(コード内のコメントの通り、textScrollListだけはエラーが出るようになっています。)
まあ、これ以外にもコマンドを設定できるコントロールはありますが、ヘルプドキュメントからは「#1」が設定できるかどうかわかりませんので、上のコードを変更して、動くかどうか確認していくことになります。
Pythonで実行させる場合
MELでは引数の数が合わなければ関数実行のエラーとなります。
Pythonでは可変長引数が使えますので、次のように簡単に実装して、テストできます。
import maya.cmds as cmds
def testFuncArg(*args):
print('testFuncArg:', args)
cmds.window()
cmds.columnLayout()
cmds.button(c=testFuncArg) # #1 は False (NULL)
cmds.textField(changeCommand=testFuncArg) # #1 はフィールドの値
cmds.textFieldButtonGrp(buttonCommand=testFuncArg, changeCommand=testFuncArg) # buttonCommandは何も来ない。changeCommandは文字列が来る
cmds.floatSliderGrp(field=True, changeCommand=testFuncArg)
cmds.floatFieldGrp(numberOfFields=4, changeCommand=testFuncArg) # #1~#4 にはそれぞれのフィールドの値
cmds.optionMenuGrp(label="Colors", changeCommand=testFuncArg) # #1 には選んだmenuItemのラベル名
cmds.menuItem(label="Red")
cmds.menuItem(label="Green")
cmds.radioButtonGrp(numberOfRadioButtons=4, changeCommand=testFuncArg, label='Colors', labelArray4=['Red', 'Blue', 'Green', 'Purple'] )
cmds.showWindow()
次のウインドウが立ち上がりますので、値を変えたりしてみてください。
これで期待している引数の数を確認してから、MELで#の数を設定すると簡単です。(Pythonでそのまま実装することのほうが多いと思いますが…)
まとめ
というわけで、なんとなく使えそうだけど使い方がわからない「#1」について見てきました。
知ってみれば動作は単純ですし、期待した値が来なければいつもの方法にすれば良いだけですので、安全に使用できるとお分かりいただけたのではないでしょうか。
ぜひコードを書くときに利用してみてください。