前回のエントリ「ウインドウの作成(2): ボタン」で、ボタンで実行できるものに、コマンドとプロシージャーがあると書いた。
コマンドを使えるようにするのは簡単だったが、やはりMelスクリプトでGUIを使って自分のスクリプトを使えるようにするには、プロシージャが不可欠となってくる。
プロシージャーを使うことで、スクリプティングが格段にやりやすくなる。
特定の機能をブロック単位でわけて考えることが出来、必要に応じてそれを部品として利用することができるようになる。
今まで、このブログでは、学習過程をシンプルにするために、プロシージャーについてはほとんど触れなかったが、それについて、一歩踏み込む必要がでてきたようだ。
そこで、おさらいを兼ねて「プロシージャ」について復習してみた。
そこででてきた疑問が、プロシージャーには大別してグローバル・プロシージャとローカルプロシージャの2種類があるが、その違いは何か?ということだ。
他者の作ったスクリプトを解析していて、よく見るのは「global proc」とかかれたグローバル・プロシージャである。
ローカル・プロシージャを使っているのはあまりお目にかかったことがないか、出会ってもあまり注意を払っていなかったせいか記憶にない。
このふたつの違いは、なんとなくはわかったつもりだったが、より明確にするために少し実験をしてみた。
以下の物は、DigitalMatrixの「プロシージャの作り方 」にあった例をよりシンプルにしたグローバル・プロシージャーの例である。
これを仮に「プロシージャA」と呼ぶことにする。
global proc makeSphere1()
{
polySphere;
}
これをスクリプトエディターに入力して実行しただけでは、見た目には何も起きない。
しかし、メモリ内にはこのプロシージャーが保存されている。
そのため、実行後には、
makeSphere1
と入力して実行するだけでプロシージャーが実行される。
結果は、ポリゴン・スフィアが作成される。
このようにプロシージャーは「makeSphere1」という自前のコマンドとして使えるようになる。
次に同じプロシージャー名で、中のスクリプトが異なるグローバル・プロシージャーを作ってみた。
これを仮に「プロシージャB」と呼ぶ。
global proc makeSphere1()
{
sphere;
}
入力して実行。
そしてさきほどと同じコマンド
makeSphere1
を入力して実行してみる。(プロシージャー名が同じであることに注意)
すると今度はNurbsスフィアが作成される。
何が起きたかというとメモリ上にあるプロシージャーが上書きされて内容が後者の物に変わってしまったのだ。
このことはMayaのヘルプ「グローバル プロシージャを回避する 」に書かれている。
「グローバル プロシージャの潜在的な問題として、メモリ要件も挙げることができます。Maya は、宣言されたグローバルプロシージャをすべてメモリに保存します。多くのグローバル プロシージャをロードすると、グローバルプロシージャの保存に、それだけ多くのメモリが使用されます。」
簡単におさらいすると
1)グローバル・プロシージャはいつでもそのプロシージャ名をコマンドとして利用できる。
2)同じ名前のプロシージャは上書きされる。
----------------------------------------
では次にローカルプロシージャについて実験してみた。
ローカルプロシージャは「global proc」から「global 」を取り除けば良いだけである。
(参照:DigitalMatrix プロシージャの形式 )
proc makeSphere1()
{
polySphere;
}
これをスクリプトエディターから実行しmakeSphere1を実行すると同じ結果がでる。
次にNurbsスフィアを作るローカル・プロシージャを作ってみた。
proc makeSphere1()
{
sphere;
}
これもスクリプトエディターから実行しmakeSphere1を実行すると同じ結果がでる。
.....。
これではグローバル・プロシージャで実験したのと同じで、上書きされている。
----------------------------------------
次に、先に実行する物をグローバル・プロシージャにして後の物をローカルにしてみた。
global proc makeSphere1()
{
polySphere;
}
次に下記を実行。
proc makeSphere1()
{
sphere;
}
実はこれでもmakeSphere1の内容は上書きされてしまう。
どうも違いがよくわからない。
----------------------------------------
Digital Matrixのページで、プロシージャの形式の項目で、「global」の箇所をよく見直してみる。
「ローカル プロシージャは記述してあるファイルの内部からしか実行できません。 また、ローカル プロシージャは、スクリプト エディタ のインプットウインドウで実行することはできません。 」
この説明では、ローカル・プロシージャは「記述してあるファイルの内部からしか実行できない」と書かれている。
言い換えればスコープされている状況で内部でしか実行できないということ。
(スコーピングについてはエントリ:「構文 (1)」を参照)
この部分を明確にするには、
1)グローバル・プロシージャを宣言(実行)
2)スコーピングされた内部で同じ名前のプロシージャをローカルとして宣言(実行)
3)スコーピングされた内部でプロシージャを実行
4)後ほど同じプロシージャを実行
このステップを踏めばプロシージャ名は同じでも
「3」ではローカルプロシージャが実行された結果、
「4」でグローバル・プロシージャが実行された結果が得られるはずである。
そして「ローカル・プロシージャはスクリプト・エディタのインプットウインドウで実行することができない」という意味がわかるはずだ。
まず「ステップ1」。グローバル・プロシージャのスクリプトを実行。
global proc makeSphere1()
{
sphere;
}
この段階では
makeSphere1
を実行すればNurbsスフィアが作成される。
次に「ステップ2」と「ステップ3」
ブロック({ })で区切られた内部でプロシージャを宣言し、makeSphere1を実行。
{
proc makeSphere1()
{
polySphere;
}
makeSphere1;
}
これによりポリゴン・スフィアが作成された。
では、最後に「ステップ4」である。
makeSphere1
あれっ?
ポリゴン・スフィアが作成された???
どうもプロシージャーをスクリプトエディター内で実行しただけではちゃんとした区別はされないらしい。
どちらもグローバル・プロシージャとして判断されているようだ。
「{ }」を使ってブロック内でプロシージャを宣言してもスコーピングされてはいないのか。
もう一度DigitalMatrixのページを見直してみる。
「ローカル プロシージャは記述してあるファイルの内部からしか実行できません。」
「ファイル」と書いてある。
オンラインヘルプの「ローカル プロシージャ 」にも明確に書いてあった。
「スクリプト エディタ(Script Editor)でローカル プロシージャを定義することはできません。これらは、外部スクリプト ファイルのみで使用可能です。 」
なるほど、スクリプトエディターでは
proc makeSpehre1()
と書いてもローカルプロシージャの定義はできないので、これはグローバル・プロシージャとして判断されているということだろうか?
----------------------------------------
そこでこんどはスクリプトファイルを作成して試してみた。
まずグローバル・プロシージャ用のスクリプトファイル
ファイル名は「globaltest.mel」で保存した。
global proc makeSphere1()
{
sphere;
}
これをスクリプトエディターからソース・スクリプトにて読み込んだ後、
makeSpehre1
を実行するとNurbsスフィアが作成される。
つぎに、ローカルプロシージャ用のスクリプト・ファイルを作成。
ファイル名は「localtest.mel」で保存。
proc makeSphere1()
{
polySphere;
}
これをスクリプトエディターからソース・スクリプトにて読み込んだ後、
makeSpehre1
を実行するとNurbsスフィアが作成された。
ポリゴン・スフィアが作成されないということはグローバル・プロシージャのみがコマンドとして実行されていると言うことだ。
----------------------------------------
これでローカルプロシージャというのがなんとなくわかってきた。
ヘルプにも「他の言語では、プロシージャをサブルーチンと呼ぶことがあります。 」と書かれているようにローカルプロシージャはまさにサブルーチン的だ。
グローバル・プロシージャは一つのスクリプト・ファイル内に収まっている必要はない(別のスクリプト・ファイルに記述されていても利用できる。)のだが、ローカルは一つのスクリプト・ファイル内に含まれていなくてはならない(同一のスクリプトファイル内からだけ利用可能。)。
サブルーチンの定義をWikiで見ると
「繰り返し利用されるルーチン作業をモジュールとしてまとめたもので、呼び出す側の「主」となるもの(メインルーチン)と対比して「サブルーチン」と呼ばれる。」
と書かれている。
現時点で、今ひとつローカル・プロシージャの使い道がわからないが、思いつくのは、サブルーチンの定義から推測すると、「ローカル・プロシージャは、メインのフローを持ったスクリプトの中で使われるもの」だということなのだろう。
「プロシージャ」、「サブルーチン」、「関数」という言葉は似たような概念を表しているが、プログラミング言語によって、その言葉があらわしている定義が若干異なることがあるようで、今回の考え方はMelにのみ当てはまる。
0 件のコメント:
コメントを投稿