for
ループを使用すると、配列またはオブジェクト セットなど、ある範囲の数、時間値、一連の値の集合を繰り返すことができます。
for
ループの構文を以下に示します。
for <var_name> [, <index_name>[, <filtered_index_name>]] ( in | = )<sequence> ( do | collect ) <expr>
ここで、<var_name>
は、ループ値を保持するループ項目変数の名前です。<sequence>
は、ループの値のソースです。
<index_name>
と <filtered_index_name>
はループのインデックスを保持するオプションの変数です。<index_name>
は、フィルタ式(where)の影響を受けません。また、元の値の位置に対応します。<filtered_index_name>
は、フィルタ リスト内の値の位置です。これら 2 つのインデックスの違いについては、以下の例を参照してください。
3ds Max 2021 以降 で使用可能です。<sequence>
は、次のいずれかです。
<expr> to <expr> [ by <expr> ] [while <expr>] [where <expr> ]
<expr> [while <expr>] [ where<expr> ]
<expr> to <expr> [ by <expr> ] [where <expr> ]
<expr> [where <expr>]
例:
for i = 1 to 10 do print i -- sequence numbers
for item in table1 do x = x + item.height -- sequence an array
for t in 0f to 100f by 5f do sliderTime=t -- sequence time (given as frames, here)
bigones = for obj in $box* -- you can sequence pathnames! where obj.height > 100 collect obj -- collect the big boxes into an array
for i,j,k = 12 to 24 where (mod i 3 == 0) do ( -- filter numbers divisible by 3 format "val:% index:% filtered index:%\n" i j k ) --> produces this output: val:12 index:1 filtered index:1 val:15 index:4 filtered index:2 val:18 index:7 filtered index:3 val:21 index:10 filtered index:4 val:24 index:13 filtered index:5
最初の <sequence>
形式は従来の数ループ、最初の <expr>
値は開始値、to <expr>
値は制限値、オプションの by <expr>
値はループ値の増分です。使用できる値のタイプは整数、浮動小数点、および時間です。by
の値が指定されない場合、既定値は 1 になります。
<sequence>
の 2 つ目の形式は、配列または ObjectSet などの順序付けできるコレクションであり、すべての値を繰り返し、コレクションの連続要素をループ値に代入します。MAXScript には、PathName 値、現在の選択セット、子ノード、オブジェクト上のモディファイヤのスタックなど、シーケンス コレクションがいくつかあります。for
ループ内でコレクションを使用する場合の注意事項については、「コレクション」を参照してください。
オプションの while <expr>
テストが指定されている場合、このテストで false
と評価されたら for
ループは終了します。while
テスト式は、ブール値(true
/false
)に評価されます。
パフォーマンスに関する警告
exit
構文を使用したループの脱出が try/catch によって内部的に実装されていますが、これは非常に低速です。したがって、パフォーマンス上の理由から、
exit
の使用よりもwhile
テストの使用が推奨されます。while
式はwhere
式より前に評価されます。
例:
function findByClass _obj _className = ( local notFound = true local res = 0 local searchName = _className as name for i = 1 to _obj.NumBakeElements() while notFound do ( local myElement = _obj.GetBakeElement i if myElement.enabled do ( local eleName = (classof myElement as string) as name if eleName == searchName do ( res = i notFound = false ) ) ) return res )
各 <sequence>
ソース形式は、true
または false
に評価されるオプションの where <expr>
を受け取ります。where
式は各ループの最初で評価され、where
式の値が true
の場合にのみループ本体が実行されます。
do <expr>
形式は、ソース内の値ごとに 1 回だけ本体式を評価します。ループ変数は、あたかもローカルで宣言され、毎回連続したループ値で初期化されているかのように見えます。do <expr>
形式での for
ループが式として使用された場合、その戻り値は常に OK
です。
collect <expr>
形式は、ループ反復から式の値を収集してその値を配列内に格納し、for
ループの結果として配列を生成します。これは、シーンからオブジェクトの一連の選択を収集するのに便利です。where
式を collect
形式の for
ループとともに使用すると、where
式が、true
になる値だけが収集されます。これは、フィルタ処理した反復値のサブセットを収集する場合に使用できます。また、for
ループでの別のコレクションのフィルタ処理として、where
式を使わずに dontCollect
を使用してコレクションに特定の値を追加しないようにすることもできます。
「変数のスコープ」で解説されているように、for
ループは新しいスコープのコンテキストを作成します。for
ループのインデックス変数のスコープは、同じ名前の変数が既に存在する場合でも、常に for
ループの範囲内にあります。for
ループが終了すると、for
ループのインデックス変数にアクセスできなくなります。for
ループ内で作成された変数のスコープは、常に for
ループの範囲内に存在します。 以下に例を示します。
例:
obj=box() avg_pos=[0,0,0] offset_pos=[100,100,0] -- new for loop index variable obj created even though -- a variable named obj already exists, scope is for loop for obj in $* do ( -- new variable pos created, scope is for -- loop offset_pos already exists outside -- for loop, its value will be used pos=obj.pos-offset_pos -- avg_pos already exists outside for loop, -- its value will be used for loop index since variable -- obj goes out of scope avg_pos += pos ) avg_pos /= $*.count