Вы находитесь на странице: 1из 23

Часть 1

MAXScript – встроенный в 3ds max язык написания скриптов. Скрипт – это текстовый
файл, обычно с расширением .ms.
При помощи скриптов можно:
1. Программировать множество действий пользователя, таких как моделирование,
анимация, наложение материалов, визуализация (rendering) и др.
2. Интерактивно контролировать программу из командной строки окна Listener.
3. Создавать для скриптов стандартный пользовательский интерфейс, размещая его
элементы в свитках панели Utility, или в управляющих окнах.
4. Создавать из скриптов макрокоманды и вставлять их в качестве кнопок на панели
инструментов 3ds max.
5. Расширять или изменять пользовательский интерфейс для объектов (objects),
модификаторов (modifiers), материалов (materials), текстур (textures), эффектов
визуализации (render effects) и атмосферных эффектов (atmosperic effects).
6. Создавать дополнения для собственных объектов-сеток (mesh objects),
модификаторов и эффектов визуализации.
7. Создавать свои собственные инструменты импорта/экспорта с помощью
встроенного средства ввода/вывода файлов (file I/O).
8. Писать процедурные контроллеры и с их помощью управлять состоянием всей
сцены.
9. Создавать инструменты групповых вычислений, например, скрипты для
последовательной визуализации множества сцен.
10. Управлять внешними приложениями через механизм OLE Automation.
11. Записывать свои действия в 3ds max, как команды MAXScript.
12. Хранить в файлах сцен скрипты, которые будут запускаться при каждом из
определенных событий, например, до и после открытия файла сцены, созданием
нового файла, после и перед визуализацией, изменением выбранных объектов и т.п.
Доступ к MAXScript: Command Panel > Utility > MAXScript
MAXScript – падающее меню
Инструмент Описание
Open Listener отображает окно MAXScript Listener. Это окно также можно открыть,
нажав кнопку F11.
New Script отображает окно MAXScript Editor для записи нового скрипта.
Open Script открывает диалоговое окно File Open. Выбранный скрипт
отображается в новом окне MAXScript Editor.
Run Script открывает диалоговое окно File Open. Выбранный скрипт
прочитывается и выполняется. Все выходные данные печатаются в
окне Listener.
Utilities отображает список доступных программ-скриптов (утилит). Имя
утилиты не появится в окне до тех пор, пока MAXScript ее не
запустит.
Close Закрывает свиток MAXScript и все свитки утилит.

Окно MAXScript Listener


Свойства
Чтобы выделить строку целиком, нужно подвести курсор к ее левому краю (он
примет вид стрелки) и щелкнуть один раз. Если щелкнуть, не отпуская, и повести
мышкой, выделяться будут сразу несколько строк.
Методом drag-and-drop можно перемещать выделенный текст между частями окна
Listener и между окнами Editor и Listener. Если переместить его на панель инструментов
3ds max, создается макроскрипт с этим текстом.
Выделенный текст автоматически загружается в поле поиска, когда пользователь
выбирает из падающего меню Search пункт Find или Replace.
Цветовое кодирование: вводимый пользователем текст – черный, выходной текст
MAXScript – синий, текст сообщений об ошибках – красный.
Некоторые полезные команды
CTRL+B Выделяет текст внутри скобок любого типа. Можно нажимать
несколько раз, если есть еще скобки, выделение будет
расширяться (В Editor тоже работает).
ENTER Если курсор находится на конце последней строки, она
выполняется, в окне Listener печатается выходной текст и
курсор переходит на новую строку.
Если курсор находится в другом месте, добавляется новая
строка, начиная с его текущей позиции.
Number-Pad ENTER Выполняется строка, содержащая курсор.
SHIFT+ENTER То же самое, если текст не выделен. Иначе выполняется
только выделенный текст.
? Всякий раз, когда выполняется одна или несколько команд,
последний вычисленный результат, отображаемый в окне
Listener сохраняется во внутренней переменной ?. Для
дальнейшего использования можно присвоить его любой
пользовательской переменной: x = ?

Окно MAXScript Editor


Некоторые полезные команды
File>Evaluate All, CTRL+E Выполняет весь код из окна MAXScript Editor. Также
можно выделить весь текст и нажать SHIFT+ENTER.
TAB, CTRL+I Смещает выделенный текст вправо на один шаг
табуляции.
SHIFT+TAB, SHIFT+CTRL+I Смещает выделенный текст влево на один шаг
табуляции.
Number-Pad ENTER Посылает выделенный текст для выполнения в окно
Listener, результаты печатаются в конце текущего
текста окна Listener. Если текст не выделен, в Listener
для выполнения посылается строка, содержащая
курсор.
SHIFT+ENTER То же самое.
CTRL+Right-Click Отображает меню со всеми определениями элементов,
существующих в данном скрипте: utility, structure, user-
interface item, function, handler, plugin, tool, Macro Script,
rcmenu. Выберите любой пункт, и его определение
окажется в верхней строке окна Editor. Эта
возможность упрощает навигацию по большим
скриптам.
CTRL+B Выделяет текст внутри скобок любого типа. Можно
нажимать несколько раз, если есть еще скобки,
выделение будет расширяться.
CTRL+D Перекрашивает текст: комментарии – зеленым,
зарезервированные слова – синим, строковые
переменные – красным. Изначально весь текст
печатается черным.
CTRL+R Помещает курсор в его предыдущую позицию
(задается щелчком левой кнопки или операцией
поиска). Последовательное нажатие перемещает курсор
по последним восьми запомненным позициям. Эта
возможность сильно сокращает количество мышиных
щелканий.
ESC Нажмите и не отпускайте до тех пор, пока работающий
скрипт не закончит выполняться. Кнопка останавливает
выполнение любого скрипта, откуда бы его ни
запустили.

Синтаксис
Если строка длинная, ее можно разбить. Исходная строка: a + b * c / d – e + f * g / h
Можно разбить только после любого оператора. MAXScript будет искать продолжение на
следующей строке.
Так работает: a+b*c/d–e+ А так не работает: a+b*c/d–e
f*g/h +f*g/h
Можно разбить, добавив символ “\”: a+b*c/d–e\
+f*g/h
Несколько выражений можно записать в одной строке, разделив их символом “;”:
print “End of input data reached” to: f; close f; f = undefined
Комментарий первого типа в MAXScript начинается с символов “--” и распространяется до
конца строки: a = 5 -- В переменную а записано число 5
/* Комментарий второго типа
может располагаться
на нескольких строках*/

Целые (integer) и вещественные (float) числа


При выполнении простейших математических операций результат, как правило,
имеет тот же тип, что и аргументы: 3 + 4 возвращает 7, 3.0 + 4.0 возвращает 7.0. Однако,
если совместно используется оба типа чисел, целое понимается как вещественное: 3 + 4.0
возвращает 7.0

Переменные
variable_name = variable_value -- присвоение переменной значения
variable_name = “Текст” -- строковая переменная
local y = 2, x -- объявление локальных переменных (действуют в текущем блоке)
global bzzz -- объявление глобальных переменных (действуют всю сессию 3ds max)
Имя переменной должно начинаться с буквы или символа “_”. Ее значение – любое число,
строка или выражение.

Массивы
В массиве может содержаться любое количество элементов, каждый любого типа.
a = #( ) -- пустой массив
a = #(5, “four”, pi, 11.17) -- массив с элементами
a[int] -- элемент массива, int - номер элемента (целое число, нумерация с 1)
Например: a[2] возвращает “four”

Простейшие математические операторы и выражения


С числами
4/3 * pi * 2.5^3 -- формула объема сферы радиусом 2.5. Возвращает 49.0874
3 as string -- возвращает “3”

