ブロック式とは、構成コードの基本的なコンストラクタのことです。グループ式を使用して一連の式をグループ化し、グループ化された式を 1 つの式のように順に評価することができます。
<block_expr>
の構文は以下のとおりです。
( <expr> { (; | <eol>) <expr> } )
それぞれの <expr>
が行区切りかセミコロン ; で分割され、カッコで囲まれた一連の式です。
MAXScript では空のブロック式 ()
も使用できます。これは、後でパスが埋められる空の式を含むコードを増分して構築するときに便利です。空の式を評価すると、undefined
値が生成されます。
例:
x = 2 y = 3 z = 4 p = [10,10,10] centre = [20,20,20] ( d = centre.x^2 - (p.x^2 + p.y^2) newz =if d > 0 then sqrt d else p.z print newz ) if x < y then (print x; print y; u += 10; print u)
次のように、行区切りまたはセミコロンを混合して使用することができます。
例:
( print x; print y p.x += 10 print p.x; print p.y )
ブロック式は <operand>
なので、<operand>
を入れることのできる場所ならどこにでもブロック式を挿入することができます。他のほとんどの言語はコードのブロックを入れることのできる場所をわずか数ヶ所に制限していますが、MAXScript はこの点が異なります。
さらに、MAXScript ではすべての構成が式なので、ブロック式はブロックの最後の <expr>
になるよう定義された値を生成します。これにより、次のようにネストされた一連の式を一部の演算のオペランド計算に使用できるようになります。
例:
b = box() b.pos.z = ( d = x^2 - y^2 if d > 0 then sqrt d else z )
ここでは、ブロック式の結果は
if
式の最終結果であり、b.pos.z
に代入されます。
カッコで囲まれた項目は any<expr>
なので、MAXScript の構文をカッコで囲むことにより構文をオペランドに変えることができます。インデックスで指定されたオペランドが if
式の条件結果となる次のような例を記述することができます。
(if a > b then c else d)[n + 1]
「変数のスコープ」で説明されているように、スクリプト ファイルまたはリスナー内のトップ レベルのカッコによって、新しい変数スコープが作成されます。トップ レベルのブロック式を含むブロック式は、すべて新しい変数スコープを作成しません。これは、その変数が内部のブロック式の中でローカルとして明示的に宣言されている場合も同じです。変数のスコープは、そのスコープ内にあるすべてのブロック式にもあてはまります。スコープ内で変数をローカルとして宣言した場合、新しく宣言されたローカル変数は同じ名前の外側の変数をすべて不可視にします。ローカル変数のスコープ内でのこの変数名への参照は、以後この新しいローカル変数が使われます。ローカル変数のスコープの最後に到達すると、次の外部変数が再び可視になります。以下に例を示します。
スクリプト:
a=1 ( local a=2 ( local a=3 ) print a ) a
出力:
1 -- result of line 1 3 -- output of line 7 3 -- result of block-expression lines 2 to 8 1 -- result of line 9
高いスコープ レベルで作成されたブロック式で使われる変数名は、現在のスコープで黙示的にローカルとして宣言されます。これは、スクリプトが正しく設定されていない場合に、予期しない実行結果をもたらします。
次のスクリプトを例に考えてみます。
(b=bend();addmodifier Objs b) -- create bend modifier and apply to objects b.angle=10
このスクリプトを最初に実行すると、次のエラー メッセージが表示されます。
-- Unknown property: "angle" in undefined
このスクリプトは、再び実行すると正常に動作します。理由は、
b
という名前の変数が実際には 2 つあり、一方はブロック式に対してローカルでブレンド モディファイヤの値を保持し、もう一方はグローバルでundefined
値を保持するためです。2 回目の実行時には、グローバル変数b
が存在するため、ブロック式は黙示的に新しい変数b
を宣言せず、グローバル変数b
を使用します。
また、スクリプトを作成するときは、特にグローバル変数を使用したい場合を除き、すべての変数をローカルとして宣言することをお勧めします。これは、次のような理由によります。
ブロックまたは関数で使用するすべての変数名をひとまとめにできるため、変数名を見つけるのが簡単で、スクリプト内で誤った名前の使用を防ぐことができます。
同時に複数のスクリプトを実行する場合(たとえば、スクリプト ユーティリティを実行し、シーン内にスクリプト コントローラがある場合)、両方のスクリプトで同じグローバル変数名が使用されているとスクリプト同士が干渉し、一方または両方のスクリプトで予期できないエラーが発生する場合があります。
上のレベルのスコープで同じ名前の変数が既に宣言されている場合でも、確実に正しい変数を使用でき、上のレベルの変数の値を無意識に変更することはありません。
ローカルとして明示的に定義された変数の値は、エラー コールスタック トレースバックに表示されます。
3ds Max R2.5 では、3ds Max クラス、MAXScript メソッド、または MAXScript 読み込み専用グローバル変数が暗示宣言ローカル変数と同じ名前を持ち、その変数名への代入が発生した場合には、MAXScript ランタイム エラーが生成されます。変数名が既にグローバル スコープに存在していたため、暗示宣言ローカル変数は作成されませんでした。ユーザがロードしたサード パーティのプラグインによって 1 つ以上の新規 3ds Max クラスが作成されるため、変数名がグローバル変数名の場合は前もってこれを知ることができませんでした。3ds Max 4 以降では、これらの変数への最初の参照が代入であることが MAXScript コンパイラにより検出されると、読み込み専用のシステム グローバルへの参照としてそのままにするのではなく、暗示的にローカル変数が宣言されます。
例:
3ds Max R2.5 で次の式を実行すると、値は
Box
になります。これは、Box
が 3ds Max オブジェクト クラスであるためです。3ds Max V 4 以降では、変数
box
の最初の使用が代入であることが MAXScript により検出され、暗示宣言ローカル変数box
が作成されます。3ds Max V 4 以降でのこの式の結果は
undefined
です。(if false do box=10;box)