制御構造(ループ)
コマンドを繰り返し実行する方法
MEL のスクリプトを作っていると
同じ、または似たようなコマンドを何度も繰り返し実行しなければならない場合がよくあります。
MEL においてそのように同じコマンドを繰り返して実行しなければならない場合には for, while, do while などを使用します。
ループを終了するための条件には条件演算子を使用します。
for, while, do while の文法
- for 
	
- 
	for 文は一番よく使用されるループの構文です。
for(初期化のための式 ; 条件式 ; 式)
{
	MEL文;
}
for 文では以下のように実行が進みます。
	- "初期化のための式" が最初に 1 度だけ実行されます。
	
- "条件式" が成り立つかどうか調べます。
		
 成り立っていれば 3. に進みます。
 成り立っていなければループを終了します。
- ブロック ( { から } まで) の中の MEL 文を実行します。
	
- "式" を実行します。
	
-  2. に戻ります。
	
 
- while
	
- 
	while 文は for 文から "初期化のための式" と "式" の部分を省略したものになっています。
while(条件式)
{
	MEL文;
}
while では以下のように処理が進みます。
	-  "条件式" が成り立つかどうか調べます。
		
 成り立っていれば 3. に進みます。
 成り立っていなければループを終了します。
- ブロック ( { から } まで) の中の MEL 文を実行します。
	
-  1. に戻ります。
	
 
- do while
	
- 
	条件式が成り立っているかどうか調べる前に 1 度ブロック内を実行しておきたい場合に使用します。
do
{
	MEL文;
} while(条件式);
do while では以下のように処理が進みます。
	- ブロック ( { から } まで) の中の MEL 文を実行します。
	
-  "条件式" が成り立つかどうか調べます。
		
 成り立っていれば 1. に戻ります。
 成り立っていなければループを終了します。
 
-  for( in )
	
- 
	for( in ) はリストの中の要素を 1 つづつ変数に代入してコマンドを実行するものです。
	
 リストとは具体的にいうと変数・配列などのことです。
 例えば、選択されたオブジェクトのリストから 1 つづつオブジェクトを取り出して何かのコマンドを実行したい場合に便利です。
for( 変数 in リスト )
{
	MEL文;
}
for( in ) では以下のように処理が進みます。
	-  "リスト" から要素を 1 つだけ取り出します。
		
 もし取り出す要素が無ければループを終了します。
- 取り出した要素を "変数" に代入します。
	
- ブロック ( { から } まで) の中の MEL 文を実行します。
	
 
continue と break
ループの途中で処理の流れを変更するために continue と break が使用されます。
-  continue
	
- ループ内の処理を中断して、
	ループの最初から処理を実行し直します。
-  break
	
- ループ内の処理を中断して、
	ループをただちに終了します。
条件演算子
上の説明に出てきた条件式の部分には以下のような条件演算子を使用します。
これらの演算子の左右に数値(int, float)、文字列(string)、変数やグループ化された条件式を書いて条件式を表します。
- ==
	
- 左右が等しい
- !=
	
- 左右が等しくない
- <
	
- 左が右より小さい
- >
	
- 左が右より大きい
- <=
	
- 左が右より小さいか等しい
- >=
	
- 左が右より大きいか等しい
- &&
	
- 左右の条件がどちらも成り立つ場合
- ||
	
- 左右の条件がどちらかが成り立つ場合
- ( )
	
- 条件式のグループ化
条件演算子の例
-  $i < 10
	
- $i が 10 未満の場合に条件が成り立ちます。
	
 10 を含まないことに注意してください。
-  $x <= 5
	
- $x が 5 以下の場合に条件が成り立ちます。
	
 5 を含むことに注意してください。
-  $x >= 7.5
	
- $x が 7.5 以上の場合に条件が成り立ちます。
	
 7.5 を含むことに注意してください。
-  $y == $z
	
- $y と $z が等しい場合に条件が成り立ちます。
-  $s != "test"
	
- $s が文字列 "test" と等しくない場合に条件が成り立ちます。
-  $a == $b && $c == $d
	
- $a が $b と等しいという条件と、$c が $d と等しいという条件が
	同時に成り立つ場合に条件が成り立ちます。
-  $e != $f || $g != $h
	
- $e が $f と等しくないか、または、$g が $h と等しくない場合に条件が成り立ちます。
	
 両方の条件のどちらか一方が成り立てばよいのですが、
	両方が同時に成り立っていてもかまわないことに注意してください。