Со строками
a = “MAXScript”; b = “ FOREVER”
a + b -- возвращает “ MAXScript FOREVER”
“3” as float -- возвращает 3.0
“3.56” as integer -- возвращает 3

Создание случайных чисел


Тип числа зависит от типа первого аргумента в операторе random
random 1 100 -- возвращает случайное целое число между 1 и 100
random 1.0 100 -- возвращает случайное вещественное число между 1 и 100
Числа будут одинаковыми всякий раз при перезагрузке 3ds max. Чтобы избежать
этого, можно использовать оператор seed <number>, где <number> это любое целое или
вещественное число. Пример: seed 5

Приращения
<переменная> += <выражение> добавляет <выражение> к переменной
<переменная> -= <выражение> вычитает <выражение> из переменной
<переменная> *= <выражение> умножает переменную на <выражение>
<переменная> /= <выражение> делит переменную на <выражение>
Поэтому запись x = x + 1 равносильна записи x += 1

Операторы сравнения
<compare_operand> == <compare_operand> оба операнда равны
<compare_operand> != <compare_operand> оба операнда не равны
<compare_operand> < <compare_operand> левый операнд меньше правого
<compare_operand> <= <compare_operand> левый меньше или равен правому
<compare_operand> > <compare_operand> левый операнд больше правого
<compare_operand> >= <compare_operand> левый больше или равен правому
Логические операторы
<logical_operand> and <logical_operand> истина, если истинны оба
<logical_operand> or <logical_operand> истина, если истинен хотя бы один
not <logical_operand> истина, если операнд ложен

Управляющие конструкции
if <if_expr> then <expr> [else <expr>]
if <if_expr> do <expr>
Результат выполнения выражения <if_expr> должен быть либо истиной (true), либо ложью
(false).
Пример 1:
if a > b and a < c do (print d; print e)
if a == b then c = 0
a = (if d == 0 then 0 else a / d)
Пример 2:
if a > b then
(
print c
x = sqrt (c)
)
else (print d; x = sin (e))
Выражения, находящиеся внутри круглых скобок, образуют блок. Значение
последнего выражения в блоке является значением всего блока. Поэтому можно писать,
например, так: if a > (y = sin b; sqrt (y*z)) then print c
case [ <case_expr> ] of ( <cases> )
Выражение <case_expr> сравнивается с метками выражений <cases>:
<factor>: <expr>
default: <expr>
Пример:
new_width = case obj.width of
(
2: copy $Box01
3: instance $Box01
default: reference $Box01
)
Выражение после ключевого слова default будет выполнено, если не выполнятся
остальные условия. Если default не задано и другие условия не выполнились, выражение
case возвращает значение undefined.
Если выражение <case_expr> не задано, метки должны быть булевыми (Boolean)
величинами или выражениями, и первая метка, дающая истину, определяет выполняемое
выражение <expr>. Пример:
case of
(
(a > b): print “a is big”
(b < c): print “b is little”
(c <= d*3): ...
default: ...
)

Циклы
do <expr> while <test_expr> -- форма do
while <test_expr> do <expr> -- форма while
Циклы while и do повторяют выполнение выражения <expr> до тех пор, пока
тестовое выражение <test_expr> не возвратит ложь, т.е. пока оно истинно, они работают.
Форма do выполняется минимум один раз, вычисляя тестовое выражение в конце каждого
прохода. Форма while вычисляет тестовое выражение в начале каждого прохода и может
не выполниться ни разу. Обе формы в качестве своего значения возвращают результат
выражения <expr> после последнего удачного прохода. Форма while возвратит значение
undefined, если тестовое выражение ложно изначально и ни одного прохода не
выполнится.
Пример 1: Пример 2:
x = -10 do
while x < 0 do (
( print x exchanged = false
x += 1 for i=1 to imax do
) (
j=i+gap
if (compare array[j] array[i]) do
(swap array[j] array[i];exchanged=true)
)
)
while exchanged

for <var_name> (in | = ) <sequence> (do | collect) <expr>


Цикл for повторяет определенное число проходов, которое может задаваться
диапазоном чисел, временным интервалом или последовательностью определенных
величин, таких, как массив или набор выделенных объектов. Переменной с именем
<var_name> последовательно присваиваются значения из набора <sequence>, формат
которого бывает либо такой: <expr> [where <expr>], либо такой: <expr> to <expr> [by
<expr>] [where <expr>]
Примеры:
for i = 1 to 10 do print i -- последовательность чисел
for item in array1 do x = x + item.height -- последовательность элементов массива
for t in 0f to 100f by 5f do ... -- временной интервал (0–100) через каждые 5 фреймов

Следующий пример собирает объекты в массив bigones:


bigones = for obj in $box* -- для всех объектов, чье имя начинается с box
where obj.height > 100 collect obj -- собирать объекты с высотой больше 100
Выражение <expr>, стоящее после ключевого слова where, вычисляется перед
каждым проходом и должно возвращать либо true – тогда проход просчитывается, либо
false – цикл игнорирует текущий проход и переходит к следующему.

Пропуск проходов и принудительный выход из циклов


Оператор continue осуществляет мгновенный переход в конец цикла и начинает
следующий проход.
Примеры:
for i=1 to 8 do (if i == 5 do continue; print i) -- печатает 1..4, 6..8
for i=1 to 8 collect (if i == 5 do continue; i) -- возвращает #(1, 2, 3, 4, 6, 7, 8)
while not eof do -- читает данные, пока не дойдет до конца файла
(
local line=readline f -- считывает одну строку
if line[1] == “-” do continue -- если комментарий, переход на следующую строку
line1=parser1 line -- вызов функции parser1
processobjs line1 -- вызов функции processobjs
)
Оператор exit немедленно прекращает выполнение любого цикла, даже если
тестовое выражение по-прежнему истинно. Он полезен при поиске ошибок в телах
циклов. exit [with <expr>]
Пример:
while x < y do
(
local delta = x – y
if delta <= 0 then exit -- условие выхода
$foo.pos.x = compute_x (foo / delta)
x += 0.1
)
Необязательный параметр with позволяет задать выражение, которому будет равно
общее значение цикла, если он завершится преждевременно. Если его не задать, цикл, из
которого вышли оператором exit, возвратит значение undefined.
Выход из цикла for ... do с использованием параметра with <expr> возвращает
значение OK.
Выход из цикла for ... collect с использованием параметра with <expr> возвращает
массив величин, собранный на момент выхода.

Часть 2
Функции
[mapped] (function | fn) <name> { <parameter> } = <expr> , где <name> – имя функции,
<expr> – тело функции, <parameter> – ее параметры (их может не быть вообще или быть
несколько), которые записываются так: <parameter name>, либо так: <parameter name>:
[<operand>] – необязательное значение по умолчанию, если не его задать, возвращается
значение unsupplied. Префих mapped означает, что функция будет автоматически
повторно вызываться на каждом элементе коллекции, если колЧасть задана в качестве
первого аргумента функции.
Примеры:
function add a b = a + b
fn factorial n = if n<=0 then 1 else n * factorial(n-1) -- рекурсивная функция
mapped function rand_color x =
x.wireColor = random (color 0 0 0) color (255 255 255)

fn starfield count extent: [200, 200, 200] pos: [0, 0, 0] =


