The for loop iterates through a range of numbers, time values, or a sequenced collection of values, such as an array or object set.
The syntax for the for loop is:
for <var_name> ( in | = ) <sequence> ( do | collect ) <expr>
where <var_name> is the name of the loop index variable that holds the loop value, and <sequence> is the source of values for the loop.
The <sequence> can be one of the following:
<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
The first <sequence> form is the standard number loop, the first <expr> value is the start value, the to <expr> value is the limit value and the optional by <expr> value is the loop value increment. The allowable value types are integer, float and time. If the by value isn't given it defaults to 1.
The second form of <sequence> takes a sequencable collection, such as an array or ObjectSet, and iterates through all its values, assigning successive elements in the collection to the loop value each time through the loop. MAXScript contains several sequence collections, including PathName values, the current selection set, the children of a node, and the stack of modifiers on an object. See also Collections for caveats when using a collection in a for loop.
If an optional while <expr> test is specified, the for loop will terminate if the test evaluates to false. The while test expression must evaluate to a boolean (true/false). Note: Breaking out of a loop using an exit construct is implemented internally using try/catches, which are extremely slow. This is why the use of the while test is recommended over the use of exit for performance reasons. The while expression is evaluated before the where expression.
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
Each <sequence> source form takes an optional where <expr> which must evaluate to true or false. The where expression is evaluated at the beginning of each loop and only executes the loop body for that loop value if the where expression is true.
The do <expr> form simply evaluates the body expression once for each value in the sequence. The loop variable is visible to the code in the body expression as though it was declared locally and initialized to the successive loop values each time. When the do <expr> form of a for loop is used as an expression, its return value is always OK.
The collect <expr> form gathers the expression values from the loop iterations and stores them in an array, which is then yielded as the value of the overall for loop. This, for example, is a good way to gather procedural selections of objects from a scene. If the where expression is used with the collect form of the for loop, only the values from those iterations for which the where expression is true are collected. This can be used to collect a filtered sub-set of the iterated values. You can also achieve this collection filtering in a for loop that does not use a where expression by yielding the special value dontCollect for those iterations that should not be added to the collection.
As described in Scope of Variables, a for loop creates a new scope context. The for loop index variable's scope is always the extent of the for loop, even if another variable of the same name already exists. Once the for loop exits, the for loop index variable is no longer accessible. The scope of any variables created in a for loop is always the extent of the for loop. This is shown in the following example:
for obj in $* do -- new for loop index variable obj
-- created even though a variable named
-- obj already exists, scope is for loop
( pos=obj.pos-offset_pos -- new variable pos created, scope is for
-- loop offset_pos already exists outside
-- for loop, its value will be used
avg_pos += 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 /= $*.count
Skipping Loop Iterations