Tips
条件演算子を使用する場合は、必ずいつかは条件が成り立たなくなるように条件式を組み立ててください。
そうしないとループが永久に終らなくなり、Maya で他の処理ができなくなってしまいます。
そうなると最悪の場合 Maya を強制終了しなくてはならなくなります。
しかし、時にはわざと永久ループを作る必要がある場合もあります。
そのような場合には、以下のような文を使用します。
for, while, do while の使用例
以下の例では、いづれも変数 $i をループの実行回数をかぞえるカウンターとして使っています。
-  MEL 文を 10 回実行する for 文の例です。
for($i = 0; $i < 10; $i++)
{
	MEL 文;
}
-  MEL 文を 10 回実行する while 文の例です。
$i = 0;
while($i < 10)
{
	MEL 文;
	$i++;
}
-  MEL 文を 10 回実行する do while 文の例です。
$i = 0;
do
{
	MEL 文;
	$i++;
} while($i <= 10)
ループの使用例
for 文を使って、
球を原点(0, 0, 0)を中心に半径 $rad の円上に $num 個並べる MEL スクリプトを作ってみましょう。
- 以下のMELスクリプトを circleSphere1.mel という名前で作ります。
global proc circleSphere1(float $rad, int $num)
{
	int $i;
	float $r = 0.0;
	float $add = 360.0 / $num;
	for($i = 0; $i < $num; $i++)
	{
		sphere;
		move $rad 0 0;
		rotate -ws -p 0 0 0  0 $r 0;
		$r += $add;
	}
}
- スクリプト エディタ の  によって circleSphere1.mel を読み込みます。
- スクリプト エディタ のインプットウインドウで circleSphere1(5.0, 6) と打ち込んで実行します。
- 半径1の球が半径 5 の円上に 6 個作られます。
	
 ![[circleSphere1(5, 6)の実行結果]](../mel-ad01/circleSphere1.jpg)  
スクリプトの解説
- global proc circleSphere1(float $rad, int $num)
- 円の半径を表す float の引数($rad)と、
	球の個数を表す int の引数($num)をとるプロシージャーです。
- int $i;
- for 文のカウンタとして使うための変数です。
- float $r = 0.0;
- 球を回転させるための角度を入れておく変数です。
	
 最初は回転させないので 0.0 を代入しておきます。
- float $add = 360.0 / $num;
- 角度の増分を入れておくための変数です。
	
 360 度(円の 1 周の角度)を球の個数($num)で除算しています。
- for($i = 0; $i < $num; $i++)
- $num 回 for ループを実行します。
	
 以下は for ループ内の処理です。
- sphere;
- NURBS の球を作ります。
- move $rad 0 0;
- 球を($rad, 0, 0)の位置に移動します。
- rotate -ws -p 0 0 0  0 $r 0;
- 移動された球をワールドスペース内で(0, 0, 0)を中心として Y 軸周りに $r だけ回転します。
	
 各フラグの意味は以下の通りです。
	-  -ws
		
- ワールドスペースで回転させます。
		
 ローカル座標で回転させても意味の無いことに注意してください。
-  -p 0 0 0
		
- 回転の中心を(0, 0, 0)にします。
	
-  0 $r 0
		
- X軸周りに 0 度、Y 軸周りに $r 度、Z 軸周りに 0 度回転させます。
	
 
- $r += $add;
- 次の回転角度を求めます。
練習
-  上の circleSphere1.mel を参考にして circleSphere2.mel という MEL スクリプトを作り、球の半径も引数で変えることができるようにしてみましょう。
	
 引数の 1 番目に球の半径(float)を追加してください。
 circleSphere2(float 球の半径, float 円の半径, int 円上の球の個数)
 例えば、スクリプト エディタ から読み込んで circleSphere2(3.0, 5.0, 6) を実行すると、半径 3.0 の球が半径 5.0 の円上に 6 個作られるようにします。
 ![[circleSphere2(3.0, 5.0, 6)の実行結果]](../mel-ad01/circleSphere2.jpg)  
-   上の circleSphere2.mel を参考にして circleSphere3.mel という MEL スクリプトを作り、 球が2重に並ぶようにしてみましょう。
	
 ただし、内側と外側の球が接するように並ぶようにし、
	内側の球が並ぶ円の半径が 2 番目の引数になるようにしてください。
 すべての球は同じ半径にしてください。
 circleSphere3(float 球の半径, float 円の半径, int 円上の球の個数)
 例えば、スクリプト エディタ から読み込んで circleSphere3(2.0, 5.0, 6) を実行すると、以下の図のように球が並ぶようにしましょう。
 ![[circleSphere3(2.0, 5.0, 6)の実行結果]](../mel-ad01/circleSphere3.jpg)  
 まとめ
- コマンドの繰り返しにはループを使用します。
	
 ループには
	for, while, do while
	などの種類があります。
- ループの続行・終了の判定には条件式を使用します。
	
 条件式は条件演算子によって組み立てられます。
 練習課題
 参考
Prev | Next
Home | Contents
Mail