
Управление порядком выполнения операторов
Как и все языки программирования MAXScript содержит ряд средств, для того чтобы операторы, составляющие программу, выполнялись в нужном программисту порядке.
К ним относятся
Условный оператор if
Оператор выбора case
Операторы цикла do и while
Оператор цикла for
Операторы принудительного завершения и пропуска цикла exit и continue
Оператор обработки исключительных ситуаций try
Имеются еще операторы on и when, но до них, Бог даст, дойдем в свое время. Пока же разберем названные операторы в порядке перечисления.
Условный оператор if
Этот оператор может выступать в двух формах:
if … then … else …
или
if … do …
Первая форма работает следующим образом. Если выражение, стоящее после if имеет значение true, то выполняются операторы, стоящие после then, в противном случае, те которые стоят после else. Рассмотрим пример
x = 1
if x = = 1 then print “x equal 1” else print “x not equal 1”
Приведенный скрипт напечатает “x equal 1” (заставить MAXScript говорить по-русски мне не удалось). Естественно, после слов then и else не обязательно должен стоять один оператор, но если их несколько, то они должны быть заключены в скобки
x =2
if x = =1 then
( print "x equal 1"
y = 5
)
else
( print "x not equal 1"
y = 6
)
Теперь напечатается строка “x not equal 1”, а переменная y получит значение 6. Вообще-то else – необязательный элемент условного оператора. Можно, например, написать такой скрипт
x = 1
if x = = 1 then print “x equal 1”
Конкретно в этом случае напечатается “x equal 1”, а если в начале поставить “x = 2”, то не напечатается ничего. Без else оператор if … then … полностью идентичен оператору if … do…. Разница между этими операторами проявляется только при работе с окном интерпретатора. Если Вы введете, например, такую строку
if x = = 1 then print “x equal 1”
и нажмете на клавишу “Enter”, то интерпретатор будет ждать, пока Вы не введете else или какой-нибудь другой оператор. Если же Вы введете
if x = = 1 do print “x equal 1”
то результат последует незамедлительно.
И последнее, что следовало бы сказать об операторе if. Как и все другие выражения и операторы в MAXScript, он обладает необычным для языков программирования свойством – возвращать значение. При этом возвращается значение последнего выполненного выражения. Благодаря этому с помощью оператора if можно присвоить переменной значение в зависимости от некого условия. Например:
x = if ( y > 1 ) then 1 else y
присвоит переменной x значение переменной y или единицу в зависимости от величины переменной y.
Оператор case
Case несколько напоминает if. Разница только в том, что с его помощью можно организовывать не две, а неограниченное количество ветвей выполнения программы. Записывается он примерно так
case a of
(
1: y = x + 3
2: y = x – 2
0: y = 0
default: y = x
)
Выполнение этого скрипта осуществляется следующим образом. Проверяется значение переменной a и если оно равно 1, то переменная y получает значение x + 3, если 2, то x – 2, если 0, то 0, а во всех остальных случаях просто x. Как и в случае с оператором if, оператор case можно использовать для присвоения значений переменной. Для этого приведенный скрипт можно переписать так.
y = case a of
(
1: x + 3
2: x – 2
0: 0
default: x
)
Разумеется, в реальных программах ветки могут быть более сложными и вместо простенького x + 3 может стоять сложный блок операторов, заключенный в скобки. Так же и вместо тех значений, с которыми сравнивается управляющая оператором case переменная, в нашем случае это a, могут быть и переменные, и выражения заключенные в скобки. Вместо управляющей переменной тоже может стоять любое выражение. Например
y = case a + 1 of
(
1: x + 3
(z + 3): ( t = 77
x - 2
)
0: ( t = 64
0
)
default: x
)
В этом случае, если а + 1 равно 1, то y будет равно x + 3, если a + 1 равно z + 3, то переменной t присвоится значение 77, а y получит значение последнего выражения в блоке, то есть x – 2 . Если a + 1 равно 0, то t будет равно 64, а y нулю, а во всех прочих случаях y получит значение x. При выполнении такого скрипта может сложиться пикантная ситуация, когда z + 3 равно нулю или единице, и будет неясно по какой из веток идти программе. Ответ прост: в этом случае вычисляется та группа операторов, которая записана первой. Например, если a + 1 равно единице, и z + 3 тоже, то y в результате будет равен x + 3.
Выражение, управляющее оператором case, может и вовсе не указываться. В этом случае выражения перед двоеточиями обязаны иметь значение true или false.
y = case of
(
( x > 2 ): 2
( x > 1 ): 1
( x > 0 ): 0
default: 3
)
Выполняется первая из веток, у которой выражение, стоящее перед двоеточием имеет значение true.
Операторы цикла do и while
Это, пожалуй, наиболее простые операторы в MAXScript. В общем виде они записываются так.
do группа операторов while логическое выражение
while логическое выражение do группа операторов
Рассмотрим пример
x = 0
s = 0
while x < 100 do
( x = x + 1
s = s + x
)
Таким образом можно подсчитать сумму целых чисел от 1 до 99. В приведенном скрипте оператор цикла работает так. Сначала подсчитывается значение логического выражения, стоящего после while. Если это значение равно true, то выполняется группа операторов после do, затем снова вычисляется логическое выражение while и т.д. При этом на совести программиста остается обязанность следить за тем, чтобы условие, стоящее после while хотя бы когда-нибудь получило значение false. В противном случае 3ds max зависнет и его придется выгружать насильно. Вторая форма этого оператора, когда сначала стоит do, а затем while, отличается от первой порядком выполнения.
x = 0
s = 0
do
( x = x + 1
s = s + x
) while x < 100
Сначала выполняется группа операторов, затем проверяется условие после while. Для приведенного примера это не дает никаких изменений, но бывают случаи, когда это важно. Представим себе такой случай
x = 100
s = 0
while x < 100 do
( x = x + 1
s = s + x
)
Условие проверяется, и, поскольку оно сразу false, группа операторов не выполнится ни разу. Изменим форму цикла
x = 100
s = 0
do
( x = x + 1
s = s + x
) while x < 100
Группа операторов выполнится один раз, затем проверяется условие. Убедившись, что оно равно false, программа завершает цикл. Разница налицо – в первом случае группа операторов не выполнилась ни разу, во втором один раз.
Цикл for
В MAXScript цикл for имеет большую гибкость, нежели в других языках программирования. Это достигается благодаря разным формам его записи. Вот первая из них
for имя переменной = начальное значение to конечное значение do выражение
Имя переменной – это действительно имя переменной, выражение – простое или блоковое выражение, начальное значение – любое выражение, а вот конечное значение может быть организовано довольно хитро. Самый простой случай, например такой
s = 0
for i = 1 to 100 do s = s + i
Новый способ подсчитать сумму ста первых целых положительных чисел. В конечном значении можно указать шаг изменения переменной. Например
s = 0
for i = 1 to 100 by 2 do s = s + i
Подсчитает нам сумму всех нечетных чисел от 1 до 99. И, наконец, можно указать дополнительное условие в виде логического выражения после ключевого слова where. В этом случае группа операторов будет выполняться, только если это выражение будет иметь значение true.
s = 0
for i = 1 to 100 by 2 where i != 13 do s = s + i
Теперь из суммы нечетных чисел исключена чертова дюжина.
Вторая форма записи цикла for применяется, главным образом, для того, чтобы перебрать все элементы какого-нибудь набора и выглядит примерно так
for имя переменной in набор do выражение
В качестве набора может выступать массив, группа объектов сцены 3ds max или выражение, возвращающее группу объектов. О разного рода наборах объектов речь еще будет вестись подробно, а пока разберем пример
a = #( 1 , “txt”, 3 , $box01, 7 , 11 )
for i in a do print i
Цикл выводит на экран все элементы массива a, который содержит разнотипные элементы, при этом не выясняя размерность массива. Справедливости ради следует отметить, что это можно было сделать и при помощи первой формы цикла for.
for i = 1 to a.count do print a[i]
Но вторая форма компактнее. А вот если надо, например, подсчитать общую высоту всех объектов, содержащихся в сцене, то вторая форма записи являет свое преимущество в полном блеске
h = 0
for b in $* do h + = b.height
Во второй форме так же можно применять дополнительное условие с ключевым словом where. Усложнив задачу, предположим, что надо подсчитать общую высоту всех стандартных примитивов Box.
h = 0
for b in $* where classof b = = Box do h + = b.height
В обеих формах записи вместо ключевого слова do, может применяться слово collect. В этом случае в качестве результата выполнения оператор for вернет массив значений. Его размерность будет равна количеству выполнения выражения, следующего за collect, а значения элементов будут равны тем значениям, которые это выражение возвращает. Предположим, нам надо собрать в один массив радиусы всех примитивов Sphere, чтобы вычислить их средний радиус, а затем установить этот радиус для всех сфер в сцене. Эту задачу можно решить так
ArrayR = for b in $* where classof b = = Sphere collect b.radius
R = 0
for rr in ArrayR do R+ = rr
R / = ArrayR.count
for b in $* where classof b = = Sphere do b.radius = R
Разумеется, ее можно решить и проще, но первая строка скрипта иллюстрирует применение ключевого слова collect.