チュートリアル / 読んで触ってよくわかる!Mayaを使いこなす為のAtoZ
第103回:コマンドの#1引数の謎を解き明かそう!

  • Maya
  • ゲーム
  • コラム
  • スクリプト・API
  • チュートリアル
  • 初心者・学生
第103回:コマンドの#1引数の謎を解き明かそう!

Mayaでコマンドを使ってスクリプトを書いていると、時々サンプルの中で引数に「#1」が登場します。
optionMenuコマンドのMEL例にも次のコードがあります。

第103回:コマンドの#1引数の謎を解き明かそう!

実行してみるとドロップダウンのメニューが出てきます。
選択項目を変えるごとに、選んだメニューのラベルがスクリプトエディタに出力されます。

第103回:コマンドの#1引数の謎を解き明かそう!

ということは「#1」はラベル名が来ているわけです。
optionMenuコマンドのドキュメントは丁寧で、changeCommandフラグの説明に「#1」に入る値が紹介されています。

第103回:コマンドの#1引数の謎を解き明かそう!

この「#1」は他のコントロールでも使う事ができます。うまく使うとコードが簡潔になります。
というわけで今回は引数の「#1」がどういうものか見ていきましょう!

「#1」を使うとコードが簡潔になる!

もし「#1」を使わないなら、次のようにコントロール名を指定してoptionMenuコマンドを照会モードで呼び出します。
今回は決め打ちのコントロール名にしていますが、自動的につく名前をもとにする場合は更に複雑になります。

第103回:コマンドの#1引数の謎を解き明かそう!

「#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だけはエラーが出るようになっています。)

第103回:コマンドの#1引数の謎を解き明かそう!

まあ、これ以外にもコマンドを設定できるコントロールはありますが、ヘルプドキュメントからは「#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でそのまま実装することのほうが多いと思いますが…)

第103回:コマンドの#1引数の謎を解き明かそう!

まとめ

というわけで、なんとなく使えそうだけど使い方がわからない「#1」について見てきました。
知ってみれば動作は単純ですし、期待した値が来なければいつもの方法にすれば良いだけですので、安全に使用できるとお分かりいただけたのではないでしょうか。
ぜひコードを書くときに利用してみてください。

製品購入に関するお問い合わせ
オートデスク メディア&エンターテインメント 製品のご購入に関してご連絡を希望される場合は、こちらからお問い合わせください。