スクリプトでのプログラム フロー制御

MAXScript には、ソフトウェアがスクリプトの評価を実行していくパスをコントロールできるようにするコマンドが用意されています。最も役立つコマンドは、条件ステートメントとループ ステートメントの 2 つのグループです。

続行する前に、適切な基本 シーンがあることを確認しましょう。

前のステップで開いた新しい MAXScript エディタで、

次のように入力します。

resetMaxFile #noprompt
mybox = box length:10 width:10 height:10 wirecolor:blue

その後、Ctrl+Eを押してスクリプトを評価します。これによって、「...しますか?」プロンプトが表示されることなく現在のシーンがリセットされ、新しい青いボックスが 10x10x10 の寸法で原点に作成されます。

条件ステートメント

条件ステートメントは、特定の条件が満たされた場合に指定されたコマンドを実行するよう、MAXScript に指示します。

(新しく開いたスクリプト エディタではなく)リスナーに以下のとおり入力します。

例:

if mybox.height == 10 then mybox.width = 20

これにより、ボックスの高さが 10 の場合、その幅が 20 に変更されます。

上のステートメントで、2 つの等号が連続していることに注意してください。これについては、このトピックの最後で説明します。

この「if…then…」ステートメントは、「else」ステートメントを含めることで拡張できます。

if mybox.height == 10 then mybox.width = 20 else mybox.width = 10

このステートメントは、ボックスの高さが 10 の場合には幅を 20 に変更し、それ以外の場合には幅を 10 に変更するよう MAXScript に指示します。

ステートメントの「if」、「then」、および「else」の各部分を、別の行にすることもできます。

if mybox.height == 10
then mybox.width = 20
else mybox.width = 10

MAXScript に関して一層魅力的な点は、if...then...else で 3 つの式(1 つの条件式と、条件が true であるか false であるかに応じた 2 つの代替式)が使用されるため、上記が以下のようにはるかに短い記述で済むということです。

mybox.width = if mybox.height == 10 then 20 else 10

この場合、代入文の右側は、ボックスの高さが 10 かどうかの条件を評価し、そうである場合は 20 を返し、そうでなければ 10 を返す IF 式です。結果の値はこの代入式の左側に代入されます。

この式は、括弧を使用するとより明瞭になります。括弧は任意で記述するもので、単純に可読性を向上させます。

mybox.width = (if mybox.height == 10 then 20 else 10)

リスナーの if...then 条件式

これらのコマンドを[リスナー](Listener)ウィンドウに入力しても、コマンドは通常のリスナーのように行ごとに実行されません。これは、「if」ステートメントが完結するには「then」ステートメントが必要であることをリスナーが認識しているためです。実際、リスナーは「then」ステートメントより後のステートメントを実行しません。これは、リスナーでは「else」ステートメントが含まれるかどうかを判断できないためです。こうした理由で、「then」ステートメントが入力されるか、「if…then…」ステートメントの次の行が入力されるまで、リスナーは「if…then…」ステートメントを実行しません。

リスナーへの入力時に「else」ステートメントの待機を避けるために、「if...do...」を使用することができます。「if...do...」とともに「else」を使用することはできません。このため、リスナーでは、「if」の後の条件式が true であるかぎり、待機は行われず「do」に続く式が実行されます。

比較演算子

最後のステートメントの二重等号記号「==」は、2 つの値を比較するよう MAXScript に指示します。単一の「=」記号は、常に代入値を表します。

これは、多くの標準プログラミング言語 (C++ など) で共通です。

MAXScript には、異なる条件オペレータがいくつか存在します。それらを次に示します。

  • == 等しい

  • != 等しくない

  • > より大きい

  • >= より大きい、または等しい

  • < より小さい

  • <= より小さい、または等しい

注:

MAXScript が条件式を評価する場合、結果は常に true または false になります。MAXScript は、この結果を一時的に保存します。MAXScript は「if…then」の中でこの結果を使用して、ステートメントの処理方法を判断します。「if」ステートメントの結果が true の場合、MAXScript は「then」式を評価します。結果が false の場合、MAXScript は「else」式が指定されているものと見なして「else」式を評価します。

スクリプトによっては、truefalse の代わりに、onoff がそれぞれ記述されている場合があります。これらの語は交換可能で、MAXScript に対して同じ意味を持ちます。

ループ

ループは、コマンドのコレクションを繰り返し実行するよう MAXScript に指示する場合に使用する繰り返し演算です。

ループを使用すると、1 セットのコマンドで多数のオブジェクトを変更できるため、大規模なオブジェクト グループを操作する場合に有用です。

たとえば、50 個のボックスを作成する場合、ループを使用して作成コマンドを 50 回実行すれば、50 個のコマンドを別個に実行しなくて済みます。ループは、複数のオブジェクトのプロパティを変更する場合にも有用です。

ループには、異なるいくつかのタイプが存在します。最初に、for および while ループについて説明します。

For ループ

for ループを使用すると、配列またはオブジェクト セットなど、ある範囲の数、時間値、一連の値の集合を繰り返すことができます。

for ループを使ってボックスをコピーすることが出来ます。