(
local f = pos – extent / 2
t = pos + extent / 2
for i = 1 to count do
sphere name:”star” \
radius: (random 0.1 2.0) \
position: (random f t) \
segs:4 smooth:false
)
В качестве своего значения функция возвращает значение <expr>. Если тело – блок,
то значение последнего выражения в блоке. Если нужно найти функцию используется
метод showSource <fn>, который отображает окно Editor с файлом, содержащим данную
функцию и пролистанным до места ее определения – метод полезен, когда много функций
находятся в разных файлах.
Чтобы принудительно завершить выполнение функции используется оператор
return <expr>, где <expr> – выражение, которому будет равно значение принудительно
завершенной функции. Если return используется в функции с префиксом mapped и
колЧасть задана в качестве первого аргумента, возвращаемое значение будет OK, а не
<expr>.

Объекты и классы в объектно-ориентированном программировании


Все величины (values), с которыми работает MAXScript, имеют четко
определенный тип, например integer, matrix3, twist. Тип величины – это ее класс. В
MAXScript термины величина (value) и объект (object) – синонимы. Объект – особый
отдельный представитель класса.
Например, в MAXScript Box – это класс. Это не трехмерный объект в окне
проекции 3ds max, а набор характеристик, которыми этот объект box (ящик) обладает. В
этих характеристиках заложены способы создания представителей класса Box (объектов
box); свойства этих объектов (например, Height – высота, Width – ширина, Length – длина);
операции, которые можно с ними производить (например, move – перемещение, copy –
копирование, delete – стирание). Чтобы создать объект box, можно написать: b=box()
В этой строке фраза box() – конструктор, который создает объект box и возвращает
на него ссылку, сохраняемую в переменной b. Здесь для конструктора не применяются
никакие параметры (вроде высоты или ширины), поэтому используются значения по
умолчанию, определенные в классе Box. Объект box появляется в окнах проекции 3ds max
и с ним можно делать все то же самое, что и с другими трехмерными объектами. Если
параметры для конструктора нужно применить, они заменят “()”. Пример: b=box width: 10
length: 100 – создается объект box с указанными параметрами. Все неуказанные параметры
используют значения по умолчанию.

Определения
Properties (Свойства): Доступные параметры объектов класса. Например, ширина, длина,
высота для ящиков и радиус для сфер.
Methods (Методы): Определения всех функций, которые можно вызывать для объектов
класса. Примеры: перемещение или поворот объекта, применение модификатора и
получение координат вершин объекта. Термины method (метод) и function (функция) в
MAXScript синонимы.
Operators (Операторы): Определения всех математических и других символьных
операторов, которые работают с величинами класса. Пример: оператор ”-”, который
производит математическую операцию вычитания над числами, цветами, векторами и
матрицами, но произведет булево вычитание, когда будет использован совместно с
объектами 3ds max.
Constructors (Конструкторы): Различные способы, которыми можно создавать объекты
класса. Например: Point3 0 0 0 и <color> as Point3 – конструкторы для класса Point3.
Выполнение любого из них создает новый объект Point3.
Literals (Символы): Любая символьная форма объектов класса. Примеры: [0, 0, 0] –
символьная форма класса Point3, слово “Hello world” – символьная форма класса String.

Операции со строками
Операция Описание
<value> as string Конвертирует значение <value> в строку
<string>.count Число знаков в строке (Целое число - только чтение)
<string> + <string> Сложение строк

<string> == <string> Сравнение двух строк (чувствительно к регистру)


<string> != <string> Чтобы сделать проверку не зависящую от регистра,
<string> > <string> необходимо конвертировать строки в значения Name
<string> < <string>
<string> >= <string>
<string> <= <string>

<string>[<index_number>] Возвращает знак с указанной позиции (начиная с 1)


<string> as <class> Конвертирует строку в величину указанного класса
Примеры: “Foo” as name – возвращает #foo; “123.4” as float – возвращает 123.4
Можно использовать любые числовые классы – Number, Float, Integer. В случае Number
подходящий класс определится в зависимости от синтаксиса чисел строки.

Метод Описание
copy <string> Создает независимую копию строки и возвращает ее.
Пример: newstr = copy oldstr
execute <string> Выполняет содержимое строки, как выражение
MAXScript и возвращает результат вычисления.
Примеры: execute “2+2” – возвращает 4
execute “select $Box01” – выделяет объект Box01.
findString <string> <search_string> Возвращает номер первого символа найденной
строки или undefined, если строка не найдена.
Пример: findString “Я обожаю MAXScript” “M” –
возвращает 10.
filterSting <string> <token_string> Разбивает строку на части и возвращает массив
строк. Разбиение происходит на основе символов,
заданных в строке < token_string >
Пример: filterString “MAX Script, это-супер” “, -” –
возвращает #(“MAX”, ”Script”, ”это”, ”супер”)

substring <string> <from_integer> <length_integer> – возвращает новую строку,


содержащую часть исходной строки, начиная с номера <from_integer> и длиной
<length_integer>. Если сумма чисел <from_integer> и <length_integer> больше длины
исходной строки или для <length_integer> задано отрицательное число, возвращается вся
оставшаяся часть строки, начиная с номера <from_integer>.
Пример: s=”Дирижабль”; ss=substring s 2 4 -- “ириж”; ss= substring s 6 -1 --“абль”

Чтобы включить в строку кавычки и другие полезные символы, необходимо использовать


символ “\” – обратная косая черта (backslash). Комбинации:
\” -- символ “
\n -- новая строка
\r -- возврат каретки
\t -- табуляция
\* -- символ *
\? -- символ ?
\\ -- символ \
\% -- символ %
\x{d} -- непечатные символы, где {d} - шестнадцатеричный символ (0-9, a-f)

Пример: print “Заключим в кавычки \”фу\” и перейдем на новую строку:\n”


Возвращает: “Заключим в кавычки ”фу” и перейдем на новую строку:

Примеры непечатных символов в строках:
str=”Copyright \xa9 2005, Ist02Works, Inc” --a9 – код символа ©

Следующий пример выводит в окно Listener все непечатные символы и их коды:


char=”0123456789abcdef”
for i=1 to char.count do
for j=1 to char.count do
(
s=execute(“\”\\x”+char[i]+char[j]+”\””)
format “%% %\n” char[i] char[j] s
)

Путь к файлу через строковую переменную задается так:


scene_path=”g:\\3dsmax5\\scenes”
или так:
scene_path=”g:/3dsmax5/scenes” --эта замена работает только для путей к файлам.

Операции с массивами
Операция Описание
<collection> as array Конвертирует коллекцию в массив
<array>.count Число элементов в массиве (Целое, можно изменять)
<array>[integer] Возвращает элемент массива. Номера начинаются с 1.
<array>[integer] = <value> Заносит значение в элемент массива, увеличивая число
элементов по необходимости
<array> + <collection> Создает новый массив из первого и второго аргументов
Примеры: a=#(1,2,3,4); join a #(5,6,7,8)
(cameras as array) + lights

Метод Описание
append <array> <value> Добавляет величину к массиву, при необходимости
увеличивая его размер
copy <array> [#noMap] Создает копию всех элементов массива. Возвращает значение
ОК. Если задан параметр #noMap, создается только копия
переменной массива, которая ссылается на элементы
исходного массива.
deleteItem <array><number> Стирает элемент массива, уменьшая его размер на 1
join <array> <collection> Присоединяет все элементы второго аргумента к первому
sort <array> Сортирует элементы массива по возрастанию. (Все элементы
должны быть одного типа)
findItem <array> <value> Ищет элемент массива, равный заданной величине и
возвращает номер, первого такого элемента или ноль (zero),
если элемент не найден.
insertItem <value> <array> <integer> – Вставляет значение в элемент с указанным
номером, при необходимости увеличивая размер массива
qsort <array> <function> [start: integer] [end: integer] [args] – Сортирует массив, используя
заданную пользователем функцию для сравнения двух элементов. У этой функции
необходимо определить два аргумента на входе, а возвращать она должна целое число
меньше нуля, если первый аргумент меньше второго, больше нуля, если наоборот и 0, если
они равны. Если не задан начальный и конечный номер, массив сортируется целиком.

Пример: следующий скрипт создает 10 случайных трехмерных координат, а потом


сортирует их в зависимости от расстояния до точки [0,0,0]:
positions=for i=1 to 10 collect (random [0,0,0] [100,100,0])
fn compareFN v1 v2 =
(
local d=(length v1)-(length v2)
case of
(
(d<0.): -1
(d>0.): 1
default: 0
)
)
qsort positions compareFN
for p in positions do print p

amin (<array> | {value}) Возвращает минимальное значение из элементов массива или


набора величин. Если в массиве нет элементов или набор
величин не задан, возвращается значение undefined. Примеры:
myMin=amin #(5,1,4,2,8)
myMin1=amin 5 1 4 2 8
amax (<array> | {value}) Возвращает максимальное значение из элементов массива
или набора величин. Если в массиве нет элементов или набор
величин не задан, возвращается значение undefined

Команды 3ds max в MAXScript


MAXScript позволяет запускать команды меню и панели инструментов 3ds max. Перед
командой пишется ключевое слово “max”. Например:
max file open
max unhide all
max quick render

max time ? -- показать все команды, связанные со временем


max sel ? -- показать все команды, в которых есть подстрока ‘sel’
max ? -- показать все команды (их очень много)

Ниже приведен список некоторых часто выполняемых команд и их описание.


Команда Описание
max ? Вывести все команды в Listener
max delete Стереть выделенные объекты или подобъекты
max file new Отобразить диалоговое окно создания нового файла
max file open Отобразить диалоговое окно открытия файла
max file save Сохранить файл
max move Активировать режим Select and Move
max properties Отобразить диалоговое окно свойств объекта
max quick render Запустить быструю визуализацию
max redo Вернуть отмененное действие
max reset file Создать пустую сцену
max rotate Активировать режим Select and Rotate
max select Активировать режим Select
max select all Выделить все объекты
max time end Установить ползунок шкалы времени в конечную точку
max time start Установить ползунок шкалы времени в начальную точку
max undo Отменить действие
max unfreeze all “Разморозить” все объекты
max unhide all Показать все скрытые объекты
max vpt front Сделать активный видовой экран проекцией Спереди
max zoomext sel Активировать режим Zoom Extents Selected

Часть 3
Создание свитков
Один из видов интерфейсов, создаваемых в MAXScript – свитки (rollouts) на панели
Utility. В свитках содержатся элементы интерфейса: кнопки, текстовые поля, выпадающие
списки и т.д. Любой свиток можно и нужно редактировать при помощи средства Visual
MAXScript, которое вызывается кнопкой F2 из окна Editor, когда курсор находится внутри
тела свитка. Основной свиток, с которого необходимо начинать, создается при помощи
конструкции utility:
utility <var_name><description_string>[rolledUp:<boolean>][silentErrors:<boolean>]
(<utility_body>), где:
<var_name> – имя глобальной переменной, в которой хранится данный свиток.
<description_string> – название утилиты в списке Utilities свитка MAXScript.
rolledUp: – необязательный параметр, определяющий, будет ли изначально развернут
свиток утилиты. Значения: true – свернут, false – развернут (значение по умолчанию).
silentErrors: – необязательный параметр, определяющий, будут ли появляться сообщения
об ошибках в окне Listener и в диалоговых окнах во время работы утилиты, в этом случае
выполнение утилиты прекращается (все это происходит, если для параметра установлено
значение false – оно же по умолчанию). Если установлено значение true, то никаких
сообщений об ошибках не выводится, и работа утилиты не прерывается.
<utility_body> – тело утилиты, в котором описывается весь интерфейс, функции и
события, происходящие при взаимодействии пользователя с элементами интерфейса
(нажатие на кнопку, прокрутка спиннера и т.д.)
Следующий пример создает утилиту, которая перемещает выделенные объекты по прямой
от центра выделения до позиции каждого объекта, учитывая оси координат.
utility spread "Spread objects" -- определяем имя и название утилиты
( local last_amt = 0 -- определяем и задаем значение локальной переменной
checkbox x "Распространить по x" -- создаем три флажка
checkbox y "Распространить по y"
checkbox z "Распространить по z"
spinner spread "Величина:" range:[-1000,1000,0] -- создаем спиннер
on spread changed amt do -- когда изменяется значение в поле спиннера...
(
delta = amt - last_amt -- разница между текущим и предыдущим значением
for obj in selection do -- значения для каждого выделенного объекта
(
-- вычисление новых координат на основе текущего положения и центра выделения
-- функция normalize создает вектор того же направления, но единичной длины
p = obj.pos + normalize (obj.pos - selection.center) * delta
if x.checked then obj.pos.x = p.x -- если включен флажок х, изменять положение по X
if y.checked then obj.pos.y = p.y
if z.checked then obj.pos.z = p.z )
last_amt = amt -- сохранить значение спиннера, как предыдущую величину
) -- конец события изменения величины спиннера
) -- конец определения утилиты

В утилиту можно вставить дополнительные свитки следующим образом:


utility <utility_name> <description_string>
(
...
rollout <rollout_name> <description_string>
[rolledUp:<boolean>] [silentErrors:<boolean>]
(<rollout_body>)
...
on <utility_name> open do -- при открытии утилиты…
(
...
-- добавляем свиток, поскольку просто так он не появится
addRollout <rollout_name> [rolledUp: <boolean>]
...
)
on <utility_name> close do -- при закрытии утилиты…
(
...
removeRollout <rollout_name> -- удаляем свиток
...
)
)

Параметры конструкции rollout те же самые, что и у utility.


У свитков и утилит есть свойства, вот некоторые из них:
Свойство Описание
<rollout>.name название свитка (строковая величина только для чтения)
<rollout>.title заголовок свитка
<rollout>.open свернут (false) или развернут (true) свиток
<rollout>.controls массив со всеми элементами интерфейса (только для чтения)

События
Вызов события (event) происходит, когда пользователь взаимодействует с элементом
интерфейса, для которого данное событие определено:
on <item_name> <event_name> [<argument>] do <expr>, где:
<item_name> – название элемента интерфейса, который вызывает событие.
<event_name> – тип события (зависит от типа элемента)
<argument> – дополнительная переменная, в которую заносится значение элемента.

Тип события Описание


pressed нажали на кнопку
changed изменили значение спиннера, в(ы)ключили флажок (радиокнопку)
picked указали на объект в сцене
entered изменили текст в текстовом поле
selected выбрали пункт из списка
resized изменили размер плавающего окна
moved переместили плавающее окно
open открыли свиток или утилиту
close закрыли свиток или утилиту

Элементы интерфейса
Кнопка
button <name> [<caption>] [toolTip:<string>]
где <caption> – надпись на кнопке, toolTip: – всплывающая подсказка.
События: on <button> pressed do <expr>

Флажок
checkbox <name> [<caption>] [checked:<boolean>]
где checked – начальное состояние флажка (по умолчанию false – сброшен)
Свойства: <checkbox>.checked или <checkbox>.state (оба выдают одно и то же)
События: on <checkbox> changed <arg> do <expr>, в аргументе <arg> содержится новое
состояние флажка – true или false.

Выпадающий список
dropdownlist<name> [<caption>] [items:<array_of_strings>]
[selection:<number>] [height:<number>]
где items: – массив строковых величин (пунктов списка)
selection: – номер выделенного пункта, начиная с 1 (значение по умолчанию)
height: – общая высота списка по числу пунктов (10 по умолчанию). Если нужно,
чтобы список состоял ровно из N пунктов, высота должна быть N+2.
Свойства:
<dropdownlist>.items – массив пунктов списка.
<dropdownlist>.selection – номер выбранного пункта (0, если массив пустой).
<dropdownlist>.selected – текст выбранного пункта, через это свойство его можно
поменять без обновления всего массива. Если массив пустой, равняется undefined.
Пример: dropdownlist scale_dd “Scale” items:#(“1/2”,”1/4”,”1/8”,”1/16”)
on scale_dd selected i do format “Вы выбрали %\n!” scale_dd.items[i]

Текстовое поле
edittext <name> [<caption>] [text:<string>]
[fieldWidth:<integer>] [height:<integer>] [bold:<boolean>]
где text: – текст в поле. Чтобы задать несколько строк, нужно писать между ними сразу
два символа: возврат каретки (\r) и новая строка (\n).
Пример: “First Line \r\nSecond Line”
fieldWidth: – ширина текстового поля в пикселях (по умолчанию равна расстоянию
от конца заголовка до правой границы свитка).
height: – высота поля в пикселях. Если это число больше высоты одной строки,
поле превращается в текстовую область, куда можно вводить сразу несколько строк
текста.
bold: – если параметр равен true, текст в поле будет полужирным,
если false – обычным (значение по умолчанию).
Свойства: <edittext>.text, <edittext>.caption, <edittext>.bold
События:
on <edittext> changed <arg> do <expr>, вызывается каждый раз, когда пользователь меняет
текст в поле. В аргумент <arg> записывается новый текст.
on <edittext> entered <arg> do <expr>, вызывается, когда пользователь вводит текст, а
потом нажимает кнопку ENTER или TAB, чтобы убрать курсор из поля. В аргумент <arg>
записывается новый текст.

Область группы – область с заголовком, ограниченная линией


groupBox <name> [<caption>] [pos:<point2>] [width:<integer>] [height:<integer>]
где pos:, width:, height: – свойства, чтобы регулировать размер области группы.

Метка – просто надпись.


label <name> [<string>] Пример: label lab1 “Пожалуйста, выберите объект:”
Ни свойств, ни событий у метки нет.

Кнопка выбора объекта


pickbutton <name> [<caption>] [message:<string>]
[filter:<function>] [toolTip:<string>]
где message: – дополнительный текст, отображаемый, когда кнопка нажата, в
статусной строке 3ds max. По умолчанию текста нет.
filter: – дополнительная функция, которая проверяет, соответствует ли выбранный
объект некоторым, определенным пользователем критериям. У функции должен
быть только один аргумент – выбираемый объект, а возвращать она может либо true
(подходящий объект), либо false (неподходящий). По умолчанию функция
отсутствует.
toolTip: – текст всплывающей подсказки. Если не задан – текста нет.
Пример:
fn foo_filt obj = findString obj.name “foo”==1
pickbutton chooseit “Выберите объект” filter:foo_filt
on chooseit picked obj do
(master=obj
chooseit.text=obj.name)
Свойства: <pickbutton>.object – последний выбранный объект. Равно undefined, если
объекты не выбирались. Свойство только для чтения.
События: on <pickbutton> picked <arg> do <expr>, где <arg> содержит выбранный объект.

Радиокнопки
radiobuttons <name> [<caption>] labels:<array_of_strings>
[default:<number>] [columns:<number>]
где labels: – массив строк, определяющий число радиокнопок и текст напротив каждой
из них.
default: – номер радиокнопки, активной в данный момент. По умолчанию 1, если 0 –
ни одна кнопка не выбрана.
columns: – число столбиков, которые будут заполняться радиокнопками. Ширина
всех столбиков одинаковая и равна самой длинной метке напротив радиокнопки.
По умолчанию, MAXScript располагает радиокнопки друг за другом в одной
строке, а если не убираются – в один столбик.
Свойства: <radiobuttons>.state – номер выбранной радиокнопки, согласно массиву, если ни
одна не выбрана – 0.
События: on <radiobuttons> changed <arg> do <expr>, вызывается, когда пользователь
выбирает радикнопку из данного набора, в <arg> заносится номер новой радикнопки.

Спиннер
spinner <name> [<caption>] [range:[min, max, val]]
[type:<name>] [scale:<float>]
[fieldWidth:<integer>] [indeterminate:<boolean>]
[controller:(<controller>)] [setKeyBrackets:<boolean>]
где range: – величина Point3, содержащая минимальное, максимальное и начальное
значение спиннера. По умолчанию [0,100,0]
type: – тип спиннера: #float, #integer или #worldunits. По умолчанию #float. Если
установлен в #worldunits, значение спиннера показывается в текущих единицах
отображения (display units) 3ds max, но измеряется все равно в системных
единицах.
scale: – масштаб спиннера определяет величину минимального приращения. По
умолчанию: 0.1 – для вещественных (float), 1 – для целых (integer) чисел.
fieldWidth: – ширина текстового поля спиннера в пикселях. По умолчанию, спиннер
располагается так, что его левый край находится по центру свитка, а правый – по
правой границе, исходя из этого определяется ширина.
indeterminate: – когда true, поле спиннера становится пустым, спиннер не работает,
но его старое значение все равно доступно. Установка нового значения сбрасывает
параметр в false.
controller: – связывает спиннер с определенным контроллером. Изменение значения
спиннера влияет на контроллер и наоборот.
setKeyBrackets: – включает (true) или выключает (false) красные границы спиннера,
показывающие наличие ключевых кадров в анимации.
Свойства: <spinner>.range – диапазон и начальное значение (аналогично
соответствующему параметру), <spinner>.value – значение спиннера,
<spinner>.setKeyBrackets, <spinner>.indeterminate.
События:
on <spinner> changed <arg> do <expr>, вызывается, когда пользователь прокручивает
спиннер или вводит в его поле новое значение, а потом нажимает ENTER или TAB, чтобы
выйти из поля спиннера. Аргумент <arg> содержит новое значение спиннера.
on <spinner> entered do <expr>, вызывается, когда пользователь вводит в поле новое
значение, а потом нажимает ENTER или TAB, чтобы выйти из поля спиннера. Событие on
<spinner> changed также вызывается в этот момент, если оно определено и свойство
<spinner>.value обновляется.

Часть 4
Сплайны
Сплайн – это объект, представляющий собой одну или несколько линий в
пространстве или на плоскости. Все сплайны, а также NURBS-кривые относятся к
категории Shapes (формы). Команда showclass “*:shape” выводит в окно Listener все
существующие классы сплайнов. Некоторые свойства этих классов повторяются, как
общие свойства всех сплайнов. Описывать все классы нет необходимости, рассмотрим
класс Arc (дуга):
Свойство Описание
<Arc>.radius Радиус дуги (тип значения – float, по умолчанию 25.0)
<Arc>.from Положение начальной точки, как угол, отмеряемый от
положительного направления локальной оси X. (float, 45.0)
<Arc>.to Положение конечной точки, как угол, отмеряемый от
положительного направления локальной оси X. (float, 135.0)
<Arc>.pie Достраивает дугу до замкнутого сплайна, соединяя концы с центром
прямыми сегментами. (Boolean, false)
<Arc>.reverse Инвертирует сплайн дуги, т.е. меняет порядок вершин на
противоположный. (Boolean, false)
<Arc>.steps Число разбиений сегмента между вершинами. (Integer, 6)
<Arc>.optimize Удаляет разбиение прямых сегментов сплайна. (Boolean, true)
<Arc>.adaptive Автоматически определяет и устанавливает разбиение для сплайнов.
У прямых сегментов всегда 0. (Boolean, false)
<Arc>.angle Угол поворота сечения визуализируемого сплайна. (float, 0.0)
<Arc>.thickness Диаметр (толщина) визуализируемого сплайна. (float, 1.0)
<Arc>.sides Число сторон в сетке визуализируемого сплайна. Например, значение
4 дает квадратное сечение. (Integer, 12)
<Arc>.renderable Включает показ сплайна при визуализации. (Boolean, false)
<Arc>.mapCoords Включает проекционные координаты. (Boolean, false)
Пример: duga = arc radius: 100 from: 0 to: 180 pos: [0, 0, 0]

Класс SplineShape
Методы этого класса работают с любыми сплайнами и позволяют всячески их
редактировать. Чтобы конвертировать сплайны стандартных классов в класс SplineShape,
необходимо использовать функцию convertToSplineShape <node>, где <node> – любой
объект-сплайн. Если в качестве <node> задать объект, который нельзя конвертировать,
функция возвратит значение undefined.

Методы, работающие с целым объектом Shape


updateShape <shape> – обновляет объект, этот метод необходимо запускать после
редактирования формы методами SplineShape и до работы с объектом любыми другими
операциями.
resetShape <shape> – стирает все сплайны объекта.
numSplines <shape> – возвращает количество всех сплайнов в объекте как значение типа
Integer. Эквивалент <shape>.numSplines.
setFirstSpline <shape> <spline_index_integer> – меняет порядок сплайнов таким образом,
что указанный сплайн становится первым.
addAndWeld <to_shape> <from_shape> <weldthreshold_float> – добавляет сплайны одного
объекта к другому. Конечные точки сплайнов будут объединяться, если расстояние между
ними не превысит значения <weldthreshold_float>.
bindKnot <shape> <isEnd_boolean> <splineId_integer>
<segIndex_integer> <splineSegId_integer> – связывает первую или
последнюю вершину сплайна с серединой указанного сегмента. Если значение параметра
<isEnd_boolean> - true, связывается последняя вершина, иначе первая. Параметр
<splineId_integer> задает номер сплайна, которому принадлежат связываемые вершины,
<segIndex_integer> определяет номер сегмента, к середине которого будет привязана
вершина, <splineSegId_integer> – номер сплайна, которому принадлежит этот сегмент.
unBindKnot <shape> <spline_index_integer> <isEnd_boolean> – разрывает связь конечной
или начальной вершины указанного сплайна.
updateBindList <shape> – обновляет список связей. Метод вызывается, когда меняется
топология, например, стираются вершины.
materialID <shape> <spline_index_integer> <segment_index_integer> – возвращает
идентификатор материала для указанного сегмента сплайна заданного объекта.

Методы, работающие со сплайнами объекта Shape


addNewSpline <shape> – добавляет новый пустой сплайн к объекту и возвращает его
номер (будет последним в списке всех сплайнов этого объекта)
getSplineSelection <shape> – возвращает номера выделенных сплайнов объекта как массив
целых чисел.
setSplineSelection <shape> <spline_index_array> [keep:<boolean>] – выделяет сплайны,
определенные массивом <spline_index_array>. Со сплайнов, уже выделенных к данному
моменту, выделение снимается, если только не установлен параметр keep:true.
deleteSpline <shape> <spline_index_integer> – удаляет заданный сплайн из объекта.
Оставшиеся сплайны перенумеровываются.
numSegments <shape> <spline_index_integer> – возвращает количество сегментов
указанного сплайна. Это целое число, равное числу вершин для замкнутых сплайнов и на
единицу меньше числа вершин для открытых.
numKnots <shape> [<spline_index_integer>] – возвращает число вершин в указанном
сплайне (значение типа Integer). Если номер сплайна не указан, возвращается число
вершин во всем объекте.
isClosed <shape> <spline_index_integer> – возвращает true, если указанный сплайн замкнут,
и false, если открыт.
close <shape> <spline_index_integer> – замыкает указанный сплайн. Этот метод всегда
создает новый сегмент от первой до последней вершины, даже если их координаты
совпадают.
open <shape> <spline_index_integer> – открывает указанный сплайн, удаляя сегмент между
первой и последней вершиной.
reverse <shape> <spline_index_integer> – инвертирует порядок вершин в указанном
сплайне.
setFirstKnot <shape> <spline_index_integer> <knot_index_integer> – устанавливает новый
порядок вершин в указанном сплайне так, что заданная вершина становится первой.
getSegLengths <splineShape> <spline_index> [cum:<boolean>]
[byVertex:<boolean>] [numArcSteps:<integer>] – возвращает массив
длин сегментов или расстояний между вершинами сплайна и общую длину сплайна.
Вычисления повышенной точности. Если значение cum:true – результаты складываются,
иначе отсчитываются для каждого сегмента (по умолчанию false). Если значение
byVertex:true – результаты для вершин, иначе для сегментов (по умолчанию false).
Параметр numArcSteps:<integer> по умолчанию равен 100.
subdivideSegment <splineShape> <spline_index>
<seg_index> <divisions> – разделяет сегмент на заданное количество
частей. Вычисления двойной точности.
interpCurve3D <splineShape> <spline_index> <param_float>
[pathParam:<boolean>] – возвращает <point3>-координату указанной
кривой. Если pathParam:false – значение <param_float> является частью длины сплайна,
иначе частью длины сегмента. По умолчанию pathParam:false.
tangentCurve3D <splineShape> <spline_index> <param_float>
[pathParam:<boolean>] – возвращает <point3>-касательную к
указанной кривой. Если pathParam:false – значение <param_float> является частью длины
сплайна, иначе частью длины сегмента. По умолчанию pathParam:false.

Методы, работающие с сегментами сплайнов объекта Shape


getSegmentType <shape> <spline_index_integer> <seg_index_integer> – возвращает тип
указанного сегмента заданного сплайна.
setSegmentType <shape> <spline_index_integer> <seg_index_integer>
(#curve | #line) – устанавливает тип указанного сегмента заданного
сплайна.
refineSegment <shape> <spline_index_integer> <seg_index_integer>
<seg_interp_param_float> – добавляет новую вершину к указанному
сегменту заданного сплайна. Конкретное положение вершины, определяется значением
<seg_interp_param_float>. Это число от 0.0 до 1.0 пропорционально длине сегмента.
Координаты и касательные на входе и выходе из вершины устанавливаются
автоматически, чтобы сохранить исходную кривизну сегмента. Функция refineSegment()
возвращает номер новой добавленной вершины.
getSegSelection <shape> <spline_index_integer> – возвращает номера выделенных
сегментов заданного сплайна как массив целых чисел.
setSegSelection <shape> <spline_index_integer> <seg_index_array>
[keep:<boolean>] – выделяет сегменты, определенные массивом
номеров <seg_index_array>. С сегментов, уже выделенных к данному моменту, выделение
снимается, если только не установлен параметр keep:true.
setMaterialID <splineShape> <spline_index> <seg_index> <matID> – устанавливает
идентификатор материала для заданного сегмента сплайна.
getMaterialID <splineShape> <spline_index> <seg_index> – возвращает идентификатор
материала для заданного сегмента сплайна.

Методы, работающие с вершинами сплайнов объекта Shape


addKnot <shape> <spline_index_integer>
(#smooth | #corner | #bezier | #bezierCorner)
(#curve | #line) <position_point3> [invec_point3 outvec_point3]
[where_integer] – добавляет к указанному сплайну новую вершину и
возвращает ее номер. Третий аргумент определяет тип вершины, четвертый – тип сегмента
на выходе из вершины, пятый – координаты новой точки в текущей системе координат.
Если тип вершины bezier или bezierCorner, необходимо задать векторы входящей и
исходящей касательной (6-ой и 7-ой аргументы). Дополнительный последний аргумент
устанавливает номер новой вершины в массиве вершин сплайна, если его не задать, она
будет последней.
deleteKnot <shape> <spline_index_integer> <knot_index_integer> – удаляет указанную
вершину с заданного сплайна. Оставшиеся вершины перенумеровываются.
getKnotType <shape> <spline_index_integer> <knot_index_integer> – возвращает тип
указанной вершины с заданного сплайна. Значения (тип name) бывают следующими:
#smooth, #corner, #bezier, #bezierCorner.
setKnotType <shape> <spline_index_integer> <knot_index_integer>
(#smooth | #corner | #bezier | #bezierCorner) – задает тип указанной
вершины заданного сплайна.
getKnotPoint <shape> <spline_index_integer> <knot_index_integer> – возвращает
координаты (тип point3) в текущей системе координат указанной вершины заданного
сплайна.
setKnotPoint <shape> <spline_index_integer> <knot_index_integer> <point3> –
устанавливает координаты (point3) указанной вершины заданного сплайна в текущей
системе координат.
getInVec <shape> <spline_index_integer> <knot_index_integer> – возвращает вектор (point3)
входящей касательной для указанной вершины в текущей системе координат.
setInVec <shape> <spline_index_integer> <knot_index_integer> <point3> – задает вектор
(point3) входящей касательной для указанной вершины в текущей системе координат.
getOutVec <shape> <spline_index_integer> <knot_index_integer> – возвращает вектор
(point3) выходящей касательной для указанной вершины в текущей системе координат.
setOutVec <shape> <spline_index_integer> <knot_index_integer> <point3> – задает вектор
(point3) выходящей касательной для указанной вершины в текущей системе координат.
getKnotSelection <shape> <spline_index_integer> – возвращает номера выделенных вершин
заданного сплайна как массив целых чисел.
setKnotSelection <shape> <spline_index_integer> <knot_index_array>
[keep: <boolean>] – выделяет вершины, определенные в массиве
<knot_index_array>, представляющем собой набор целых чисел – номеров вершин. С
вершин, уже выделенных к данному моменту, выделение снимается, если только не
установлен параметр keep:true.

Часть 5
Простейшие диалоговые окна
messageBox <message_string> [title: <window_title_string>] [beep: <boolean>]
Отображает диалоговое окно с текстом сообщения и кнопкой ОК. Параметр title
определяет заголовок окна, параметр beep – звуковой сигнал (true по умолчанию).
queryBox <message_string> [title: <window_title_string>] [beep: <boolean>]
Отображает диалоговое окно с текстом сообщения и кнопками Yes и No. Эта функция
возвращает true, если пользователь нажимает Yes и false – если No.
yesNoCancelBox <message_string> [title: <window_title_string>] [beep: <boolean>]
Отображает диалоговое окно с текстом сообщения и кнопками Yes и No и Cancel. Функция
возвращает #yes, #no или #cancel, в зависимости от нажатой кнопки.
Примеры: messageBox “Этого делать не нужно”
if queryBox “Хотите продолжить?” beep:false then ...

Некоторые из методов работы с объектами


Метод Описание
copy <node> создает объект-копию.
reference <node> создает объект-ссылку.
instance <node> создает объект-образец.
delete <node> удаляет объект.
attachObjects <node1> <node2> делает <node2> потомком <node1>. Потомок
[move: <boolean>] перемещается в позицию предка, если не задан
параметр move:false.
isValidNode <var> возвращает true, если <var> является объектом (или его
переменной), который не был удален. В противном
случае возвращает false.
Пример: proverka=isValidNode $Box01
isShapeObject <node> возвращает true, если <node> является одним из
объектов-сплайнов или false, если не является.
hide <node> скрывает объект. (unhide <node> – показывает)
clearSelection() снимает любое текущее выделение.
select <node> снимает текущее выделение и выделяет заданный
объект(ы). Пример: select $box*
selectMore <node> добавляет заданные объекты к набору уже выделенных.
deselect <node> снимает выделение с заданных объектов.
deselectNode <node> снимает выделение только с одного объекта.
distance <node1> <node2> вычисляет расстояние между опорными точками двух
заданных объектов.

Характерные точки объектов


<node>.pivot=<point3> опорная точка объекта (место, где находятся
локальные оси координат)
<node>.center=<point3> центр габаритного контейнера объекта.
Пример: b=box(); b.pivot=[100,200,300] --перемещаем опорную точку

Системы координат
Любые изменения геометрии объектов происходят в текущей системе координат.
Соответственно, в разных системах координат, они будут работать неодинаково.
Текущая система координат определяется при помощи ключевого слова coordsys:
[in] coordsys world мировая система координат (МСК).
[in] coordsys local локальная система координат объекта.
[in] coordsys parent система координат объекта-предка данного объекта.
[in] coordsys grid система координат активной в данный момент сетки.
[in] coordsys screen система координат активного окна проекции.
[in] coordsys <node> система координат определенного объекта.
[in] coordsys <matrix3> система координат, определяемая заданной матрицей.
Пример: in coordsys local selection.pos=random [-20,20,20] [20,20,20]

Координатные сетки
Можно создать свою собственную координатную сетку, сделать активной и
работать в ее системе координат. Сетка создается при помощи конструктора grid и
обладает следующими свойствами:
<grid>.length длина сетки (float, 50.0 – по умолчанию)
<grid>.width ширина сетки (float, 50.0 – по умолчанию)
<grid>.grid размер ячейки (float, 10.0 – по умолчанию)
Пример:
setka=grid position: [0,0,0] -- создаем координатную сетку
rotate setka 90 [1,0,0] -- поворачиваем на 90 градусов относительно оси Х
activeGrid=$Grid01 -- активируем сетку по имени
in coordsys grid -- в системе координат сетки рисуем сплайн
(
item = splineShape ()
item.name = "Фигура"
item.steps = 0
item.optimize = true
addNewSpline item
addKnot item 1 #corner #line [0,0,0]
addKnot item 1 #corner #line [200,0,0]
addKnot item 1 #corner #line [200, 100,0]
addKnot item 1 #corner #line [0, 100, 0]
close item 1
item.pivot = [50, 0, 0]
updateShape item
in coordsys world setKnotPoint item 1 3 [200, 0, 300] -- в МСК перемещаем точку
addModifier item (Extrude amount: 10) -- применяем модификатор
)
activeGrid=homeGrid -- активируем стандартную сетку
delete setka -- стираем старую сетку
clearlistener() -- очищаем Listener

Определение угла между двумя векторами


a=[10, 0, 0]; b=[-10, 10, 0] -- первый и второй вектор
--ПЕРВЫЙ СПОСОБ - ПЛОХОЙ
c=cross a b -- вектор-нормаль к плоскости из первых двух векторов
ugol=asin(length(c)/(length(a)*length(b))) -- формула определения угла
messagebox (ugol as string)
--ВТОРОЙ СПОСОБ - ХОРОШИЙ
scalar_mult=a.x*b.x+a.y*b.y+a.z*b.z -- скалярное произведение векторов
ugol=acos(scalar_mult/(length(a)*length(b))) -- формула определения угла
messagebox (ugol as string)

Представление ориентации при помощи кватернионов (quaternions)


Кватернион – набор четырех значений, первое (скалярная часть) определяет
поворот вокруг вектора, остальные три (векторная часть) определяют вектор оси поворота.
Нормированный (normalized) кватернион, т.е. тот, у которого сумма квадратов всех
компонентов равна единице, обладает следующими свойствами: скалярная часть равна
косинусу половины угла поворота, векторная часть – ось вращения, длина вектора оси
равна синусу половины угла поворота. Нормированный кватернион может определять
повороты только от –PI до +PI.
Именно кватернионы, а не углы Эйлера используются в 3ds max (и вообще в
компьютерной графике) для хранения поворотов объектов, поскольку это наиболее
надежный и удобный способ. Вектор можно выразить через кватернион, у которого
скалярная часть равна нулю.
Повороты в MAXScript происходят по правилу правой руки, т.е. против часовой
стрелки вокруг положительного направления оси при вращении на положительный угол.
Конструкторы:
1. quat <x_float> <y_float> <z_float> <w_float>, где x, y, z – вектор, w – поворот.
2. quat <degrees_float> <axis_point3>, где <degrees_float> – угол в градусах, <axis_point3>
– ось вращения (величина Point3).
3. <angleaxis> as quat – перевести величину <angleaxis> (ось и угол) в кватернион.
Выражение типа <angleaxis> представляет собой набор из двух значений: угла
поворота в градусах и вектора оси вращения (величина Point3).
4. <eulerangle> as quat – перевести величину <eulerangle> (угол Эйлера) в кватернион.
Выражение типа <eulerangle> представляет собой набор углов поворотов вокруг осей
координат: x, y, z.
5. <matrix3> as quat – перевести в кватернион ту часть матрицы 4х3, которая отвечает за
поворот.
Можно и кватернионы переводить в углы Эйлера, выражения типа ось и угол или
матрицы: <quat> as eulerAngles, <quat> as angleaxis, <quat> as matrix3.
Свойства: <quat>.w; <quat>.x; <quat>.y; <quat>.z – у всех тип Float.
Вычисляемые свойства: <quat>.angle – тип Float, <quat>.axis – тип Point3.
Некоторые из методов:
normalize <quat> – возвращает нормированный кватернион.
inverse <quat> – возвращает обратный кватернион (1/q).
Вектор q*v*(1/q) равен повернутому вектору v, выраженному через кватернион.

Создание вспомогательных объектов-пустышек Dummy


Вспомогательные объекты не визуализируются. Их можно и нужно использовать
для хранения значений положения и поворота.
Свойство: <dummy>.boxsize – размер пустышки (Point3). По умолчанию [10,10,10]
Пример: d=dummy pos: [10, 20, 30] rotation: (quat 10 [10, 10, 10]) --кватернион
b=box(); b.rotation=d.rotation; b.position=10*d.position

Изменение общих параметров анимации


animationRange -- получить текущий диапазон анимации (interval 0f 100f)
animationRange = interval 10 50 -- задать диапазон анимации от 10-го кадра до 50
frameRate -- количество кадров в секунду (целое число)
animateonRange.start -- начальный кадр анимации (величина только для чтения)
animationRange.end -- конечный кадр анимации (величина только для чтения)

Анимация вершин сплайнов


Чтобы получить доступ к анимации вершин объекта класса SplineShape,
необходимо воспользоваться методом animateVertex, который задает диапазон
анимируемых вершин. Впоследствии к этим вершинам можно применять различные
контроллеры анимации.
animateVertex <shape> <vertex_spec>, где <vertex_spec> – индекс, массив индексов или
ключевые слова #all или #selected (соответствуют всем или только выбранным вершинам).
У каждой вершины сплайна есть три индекса: для входящей касательной, самой вершины
и выходящей касательной. Индексы всегда следуют друг за другом строго по порядку, в
случае нескольких сплайнов сначала для всех вершин первого сплайна в объекте класса
SplineShape, потом для второго и т.д.
После определения диапазона анимируемых индексов, становятся доступными
свойства вершин и касательных. Вот, например, свойства первых двух вершин первого
сплайна объекта $Circle01, которые можно анимировать:
Свойство: Тип: Значение:
$Circle01.Spline_1___InVec_1 Point3 [-75,33,0]
$Circle01.Spline_1___Vertex_1 Point3 [-75,33,0]
$Circle01.Spline_1___OutVec_1 Point3 [-50,0,0]
$Circle01.Spline_1___InVec_2 Point3 [-20,-33,0]
$Circle01.Spline_1___Vertex_2 Point3 [7,-66,0]
$Circle01.Spline_1___OutVec_2 Point3 [32,-95,0]

Пример анимации вершин и касательных объекта из двух сплайнов – окружностей:


animateVertex $Circles #(4, 10, 14, 20)
animate on
( at time 0 ($Circles.spline_1___InVec_2.z = 50)
at time 100 ($Circles.spline_1___InVec_2.z = -50)
at time 0 ($Circles.spline_1___InVec_4.z = -50)
at time 100 ($Circles.spline_1___InVec_4.z = 50)
at time 0 ($Circles.spline_2___Vertex_1.z = 50)
at time 100 ($Circles.spline_2___Vertex_1.z = -50)
at time 0 ($Circles.spline_2___Vertex_3.z = -50)
at time 100 ($Circles.spline_2___Vertex_3.z = 50) )

Примеры контроллеров анимации path constraint и link constraint


--Анимация движения объекта по пути при помощи контроллера path constraint:
thePath=$line01 -- объект line01 будет являться путем
theObj=$Box00 -- объект Box01 будет перемещаться по пути
theObj.pos.controller=path follow:true constantVel:true loop:true -- контроллер
PosCont=theObj.pos.controller -- записываем контроллер в переменную
PosCont.path=thePath -- заносим путь в контроллер
PosCont.axis=0 -- выравниваем локальную ось Z объекта по пути
animate on -- анимируем
( at time 0 PosCont.percent=0 -- в кадре 0 - 0% пути
at time 100 PosCont.percent=100 ) -- в кадре 100 - 100% пути
--Связь объекта с другими на время при помощи контроллера link constraint
b=box pos: [-100, 0, 0]; d1=dummy pos:[0, 0, 0]; d2=dummy pos:[0, 0, 0]
animate on
( at time 0 d1.rotation=quat 0 [0, 0, 1]
at time 25 d1.rotation=quat 90 [0, 0, 1]
at time 25 d2.rotation=quat 0 [1, 0, 0]
at time 50 d2.rotation=quat 180 [1, 0, 0] )
b.transform.controller=Link_Constraint(); links=b.transform.controller
sliderTime=0f; links.AddTarget d1 0 --связываем Box01 с Dummy01 в кадре 0
sliderTime=25f; links.AddTarget d2 25 --связываем Box01 с Dummy02 в кадре 25
sliderTime=50f; links.addWorld frameNo: 50 --убираем связь с Dummy02
animate on
( at time 51 move b [0, 0, 0]
at time 100 move b [100, 0, 0] )

Методы print и format


print <value> [to:<stream>] [#noMap]
Печатает величину в окно Listener (по умолчанию), в окно Editor, или в файл, если таковой
определен заранее. Если аргумент <value> является коллекцией, а параметр #noMap не
задан, то каждый элемент коллекции напечатается в отдельной строке, а если задан – вся
колЧасть будет на одной строке.
Примеры:
debug=newScript() --определяем выходной поток
print “something” to:debug --печатаем в окно Editor
file_1=createFile “my_script.ms” --создаем новый файл
print selection to:file_1 --печатаем коллекцию в файл

format <format_string> { <value> } [to:<stream>]


Работает аналогично методу print, позволяя добавлять значения параметров <value> в те
места строки <format_string>, где есть знак %. Каждый знак % заменяется по порядку
соответствующим значением.
Пример: format “название: %, координаты: %\n” obj.name obj.pos
На выходе: название: box01, координаты: [0, 150.0, 0.5]
Метод format не переходит новую строку автоматически, поэтому для ее создания нужно
писать символ ‘\n’.

Оценить