このレッスンの初めに開始したスクリプトを展開してみましょう。

スクリプト例:

resetMaxFile #noprompt --reset the scene
mybox = box length:10 width:10 height:10 wirecolor:blue --new box
for i = 1 to 5 do --repeat five times, for each iteration do:
(
box_copy = copy mybox --create a copy of the original box
box_copy.pos = [i*20, 0, 0] --place it i*20 units along x
box_copy.wirecolor = [i*25,i*50,(5-i)*50] --blue-green gradient
)--end of the for loop

カッコで囲まれた部分はすべて、「ブロック」と呼ばれます。ループ ステートメントはすべて、ブロックとして作成する必要があります。このステートメントは 5 回実行されます。実行されるたびに新しいボックスが 1 つ作成されます。

  • for ステートメントは、「for」という語で始まります。

  • 次に、ステートメントを繰り返す回数を定義する必要があります。ここでは、変数 「i」を使ってループをコントロールしています。「for i = 1 to 5」という行は、変数「i」を値 1 に設定してからループ ボディの内容を実行し、次に変数「i」を値 2 に設定してからループ ボディを実行する、といった具合に処理を行うよう MAXScript に指示しています。

  • 変数「i」は、ループの「インデックス」と呼ばれます。ループを実行するたびに、インデックス値は 1 だけ自動的に増加します。ユーザが入力する必要はありません。ループの各繰り返しは、反復と呼ばれます。

  • MAXScript のインデックス増分値に 1 以外の値を指定する場合、インデックス ステートメントの後に「by x」(x はインデックスの増分値) を挿入します。

次のステートメントでは、インデックスは順に 1、3、5 に設定されます。

resetMaxFile #noprompt --reset the scene
mybox = box length:10 width:10 height:10 wirecolor:blue --new box
for i = 1 to 5 by 2 do --repeat with step of 2:
(
box_copy = copy mybox --create a copy of the original box
box_copy.pos = [i*20, 0, 0] --place it i*20 units along x
box_copy.wirecolor = [i*25,i*50,(5-i)*50] --blue-green gradient
)--end of the for loop

 

  • 「do」キーワードは、ループが繰り返されるたびに続くブロックまたはステートメントを実行するよう MAXScript に指示します。ループの中には、等号「=」の代わりに「in」が記述されているものもあります。ループで使用する場合、どちらも同じ意味を表し、交換可能です。

  • 新規ボックスの位置を設定するために、インデックスがループ ステートメント内でどのように使用されているかに注目してください。複数のオブジェクトを作成する場合、これは有用な方法です。カラーには同じ方法が使用され、インデックスに基づき R、G、B 要素が変更されました。

for ループは、配列の作成や、配列内の値へのアクセスを行う場合にも有用です。次の例では、for ループを使って「arr」という配列を作成します。

 

上の例では、変数 arr に for ループ式を代入しています。このように、MAXScript は式をベースとする言語であるため、変数の代入に式を利用できます。

上の for ループ内の「collect」ステートメントに注目してください。これは、配列内の各反復の結果を単に計算するだけでなく、収集するよう MAXScript に指示しています。ここでは、MAXScript に対しインデックスの値を収集するよう指示しているだけですが、各式の反復を収集することもできます。

さらに、for ループを使用して、配列の内容に対して反復を実行することもできます。次の例は、前の例で作成した配列の値に、for ループを使ってアクセスします。

 

「print」コマンドは、指定された変数をリスナー ウィンドウに表示する MAXScript の関数です。この例では、等号の代わりに「in」を使用していますが、配列内の値にアクセスする場合にはどちらを使用してもかまいません。

注:

.count プロパティを使用すれば、配列内の要素数にアクセスすることもできます。

たとえば、上の例を次のように記述することも可能です。

for i = 1 to arr.count do print arr[i]

これにより、同じ結果が得られます。

While ループと Do ループ

while および do ループは、テスト式の評価が false になるまで、実行を繰り返すために使用されます。while および do ループは、互いに簡単なバリアントです。

構文は次のようになります。

do <expr> while <expr> -- do loop
while <expr> do <expr> -- while loop

次の例は、反復ごとの変数の増分値を -1 に設定して、変数の値を返します。

x=10
while x>0 do print (x-=1)

戻り値:

9
8
7
6
5
4
3
2
1
0
0

MAXScript は、自動的にループの最後の値をリスナーに返します。この例では、ループの各反復の値を返すよう MAXScript に指示しています。このため、最後の値は 2 度返されます。

どちらのループでも、while <expr>によって true 値に評価される間、do <expr>が繰り返し実行されます。do 形式は、ループの最後でテスト式を評価する前に、do <expr>を最低 1 回実行します。while 形式は、ループの始めにテスト式を評価するので、1 回もループしない場合があります。

いずれの形式も、最後に正しく実行したループ反復処理から do <expr>の結果を値として返します。テスト式がすぐに false を返す場合、while 形式は undefined 値を返します。

x=10
do print (x-=1) while x>10

戻り値

9
undefined

一方、

x=10
while x>10 do print (x-=1)

戻り値

undefined

次のトピック

ローカルおよびグローバル変数