/
Автор: Берштейн И.В.
Теги: компьютерные технологии программирование информационные технологии языки программирования
ISBN: 5-8459-1044-7
Год: 2006
Текст
Основы
Прилагается
3ds Мах 8 ~~~
MaxScript
Учебная программа по мультимедийным
и развлекательным приложениям
компании Autodesk
3ds Max' 8
MaxScript
Essentials
Focal Press
30 Corporate Drive, Suite 400, Burlington, MA 01803, USA
Linacre House, Jordan Hill, Oxford OX2 8DP, UK
Основы
3dsMax8
MaxScript
Учебная программа по мультимедийным
и развлекательным приложениям
компании Autodesk
W
Москва • Санкт-Петербург • Киев
2006
ББК 32.973.26-018.2.75
All
УДК 681.3.07
Издательский дом “Вильямс”
Зав. редакцией С.Н. Тригуб
Перевод с английского и редакция И. В. Берштейна
По общим вопросам обращайтесь в Издательский дом “Вильямс” по адресу:
info@williamspublishing.com, http://www.williamspublishing.com
115419, Москва, а/я 783; 03150, Киев, а/я 152
Autodesk, Inc.
Al 1 Основы 3ds Max 8 MAXScript: учебный курс от Autodesk. : Пер. с англ. — М. :
Издательский дом “Вильямс”, 2006. — 256 с. : ил. — Парад, тит. англ.
ISBN 5-8459-1044-7 (рус.)
Эта книга представляет собой практическое пособие по изучению прин-
ципов и методов создания сценариев MAXScript как весьма эффективного
средства повышения производительности труда в Autodesk 3ds Max 8. Мно-
гочисленные примеры и простые упражнения, включенные в учебный мате-
риал этой книги, позволяют освоить основы программирования на языке
Autodesk 3ds Max 8 MAXScript и научиться создавать и отлаживать сценарии
для построения пользовательского интерфейса, автоматизации рутинных
операций преобразования объектов, текстурирования, освещения, анимации
и визуализации сцен. Дополнительный учебный материал к книге прилагает-
ся на CD-ROM. Книга адресована тем пользователям Autodesk 3ds Max 8,
которые стремятся повысить эффективность своего труда с помощью сцена-
риев, автоматизирующих многие часто повторяемые операции.
ББК 32.973.26-018.2.75
Все названия программных продуктов являются зарегистрированными торговыми марками
соответствующих фирм.
Никакая часть настоящего издания ни в каких целях не может быть воспроизведена в ка-
кой бы то ни было форме и какими бы то ни было средствами, будь то электронные или ме-
ханические, включая фотокопирование и запись на магнитный носитель, если на это нет
письменного разрешения издательства Focal Press.
Authorized translation from the English language edition published by Focal Press, Copyright © 2006,
Elsevier Inc.
All rights reserved. No part of this book may be reproduced or transmitted in any form or by any
means, electronic or mechanical, including photocopying, recording or by any information storage
retrieval system, without permission from the Publisher.
Russian language edition published by Williams Publishing House according to the Agreement with
R&I Enterprises International, Copyright © 2006
ISBN 5-8459-1044-7 (pyc.)
ISBN 0-240-80858-4 (англ.)
© Издательский дом “Вильямс”, 2006
© 2006, Elsevier Inc., 2006
Оглавление
Введение 12
Глава 1. Основы MAXScript 15
Глава 2. Построение пользовательских интерфейсов 78
Глава 3. Интерфейс 3ds Мах 103
Глава 4. Объекты и классы 124
Глава 5. Преобразования и анимация 145
Глава 6. Работа с объектами в MAXScript 178
Приложение 195
Предметный указатель 246
Содержание
Введение 12
Новое в этом издании 13
О копировании файлов упражнений 14
От издательства 14
Глава 1. Основы MAXScript 15
Задание 16
Введение 16
Синтаксис и организация сценария Комментарии Многострочные операторы Переменные и данные Нетипизированные переменные 16 16 17 18 19
Приемник команд MAXScript Listener 20
Применение MAXScript Listener 22
Свойства объектов 26
Дополнительные свойства объектов 27
Макрорегистратор 29
Функции 34
Параметры и обозначение функций 35
Создание собственных функций 37
Передача аргументов по значению 41
Передача аргументов по ссылке 42
Исключение из правила передачи аргументов по значению
(дополнительный материал) 43
Возврат значений из функций 44
Локальные и глобальные переменные 45
Определение переменных 45
Глобальные переменные 46
Локальные переменные 47
Содержание
Условные операторы 48
Операторы if-then 48
Логические операторы НЕ, И, ИЛИ 48
Операторы if-then-else 49
Перечень операторов 51
Циклические конструкции 51
Цикл for 51
Циклы с многими операторами 52
Циклы while 54
Совокупности 56
Массивы 56
Функции для массивов 58
Вывод массивов на печать 59
Многомерные массивы (дополнительный материал) 60
Метасимволы 62
Структуры 64
Синтаксис структуры 65
Функция-конструктор структуры 65
Инициализация структуры 66
Функции-члены структуры 67
Вызов функций во время построения структуры (дополнительный
материал) 68
Строки 69
Сцепление 69
Поиск содержимого строки 69
Замена 70
Взаимное преобразование чисел и строк 70
Создание и выполнение сценариев 71
Работа с выражениями 73
Изменение цвета каркаса объектов в цикле 74
Заключение 77
Глава 2. Построение пользовательских интерфейсов 78
Задание 79
Введение 79
Построение пользовательских интерфейсов 79
Типы пользовательских интерфейсов 79
Виды сценариев 79
Макросценарии 80
7
Содержание
Файлы сценариев 81
Свитки 81
Ввод элементов пользовательского интерфейса 84
Обработчики событий 88
Группы в свитке 89
Создание рабочего сценария 89
Создание пользовательского интерфейса 90
Ввод обработчиков событий 93
Точная настройка пользовательского интерфейса 95
Автоматическое удаление диалоговых окон 96
Ввод событий для кнопки выбора 97
Использование локальных переменных 98
Включение и отключение элементов пользовательского интерфейса 100
Заключение 102
Глава 3. Интерфейс 3ds Мах юз
Задание 104
Введение 104
Получение копии, экземпляра и ссылки 104
Копия 105
Экземпляр 105
Ссылка 106
Клонирование узлов с помощью функции maxOps.CloneNodes 107
Копирование массивов 109
Команды Мах 109
Панели команд 110
Основная панель инструментов 111
Выбор объектов на сцене 111
Выбор точек ИЗ
Функция mouseTrack (дополнительный материал) 114
Интерфейс раскраски (дополнительный материал) 119
Заключение 123
Глава 4. Объекты и классы 124
Задание 125
Введение 125
8
Содержание
Объектно-ориентированное программирование 125
Иерархия классов 127
Наследование классов 129
Определение типов классов 130
Экземпляры 132
Свойства 132
Класс MAXWrapper 135
Методы 137
Конструкторы 137
Методы типа get и set 138
Отображаемые методы 139
Работа со справочным руководством по MAXScript 140
Грамматика MAXScript 140
Необязательные параметры 142
Возвращаемые значения 142
Присваивание ссылок 143
Заключение 144
Глава 5. Преобразования и анимация 145
Задание 146
Введение 146
Свойства преобразований изменением положения
и масштабированием 146
Преобразование изменением положения 146
Преобразование масштабированием 147
Преобразование вращением 148
Метод Euler Angles 149
Рамочная система координат 153
Локальные вращения 155
Кватернионы 155
Метод AngleAxis 158
Контексты 158
Контекст coordsys 162
Анимация 163
Контроллеры 163
Ключевые кадры анимации 164
Значения ключевых кадров 165
Типы контроллеров 167
9
Содержание
Ось вращения Удаление ключевых кадров Касательные к ключевым кадрам Заключение 174 176 176 177
Глава 6. Работа с объектами в MAXScript 178
Задание 179
Введение 179
Применение модификаторов 179
Источники света и камеры Источники света Камеры 181 181 185
Материалы 186
Управление средством визуализации 187
Обратные вызовы 189
Внесение элемента случайности 192
Заключение 194
Приложение Отладка, перехват и обработка ошибок Виды ошибок Периоды компиляции и выполнения Методы отладки сценариев Обратное отслеживание по стеку Перехват и обработка ошибок Отладчик MAXScript Debugger Доступ к отладчику Команда прерывания Окно вывода из отладчика Командная строка отладчика Окно диспетчера наблюдения Исправление ошибок в отладчике Установка активного кадра стека Интерфейс отладчика 195 196 196 198 198 201 203 204 204 205 206 208 209 213 214 216
10
Содержание
Файловый ввод-вывод 217
Указатель файла и смещение 219
Запись в файлы 221
Доступ к файлам на уровне системы 222
Диалоговые окна открытия и сохранения файлов 223
Открытие диалогового окна сохранения файлов 225
Ввод-вывод в двоичные файлы 226
Запись в двоичный файл 226
Чтение из двоичного файла 228
Дополнительные функции двоичного ввода-вывода 229
Редактор Visual MAXScript 229
Сохранение и активизация панелей, созданных в редакторе
Visual MAXScript 232
Другое применение редактора VMS 235
Встраивание элементов управления ActiveX в свитки средствами
MAXScript 236
Система публикации функций и интерфейсы 240
Контроллеры управления по выражению и по сценарию 243
Предметный указатель 246
11
Введение
Приглашаем вас изучить основы программирования на языке MAXScript для
приложения Autodesk® 3ds Max® 8. В этой книге вам предоставляется возмож-
ность освоить ряд методов автоматизации рутинных операций средствами языка
создания сценариев MAXScript, чтобы научиться с его помощью настраивать сре-
ду 3ds Мах для более продуктивной работы в данном приложении.
Средства MAXScript позволяют взаимодействовать со сценой 3ds Мах и авто-
матически управлять действиями или операциями из сценария посредством опе-
раторов. Для этого операции записываются в форме текста (сценария), a 3ds Мах
интерпретирует сценарий и выполняет последовательность операций. Такие тек-
стовые сценарии можно сохранить и повторно использовать в любой момент.
MAXScript охватывает практически все свойства 3ds Мах.
Научиться писать сценарии на определенном уровне может каждый, однако
сложность сценариев в конечном итоге зависит от трех следующих факторов.
• Практика. Постоянная работа с MAXScript и изучение сценариев, написан-
ных другими, способствуют развитию способностей создания сценариев.
• Математическая подготовка. Для написания сценариев очень важно знать
основы математики, и особенно — тригонометрии.
• Опыт программирования. Для создания сценариев полезно иметь некото-
рый опыт программирования, хотя и необязательно.
Самым лучшим источником информации, необходимой для работы с MAXScript,
служит руководство по MAXScript, которое составлено в виде оперативной справ-
ки, входящей в состав 3ds Мах. Основное назначение данного руководства — дать
исчерпывающую справку по всем инструментам MAXScript и показать, как ими
пользоваться. Поэтому для того, чтобы научиться писать сценарии, очень важно
уметь пользоваться руководством по MAXScript. В одном из упражнений, вклю-
ченных в настоящее издание, показано, каким образом следует искать нужную
информацию в оперативной справке, чтобы продолжить изучение MAXScript по
завершении данного практического курса.
Проработав материал этой книги, вы сможете самостоятельно анализировать
сценарии, написанные другими. В таких сценариях вы можете обнаружить неиз-
вестные вам методы создания сценариев или те же самые задачи, решаемые по-
другому. Как правило, при написании сценариев допускается несколько вариан-
тов решения одной и той же задачи, и по ходу создания все более крупных и слож-
ных сценариев у вас постепенно выработается собственный стиль их написания.
Введение
Новое в этом издании
В настоящее издание включен новый материал, который можно разделить на
три категории.
• Принципы программирования. Это общие, а не присущие только MAXScript
принципы, положенные в основу программирования на компьютере. В этом
издании данная тема переработана и рассмотрена более подробно. В част-
ности, материал предыдущего издания дополнен сведениями о структурах,
функциях, передаче переменных и логических переходах.
• Дополнительный материал. В этом издании рассмотрен ряд основных по-
нятий MAXScript. Эти понятия не являются новыми для версии 3ds Мах 8,
однако благодаря им раскрываются важные принципы создания сценариев.
В дополнительный материал включены такие темы, как клонирование объ-
ектов, выполнение команд 3ds Мах, доступ к панелям инструментов, выбор
узлов сцены и отдельных точек, применение интерфейса команд отслежи-
вания перемещений мыши и раскраски, а также материал о публикации
функций и об интерфейсах.
• Дополнения MAXScript. Это изменения, внесенные в MAXScript после вы-
пуска версии 3ds Мах 6. К этим изменениям относятся усовершенствования
языка программирования, а также дополнительные инструменты и коман-
ды, доступные для MAXScript. Подобные нововведения отмечаются особо
на протяжении всей книги. Помимо этого, в настоящее издание включен
учебный материал по применению отладчика MAXScript Debugger и цик-
лическому выбору свойств узлов.
Главы этой книги организованы следующим образом.
• В главе 1 даются основы написания сценариев средствами MAXScript. В этой
главе вы научитесь создавать переменные и присваивать им значения, озна-
комитесь со сценариями и макросценариями, а также с основными принци-
пами программирования на компьютере. В завершение главы вам предсто-
ит создать рабочий сценарий. При этом подробно объясняются все этапы
данного процесса.
• В главе 2 будут созданы элементы специализированного пользовательского
интерфейса, в том числе свитки, диалоговые окна и утилиты.
• В главе 3 вы научитесь получать доступ к наиболее важным областям поль-
зовательского интерфейса 3ds Мах, пользуясь средствами MAXScript.
• В главе 4 вы ознакомитесь с базовой структурой MAXScript и классифика-
цией различных объектов в MAXScript, а также научитесь пользоваться ру-
ководством по MAXScript для поиска нужных вам команд.
• В главе 5 вам предстоит поработать с преобразованиями, в частности с вра-
щением, в сценарии MAXScript.
• В главе 6 вы ознакомитесь с рядом дополнительных инструментальных средств
MAXScript, включая строки и обратные вызовы функций, а также модификато-
ры, источники света, камеры, материалы и средства визуализации.
13
Введение
• В приложении вы обнаружите дополнительный материал для дальнейшего
изучения MAXScript, включая методы отладки сценариев, применение от-
ладчика и введение в публикацию функций и интерфейсы. В приложение
также включен материал по файловому вводу-выводу и применению элемен-
тов управления ActiveX в свитках, формируемых по сценарию MAXScript.
О копировании файлов упражнений
На прилагаемом к этой книге CD-ROM находятся файлы, необходимые для
выполнения упражнений. Вы можете открыть и использовать эти файлы непо-
средственно из CD-ROM либо скопировать их на свой локальный или сетевой
диск. Для удобства файлы упражнений рекомендуется скопировать из CD-ROM
на жесткий диск.
Файлы упражнений для отдельных глав распределены на CD-ROM по каталогам
с наименованиями соответствующих глав (\chapterl, \chapter2 и \ chapters).
Скопируйте эти файлы в подходящий каталог на жестком диске, например
с:\courseware\maxscript\chapterl.
Благодарности издательства
Издательский дом "Вильямс" благодарит Ерофеева Сергея за большой вклад в подго-
товку издания книги.
От издательства
Вы, читатель этой книги, и есть главный ее критик. Мы ценим ваше мнение
и хотим знать, что было сделано нами правильно, что можно было сделать лучше
и что еще вы хотели бы увидеть изданным нами. Нам интересны любые ваши за-
мечания в наш адрес.
Мы ждем ваших комментариев и надеемся на них. Вы можете прислать нам
бумажное или электронное письмо либо просто посетить наш Web-сервер и оста-
вить свои замечания там. Одним словом, любым удобным для вас способом дайте
нам знать, нравится ли вам эта книга, а также выскажите свое мнение о том, как
сделать наши книги более интересными для вас.
Отправляя письмо или сообщение, не забудьте указать название книги и ее ав-
торов, а также свой обратный адрес. Мы внимательно ознакомимся с вашим мне-
нием и обязательно учтем его при отборе и подготовке к изданию новых книг.
Наши электронные адреса:
E-mail: inf o@williamspublishing. com
WWW: http: //www. williamspublishing . com
Наши почтовые адреса:
в России: 115419, Москва, а/я 783
в Украине: 03150, Киев, а/я 152
14
Основы MAXScript
Глава 1
Изучение основ MAXScript сродни
овладению основами программирования
на любом другом языке.
В этой главе вам предстоит сначала
научиться получать доступ к средствам
MAXScript, а затем ознакомиться
с такими общими для языков
программирования понятиями,
как синтаксис, логика и ход выполнения
программы. И в заключение
этой главы вы освоите процесс написания
элементарного сценария.
Основы MAXScript
Задание
После изучения этой главы вы должны уметь следующее.
• Ясно представлять основы MAXScript
• Уметь пользоваться MAXScript Listener и Macro Recorder
• Создавать переменные, работать с разными типами данных и пользоваться
функциями
• Создавать и видоизменять объекты
• Организовывать массивы и циклы
• Работать с приемником команд и редактором сценариев MAXScript
Введение
В этой главе представлено введение в MAXScript и ряд наиболее часто приме-
няемых инструментальных средств данного языка создания сценариев. Освоив эту
главу, вы будете уметь писать простые сценарии и пользоваться приемником ко-
манд MAXScript Listener, а также редактором сценариев MAXScript Editor.
Для выполнения упражнений в этой книге вам следует пользоваться 3ds Мах
в стандартной конфигурации с установленными базовыми единицами измерения
(Generic Units).
Синтаксис и организация сценария
Сценарий представляет собой последовательность операторов, записанных в фор-
ме текста. 3ds Мах интерпретирует содержимое сценария, а затем выполняет соот-
ветствующие действия. Если операторы написаны неверно, сценарий выполняется
неправильно или же вообще не выполняется. Поэтому последовательность и орга-
низация команд сценария, называемая синтаксисом, должна быть достаточно точ-
ной. Отклонения от правильного синтаксиса приводят к ошибкам в сценарии. Как
правило, в MAXScript уведомляется о том, что сценарий содержит недоступное для
правильной интерпретации содержимое.
Очень важно сохранять ясность и удобочитаемость своих сценариев. Для созда-
ния удобочитаемых сценариев пользуйтесь отступами с табуляцией и пробелами,
чтобы выделить отдельные элементы или функции. В 3ds Мах символы пробелов
и табуляции игнорируются во время обработки сценариев. В примерах сценариев,
приведенных в этой главе, демонстрируется один из способов организации
содержимого сценариев с отступами. Отступами можно пользоваться и по-другому,
но при этом всегда нужно быть последовательным.
Комментарии
Пользуйтесь комментариями, чтобы сделать свой сценарий более понятным
для других. Комментарии представляют собой текстовые блоки в сценарии, напи-
санные простым и понятным языком. Они поясняют или документируют назначение
16
Глава 1
сценария и порядок его выполнения. Старайтесь снабжать комментариями все свои
сценарии. Это особенно важно для крупных и сложных сценариев.
Комментарии не относятся к выполняемым операторам сценария. Они выде-
ляются в тексте сценария двойным дефисом ( - - который ставится в начале ком-
ментария. В таком случае любой текст, начинающийся с двойного дефиса, игно-
рируется. Двойной дефис можно, если требуется, использовать в нескольких
строках, например:
b = box()
b.length = 20.0
-- Это комментарий.
-- А это еще один комментарий, имеющий продолжение в
-- этой строке. Следующая строка уже относится к самому сценарию,
b.width = 30.0
В следующем примере показано, каким образом комментарий помещается в той
же строке, что и оператор сценария:
b = box () -- Создать параллелепипед, комментарий игнорируется.
Комментарии могут занимать несколько строк, если они начинаются двумя
символами /* и оканчиваются еще двумя символами */ (или признаком конца
файла). Все, что находится между этими символами, считается комментарием.
Комментарии, определенные подобным образом, называются блочными коммен-
тариями, например:
s = sphere()
/* Здесь содержится большой комментарий,
не требующий ограничителей в каждой строке,
поскольку в данном случае используются
блочные комментарии.*/
s.radius = 10.0
Такие комментарии можно поместить и в одной строке, внутри текста самого
сценария:
s = sphere /‘большой радиус*/ radius:100.0
Многострочные операторы
Операторы сценария выполняются, или интерпретируются, построчно. Но
иногда оператор MAXScript может оказаться достаточно длинным. Поэтому для
размещения длинных операторов в нескольких строках служит символ обратной
косой черты (\), указывающий на продолжение оператора. В следующем примере
показан длинный оператор, записанный в нескольких строках.
Исходная команда сценария:
torus radiusl:10 pos:[0, 0, 20] wirecolor: [225, 230, 100]
Та же команда, разбитая на несколько строк:
torus radiusl:10 \
pos: [0, 0, 20] \
wirecolor: [225, 230, 100]
17
Основы MAXScript
В каждой новой строке текст сценария указан с отступом. В 3ds Мах пробелы
игнорируются, а благодаря отступам сценарий легче читать как его автору, так
и другим создателям и пользователям сценариев MAXScript.
Переменные и данные
В любом языке программирования отдельные элементы данных представлены
переменными. Переменные — это заполнители, или контейнеры, представляющие
(и хранящие) данные в программе. У каждой переменной имеется свое имя, которое
ей присваивается. Например, переменные могут иметь следующие имена: а, Ь, х
и countNum.
Данные, хранящиеся в переменной, называются значением, а порядок установ-
ки переменной, равной конкретному значению, называется присвоением этого зна-
чения переменной, например:
х = 5
В данном примере значение 5 присваивается переменной х, а данные относятся
к числовому типу. Значение может иметь любой тип данных, распознаваемый
в MAXScript. Чаще всего используются следующие типы данных: числовые, стро-
ковые и логические.
Числовые типы данных
Имеются две разновидности числовых типов данных: целые числа и числа
с плавающей точкой.
• Целое число — это положительное или отрицательное десятичное число без
дробной части. Например: 0,1,2, -10, 345.
• Число с плавающей точкой — это положительное или отрицательное деся-
тичное число с дробной частью. Например: 0.0, 33.3, 0.75, -5.8.
Если определить переменную и присвоить ей значение числового типа данных,
над такой переменной можно будет выполнять математические операции, например:
- - Присвоить значение 5.0 переменной х.
х = 5.0
- - Присвоить значение 6.0 переменной у.
у = 6.0
- - Умножить х на у и присвоить результат переменной z.
Z = X * у
- - Теперь z = 30.
Конкретный тип данных определяется при присвоении переменной значения,
которое может иметь дробную часть, например:
- - Присвоить целое значение переменной х.
х = 5
- - Присвоить переменной х значение с плавающей точкой.
х = 5.0
18
Глава 1
Если математические операции выполняются над переменными, содержащими
только целые числа, результат всегда будет целым числом. Если же хотя бы одна
переменная содержит число с плавающей точкой, в результате получится число
с плавающей точкой.
Строковые типы данных
Данные строкового типа содержат текст. Например, в переменной msg можно
поместить текст "File not found." (Файл не найден), а затем отобразить его
для пользователя:
msg = "File not found."
messagebox msg
Текстовые значения должны всегда указываться в кавычках, чтобы отличить
их от данных других типов, например:
numl = 5.0
messagel = "5.0"
В данном случае математические операции можно выполнять над переменной
numl, но не над переменной messagel. В MAXScript предоставляются самые раз-
ные функции для манипулирования строками. Речь о них пойдет далее в этой главе.
Логические типы данных
В MAXScript часто применяется еще один тип данных — логический (или бу-
лев). Логические данные могут принимать следующие значения: true (истина),
on (включено), false (ложь) или off (выключено),
ready = true
ready = off
Значение on равнозначно значению true, тогда как значение off равнозначно
значению false.
Логические данные используются, главным образом, для проверки условий в сце-
нарии с помощью условных операторов. Более подробно они рассматриваются далее
в этой главе.
Нетипизированные переменные
Присваивая значения переменным, не нужно объявлять конкретный тип дан-
ных, которые допускается хранить в переменной. Этим MAXScript отличается от
таких языков программирования, как С, C++ и Java, в которых каждая переменная
объявляется со своим типом данных. Таким образом, MAXScript является языком
создания сценариев без контроля типов. Во время присваивания в 3ds Мах авто-
матически допускается манипулирование переменной в соответствии с правила-
ми, связанными с конкретным типом данных. Например, следующая запись в сце-
нарии является вполне допустимой:
msg = "File not found."
messagebox msg
msg = 5.6
z = msg + 7.0
19
Основы MAXScript
Если переменной msg присвоена строка, в 3ds Мах допускается манипулиро-
вание ею, как строкой. Если же затем присвоить переменной msg число, ею можно
далее манипулировать, как числом.
Этих кратких сведений уже достаточно для того, чтобы приступить к выполне-
нию операторов сценария.
Приемник команд MAXScript Listener
Команды сценария могут быть выполнены несколькими способами. Самый
простой из них — воспользоваться приемником команд MAXScript Listener, кото-
рый обеспечивает выполнение команд MAXScript в диалоговом режиме. Прием-
ник команд удобен для последовательного выполнения отдельных строк кода или
проверки правильности этих строк.
Доступ к приемнику команд осуществляется следующими способами.
• Из главного меню по команде MAXScript^MAXScript Listener
• Из панели Utilities по команде Utilities^MAXScript^Open Listener
• Из области Mini Listener
• С помощью клавиатурного эквивалента команды <F11 >
Примечание. Начиная с версии 3ds Мах 7, приемник команд можно открывать
и закрывать с помощью функциональной клавиши <F11>.
Для доступа к приемнику команд выполните следующее.
1. Установите 3ds Мах в исходное состояние.
2. Выберите из главного меню команду MAXScript^MAXScript Listener.
Появится окно MAXScript Listener.
20
Глава 1
3. Закройте приемник команд.
Область Mini Listener представляет собой бело-розовый участок в левом
нижнем углу интерфейса (в районе строки состояния). Если строка Mini
Listener не видна, перетащите вправо вертикальную разделительную ли-
нию, расположенную в конце строки состояния, чтобы отобразить область
Mini Listener.
4. Щелкните правой кнопкой мыши в области Mini Listener. Выберите из
всплывающего контекстного меню команду Open Listener Window (Открыть
окно приемника команд). Появится окно приемника команд. В этом окне
можно увидеть одно или два подокна. Если оба подокна не видны, восполь-
зуйтесь мышью, чтобы перетащить вниз горизонтальную разделительную
линию, расположенную в верхней части окна приемника команд. Фон
верхнего подокна приобретет розовую окраску.
Если при выполнении операции в 3ds Мах сформируется макрокоманда
MAXScript, она отобразится в верхнем подокне. Отдельные строки кода
можно вводить как в верхнем, так и в нижнем подокнах. А результаты вы-
полнения кода всегда отображаются в нижнем подокне.
В приведенном далее упражнении будет использоваться только нижнее
подокно.
5. Переместите горизонтальную разделительную линию вверх, чтобы скрыть
верхнее подокно.
21
Основы MAXScript
Применение MAXScript Listener
Приемник команд можно использовать двумя способами.
• Вводить команды по очереди в его окне. После каждой команды следует не-
пременно нажать комбинацию клавиш <Shift+Enter>. При нажатии этой
комбинации клавиш выполняются введенная команда и соответствующая
ей операция.
• Оставить окно приемника команд открытым при выполнении готовых сце-
нариев, чтобы наблюдать за формированием возвращаемых значений, со-
общений об ошибках и макрокодом по ходу выполнения сценария.
Приемник команд выполняет роль текстового редактора, что дает возможность
копировать и вставлять фрагменты кода, отменять операции и т.д. Вводимый
текст сценария выделяется черным цветом, а текст, автоматически формируемый
в приемнике команд, выделяется голубым цветом для результатов успешного вы-
полнения сценария и красным цветом для сообщений об ошибках.
Фрагменты кода могут быть также выполнены в приемнике команд следую-
щими способами.
• Для выполнения группы строк кода выделите эту группу строк и нажмите
комбинацию клавиш <Shift+Enter>.
• Клавиша <Enter> на вспомогательной цифровой клавиатуре служит экви-
валентом комбинации клавиш <Shift+Enter> и может также быть исполь-
зована для выполнения команд. Возможно, этот способ покажется вам бо-
лее удобным и быстрым.
Если требуется очистить окно приемника команд от всего текста, выберите из
меню этого окна команду Edit^Clear АП (Правка^Очистить все). При этом очи-
щается выделенное в настоящий момент подокно (верхнее или нижнее).
Для ввода простого оператора сценария выполните следующее.
1. Откройте приемник команд MAXScript Listener.
2. Введите в приемнике команд следующее выражение, а затем нажмите ком-
бинацию клавиш <Shift+Enter>:
Ь = box()
22
Глава 1
3. В видовых окнах создается параллелепипед. Кроме того, синим цветом в при-
емнике команд выделяется текст Box: ВохО 1 @ [0.000,0.000, 0.000].
Это означает, что данная команда выполнена успешно.
Примечание. Для выполнения упражнений, приведенных в данной книге, следует
непременно нажимать комбинацию клавиш <Shift+Enter> после каждой команды,
вводимой в приемнике команд, даже если для этого не дается специальных указаний.
Функции
Выражение box () называется функцией. Функция — это операция, обозначае-
мая именем функции. В приведенном выше примере имя функции — box. В име-
ни функции используются круглые скобки, чтобы уведомить 3ds Мах, что в дан-
ном случае вызывается функция формирования параллелепипеда. Функция иначе
еще называется вызовом функции.
В результате ввода выражения b = box () вызывается функция box. В итоге
вся информация о созданном параллелепипеде присваивается переменной Ь. Вы
уже знаете о числовых, строковых и логических типах данных, однако переменная
b к ним не относится. При создании объекта выбирается тип данных, характерных
для конкретного объекта.
Примечание. Имена функций не зависят от регистра. Иными словами, имя функции
Box () равнозначно имени box ().
Ссылки
При создании объекта MAXScript формирует ссылку на объект. Ссылка пред-
ставляет собой идентификатор, дескриптор или маркер, предоставляющий доступ
к объекту и всем его свойствам. Ссылка — это не просто имя объекта. Аналогично
числовым, строковым и логическим типам данных для переменных существуют ти-
пы данных и для объектов. Так, функция box () создает сначала параллелепипед
в сцене, а затем возвращает ссылку на этот параллелепипед. Если теперь потребу-
ется обратиться к параллелепипеду, достаточно будет воспользоваться ссылкой Ь.
23
Основы MAXScript
Имя класса и имя объекта
Сообщение $Вох:BoxOl @ [0.000000, 0.000000, 0.00 0 00 0], появляю-
щееся в приемнике команд в ответ на выполнение функции, буквально
подтверждает, что параллелепипед создан успешно. Первая половина этого
сообщения ($Вох: BoxOl) состоит из двух частей в форме ClassName:
Obj ectName (Имя_класса:Имя_объекта). Имя объекта — это имя, присваи-
ваемое самому объекту. Оно отображается в интерфейсе 3ds Мах, например, при
нажатии клавиши <Н> для открытия диалогового окна Select Objects
(Выделение объектов). Более подробно классы рассматриваются в главе 4, а по-
ка что класс можно представить в качестве типа объекта (в данном случае — па-
раллелепипеда).
Путевые имена
При создании объекта в 3ds Мах ему присваивается также путевое имя. Путевые
имена служат для обозначения объектов на сцене. Все объекты на сцене организованы
в иерархическом порядке, который можно наблюдать при открытии окна Track View
(Вид трека). Путевые имена в MAXScript всегда начинаются со знака денежной еди-
ницы ($). Так, путевое имя параллелепипеда — $Вох01. С помощью путевых имен
описываются отдельные элементы внутри связанной иерархии, например $body/
right_arm/right_hand (тело/правая_рука/левая_рука). Дополнительные
сведения о путевых именах приведены в разделе “Pathname Literals” (Литералы
путевых имен) справочного руководства по MAXScript.
Примечание. Отдельные темы можно найти в справочном руководстве по
MAXScript (MAXScript Reference Help), воспользовавшись вкладкой Index
(Предметный указатель). Для этого следует ввести в поле критерия поиска
название искомой темы, например Pathname Literals. В итоге появится
предметный указатель с названием темы Pathname и тремя подтемами, одна из
которых относится к литералам. Выделите искомую тему в предметном указателе,
чтобы отобразить ее в основном окне справочного руководства по MAXScript.
Для того чтобы продолжить работу с операторами сценария, выполните сле-
дующее.
1. Выберите команду Edit^Clear АН из меню в окне приемника команд.
2. Введите следующее выражение в окне приемника команд и нажмите ком-
бинацию клавиш <Shift+Enter>:
sphere()
В итоге будет создана сфера. С помощью функций, подобных box (), в 3ds Мах
можно создать любой примитивный объект. В действительности подобным
образом в 3ds Мах можно создать практически любой объект, будь то при-
митив, источник света, камера, система частиц и т.д.
А теперь посмотрим, что произойдет, если ввести нечто недопустимое.
3. Введите следующее выражение в окне приемника команд и нажмите ком-
бинацию клавиш <Shift+Enter>:
а = triangle()
24
Глава 1
В окне приемника команд появится выделенное красным цветом сообщение
об ошибке.
Это означает, что MAXScript неизвестна функция triangle. Ведь в 3ds Мах
треугольный примитив не поддерживается, и поэтому выполнение введен-
ной выше команды приводит к появлению сообщения об ошибке.
Оперативное определение путевых имен
(дополнительный материал)
Сценарии можно писать для манипулирования всеми находящимися на сцене
объектами. Но если в сцене присутствуют многие тысячи объектов, для заверше-
ния некоторых сценариев потребуется существенно больше времени, что приведет
к снижению производительности. Для устранения этого недостатка в версии 3ds Мах 7
было внедрено новое свойство.
Этим свойством является узел под названием кэш. Он используется в MAXScript
для определения путевых имен (подобных $Ьох01) по узлам сцены. Подобная оп-
тимизация вступает в действие, главным образом, вместе с контроллерами управ-
ления по сценарию, в которых используются путевые имена. Так, в сцене с 5001 узлом
и контроллером управления по сценарию, в котором дважды происходит обраще-
ние к 5001-му узлу по имени, время для 10 тысяч вычислений, выполняемых дан-
ным контроллером, сокращается со 147 секунд до 1,6 секунды.
На вкладке MAXScript диалогового окна Preference Settings (Глобальные па-
раметры настройки) для этой цели введен новый флажок Use Fast Node Name
Lookup (Использовать ускоренный поиск имен узлов).
• Если этот флажок установлен, имена узлов сцены помещаются в кэш при вы-
полнении сценария MAXScript, в результате чего значительно ускоряется оп-
ределение явно заданных путевых имен (например, $Ьох01) по именам узлов.
• Если же этот флажок сброшен, имена узлов перечисляются в поисках име-
ни узла, совпадающего с искомым путевым именем.
Свойства объектов
Необходимо не только создавать объекты, но и просматривать и изменять их
свойства. Любой объект, создаваемый в 3ds Мах, имеет ряд свойств, или атрибу-
тов, определяющих этот объект.
25
Основы MAXScript
Для обращения к свойствам объектов служит переменная ссылочного типа.
Ранее в этой главе была создана такая переменная Ь. Для доступа к конкретному
свойству параллелепипеда b перед именем этого свойства ставится точка ( .), как
в следующих примерах:
b.length
b.width
b.height
Свойства объектов можно распознать по названиям соответствующих пара-
метров, появляющихся на панели Create или Modify при создании объекта непо-
средственно в видовом окне.
С помощью функции box () ранее был создан параллелепипед, и поэтому все
его свойства исходно имеют устанавливаемые по умолчанию значения. При этом
не было указано, в какой точке мирового пространства должен располагаться па-
раллелепипед, какими должны быть его размеры и сколько у него должно быть
сегментов. Таким образом, данная функция позволяет создать параллелепипед
с устанавливаемыми по умолчанию значениями всех его свойств.
В приемнике команд отображаются координаты (0,000000, 0,000000,
0,0 00 00 0) стандартного положения параллелепипеда, но не его стандартные
длина, ширина и высота. Если перейти к панели Modify и посмотреть на парамет-
ры параллелепипеда, то можно заметить, что его длина, ширина и высота состав-
ляют 25,0, 25,0 и 25,0 соответственно.
Для обнаружения имеющихся свойств объекта конкретного типа служит
функция showProperties:
showProperties <увел>
Функцию showProperties следует применять к переменной, содержащей сам
объект, а не его тип. Для этого необходимо использовать следующий фрагмент кода:
b = box()
showProperties b
А в ответ на следующую команду появится сообщение об ошибке:
showProperties box
Примечание. Еще один способ доступа к функции showProperties состоит
в использовании псевдонима show.
Для видоизменения свойств объекта достаточно установить новые значения
этих свойств. Например, в следующей строке кода устанавливается длина парал-
лелепипеда — 4 0 единиц:
box.length =40
Всякий раз, когда требуется просмотреть значение свойства объекта, в прием-
нике команд достаточно ввести имя объекта и его искомое свойство, чтобы полу-
чить в ответ значение этого свойства.
Для того чтобы видоизменить свойства объекта, выполните следующее.
1. Введите в окне приемника команд следующую строку кода:
s = sphere()
26
Глава 1
2. Введите в окне приемника команд следующую строку кода:
show s
В данном случае появляется радиус в качестве свойства объекта, имеющего
сферический тип данных.
3. Для просмотра текущего значения радиуса сферы введите следующую
строку кода:
s.radius
4. Для изменения радиуса сферы введите следующую строку кода:
s.radius = 50
В итоге радиус сферы изменится в видовых окнах.
Дополнительные свойства объектов
Некоторые свойства являются общими для всех находящихся на сцене объек-
тов, в том числе примитивов, вспомогательных объектов и пространственных
исказителей. Такие свойства не перечисляются при выполнении функции
showProperties, но и они могут быть использованы. Например, у каждого объ-
екта данного типа имеется свойство . имя.
Свойство положения
Находящиеся на сцене объекты имеют свойства, определяющие их положение.
Свойство положения имеет тип данных Point3. Значение типа Point3 обознача-
ется тремя числами в квадратных скобках, например [20, 45, 10]. Для выполнения
преобразований эти три числа обозначают координаты х, у и z положения объекта
(в данном случае х = 20, у = 45, z = 10). Так, для изменения положения эти число-
вые значения соответствуют положению объекта по осям X, Y и Z.
Для доступа к свойству положения созданной ранее сферы можно воспользо-
ваться следующей строкой кода:
s .pos
В ответ будет возвращено значение типа Point3. А для доступа к отдельным
составляющим этого значения следует указать . х, . у или . z после свойства pos.
Например, для доступа к координате X положения сферы достаточно воспользо-
ваться следующей строкой кода:
s.pos.X
Аналогичные свойства имеются у преобразований вращением и масштабиро-
ванием. О применении этих свойств речь пойдет в главе 5.
Для коррекции положения объекта выполните следующее.
1. Введите в окне приемника команд следующую строку кода:
s.pos = [10, 15, 20]
Сфера переместится в новое положение. Этот факт подтверждает текст, по-
являющийся в окне приемника команд в квадратных скобках.
27
Основы MAXScript
Для изменения положения объекта по оси X возникает искушение ввести
строку кода s . х = 50.0. Однако данное свойство объекта обозначается не
как . х, а как . рое . х.
2. Введите в окне приемника команд следующую строку кода:
s.pos.x = 50
Сфера переместится в новое положение с координатами [50,15,20].
Свойства цвета
С помощью свойства .wirecolor выбирается цвет каркаса объекта. Анало-
гично положению объекта его цвета могут быть представлены типом данных
Points. В частности, три числовых значения обозначают основные цвета RGB
(красный, зеленый и синий соответственно). Каждое такое значение является целым
числом в пределах от 0 до 255 и соответствует значениям RGB в селекторе цвета.
• Белый цвет: [255, 255, 2551
• Черный цвет: [0, 0. 0]
• Чистый красный цвет: [255,0,0]
• Ярко-желтый цвет: [255, 255, 0]
• Умеренно-синий цвет: [0,50,150]
Новый цвет каркаса объекта назначается с помощью свойства .wirecolor,
например:
S.wirecolor = [40,120,200]
Для изменения цветов в любой момент достаточно получить доступ к подсвойст-
вам .г, .ди .Ь, например:
s.wirecolor.г = 156
Кроме того, цвет можно сохранить в переменной с помощью функции color,
а затем назначить его для свойства . wirecolor объекта:
newColor = color 40 120 200
s.wirecolor = newColor
28
Глава 1
Для указания альфа-составляющей цвета служит следующая конструкция, со-
стоящая из четырех цветов вместо трех:
newColor = color 20 120 200 128
Четвертым параметром в данном выражении является альфа-составляющая
цвета (т.е. альфа-канал). Доступ к ней осуществляется с помощью свойства . а:
alphaNum = newColor.а
Макрорегистратор
Макрорегистратор (Macro Recorder) фиксирует отдельные действия и форми-
рует соответствующие команды MAXScript. Эти команды можно сохранить в виде
сценариев для последующего вызова или даже поместить в виде кнопок на панели
инструментов для быстрого доступа к ним.
Результаты действия Macro Recorder можно наблюдать в окне приемника ко-
манд (в верхнем подокне розового цвета). Если в окне приемника команд видно
только одно подокно, воспользуйтесь мышью, чтобы перетащить вниз горизон-
тальную разделительную линию, расположенную в верхней части этого окна,
и тем самым показать оба подокна. В верхнем подокне отображаются команды по
мере их регистрации.
В Macro Recorder регистрируется большая часть действий, выполняемых
в 3ds Мах, включая щелчки на кнопках панелей инструментов, вывод информации
в строку состояния, обращение к панелям Create и Modify.
К одним из наиболее примечательных свойств Macro Recorder относится воз-
можность помещать на панели инструментов указатель на сценарий. В следующем
упражнении вам предстоит сформировать простой сценарий с помощью Macro
Recorder и поместить ссылку на него в виде макрокнопки на панели инструментов.
Для того чтобы воспользоваться Macro Recorder, выполните следующее.
1. Установите 3ds Мах в исходное состояние.
2. Откройте меню MAXScript и убедитесь в том, что Macro Recorder активизиро-
ван (о чем свидетельствует “галочка” рядом с пунктом меню Macro Recorder).
В противном случае выберите пункт меню Macro Recorder, чтобы активи-
зировать макрорегистратор.
29
Основы MAXScript
3. Откройте окно приемника команд и убедитесь в том, что видно подокно ро-
зового цвета, служащее для вывода результатов макрорегистрации. В про-
тивном случае перетащите вниз горизонтальную разделительную линию,
расположенную в верхней части окна приемника команд, чтобы показать
подокно макрорегистрации.
Примечание. Для макрорегистрации совсем не обязательно держать
открытым окно приемника команд. В данном упражнении это делается лишь
для большей наглядности.
4. Перейдите к панели Create и щелкните на кнопке Sphere.
В подокне макрорегистрации появится текст, обозначающий команду
MAXScript, по которой создается сфера с ее атрибутами. На самом деле
данный объект не появляется на сцене — он лишь формируется внутренним
образом в 3ds Мах.
Как видите, в данном сценарии указан нулевой радиус сферы и прочие уста-
навливаемые по умолчанию значения свойств и параметров данного объекта.
5. Щелкните в любом видовом окне и перетащите курсор, чтобы сформиро-
вать сферический объект.
30
Глава 1
Перетаскивая курсор, следите за тем, как увеличивается значение радиуса
в подокне макрорегистрации.
6. Выберите команду MacroRecoderdEnable из меню в окне приемника ко-
манд или команду MAXScript< MacroRecoder из главного меню, чтобы вы-
ключить Macro Recorder.
7. Выделите весь текст в подокне макрорегистрации внутри окна приемника
команд.
Примечание. Если режим Auto Backup (Автосохранение) включен, то можно
заметить, как формируются команды автосохранения. Если эти команды
не нужны, выключите режим Auto Backup, перейдя к одноименной области
диалогового окна Preference Settings по команде Customized Preferences^
Files (Специальная настройка^Глобальные параметры^Файлы) и сбросив
флажок Enable (Активизировать), или же выделите и удалите их из подокна
макрорегистрации.
8. Поместите курсор над текстом в подокне макрорегистрации и нажмите
левую кнопку мыши. Перетащите курсор вверх к основной панели инст-
рументов.
Как только курсор достигнет основной панели инструментов, под курсором
появится небольшой знак “плюс”, указывающий на место, где можно опус-
тить перетаскиваемый сценарий MacroScript.
На основной панели инструментов появится небольшая пиктограмма, обо-
значающая сценарий, зарегистрированный в Macro Recorder.
{£> MAXScript Listener
clearSelectioni>
ВЕГ®
Sphere radius:-О.0585 smooth:on зедз:32 chop:0 slice:off sliceFronrO .
M mi
| Standard Primit
9. Удалите только что созданную сферу, а затем щелкните на пиктограмме
сценария. Выбранный сценарий выполнится, и в итоге будет создана еще
одна сфера.
31
Основы MAXScript
10. Для правки сценария щелкните правой кнопкой мыши на основной панели
инструментов и выберите команду Edit Macro Script из всплывающего
контекстного меню. Откроется окно редактора MAXScript Editor, в кото-
ром вы можете внести любые изменения в выбранный сценарий (в дан-
ный момент он называется MacroScript). Код в этом окне может быть со-
хранен в файле maxscript (с расширением . ms) или же в файле MacroScript
(с расширением .mcr).
Дополнительные сведения о специальной настройке панели инструментов,
правке внешнего вида ее кнопок и сценариях MacroScript вообще приведены
в разделе “Defining Macro Scripts” (Определение макросценариев) справочного
руководства по MAXScript.
Как упоминалось выше, Macro Recorder можно также включать и выключать
из меню MacroRecorder в окне приемника команд. В этом меню имеются и другие
пункты. В частности, они дают возможность сделать выбор между явными имена-
ми находящихся на сцене объектов или же относительными именами выделенных
на сцене объектов. В первом случае Macro Recorder формирует команды для от-
дельно (т.е. явно) выделенных на сцене объектов, а во втором — для объектов, вы-
деленных на сцене в виде совокупности (т.е. выделенных относительно).
Для того чтобы воспользоваться явными и относительными именами
выделенных на сцене объектов, выполните следующее.
1. Установите 3ds Мах в исходное состояние.
2. Создайте сферу в любом видовом окне.
3. Выберите команду MacroRecorder^tEnable из меню в окне приемника ко-
манд, чтобы активизировать Macro Recorder.
4. Выберите команду MacroRecorder^Explicit Scene Object Names (Макро-
регистратор ^Явные имена находящихся на сцене объектов) из меню в окне
приемника команд.
32
Глава 1
(fc) MAXScript Listener
MacroRecorder
File Edit Sea-ch
Debugger Help
Enable
• E • pilot scene object names
Selection-relative scene object names
Absolute transform assignments
• Relative transforms operations
Explicit sub-object sets
• Selection-relative sub-objec: sets
Show command panel switchings
Show tool selections
Show menu item selections
5. Удалите только что созданную сферу и обратите внимание на код, сформи-
рованный в Macro Recorder. Он должен быть следующим:
select $sphere01
delete $sphere01
6. Установите 3ds Max в исходное состояние и повторите приведенные выше
пункты данного упражнения, выбрав на этот раз команду MacroRecorder^b
Selection-Relative Scene Object Names (МакрорегистратороОтносительные
имена выделенных на сцене объектов) из меню в окне приемника команд.
7. Если теперь зарегистрировать действия, аналогичные описанным выше, то
появится следующий код:
select $sphere01
delete $
Несмотря на то что в данном случае был удален конкретный объект, дан-
ный факт явно не указан в командах, зарегистрированных в Macro Recorder.
Вместо этого явная ссылка на сферический объект была заменена знаком
денежной единицы ($). Этот знак обозначает выделенный в данный момент
объект или несколько объектов.
Кроме того, в меню MacroRecorder можно сделать выбор между абсолютными
и относительными операциями преобразования.
Для того чтобы зарегистрировать абсолютные и относительные операции пре-
образования, выполните следующее.
1. Установите 3ds Мах в исходное состояние.
2. Создайте сферу любыми средствами.
3. Выберите команду MacroRecorden >Absolute Transform Assignments (Макро
регистратор^ Присвоение абсолютных преобразований) из меню в окне
приемника команд. Затем выберите команду MacroRecorderd> Explicit Scene
Object Names из этого же меню.
33
Основы MAXScript
4. Выделите сферу и удалите ее. Сформированный в итоге код будет иметь
вид, аналогичный следующему:
$sphere01.pos = [20.222, 10.011, 4.75]
В этой строке кода сфера устанавливается в положение, определяемое ука-
занными в нем координатами, независимо от местоположения сферы до
выполнения данной строки кода.
5. Выберите команду MacroRecorder^Relative Transform Operations (Макро-
регистратор1^ Относительные операции преобразования) из меню в окне
приемника команд, а затем переместите сферу. В итоге сформируется код,
аналогичный следующему:
move $sphere01 [5.44, 0.0, 0,0]
В этой строке кода сфера перемещается на 5,44 единиц относительно ее
положения, предшествовавшего выполнению данной строки кода.
Функции
Функции играют очень важную роль в MAXScript, как, впрочем, и в любом
языке программирования. Функция представляет собой одну или несколько ин-
струкций, предписываемых компьютеру для выполнения. В язык программирова-
ния MAXScript встроено немало функций, а в дальнейшем вы научитесь создавать
собственные функции.
Параметры и обозначение функций
Выше уже был показан один из способов применения функции с использова-
нием ее имени и круглых скобок, например box (). В функциях можно также пе-
редавать отдельные значения, указываемые после имени функции и используемые
в ней для выполнения конкретного задания. Так, три или четыре значения, указывае-
мых после имени функции выбора цвета, определяют конкретный цвет, например:
myRedColor = color 55 10 255
Подобным образом указываются аргументы функции. Если после имени
функции следуют круглые скобки, данная функция вызывается без передаваемых
аргументов. А если аргументы передаются функции, круглые скобки опускаются.
Для нормального выполнения некоторых функций необходимо всегда указы-
вать один или два аргумента (т.е. список аргументов). Так, для функции выбора
цвета требуется указать три или четыре аргумента. Однако для многих функций
указывать аргументы необязательно.
Аргументы передаются функции одним из следующих трех способов.
• В определенном порядке.
• В любом порядке, но после ключевого слова, обозначающего соответствие
аргумента и конкретного значения.
• В определенном порядке с необязательными ключевыми словами, которые
следуют после указываемых по порядку аргументов. Например, у функции
34
Глава 1
могут быть два обязательных аргумента, которые должны быть указаны пе-
ред тремя необязательными аргументами. Необязательные ключевые слова
могут следовать в любом порядке. Функция такого типа является самой
сложной из всех трех рассмотренных типов функций.
Число аргументов наряду с их конкретными типами и порядком следования
называется обозначением функции.
Например, обозначение функции выбора цвета состоит из имени функции
и трех последующих целых чисел:
color спелое число> сцелое число> сцелое число>
Определенный порядок следования параметров функции
Самым важным типом данных в программе трехмерной графики и анимации
является точка в трехмерном пространстве. В математике эта точка обычно
описывается вектором с тремя составляющими по осям X, Y и Z. В 3ds Мах
этот вектор описывается типом данных Point3. У этого типа данных имеются
три свойства: . х — для составляющей по оси X, . у - для составляющей по оси
Y и . z — для составляющей по оси Z. В машинной графике векторы и точки все-
гда описываются в определенном порядке: х, у, z. То же самое имеет место и для
данных типа Point3 в MAXScript. Так, для создания данных типа Point3 доста-
точно выполнить следующее.
1. Введите в окне приемника команд следующее выражение и нажмите
комбинацию клавиш <Shift+Enter>:
myPoint = point3 15 33 7
В ответ в окне приемника команд появится следующее:
[15,33,7]
Совет. Переменную типа Point3 можно создать и более простым способом:
myPoint = [15,33,7]
Произвольный порядок следования параметров функции
Функция создания параллелепипеда имеет ряд дополнительных параметров,
которые могут следовать в произвольном порядке, но требуют указания ключевых
слов. Покажем на конкретном примере, каким образом указываются такие пара-
метры функции.
1. Установите 3ds Мах в исходное состояние.
2. Введите в окне приемника команд следующее выражение и нажмите
комбинацию клавиш <Shift+Enter>:
Ы = box length:20.5 width:15.0 height:5.6
3. Сместите параллелепипед в сторону.
35
Основы MAXScript
4. Введите в окне приемника команд следующее выражение и нажмите
комбинацию клавиш <Shift+Enter>:
Ь2 = box height:5.6 length:20.5 width:15.0
В итоге будет создан второй параллелепипед с такими же значениями свойств,
как и у первого параллелепипеда. Результат выполнения данной функции не меня-
ется, хотя порядок следования аргументов иной. Ключевые слова указывают функ-
ции, какие именно значения соответствуют длине, ширине и высоте параллелепипеда
Определенный порядок следования параметров функции
с указанием дополнительных параметров с помощью
ключевых слов
В MAXScript имеется функция LoadMaxFile для загрузки файла сцены 3ds Мах.
Обозначение данной функции состоит из следующих элементов.
• Обязательное строковое значение с именем файла, которое должно следо-
вать непосредственно после имени функции
• Два или более необязательных аргументов, сопровождаемых ключевыми
словами
Если функция выполняется успешно, она возвращает логическое значение
true, а если ее выполнение окажется неудачным (например, при отсутствии ука-
занного файла), она возвратит логическое значение false.
Ниже приведены четыре разных, но вполне допустимых способа вызова дан-
ной функции:
result = LoadMaxFile "с:/scenes/trucks.max"
result = LoadMaxFile "c:/scenes/trucks.max" useFileUnits:true
result = LoadMaxFile "c:/scenes/trucks.max" quiet:true
useFileUnits:false
result = LoadMaxFile "c:/scenes/trucks.max" useFileUnits:false
quiet:true
Обратите внимание на два последних примера. В обоих случаях функции пе-
редаются одинаковые аргументы, изменен лишь порядок следования двух необя-
зательных аргументов.
Другие способы вызова функций
Ниже представлены другие способы вызова функций в зависимости от того,
как они определены.
• FunctionName О — у функции отсутствуют аргументы. Функция не тре-
бует аргументов или использует устанавливаемые по умолчанию значения.
Например, функция sphere () создает сферу со стандартными значениями
параметров.
• FunctionName значение! значение2 — у функции имеются аргу-
менты, поэтому круглые скобки не используются. Такая функция вос-
36
Глава 1
принимает один или несколько параметров. Из определения функции
можно установить порядок следования ее параметров, чтобы указать пере-
даваемые значения в правильном порядке. Например, функция subtract
varl var2 вычитает переменную varl из переменной var2.
• FunctionName ключевое_слово1:значение! ключевое_слово2:
значение 2 — у функции имеются аргументы, указываемые в произвольном
порядке. Для указания конкретных передаваемых функции значений служат
ключевые слова и знак двоеточия (:). Например, функция box height: 10
length: 2О создает параллелепипед высотой 10 и длиной 20 единиц.
• FunctionName значение! ключевое_слово2:значение2— это вари-
ант, комбинированный из предыдущих способов вызова функций. Такой спо-
соб вызова функции используется нечасто. Первый аргумент функции —
обязательный, второй аргумент — необязательный, и если он не указывает-
ся, то в функции используется устанавливаемое по умолчанию значение.
Создание собственных функций
В MAXScript встроено немало эффективных функций. Однако для написания
сценариев функций, предоставляемых MAXScript, как правило, оказывается не-
достаточно. Создавать собственные функции полезно по целому ряду причин. Во-
первых, собственную функцию можно вызвать из сценария вместо того, чтобы пе-
реписывать все ее операторы всякий раз, когда она потребуется. И во-вторых, соб-
ственные функции можно сделать доступными для других создателей сценариев.
Параметры функции были рассмотрены в предыдущем разделе, поэтому обрати-
тесь, если требуется, к материалу этого раздела, прежде чем приступать к созда-
нию собственной функции.
Создание простой функции
В следующем упражнении вам предстоит создать функцию, устанавливающую
красный цвет каркаса геометрического объекта.
1. Откройте новое окно редактора MAXScript Editor, выполнив следующее.
• Выберите команду MAXScript^New Script из главного меню 3ds Мах.
• Выберите команду File^New Script (Файл^Новый сценарий) из меню
в окне приемника команд.
2. Введите следующий фрагмент кода:
-- Определение функции "ChangeToRed"
fn ChangeToRed obj =
(
if superclassof obj == geometryclass then
(
obj.wirecolor = [255, 0, 0]
)
)
37
Основы MAXScript
3. Нажмите комбинацию клавиш <Ctrl+E>, чтобы выполнить сценарий.
В ответ на это действие в приемнике команд появится сообщение
ChangeToRed (), указывающее на успешную загрузку данной функции.
Если на сцене находятся объекты, с ними ничего не произойдет. Ведь функ-
ция только загружена и ожидает вызова, но пока еще не вызвана.
В определении данной функции аргумент obj обозначает параметр, кото-
рый будет передан функции при ее вызове, в чем вы сможете убедиться да-
лее в этом упражнении.
Если поместить данное определение функции в начало сценария, 3ds Мах
будет известно, что означает ChangeToRed, всякий раз, когда потребуется
данная функция.
4. Введите в новом окне редактора MAXScript Editor следующий фрагмент кода:
for i = 1 to 3 do
(
sphere pos:[random -80 80, random -80 80, random -80 80]
cone pos:[random -80 80, random -80 80, random -80 80]
cylinder pos:[random -80 80, random -80 80, random -80 80]
)
Теперь на сцене имеется несколько объектов.
5. Воспользуйтесь функцией ChangeToRed в цикле. Для этого введите в окне
редактора MAXScript Editor следующий фрагмент кода:
for obj in objects do
(
ChangeToRed obj
)
Все объекты изменят свой цвет. (Для того чтобы увидеть это изменение,
возможно, потребуется щелкнуть в видовом окне и сделать его активным.)
38
Глава 1
Perspective
Массив objects представляет все находящиеся на сцене объекты. Такой
массив создается в 3ds Мах автоматически. В приведенном выше цикле
сначала происходит обращение по очереди ко всем объектам, находящимся
на сцене, а затем — вызов функции ChangeToRed для изменения на крас-
ный цвета каждого из них.
Значения, возвращаемые функцией
Функция возвращает некоторое значение после своего выполнения. Это значение
получается в результате выполнения последнего оператора функции. В следующем
упражнении будет показано, каким образом значение возвращается из функции.
1. Введите в новом окне редактора MAXScript Editor следующий фрагмент
кода, а затем выполните его:
function addnums х у =
(
z = (х + у)
)
2. Введите в окне приемника команд следующее выражение:
а = addnums 1 3
Функция addnums возвращает сумму указанных чисел.
А теперь внесите в данную функцию коррективы, видоизменив ее имя и по-
следний (в данном случае единственный) ее оператор.
3. Введите в окне редактора MAXScript Editor следующий фрагмент кода,
а затем выполните его:
function addnums2 х у =
(
X + у
)
Оператор х + у по-прежнему вычисляет сумму х + у, несмотря на то что в теле
функции никакого присваивания значений переменных не происходит.
39
Основы MAXScript
4. Введите в окне редактора MAXScript Editor следующее выражение, а затем
нажмите клавишу <Enter>:
b = addnums2 4 9
В итоге вы получите ожидаемый результат.
Типы параметров функции
Параметры функции бывают двух типов: позиционные и ключевые. В предыду-
щем разделе были представлены способы вызова функций. А в этом разделе будет
показано, каким образом определяются функции, использующие оба указанных
типа параметров.
Позиционные параметры
Позиционные параметры используются в том случае, если для вызова функ-
ции требуется указать ее аргументы. В общем, порядок следования аргументов
имеет значение, хотя зто правило может и не распространяться на конкретную
функцию. (Рассмотренная выше функция addnums действует независимо от по-
рядка следования обоих ее аргументов. Если бы эта функция вычитала одно число
из другого, порядок следования ее аргументов имел бы значение.)
Ключевые параметры
Ключевые параметры уже не раз использовались в функциях ранее в этой гла-
ве. А в следующем упражнении будет показано, каким образом собственные
функции определяются с помощью ключевых параметров. Определение функции
остается без изменения, но при этом ключевые параметры объявляются явно.
1. Введите в новом окне редактора MAXScript Editor следующий фрагмент кода:
function putUpMessage textl:"File Not found." =
(
messageBox textl title: "Warning" beep: true
)
Итак, создана функция, которая воспринимает одну переменную, однако
в определение данной функции введены знак двоеточия (: ) и стандартное
значение.
2. Выполните сценарий, нажав комбинацию клавиш <Ctrl+E>, чтобы загру-
зить созданную выше функцию.
3. Введите в окне приемника команд следующий фрагмент кода:
s = sphere()
msgl = "The sphere's radius is "
msg2 = s.radius as string
putUpMessage textl:(msgl + msg2)
Появится сообщение о радиусе сферы.
Позиционные параметры можно сочетать с ключевыми. В этом случае в оп-
ределении функции следует указать сначала позиционные параметры, а за-
тем — ключевые параметры:
40
Глава '
function mysphere rad position:[0, 0, 0] =
(
sphere radius:rad pos:position
)
Данная функция лишь размещает “оболочку” вокруг стандартной для 3ds Мах
функции сферы sphere (). Для функции mysphere требуется параметр газ.
однако позиционный параметр данной функции является необязательным.
Передача аргументов по значению
Важным принципом передачи аргументов функциям, который следует усво-
ить, является передача аргументов по значению. Это означает, что телу функции
фактически передается копия аргумента, а его исходное значение, остающееся вне
функции, не меняется. Эта копия видоизменяется как угодно внутри функции, не
оказывая влияния на исходное значение, которое было передано функции. Дан-
ный принцип демонстрируется в следующем упражнении.
1. Введите в новом окне редактора MAXScript Editor следующий фрагмент
кода и вычислите результат:
m = 30.4
п = 23.0
function addnums2 х у =
(
х = 10.0
х + у
)
addnums2 m n
2. В ответ в окне приемника команд появляется значение 33,0.
3. Введите m в окне приемника команд и вычислите значение данной пере-
менной.
4. В результате значение переменной m оказывается равным 3 0,4.
Обратите внимание на то, что сумма чисел равна 33,0. Когда функция по-
лучает аргументы, переменным х и у присваиваются копии передаваемых
значений. В данном случае переменная х получает копию значения 30,4
аргумента т, а переменная у — копию значения 23,0 аргумента п. После
выполнения функции значение аргумента m остается без изменения, по-
скольку переменная х содержит лишь копию значения аргумента т.
Как видите, данная функция может возвращать лишь одно значение, т.е. сумму
двух чисел. При передаче аргументов по значению из функции можно получить лишь
одну переменную. Во многих случаях этого оказывается вполне достаточно. Так,
упоминавшаяся ранее функция LoadMaxFile возвращает лишь одно логическое
значение, указывающее на успешное или неудачное выполнение данной функции.
Однако в некоторых ситуациях требуется, чтобы функции возвращали не-
сколько значений. О том, как это делается, речь пойдет в следующем разделе.
41
Основы MAXScript
Передача аргументов по ссылке
Передача аргументов по ссылке используется для передачи нескольких значе-
ний функции, их обработки и получения обратно. Это означает, что адрес памяти,
выделяемый для аргумента, передается в тело функции и что исходное значение,
которое существует вне функции, подвержено изменению со стороны переменной
аргумента, находящейся в теле функции. Таким образом, при изменении аргумен-
та внутри функции изменяется и переменная вне функции.
Для передачи аргументов по ссылке необходимо сделать следующее.
• Передать функции адрес аргумента, а не его значение. Для этого перед пе-
ременной указывается символ амперсанда (&), например:
addnums2 &m n
• Указать символ & перед соответствующим параметром в обозначении
функции, например:
function addnums2 &х у =
В MAXScript (как и в других языках программирования) символ & называется
оператором ссылки. Такой оператор обозначает адрес переменной. Более подроб-
ное рассмотрение адресов и связанных с ними вопросов программирования выхо-
дит за рамки данной книги.
Следующее упражнение отличается от предыдущего лишь тем, что в нем де-
монстрируется передача аргументов не по значению, а по ссылке.
1. Откройте новое окно редактора MAXScript Editor по команде MAXScript1^
New Script из меню в этом окне.
2. Введите в окне редактора сценариев следующий фрагмент кода и выполните
его, нажав комбинацию клавиш <Ctrl+E>:
m = 30.4
n = 23.0
function addnums2 &x у =
(
x = 10.0
X + у
)
addnums2 &m n
В окне приемника возвращается значение 33,0.
3. Введите m в окне приемника команд и вычислите значение данной пере-
менной.
В результате значение переменной m оказывается равным 10,0.
Как видите, данная функция по-прежнему возвращает значение 33,0, од-
нако значение переменной m теперь равно 10,0, а не 30,4, поскольку оно
изменилось внутри функции.
Примечание. При создании функции любые параметры можно определить
“по ссылке”. Так, в функции addnums2 можно было бы указать “по ссылке”
оба параметра, а не один лишь параметр (&х).
42
ЯЯМ1
Исключение из правила передачи аргументов
по значению (дополнительный материал)
Из правила передачи аргументов функциям MAXScript по значению имеется
следующее исключение: если переменная, имеющая подсвойства, передается
функции, указатель или переменная объекта передается по значению. Однако
подсвойства объекта передаются по ссылке. Эта ситуация демонстрируется в сле-
дующем упражнении.
1. Установите 3ds Мах в исходное состояние.
2. Откройте новое окно редактора MAXScript Editor по команде MAXScript1^
New Script из меню в этом окне.
3. Введите в окне редактора сценариев следующий фрагмент кода и выполните
его, нажав комбинацию клавиш <Ctrl+E>:
myPoint = point3 10 20 30
function modifyPoints pnt =
(
pnt.x = 3
pnt = points 7 14 21
)
modifyPoints myPoint
В окне приемника команд возвращается литерал [7, 14, 21] типа points,
который представляет собой новое значение типа points, созданное внут-
ри функции.
4. Введите myPoint в окне приемника команд и вычислите значение данной
переменной.
Результат равен [3,20,30].
Как видите, значение переменной myPoint не изменилось в результате при-
своения нового значения переменной pnt внутри функции. В то же время значе-
ние свойства .х переменной myPoint изменилось в результате присвоения нового
значения свойству pnt. х внутри функции.
Фрагменты кода из приведенных выше упражнений можно обнаружить в фай-
ле сценария \chapterl\pass_by_value_reference.ms на прилагаемом к этой
книге CD-ROM.
Возврат значений из функций
По окончании выполнения ряда операторов внутри функции из нее возвращает-
ся определенное значение. Если в строке кода, вызывающей функцию, осуществ-
ляется присваивание значения переменной, это значение присваивается перемен-
ной. В целом, функции можно разделить на две категории: те, которые
возвращают значение, и те, которые не возвращают значение. Функции, возвра-
щающие значение, обычно делают это в своем конце. А функции, не возвращаю-
щие значение, называются пустыми, поскольку по завершении таких функций от
43
Основы MAXScript
них не ожидается никакой информации. Еще один способ возврата значения из функ-
ции состоит в передаче ей значения по ссылке, что и было показано ранее в этой главе.
Вероятно, самый простой способ возврата значения из функции состоит в том,
чтобы просто поместить его в последней строке тела функции, например:
function foo =
(
g = 4
h = 5
g*h
)
Если теперь ввести выражение i = foo (), в окне приемника команд вернется
значение 2 0. Это означает также, что переменная i получает значение 2 о.
В отсутствие ключевого слова return может показаться непонятным, что же
именно функция возвращает. В таком случае лучше указать возвращаемое значе-
ние явно:
function foo =
(
g = 4
h = 5
return g*h
)
Данный пример наглядно показывает, где именно функция возвращает значе-
ние 2 0. Так для чего же нужен был предыдущий пример? Во-первых, для того,
чтобы продемонстрировать подобный способ возврата значения из функции. Во-
вторых, применение ключевого слова return несколько замедляет выполнение
функции. Если функция вызывается многократно, следует опустить данное клю-
чевое слово, чтобы сократить общее время выполнения.
Локальные и глобальные переменные
Терминами “локальная” и “глобальная" обозначается область действия пере-
менной. Область действия определяет место в коде сценария MAXScript, где пе-
ременная оказывается доступной. Но как только переменная будет объявлена как
глобальная, она окажется доступной в любом сценарии и в любой момент. Ло-
кальная переменная может использоваться в том блоке кода, в котором она опре-
делена, либо во вложенных в него блоках кода. Блок кода представляет собой лю-
бой фрагмент кода, заключенный в круглые или квадратные скобки.
Таким образом, правильнее было бы сказать, что локальная переменная объяв-
ляется во вложенном блоке внутри сценария и оказывается недоступной в конце
сценария, т.е. за пределами области ее действия.
Созданные до сих переменные действительны вплоть до выхода из 3ds Мах.
При вводе выражения х = 5, о в окне редактора MAXScript Editor или приемни-
ка команд фактически объявляется глобальная переменная х. Глобальная пере-
менная сохраняет свое значение вплоть до выхода из 3ds Мах, даже если закрыть
окно редактора сценариев или приемника команд либо установить 3ds Мах в ис-
ходное состояние.
44
Глава 1
Определение переменных
При обработке сценариев в 3ds Мах никаких прогнозов не делается. В приве-
денных ниже упражнениях показано, что переменной нельзя воспользоваться до
тех пор, пока она не будет определена.
Для того чтобы правильно определить переменную, выполните следующее уп-
ражнение.
1. Установите 3ds Мах в исходное состояние.
2. Откройте новое окно редактора MAXScript Editor по команде MAXScript1^
New Script из меню этого окна.
3. Введите в окне редактора сценариев следующий фрагмент кода, а затем
выполните его, нажав комбинацию клавиш <Ctrl+E>:
rad = 10
sphere radius:rad
cylinder radius:rad
Данный код выполняется без ошибок, поскольку переменные определены
в правильном порядке.
4. А теперь вам предстоит создать код, объявляющий переменные в неверном
порядке. Замените существующий сценарий приведенным ниже и выпол-
ните его:
cylinder radius:new_rad
new_rad = 10.0
Переменная new_rad отсутствует вплоть до первого ее определения. В дан-
ном случае возникает ошибка, поскольку в первой строке сценария присут-
ствует неизвестная переменная new_rad.
5. Выполните сценарий еще раз.
На этот раз ошибка не возникает. В первый раз ошибка возникла в первой
строке сценария, хотя вторая его строка была все равно выполнена и в итоге
переменной new_rad было присвоено значение 10. С этого момента пере-
менная new_rad стала доступной и действительной на момент выполнения
сценария во второй раз.
Это типичное затруднение, с которым сталкиваются многие начинающие
создатели сценариев. При появлении ошибок в сценарии проанализируйте
его на предмет объявления переменных в правильном порядке.
Глобальные переменные
Глобальная переменная представляет собой любую переменную, объявленную
или определенную вне всех блоков кода. В предыдущем упражнении все перемен-
ные были глобальными, поскольку они не были объявлены внутри цикла for или
while, оператора функции или же другого блока кода.
Примечание. Циклические конструкции рассматриваются далее в этой главе.
45
Основы MAXScript
Глобальную переменную можно также объявить явно. Ниже приведены при-
меры правильного объявления глобальной переменной:
global а
global а = 2
а = 2 -- если переменная определена внутри сценария, но не блока
В целом, применения глобальных переменных следует избегать. Ведь если объя-
вить глобальную переменную в сценарии, который может быть использован в каком-
нибудь другом месте 3ds Мах, а затем перезаписать значение такой переменной, то дру-
гие сценарии или подключаемые модули могут работать не вполне предсказуемым об-
разом. В некоторых примерах, приведенных в данной книге, глобальные переменные
все же используются, однако такие переменные, как а, Ь, х, у и другие однобуквен-
ные переменные, вряд ли будут вступать в конфликт с глобальными переменными
из других выполняемых сценариев. Тем не менее, если сценарий предполагается ис-
пользовать часто или же распространять среди других пользователей, во избежание
конфликтов рекомендуется применять, в основном, локальные переменные.
Локальные переменные
Переменные, объявленные (или определенные) в предыдущем упражнении,
являются глобальными, поскольку находятся вне блока кода. Для ограничения
области действия переменной ее достаточно объявить как локальную. Локальные
переменные действительны в пределах блока кода, в котором они определены, или
же во вложенных в него блоках. В этой связи блок кода иногда еще называется
контекстом области действия. Примеры блоков кода будут представлены при
рассмотрении циклов и условных операторов далее в этой главе.
Локальная переменная объявляется несколькими способами. Ниже приведены
все действительные способы объявления локальной переменной b (напомним, что
она должна быть внутри блока):
( local b )
( local Ь = 2 )
( b = 2 — если переменная определена внутри блока )
Если переменная объявлена как локальная вне всех блоков кода, компилятор
выдаст сообщение об ошибке "No local declarations at top level:
. . . .11 (Объявления локальных переменных на верхнем уровне отсутствуют).
Как только локальная переменная будет объявлена, она может быть использо-
вана в том же блоке кода, где она была определена, или же во вложенных в него
блоках. Рассмотрим, например, следующий сценарий:
s = sphere()
for i = 1 to 5 do
(
a = instance s pos:[i*50, 0, 0]
if (s.pos.x > 150) then
(
s.pos.y = 50
c = (30 + i)
)
46
Глава 1
b = с -- Переменная с не определена в этом блоке.
Ь = сору а -- Переменная а определена в этом же блоке,
-- поэтому она действительна.
)
В данном сценарии имеются два блока кода, вложенных один в другой. Пере-
менная с объявлена внутри блока if-then, поэтому она действительна только
внутри круглых скобок, обрамляющих данный блок кода. Переменная а объявле-
на внутри блока цикла for, поэтому она может быть использована в блоке данно-
го цикла, а также в блоке if - then.
Если выполнить данный сценарий, включив в него оператор построчного вы-
вода после строки кода b = с, значение переменной с будет выведено как неопре-
деленное (undef ined).
Локальные переменные из одного блока кода можно использовать повторно
внутри другого блока кода в сценарии. В действительности многие программисты
предпочитают пользоваться при каждой возможности переменными i, j и к для
определения циклов. Это означает, что такие переменные используются много-
кратно внутри одной и той же программы.
Условные операторы
Само по себе понятие условного оператора несложное. Такой оператор позво-
ляет управлять процессом выполнения программы. Условные операторы могут
быть реализованы разными способами.
Операторы if-then
К первому типу условных операторов относится оператор if- then.
if s.pos.x == 10 then s.radius = 40
В приведенном выше примере оператор изменяет радиус сферы только в том
случае, если значение координаты х ее положения равно 10. Двойным знаком ра-
венства (==) обозначается операция логического сравнения, тогда как одиночным
знаком равенства — операция присваивания.
В условном операторе непременно должны присутствовать слова if и then.
Если вы забудете включить их в данный оператор, в MAXScript будет сформиро-
вано в ответ сообщение об ошибке.
Логические операторы НЕ, И, ИЛИ
В одном условном операторе может быть указано несколько условий. Для этой
цели служат логические операторы НЕ (not), И (and) и ИЛИ (or). Ниже приве-
ден ряд соответствующих примеров.
if (not s.radius == 10) then messagebox "Radius is not 10."
if (x == 5 and у == 6) then z = 0
if (x == 5 or у == 6) then z = 0
47
Основы MAXScript
Если оператор not окажется не совсем удобным, условие “не равно” можно
проверить и по-другому, используя синтаксис is ! =, например:
if s.radius != 10 then messagebox "Radius is not 10."
При проверке нескольких условий, как правило, требуются круглые скобки
для группирования условий в логическом порядке, что особенно важно для слож-
ных выражений. Выражения в круглых скобках всегда вычисляются в первую
очередь. Каждый из операторов в следующем примере дает разные результаты:
if (х == 5 or у == 6) and z == 10 then w = 0
if x == 5 or (y == 6 and z == 10) then w = 0
Если в сложном выражении опущены круглые скобки, порядок его вычисле-
ния может быть определен с помощью правил предшествования логических опе-
раторов. Такие правила определяют старшинство одних логических операторов
над другими при вычислении выражения. Наивысшим приоритетом обладает
оператор НЕ, который вычисляется в первую очередь. Операторы И и ИЛИ вы-
числяются слева направо, причем оператор И имеет больший приоритет:
х and у or z
В соответствии с правилами предшествования приведенное выше выражение
без круглых скобок эквивалентно следующему выражению:
(х and у) or z
То же самое имеет место и в следующем выражении:
not х or у and z
Оно эквивалентно выражению
(not х) or (у and z)
Напомним, что новые операторы сценария вводятся в MAXScript с новой
строки, а для продолжения оператора на следующей строке служит обратная косая
черта (\). Но из этого правила имеется исключение для конструкции if-then:
части if и then условного оператора могут указываться в отдельных строках.
Ведь после выражения if непременно должно следовать выражение then, поэто-
му его можно поместить в следующей строке:
b = box()
if b.height != 10.0
then b.length = 40.0
Приведенная выше конструкция дает такой же результат, как и следующая:
b = box ()
if b.height != 10.0 then
b.length = 40.0
Оператор b. length указан с отступом для обозначения того факта, что он яв-
ляется частью условия if- then. Это делается только ради повышения удобочи-
таемости кода сценария.
48
Глава 1
Операторы if-then-else
Если ввести фрагмент кода из предыдущего примера в приемнике команд, то
ничего особенного при этом не произойдет. Объясняется это особенностями
управляющей структуры if-then-else. Простую конструкцию if-then можно
расширить, дополнив ее выражением else, причем каждая из частей if, then
и else условного оператора может быть указана в отдельной строке, например:
if b.pos == 10
then b.height =40
else b.height = 80
Выражение else дает возможность указать альтернативное действие, если ус-
ловие внутри выражения if не выполняется. Напомним, что операторы выпол-
няются в приемнике команд построчно по мере их ввода. В следующем выраже-
нии будет показано, каким образом приемник команд реагирует на ввод оператора
if-then-else.
1. Введите в приемнике команд следующее выражение:
b = box()
2. Введите следующее выражение:
if b.pos.х == 0 then b.height =40
После ввода данного выражения объект не изменился, а приемник команд
никак не отреагировал на это выражение — ни положительным результа-
том, ни сообщением об ошибке.
Ведь приемнику команд неизвестно, собираетесь ли вы ввести далее опера-
тор else. Ему требуется завершенная структура if-then-else, прежде
чем выполнять код сценария MAXScript. Если в следующей строке вы вве-
дете выражение else, приемник команд будет знать, что делать дальше.
Если же выражения else не окажется в следующей строке, приемник ко-
манд предположит, что его и не следует ожидать.
3. Введите в приемнике команд следующее выражение:
else b.height = 10.0
Теперь приемник команд отреагирует, и высота параллелепипеда изменит-
ся до величины 4 0,0 единиц.
49
Основы MAXScript
4. Введите следующий фрагмент кода и нажмите комбинацию клавиш
<Shift+Enter> после каждой введенной строки:
if b.pos.x == 0 then b.height = 40
messagebox "Done"
Несмотря на отсутствие в этом фрагменте кода выражения else, приемник
команд будет знать, что ввод этого кода завершен, и в итоге появится окно
сообщения.
Примечание. Если сценарии выполняются в окне редактора сценариев по команде
Evaluate АП (Вычислить все), то приведенная выше процедура ввода и вычисления
конструкции if-then-else не действует, поскольку в этом случае просто
выполняется весь сценарий.
Перечень операторов
Помимо операторов == и ! =, могут быть использованы и другие операторы.
Ниже приведен полный их перечень.
Оператор Определение
= = Равно
1 = Не равно
> Больше
> = Больше или равно Меньше
< = Меньше или равно
Циклические конструкции
Цикл представляет собой повторяющуюся, или итеративную, операцию. Он
обозначает повторяющееся выполнение группы операторов, которое прекращает-
ся в определенный момент. Так, если требуется изменить свойства 20 находящих-
ся на сцене сфер, это можно сделать внутри циклической конструкции, повто-
ряющейся 20 раз — по одному для каждой сферы в отдельности. В этом разделе
рассматриваются две циклические конструкции: циклы for и while.
50
Цикл for
В цикле for используется конструкция, аналогичная следующей:
for i = 1 to 5 do [действие]
В этом цикле значение 1 присваивается индексной переменной i. Индексной
называется такая переменная, которая изменяется (увеличивается или уменьша-
ется) при каждом повторении цикла. Индексные переменные называются также
индексными переменными цикла.
Индексная переменная должна быть объявлена в той же строке, в которой объ-
явлен цикл for. В приведенном выше примере в цикле for сначала выполняется
действие, а затем увеличивается до 2 значение переменной i, после чего действие
повторяется. И так до тех пор, пока значение переменной i не достигнет 5, когда
действие выполняется в последний раз и цикл завершается.
Для построения цикла for может быть использована любая переменная, а не
только переменная i; значение ее приращения может начинаться или оканчивать-
ся любым целым числом. Кроме того, переменную можно использовать и внутри
самого действия. Пример такого цикла приведен в следующем упражнении.
1. Установите 3ds Мах в исходное состояние.
2. Введите в окне приемника команд следующее выражение:
for i = 1 to 5 do sphere pos: [i*50,0,0]
3. В данном цикле создаются пять сфер, каждая из которых занимает разное
положение по оси X. Для этого составляющая х положения каждой новой
сферы устанавливается равной i *5 0.
Теперь сферы можно организовать в массив и выполнить операцию над
всеми сферами сразу.
Примечание. Для полноты примера в следующем упражнении в цикл введены
массивы. Более подробно массивы рассматриваются в разделе “Совокупности”
далее в этой главе.
Для того чтобы применить массив в цикле, выполните следующее упражнение.
1. Введите в окне приемника команд следующий фрагмент кода, нажимая
клавишу <Enter> после каждой введенной строки:
intArray = #()
for i = 1 to 5 do append intArray (i*5)
В этом цикле в массив intArray вводятся числа 5,10,15,20 и 25.
2. Введите следующее выражение и нажмите клавишу <Enter>:
for i in intArray do sphere pos:[i,i*2,i*3]
В данном цикле создаются пять сфер, положение которых определяется
значениями из массива intArray.
В приведенном выше цикле for знак равенства был заменен словом in. Это
типичная циклическая конструкция для выполнения операций над массивом.
51
Основы MAXScript
Циклы с многими операторами
Для выполнения цикла for с многими операторами в теле цикла эти операторы
следует указывать в круглых скобках, а слово do должно предшествовать круглым
скобкам. Как и в примерах условных операторов if-then-else, цикл не выполня-
ется в приемнике команд до тех пор, пока не будут введены всего его операторы. Это
означает, что до тех пор, пока в цикле не будет введена завершающая круглая скобка,
ничего не произойдет. Операторы внутри круглых скобок вводятся с отступом для
повышения организованности и удобочитаемости кода сценария. В качестве полез-
ного практического совета каждую новую группу операторов в круглых скобках ре-
комендуется вводить с дополнительным отступом на одну позицию табуляции.
Если тело цикла содержит только один оператор, в таком случае круглые скоб-
ки не нужны. Так, оба приведенных ниже примера равнозначны:
for i = 1 to 5 do
(
s = sphere()
)
for i = 1 to 5 do
s = sphere()
Теперь для написания многострочных сценариев вы должны пользоваться ре-
дактором MAXScript Editor. В окне этого редактора вы можете ввести целый ряд
команд, а затем выполнить сразу все эти команды.
Для создания циклов с многими операторами выполните следующее упражнение.
1. Установите 3ds Мах в исходное состояние.
2. Выберите команду MAXScript^ New Script из главного меню, чтобы от-
крыть окно редактора MAXScript Editor.
3. Введите в окне редактора MAXScript Editor следующий фрагмент кода:
for i = 1 to 5 do
(
a = sphere pos:[i*50,0,0]
messagebox a.name
)
4. Нажмите комбинацию клавиш <Ctrl+E>, чтобы выполнить сценарий и вы-
числить результат. После выполнения каждого шага цикла появляется окно
сообщения с наименованием каждой созданной сферы.
5. На запрос вычислить результат или выполнить сценарий в редакторе
MAXScript Editor вы можете нажать комбинацию клавиш <Ctrl+E> или
же выбрать команду File^Evaluate АН из меню в окне этого редактора. Для
выполнения большей части упражнений в данной книге вам придется поль-
зоваться редактором MAXScript Editor.
Для того чтобы объединить циклы и условные операторы в одном сценарии,
выполните следующее упражнение.
1. Установите 3ds Мах в исходное состояние или же удалите со сцены все объекты.
2. Выберите команду File^New из меню в окне редактора MAXScript Editor,
чтобы открыть новое окно редактора сценариев без текста.
52
3. Введите следующий фрагмент кода:
cylArray = #()
for i = -3 to 3 do
(
if i != 0 then
(
a = cylinder height:50 pos:[i*40,0,0]
append cylArray a
)
else
(
a = cone height:50 pos:[i*40,0,0]
messagebox a.name
)
)
4. Нажмите комбинацию клавиш <Ctrl+E> или выберите команду File1^
Evaluate АН из меню в окне редактора сценариев.
В данном коде внутри цикла for был помещен условный оператор. По мере
создания каждого цилиндра проверяется значение переменной i. Если зна-
чение переменной i равно 0, вместо цилиндра создается конус, а в окне со-
общения отображается имя нового объекта.
Примечание. Индекс i данного цикла начинается со значения -з и оканчивается
значением з. Индекс цикла отнюдь не обязательно должен быть положительным
числом и не всегда должен начинаться с 1.
Обратите внимание на применение круглых скобок в приведенном выше при-
мере. Операторы в условной конструкции if-then-else указаны в круглых
скобках, а сама эта конструкция также помещена в круглые скобки, определяющие
тело цикла for. Неправильное чередование открытых и закрытых круглых скобок
является типичной ошибкой программирования. Открытых скобок всегда должно
быть столько же, сколько и закрытых, причем они должны быть правильно рас-
ставлены. В противном случае сценарий не будет выполняться или же результат
его выполнения окажется непредсказуемым.
53
Основы MAXScript
Циклы while
Циклы while подобны циклам for в том отношении, что в них неоднократно
повторяется группа операторов. Отличие состоит лишь в том, что в цикле while
число повторений неизвестно или не указано заранее. Для завершения такого
цикла устанавливается определенное условие.
Имеются два типа циклической конструкции while: do-while и while-do.
Для того чтобы воспользоваться циклами do-while и while-do, выполните
следующее упражнение.
1. Установите 3ds Мах в исходное состояние.
2. Введите в пустом окне редактора MAXScript Editor следующий сценарий,
а затем выполните его:
i = О
t
do
(
t = teapot pos: [i*20, 0, i*20]
i = i + 1
) while t.pos.x < 101
В данном сценарии создается ряд располагаемых каскадом чайников.
Обратите внимание на то, что переменная t была объявлена перед телом
цикла (блоком кода do), поэтому она доступна для проверки условия while
в конце сценария. Если удалить переменную t, она окажется неопределен-
ной в следующей строке:
while t.pos.x < 101
А это приведет к формированию в MAXScript сообщения об ошибке.
3. Вновь установите 3ds Мах в исходное состояние, очистите окно редактора
MAXScript Editor, введите следующий сценарий и выполните его:
54
i = О
test = true
while test do
(
t = teapot pos:[i*20, 0, i*20]
i = i+1
test = t.pos.x < 101
)
Результат получается таким же, как и в п. 2 данного упражнения, однако
операторы сценария выполняются иначе. Если внимательно проанализиро-
вать оба приведенных выше цикла, то можно заметить, что в первом из них
операторы в теле цикла do выполняются, по крайней мере, один раз. При
этом условие не проверяется до тех пор, пока не будет выполнено тело цик-
ла. В частности, положение чайника проверяется только после его создания.
Во втором цикле сначала проверяется условие: нужно ли вообще выпол-
нять тело цикла. В зависимости от обстоятельств данное условие может не
удовлетворяться с самого начала, так что цикл не будет выполнен ни разу.
Примечание. Для вычисления логических значений в данном сценарии были
использованы выражения. Так, в выражении t.pos.x < 101 вычисляется
логическое значение true или false. Результат вычисления данного выражения
присваивается переменной test. Кроме того, оператор сценария while test do
равнозначен оператору while test == true do.
Совокупности
Термином совокупность описывается любая группа объектов или значений,
отслеживаемых в 3ds Мах. К одной из разновидностей совокупности относятся
массивы.
Совокупность ObjectSet представляет собой особый вид совокупности, под-
держиваемой в MAXScript. Ее содержимое автоматически меняется вместе с из-
менениями, происходящими в сцене. Например, совокупность объектов содержит
объекты, находящиеся на сцене в произвольный момент времени. Если объект
вводится в совокупность объектов или удаляется из нее, такая совокупность соот-
ветственно расширяется либо сокращается.
С другой стороны, если ввести объект в массив по сценарию, а затем удалить объект
со сцены, в массиве останется ссылка на удаленный объект. Это не совсем желатель-
но, поскольку при попытке доступа к такому элементу массива возникнет ошибка.
Массивы
Массив представляет собой последовательный ряд элементов. Доступ к каждо-
му элементу массива, или значению, осуществляется с помощью числового индекса.
Элементы массива могут иметь любой тип данных, включая числа, логические
значения true/false, трехмерные объекты, строки и т.д. Объекты массивов соз-
даются с помощью специального конструктора массива. В простейшем случае
массив создается с помощью следующей команды:
myArray = #()
55
Основы MAXScript
Знак # и последующие круглые скобки обозначают массив. С помощью приве-
денного выше оператора была создана переменная myArray, в которой сохранен
пустой массив.
Пустой массив пока еще не содержит никаких элементов. Такие элементы
можно ввести в массив, например, путем присваивания ему конкретных значений
во время его создания:
myArray = #(1,2,4,8,16)
Данный массив содержит пять целочисленных элементов. У каждого из них
имеется соответствующий индекс. В частности, у первого элемента массива
(перечисленного выше целого значения 1) имеется индекс 1, у второго элемента
массива — индекс 2 и т.д. Доступ к отдельным элементам массива осуществляется
по его индексу, указываемому в квадратных скобках.
В следующей строке кода возвращается значение третьего элемента массива
(целое число 4):
myArray[3 ]
А в приведенной ниже строке кода значение третьего элемента массива заме-
няется целым числом 28. Подобным способом можно заполнить массив нужными
значениями:
myArray[3] =28
Отдельные элементы присоединяются к массиву с помощью команды append:
append myArray 56
В приведенной выше строке кода к массиву присоединяется шестой его эле-
мент (целое значение 56). В массиве можно хранить любой ряд элементов, вклю-
чая трехмерные объекты.
Для того чтобы сохранить объект в массиве, выполните следующее упражнение.
1. Установите 3ds Мах в исходное состояние или же удалите со сцены все объекты.
2. Введите в окне приемника команд следующий фрагмент кода и вычислите
результат:
с = cylinder pos:[50,0,0]
b = box()
s = sphere pos:[-50,0,0]
В разных местах сцены будут созданы три объекта.
3. Введите в окне приемника команд следующее выражение и вычислите ре-
зультат:
objectArray = #(c,b,s)
В итоге будет создан массив, содержащий три объекта.
4. Введите следующий фрагмент кода и вычислите результат:
d = donut()
append objectArray d
Таким образом, к массиву будет присоединен тороидальный объект.
56
Функции для массивов
Массивы весьма полезны для выполнения однотипных операций над несколь-
кими объектами или значениями. Для последовательного обращения к элементам
массива совсем не обязательно знать число его элементов. Вот как это делается:
а = #("one", "word", "at", "a", "time")
for i = 1 to a.count do
(
messagebox a[i]
)
Свойство . count массива объектов всегда содержит общее число элементов
массива.
Для работы с массивами имеется целый ряд дополнительных функций. К их
числу относятся deleteltem, join, sort и finditem. Ниже приведены приме-
ры синтаксиса этих функций.
• Функция deleteltem удаляет элемент, обозначаемый вторым аргументом
данной функции. В приведенном ниже примере элемент агг [2] удаляется
из массива, а значение счетчика массива (arr.count) автоматически
уменьшается на 1.
агг = #(1.0, .55, .3, 2.6)
deleteltem агг 2
for i = 1 to arr.count do
messagebox (arr[i) as string)
• Функция j oin объединяет два массива, а также совокупность и массив:
for i = 1 to 3 do
(
sphere()
box()
)
arr = $sphere* as array
join arr $box*
for i = 1 to arr.count do
messagebox arr[i].name
• Функция finditem может оказаться полезной в самых разных ситуациях.
С ее помощью можно, в частности, найти конкретное значение. Она воз-
вращает индекс искомого значения. Если искомое значение отсутствует
в массиве, функция finditem возвращает 0:
агг = #(2.4, 4, 3.2, 1.1)
index = finditem arr 3.2
-- Найденный индекс будет равен 3
messagebox (index as string)
-- Значение 3.3 отсутствует в массиве, поэтому возвращаемый
— индекс равен О
index = finditem arr 3.3
messagebox (index as string)
• Функция sort организует массив в порядке убывания. Если массив состо-
ит из строк, он организуется в алфавитном порядке. Синтаксис данной функ-
ции следующий:
sort arr
57
Основы MAXScript
Функция sort дает ошибку, если элементы массива не относятся к одному
и тому же типу данных. В большинстве языков программирования массив может
содержать данные только одного типа, а в MAXScript элементы одного массива
могут быть разнотипными, например:
-- Сначала создать пустой массив
агг = #()
-- А затем ввести ряд его элементов
агг[1] = 4
агг[2] = "string stuff"
Такой массив вполне допустим, но в этом случае вам придется самостоя-
тельно определять типы данных у отдельных элементов массива по соответст-
вующему индексу.
Вывод массивов на печать
До версии 3ds Мах 7 попытка вывести массив на печать или преобразовать его
в строковый тип (т.е. выполнить так называемое приведение типов данных) при-
водила к тому, что распечатывались лишь 20 первых элементов массива. Теперь в
MAXScript появилась новая глобальная переменная, позволяющая выводить все
элементы массива на печать или выполнять приведение их типов. Эта глобальная
переменная следующая:
options.PrintAllElements
Если установлено логическое значение true данной переменной, все элементы
массива выводятся на печать или преобразуются в строку (более подробно типы дан-
ных и их приведение рассматриваются в оперативном руководстве по MAXScript).
Если же установлено логическое значение false данной переменной, то на печать
выводятся только 20 первых элементов массива.
Примечание. Дополнительные сведения о синтаксисе переменной
PrintAllElements приведены в руководстве по MAXScript.
Для того чтобы воспользоваться переменной PrintAllElements, выполните
следующее упражнение.
1. Введите в окне приемника команд следующий фрагмент кода:
options.PrintAllElements = false
h = for i = 1 to 30 collect i
2. Обратите внимание на то, что на печать выведены лишь 20 первых элемен-
тов массива:
#(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
16, 17, 18, 19, 20, ...)
3. Введите в окне приемника команд следующий фрагмент кода:
options.PrintAllElements = true
h
4. Как видите, теперь на печать выведены все элементы массива:
#(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30)
58
Глава "
Многомерные массивы
(дополнительный материал)
Многомерным называется такой массив, каждый элемент которого содержит
другой массив, т.е. это массив массивов. Такой массив бывает не только двухмер-
ным; он может иметь размерность более высокого порядка. Двухмерный массив
выглядит следующим образом:
#(#(1,2),#(3,4))
Его можно присвоить любой переменной следующим образом:
h = #(#(1,2),#(3,4))
В следующем упражнении вам предстоит создать двухмерный массив.
1. Установите 3ds Мах в исходное состояние.
2. Откройте окно редактора MAXScript Editor по команде MAXScript^New Script
из меню данного окна. Введите в окне редактора MAXScript Editor следую-
щий фрагмент кода и выполните его, нажав комбинацию клавиш <Ctrl+E>:
function array2D row column =
(
local data = #()
for i = 1 to column do
(
data[i] = #(0)
for j = 1 to row do
(
data[i] [j] = random 1 10
)
)
return data
)
myArray = array2D 2 4
3. В ответ в окне приемника команд появится новый двухмерный массив, за-
полненный произвольными числами в пределах от 1 до 10:
array2D()
#(#(10, 1), #(10, 9), #(4, 5), #(9, 4))
В следующем упражнении вам предстоит определить массив, содержащий всю
информацию, необходимую для создания объекта, а затем организовать двухмер-
ный массив из подобных массивов.
1. Введите в редакторе MAXScript Editor все операторы сценария так. как они
показаны в этом упражнении. Сценарий будет выполнен в конце данного
упражнения.
2. Создайте два массива в новом окне редактора MAXScript Editor: это будут
массивы описания цилиндров:
cylobjl = #()
cylobj2 = #()
3. Создайте ряд модификаторов для последующего применения:
tap = taper amount:-1.0
bnd = bend angle:30
59
Основы MAXScript
4. Заполните элементы обоих массивов описанием свойств цилиндрических
объектов. Первый элемент каждого массива должен содержать высоту ци-
линдра, второй — его положение по оси X, третий — наименование цилинд-
ра и четвертый — применяемый к цилиндру модификатор:
cylobjlfl] = 30.0
cylobjl[2] = 0.0
cylobjl[3] = "first cylinder"
cylobjl[4] = tap
cylobj2[l] = 60.0
cylobj2[2] = 40.0
cylobj2[3] = "second cylinder"
cylobj2[4] = bnd
5. Создайте массив из массивов описания цилиндров:
my_cylinders = #(cylobjl, cylobj2)
Для доступа к элементу двухмерного массива cylinders используется
выражение cylinders [i] [j], где первый индекс массива [i] обозначает
конкретный массив описания цилиндров, а второй индекс [ j ] служит для
индексации этого массива.
6. Постройте два цилиндра:
for i = 1 to my_cylinders.count do
(
c = cylinder height:my_cylinders[i][1] \
pos: [my_cylinders[i] [2] , 0.0, 0.0] \
name:my_cylinders[i][3] \
heightsegs:10
addmodifier c my_cylinders [i] [4]
Версию этого сценария можно найти в файле \chapterl\2_D_Arrays.ms
на прилагаемом к этой книге CD-ROM. А на приведенном ниже рисунке
показан результат выполнения данного сценария.
60
Глава •
Метасимволы
Для одновременно ввода двух объектов в совокупность можно воспользоваться
метасимволом “звездочка” (*). Как было показано выше, он служит для обозначения
операции умножения. Помимо этого, он может быть использован в качестве метки-
заполнителя для обозначения одного или более произвольных буквенно-цифровых
символов. Это равнозначно поиску в Проводнике Windows всех файлов с расшире-
нием .max по критерию *.тах. В циклах MAXScript символ “звездочка” можно
применять самыми разными способами, например в сочетании с путевыми именами.
Напомним, что каждому объекту, создаваемому в 3ds Мах, присваивается пу-
тевое имя в иерархии объектов. Именно в этом случае удобно воспользоваться по-
нятием совокупности. Так, все объекты данного типа можно рассматривать в каче-
стве совокупности MAXScript подобных объектов. Операции над каждым
объектом из такой совокупности могут быть выполнены в цикле for, хотя для
этого существует и более простой способ — воспользоваться метасимволами. При
этом не нужно указывать имя или ссылку на каждый создаваемый объект.
Для того чтобы воспользоваться совокупностями вместо массивов, выполните
следующее упражнение.
1. Установите 3ds Мах в исходное состояние и очистите окно приемника ко-
манд.
2. Создайте два чайника любыми доступными средствами. Не изменяйте их
имена, присвоенные в 3ds Мах по умолчанию.
3. Введите в окне приемника команд следующий фрагмент кода:
coll = $teapot*
arr = coll as array
В окне приемника команд появится массив, состоящий из двух чайников.
Синтаксис оператора as array такой же, как и синтаксис применявшегося
ранее оператора as string. В данном случае оператор coll as array
преобразует совокупность coll в массив (или выполняет приведение типов).
4. Выделите и удалите один из чайников, находящихся на сцене.
5. Введите в окне приемника команд следующее выражение и вычислите ре-
зультат:
arr = coll
61
Основы MAXScript
В окне приемника команд появится следующий результат: $$objects/
... /teapot*.
Переменная совокупности coll была автоматически обновлена после удале-
ния чайника. В этом сценарии вам не пришлось делать ничего особенного.
Если же создать еще один новый чайник, переменная обновится автоматически.
6. Установите 3ds Мах в исходное состояние и вновь создайте два чайника.
Введите в окне приемника команд следующий фрагмент кода и вычислите
результат:
coll = $teapot*
arr = coll as array
7. Удалите один чайник, введите в окне приемника команд следующий фраг-
мент кода и вычислите результат:
for i = 1 to arr.count do
messagebox arr[i].name
Как и следовало ожидать, при выполнении данного кода возникает ошибка.
Созданный массив существует независимо от совокупности. Если удалить
со сцены объект, не изменится ни индекс массива, ни хранящиеся в нем
значения. Если же затем попытаться обратиться к элементам массива по
индексу, это будет равнозначно попытке получить доступ к свойствам
объектов, которые уже не существуют. Следовательно, если объекты, вхо-
дящие в массив, предполагается удалять, то перед обращением к массиву
следует организовать его снова.
8. С другой стороны, для установления факта удаления объекта можно вос-
пользоваться функцией isDeleted.
9. Введите в окне приемника команд следующий фрагмент кода и вычислите
результат:
for i = 1 to arr.count do
(
if not isDeleted arrfi] then
messagebox arr[i].name
)
Этот код уже не дает ошибки.
62
Глава 1
Примечание. Символом $ обозначается объект, выделенный в настоящий
момент, нвпример:
5 . name
Этот оператор возвращает имя любого объекта, выделенного в данный момент.
Структуры
Выше были представлены основные типы данных, в том числе целые числа,
числа с плавающей точкой и строки. Эти типы данных являются основополагаю-
щими для MAXScript. Тем не менее это самые элементарные типы данные, в чем
и состоит их главный недостаток. Истинный потенциал объектно-ориентирован-
ных языков программирования состоит в том, что они допускают абстракцию по-
нятий на более высоком уровне типа данных или класса. Нетрудно, в частности,
заметить, насколько удачно целочисленный класс подходит для абстракции чисел.
Но что если в компьютерной программе требуется обобщить понятие более высо-
кого уровня, например описать автомобиль, род занятий или человека? Человека
можно описать по имени (строка), возрасту (целое число), росту (число с пла-
вающей точкой), весу (число с плавающей точкой) и прочим признакам. Следова-
тельно, о человеке можно составить следующее представление.
• Человек
• Имя: Кэрол
• Возраст: 47 лет
• Рост: 68 дюймов (около 173 см)
• Вес: 130 фунтов (около 60 кг)
Аналогичная логическая последовательность используется для создания ново-
го типа данных в MAXScript с использованием определений структур.
Сначала создается определение структуры, а затем ее экземпляр. Процесс по-
лучения нового экземпляра называется реализацией. При этом вновь полученный
экземпляр содержит все свойства и методы структуры. После создания такой объект
будет вести себя так же, как и элементы остальных типов данных, присущих
MAXScript. Ниже представлены правила создания структуры.
Синтаксис структуры
Правила создания структуры следующие.
• Структура должна начинаться с ключевого слова struct.
• После ключевого слова struct должно следовать любое имя.
• Далее должны следовать открытые скобки.
• Структура должна содержать одну или более дополнительных переменных,
которые ее описывают. Эти переменные должны быть отделены одна от
другой запятыми (,). Такие переменные называются переменными-членами,
поскольку они принадлежат структуре или являются членами группы,
63
Основы MAXScript
состоящей из элементов данных определенных типов и функций, совместно
образующих структуру.
• Структура может содержать несколько функций-членов либо не содержать
их вовсе.
• После последней переменной или функции-члена в структуре запятая не
ставится.
• Далее должны следовать закрывающие круглые скобки.
Ниже приведен пример структуры рассмотренного выше описания человека,
struct Person
(
name,
age,
height,
weight
)
Функция-конструктор структуры
Для построения объекта человека следует создать переменную и присвоить ей
результат выполнения специальной функции-конструктора с таким же именем,
которое имеет структура. Такие функции-конструкторы действуют аналогично
стандартным функциям и могут воспринимать как позиционные, так и ключевые
аргументы, например:
myPerson = Person()
В данном примере myPerson — это переменная, принимающая значение от
функции-конструктора Person, которая используется с круглыми скобками (т.е. без
аргументов).
Значение переменной myPerson можно теперь использовать аналогично лю-
бому другому числовому или строковому значению в MAXScript, в частности по-
лучить доступ к свойствам данной переменной, передать ее соответствующим
функциям и вывести результаты в окне приемника команд.
Инициализация структуры
При создании объекта, имеющего тип данных person, в него, однако, не вво-
дится никаких данных. Так, если взять переменную myPerson из предыдущего
примера, ввести код
myPerson.name
и вычислить его, в окне приемника команд появится следующий результат:
undefined
Такой результат получается потому, что в объект person не были введены
данные, а следовательно, переменная myPerson оказывается пустой.
Имеются три основных способа инициализации объекта данными.
64
^•ЗЗИй
1. Передать переменные в качестве позиционных и/или необязательных
чевых аргументов функции-конструктора. Позиционные аргументы •-ддх*-
ваются в том же порядке, что и отдельные элементы-члены струк—л з
А имена ключевых слов для функции-конструктора должны быть такими
же, как и имена каждой из переменных-членов. Инициализировать же
функцию-член нельзя. Если продолжить пример описания человека, то
можно было бы написать следующее:
myPerson = Person "Carol" 47 68 130
myPerson = Person name:"Carol" age:47 height:68 weight: 130
myPerson = Person "Carol" weight:130
Если затем ввести переменную myPerson. name в окне приемника команд,
то в качестве результата ее вычисления будет получена строка “Carol”.
2. Присвоить значения переменным-членам после создания объекта. Таким
образом, создается пустая переменная, которая затем инициализируется
или заполняется данными. Используя рассматриваемый здесь пример опи-
сания человека, можно было бы написать следующее:
myPerson = Person()
myPerson.name = "Carol"
myPerson.age =47
myPerson.height = 68
myPerson.weight =130
Такой метод инициализации оказывает более продолжительным и чрева-
тым ошибками, чем первый. Однако его можно применять в том случае, ес-
ли данные для объекта в настоящий момент отсутствуют и должны быть
введены в дальнейшем.
3. Присвоить значения переменным-членам в определении самой структуры.
Следовательно, при создании переменной она будет содержать устанавли-
ваемые по умолчанию значения данных членов структуры. Вновь обратив-
шись к примеру описания человека, можно было бы написать следующее:
struct Person
(
name = "Carol",
age = 47,
height = 68,
weight = 130
)
myPerson = PersonO
Если затем ввести переменную myPerson. name в окне приемника команд,
то в качестве результата ее вычисления будет получена строка “Carol”.
Кроме того, устанавливаемые по умолчанию значения можно переопреде-
лить, передав любые данные посредством необязательных ключевых аргу-
ментов. Так, используя последнее определение структуры Person, можно
было бы написать следующее:
myPerson name:"Sue"
Эта переменная myPerson будет иметь значение “Sue” для свойства имени
человека, тогда как значения свойств возраста, высоты и веса останутся без
изменения.
65
Основы MAXScript
Функции-члены структуры
Структуры можно сделать весьма эффективными, если включить функции-
члены в их определение. Такие функции-члены действуют аналогично обычным
функциям, за исключением того что они имеют доступ к данным-членам структуры.
Вновь обратившись к примеру описания человека, можно ввести функцию-член, ко-
торая возвращает значение высоты человека в сантиметрах, а не в дюймах, например:
struct Person
(
name,
age,
height,
weight,
function GetHeightCM =
(
cmheight = height * 2.54
)
)
В данной функции исходная высота умножается на переводной коэффициент,
и затем возвращается новое значение. Используя эту новую функцию, можно на-
писать следующий код:
tnyPerson = Person "Sue" height: 60
cmh = myPerson.GetHeightCM()
Если затем ввести переменную cmh в окне приемника команд и вычислить ее
значение, то в итоге будет получен следующий результат: 152.4.
Вызов функций во время построения структуры
(дополнительный материал)
При рассмотрении процесса построения структуры речь до сих пор шла лишь
о присвоении копий аргументов переменным-членам. А другой код при этом не
инициализировался. Но что если требуется вызвать иной код для манипулирова-
ния данными при создании структуры? Для этого достаточно присвоить функцию
переменной-члену в определении структуры, например:
struct Person
(
name,
age,
height,
weight,
function GetHeightCM =
(
height * 2.54
) ,
cmHeight = GetHeightCM()
)
Обратите внимание на новую переменную-член cmHeight, введенную в струк-
туру. В этой переменной будет храниться значение высоты человека в сантимет-
рах. Любая функция-член, присваиваемая переменной-члену, вызывается при
66
Глава *
построении структуры. Если продолжить рассматриваемый здесь пример описа-
ния человека, то можно было бы написать
myPerson = Person "Carol" height:60,
а затем ввести в окне приемника команд следующую переменную и вычислить ее
значение:
myPerson.cmHeight
В ответ на это, как и ожидалось, будет получено значение 152.4. При построе-
нии структуры можно вызвать не одну, а несколько функций. Например, в струк-
туру можно ввести переменную-член, которая содержит вес человека в килограм-
мах, а не в фунтах:
struct Person
(
name,
age,
height,
weight,
function GetHeightCM =
(
height * 2.54
) ,
function GetWeightKG =
(
weight * 2.2
) ,
cmHeight = GetHeightCM(),
kgWeight = GetWeightKG()
)
Вызов функций во время создания структуры является весьма эффективным
средством MAXScript.
Строки
Строковые переменные содержат буквенно-цифровые символы или текст, на-
пример “Hello”, “MAX4U” или “Введите ваше имя”. Строки представляют собой ли-
теральные значения, которые могут использоваться во всплывающих сообщениях
или при указании пути к файлу. Строки присваиваются строковым переменным
с помощью кавычек. Если не снабдить строку кавычками, это приведет к ошибке.
В MAXScript предоставляется целый ряд операций, которые можно выполнять
над строками.
Сцепление
Сцепление означает объединение двух строк с помощью знака “плюс” (+). Это
аналогично сложению двух строк для получения третьей:
textl = "MAXScript is"
text2 = " fun!"
text3 = textl + text2
В приведенном выше примере переменная texts будет иметь значение
“MAXScript is fun!” (MAXScript — интересный язык программирования!). Обра-
67
Основы MAXScript
тите внимание на пробел в начале строки text2, который введен для правильного
чтения строки. В строке пробел считается отдельным символом.
Для просмотра строки служит функция messageBox:
messagebox text3
На приведенном ниже рисунке показан результат выполнения представленного
выше сценария. В окне приемника команд выводятся результаты присваивания зна-
чений строковым переменным после выполнения каждой строки данного сценария.
Поиск содержимого строки
Функция findstring осуществляет поиск первого экземпляра подстроки в бо-
лее крупной строке, например:
test = "String example"
location = findString test "ex"
В приемнике команд возвращается значение 8. указывающее на то, что под-
строка "ех" начинается с восьмого символа строки test. Если искомая подстрока
отсутствует, в приемнике команд возвращается сообщение undefined.
Замена
Эта операция осуществляет замену одной строки другой. Она реализуется
с помощью функции replace следующим образом:
test = "This is a string"
test2 = "yet another"
test3 = replace test 9 1 test2
messagebox test3
Первым аргументом функции replace является строка, содержащая исход-
ный текст. Второй ее аргумент указывает на место, с которого следует заменять
строку. Третий аргумент данной функции определяет, сколько символов следует
удалить. Четвертый обозначает вставляемую подстроку. В итоге строка test3 бу-
дет иметь следующий вид: “This is yet another string” (Это еще одна строка).
Взаимное преобразование чисел и строк
При выполнении файлового ввода-вывода числовые данные в сценарии неред-
ко приходится преобразовывать в текст для последующей записи в текстовый
68
файл. С другой стороны, текст приходится читать из файла и преобраз-: 5ызг~
в числовые данные для последующего использования в сценарии. В подобных
случаях требуется взаимное преобразование числовых и строковых данных
В MAXScript такое преобразование выполняется достаточно просто.
Если попытаться сложить число со строкой, поставив между ними плюс.
MAXScript выдаст ошибку. Прежде чем присоединить число к строке, необходимо
привести числовое значение к строковому типу данных. Это делается с помощью
оператора as string.
Допустим, что требуется сформировать следующую строку:
stringl = "Your customer number is 345"
Если абонентский номер (customer number) представлен целым числом,
данную строку можно сформировать следующим образом:
custNum = 345 - custNum - это целое число
custString = custNum as string - сформировать строку из custNum
stringl = "Your customer code is " + custString
С помощью операторов as integer и as f loat строку можно преобразовать
в целое число или же в число с плавающей точкой соответственно.
Для того чтобы освоить взаимные преобразования строк и чисел, выполните
следующее упражнение.
1. Откройте новое окно редактора сценариев и введите следующий фраг-
мент кода:
s = sphere()
val = s.radius as string
textl = "The sphere's radius is "
text2 = textl + val
messagebox text2
Переменная val содержит значение радиуса сферы в виде строки.
2. Преобразуйте строку в число, введя следующий код:
val = "20.0"
s = sphere()
s.radius = val as float
Таким образом, строка “20.0” преобразуется в число с плавающей точкой,
которое затем присваивается радиусу сферы.
69
Основы MAXScript
Создание и выполнение сценариев
Итак, освоив многие рассмотренные выше аспекты процесса построения сце-
нариев, вы можете воспользоваться полученными знаниями для создания закон-
ченного сценария. При этом вы научитесь выполнять сценарий из разных частей
пользовательского интерфейса 3ds Мах.
В приведенных ниже упражнениях вам предстоит создать сценарий для распо-
ложения объектов столбиком и последующего изменения цвета их каркаса для
формирования градиента от низа до верха столбика.
В самом общем виде данный сценарий можно представить следующим образом.
• Ввести все находящиеся на сцене объекты в совокупность.
• Разместить первый объект из совокупности в точке с координатами [0,0,0].
• Получить высоту данного объекта и разместить второй объект в точке с ко-
ординатами [0,0,высота первого объекта].
• Получить высоту второго объекта и разместить его в точке с координатами
[0,0,высота второго объекта].
И так далее. Нетрудно заметить, что координата Z положения объектов может
быть рассчитана в цикле.
Для создания сценария PileUp (Складывание столбиком) выполните сле-
дующее упражнение.
1. Откройте новое окно редактора MAXScript Editor.
2. Введите в окне редактора сценариев следующие строки:
- - MyPileUp.ms
- - Сценарий для складывания примитивов столбиком по
- - параметру их высоты
Эти строки содержат комментарии, определяющие назначение данного
Сценария. Вы можете дополнить их своим именем, датой создания сценария
и прочими подробностями, которые вы сочтете нужным привести.
Данный Сценарий будет манипулировать находящимися на сцене объекта-
ми, поэтому сначала необходимо создать совокупность этих объектов.
3. Введите в окне редактора сценариев следующую строку кода:
coll = $* -- Ввести все объекты в совокупность coll
Прежде чем организовывать цикл для поочередного обращения ко всем объ-
ектам, необходимо создать переменную для хранения координаты Z положе-
ния следующего в цикле объекта. Координата Z положения первого объекта
равна 0, поэтому данная переменная исходно устанавливается равной нулю.
Введите в сценарий следующую строку кода:
zNextObject = 0 -- Переменная для хранения координаты Z
-- положения следующего объекта
4. Организуйте цикл для складывания объектов столбиком:
for i in coll do
(
70
Глава
i.pos = [0,0,zNextObject] - Задать координату Z положения объектг.
zNextObject = zNextObject + i.height - Добавить высоту объекта
)
5. Используя доступные средства пользовательского интерфейса 3ds Мах.
создайте ряд примитивов на сцене. Это должны быть примитивы, имеющие
параметр высоты (в частности, параллелепипеды, цилиндры, конусы, кап-
сулы и т.д.). Высота каждого из них должна быть представлена положи-
тельным числом.
6. Нажмите комбинацию клавиш <Ctrl+E>, чтобы выполнить введенный
сценарий.
Объекты складываются столбиком.
7. Сохраните вновь созданный сценарий в файле MyPileUp .ms.
Работа с выражениями
Дальнейшие шаги по совершенствованию сценария необходимо тщательно
продумать. При написании сценариев нередко оказывается полезным набросать
на бумаге предполагаемые действия, в том числе математические операции.
В данном случае это не требуется, но при создании собственных сценариев такой
подход может вам пригодиться.
71
Основы MAXScript
Теперь вам предстоит дополнить сценарий операциями изменения цвета кар-
каса объектов для формирования градиента от низа до верха столбика. В данном
случае цвет каркаса должен изменяться снизу вверх от красного до желтого.
Для выбора красного и желтого цветов потребуются следующие значения RGB.
• Красный цвет: [255,0,0]
• Желтый цвет: [255,255,0]
Значение второй составляющей цвета (зеленой) должно изменяться от 0 до
255 в течение всего цикла изменения цвета каркаса.
Допустим, что на сцене находятся пять объектов. В таком случае зеленая со-
ставляющая цвета каркаса должна изменяться следующим образом.
• Объект 1:1/5 * 255 = 51
• Объект 2: 2/5 *255= 102
• Объект 3:3/5 * 255 = 153
• Объект 4:4/5 * 255 = 204
• Объект 5:5/5 * 255 = 255
Итак, зеленая составляющая цвета каркаса первого объекта будет иметь значе-
ние 51. Но, если она должна иметь нулевое значение, соответствующий дробный
множитель должен изменяться не от 1/5 до 5/5, а от 0/4 до 4/4.
• Объект 1:0/4 * 255 = 0
• Объект 2:1/4 * 255 = 63.75
• Объект 3: 2/4 * 255 = 127.5
• Объект 4:3/4 * 255 = 191.25
• Объект 5:4/4 * 255 = 255
В данном случае числитель дроби (т.е. делимое число) представляет собой но-
мер объекта, уменьшающийся на единицу (-1), а знаменатель дроби (т.е. число, на
которое делят) остается без изменения и равен числу объектов минус один.
Изменение цвета каркаса объектов в цикле
В следующем упражнении вам предстоит ввести в сценарий код для изменения
цвета каркаса объектов в цикле описанным выше образом.
1. Прежде всего, нужно получить знаменатель дроби, который равен числу
находящихся на сцене объектов минус один. Для этого введите после стро-
ки кода coll = $* следующую строку:
bottomFraction = coll.count - 1 -- Получить знаменатель
Но дело в том, что для определения числителя дроби нельзя использовать
индекс совокупности объектов. В качестве выхода из этой ситуации можно
изменить способ организации цикла.
72
Глава 1
2. Замените строку в цикле for следующей строкой кода:
for i = 1 to coll.count do
В этой строке значение переменной i заменено индексом объекта вместо
самого объекта.
3. Внесите изменения в следующей строке:
coll [i] .pos = [0,0, zNextObject]
Необходимо также внести изменения в той строке, в которой определяется
координата Z положения следующего объекта:
zNextObject = zNextObject + coll[i].height
А теперь следует ввести две строки кода, в которых задается цвет каркаса.
4. Введите следующие строки кода непосредственно перед закрывающей цикл
круглой скобкой:
topFraction = i - 1
greenvalue = (topFraction / bottomFraction) * 255
coll[i].wirecolor = [255,greenvalue,0]
5. Переместите немного объекты в видовых окнах, а затем выполните данный
сценарий.
Объекты складываются в столбик, но имеют не совсем верные цвета: все
объекты, кроме верхнего, оказываются красными.
73
Основы MAXScript
6. Проанализируйте код, используемый для расчета зеленой составляющей цве-
та каркаса, и определите причину появления подобной ошибки в сценарии:
greenValue = (topFraction I bottomFraction) * 255
Обе переменные, topFraction и bottomFraction, имеют целые значения.
В результате деления целых чисел в MAXScript всегда получается целое чис-
ло, а дробная часть, если таковая образуется при делении, отбрасывается.
Следовательно, если значение переменной topFraction равно 1, при де-
лении получается следующий результат:
1/4 = О
На самом деле он должен быть равен 0,2 5. Но поскольку дробная часть
при делении целых чисел отбрасывается, результат остается равным 0
вплоть до значения 4 переменной topFraction для последнего объекта
в данной совокупности.
7. Для устранения данной ошибки достаточно привести переменную
topFraction или bottomFraction к типу чисел с плавающей точкой.
Для этого внесите следующие изменения в выражение присваивания зна-
чения переменной bottomFraction:
bottomFraction = coll.count - 1.0
Благодаря использованию в данном выражении числа 1.0 вместо целого
числа 1 значение, сохраняемое в переменной bottomFraction, автомати-
чески приводится к типу чисел с плавающей точкой. Теперь при делении
значения переменной topFraction на это числовое значение будет также
получаться число с плавающей точкой.
Примечание. Для достижения того же результата можно было бы изменить
на 1. о число в выражении topFraction = i - 1.
8. Выполните данный сценарий.
Теперь объекты получают цвета градиента от красного внизу до желтого
вверху столбика.
9. Сохраните видоизмененный сценарий в файле MyPi leUp. ms.
Завершенный вариант данного сценария можно найти в файле \chapterl\
pi le_up. ms на прилагаемом к этой книге CD-ROM.
Совет. Данный сценарий можно немного усовершенствовать, организовав
массив obj ects. Он представляет собой совокупность всех объектов, авто-
матически создаваемых в 3ds Мах. Вместо того чтобы использовать массив
coll для управления циклом for, замените соответствующую строку
в данном цикле следующей строкой кода:
for i = 1 to objects.count do
После этого следует заменить все ссылки на массив coll ссылками на мас-
сив objects и удалить строку coll = $*. В итоге получится такой же
результат, как при выполнении сценария, созданного в предыдущем уп-
ражнении. Данный вариант сценария можно найти в файле \chapterl\
pi le_up_2 . ms на прилагаемом к этой книге CD-ROM.
74
Глава 1
Заключение
В этой главе вы научились пользоваться MAXScript для создания простых
сценариев. В частности, вы использовали приемник команд MAXScript Listener
для объявления переменных и присваивания им значений, а также для определе-
ния и применения функций. Кроме того, вы ознакомились с основными понятия-
ми программирования, включая условные операторы, циклические конструкции,
область действия, передачу параметров функции, массивы и структуры. И нако-
нец вы создали рабочий сценарий, видоизменяющий свойства объектов.
75
Построение пользовательских
интерфейсов
Глава 2
В этой главе вы научитесь строить
пользовательские интерфейсы на примере
создания свитка и его заполнения
элементами управления пользовательского
интерфейса. Построенный интерфейс
вам предстоит дополнить обработчиками
событий для вызова отдельных частей
сценария с помощью элементов управления
пользовательского интерфейса.
Глава 2
Задание
После изучения этой главы вы должны уметь следующее.
• Создавать перемещаемые диалоговые окна или свитки утилиты
• Вводить в свиток элементы управления пользовательского интерфейса
• Организовывать реакцию сценария на пользовательский ввод
Введение
В MAXScript имеются средства для создания специализированных пользова-
тельских интерфейсов, которые формируются при выполнении сценария. Пользо-
вательский ввод можно получить из свитков и диалоговых окон, а затем выполнить
на его основании соответствующие команды. В этой главе описывается порядок соз-
дания элементов пользовательского интерфейса, связанных со сценарием.
Построение пользовательских
интерфейсов
До сих пор вам приходилось писать сценарии, которые действуют без пользо-
вательского ввода. Для организации ввода данных и их последующего использо-
вания в сценарии последний может быть дополнен элементами пользовательского
интерфейса.
Типы пользовательских интерфейсов
В сценарии могут быть сформированы два типа интерфейсов.
• Свитки на панели Utilities
• Перемещаемое диалоговое окно
Исключение составляет сценарный подключаемый модуль, представляющий
собой специальный сценарий, способный формировать свитки в других частях
пользовательского интерфейса 3ds Мах.
Виды сценариев
Существует несколько видов сценариев. Их можно приближенно разделить по
типу пользовательского интерфейса, который они формируют.
• Сценарная функция — состоит из одной или более функций, но не форми-
рует пользовательский интерфейс. После выполнения сценария такие
функции можно вызывать из приемника команд или другого сценария.
77
Построение пользовательских интерфейсов
• Сценарная утилита — это сценарий, определяющий один или более свитков
на панели Utilities в качестве элементов своего пользовательского интерфейса.
• Сценарный подключаемый модуль — это специальный вид сценария, соз-
дающий новые инструменты 3ds Мах или расширяющий уже существую-
щие. Во всех остальных видах сценариев применяется код для выполнения
действий, которые уже доступны из пользовательского интерфейса 3ds Мах,
например создание параллелепипедов и сфер, назначение контроллеров
и конфигурирование видовых окон. Сценарный подключаемый модуль по-
зволяет создавать новые геометрические объекты, карты, модификаторы
и прочие элементы оформления сцены. Пользовательский интерфейс ново-
го инструмента появляется в соответствующей части интерфейса 3ds Мах.
Например, новая карта появляется в окне Material/Map Browser, тогда как
новый модификатор — в списке Modifier List.
• Общие сценарии — любые сценарии, которые могут быть отнесены к кате-
гории общих. Такие сценарии позволяют сформировать перемещаемое
диалоговое окно в качестве элемента пользовательского интерфейса либо
вообще отказаться от интерфейса. Например, можно написать сценарий,
создающий ряд сфер аналогично сценариям, приведенным в главе 1. Такой
сценарий не будет формировать пользовательский интерфейс.
Макросценарии
Достаточно ввести несколько строк кода в начале общего сценария, чтобы пре-
вратить его в исполнительный элемент в диалоговом окне Customize User Interface
(Специальная настройка пользовательского интерфейса). Такой элемент можно
ввести на панели инструментов или в другом месте пользовательского интерфей-
са, чтобы вызывать оттуда сценарий. А кроме того, сценарий можно вызвать или
выполнить с помощью назначенного клавиатурного эквивалента команды.
Подобный сценарий называется MacroScript (т.е. макросценарий). Он позволя-
ет сформировать пользовательский интерфейс и определить его функции, хотя
это и не обязательно. Это просто общий сценарий с командой, которая превращает
его в исполнительный элемент.
Название MacroScript происходит от основного назначения макросценария,
который призван помочь пользователям, не знакомым с MAXScript, создавать
сценарии из кода, отображаемого в приемнике команд. Так, неоднократно повто-
ряющуюся последовательность команд можно выполнить вручную лишь один раз,
чтобы вывести ее в зарегистрированном средствами Macro Recorder виде в верх-
нем (розовом) подокне приемника команд. А затем зарегистрированную последо-
вательность команд можно скопировать и вставить в окне редактора MAXScript
Editor, выполнить полученный в итоге сценарий и далее работать с его исполни-
тельным элементом в диалоговом окне Customize User Interface.
Для превращения любого общего сценария в MacroScript достаточно сделать
одно из двух.
Ввести нужный код в начале сценария, чтобы обозначить его как макросце-
нарий, а затем выполнить сценарий.
78
Глава 2
• Выделить содержимое сценария в редакторе MAXScript Editor (или в лю-
бом другом месте 3ds Мах, где отображается код, например в приемнике
команд). При этом автоматически формируется внутреннее имя макроспе-
нария, например Macrol, Масго2 и т.д.
Файлы сценариев
Как правило, сценарий сохраняется в файле с расширением .ms. Для хранения
сценариев в организованном порядке макросценарии следует сохранять в файлах
с расширением .тсг. Формально оба вида сценариев можно сохранять в файле
с любым из двух указанных расширений, и при этом сценарий будет выполняться.
Однако правильно выбранное расширение указывает на конкретный вид исполь-
зуемого сценария.
Сценарий можно выполнять автоматически при запуске 3ds Мах. Для органи-
зации такого режима работы сценария достаточно поместить сценарий в любую из
следующих папок.
• 3dsmax/stdplugs/stdscripts
• 3dstnax/plugins или любую подпапку внутри папки с подключаемыми
модулями
• 3dsmax/ui/macroscripts или в любую другую подпапку
• 3dsmax/scripts/startup
При запуске 3ds Мах программа запуска осуществляет поиск файлов с расши-
рениями .ms, .tncr и .tnse в папках, перечисленных в указанном выше порядке.
(Расширение .tnse используется для шифрованных файлов сценариев. Более
подробные сведения по данному вопросу приведены в разделе “Encrypting Script
Files” (Шифрование файлов сценариев) справочного руководства по MAXScript.)
Свитки
Свитки составляют саму основу любого пользовательского интерфейса, фор-
мируемого средствами MAXScript. Прежде чем создавать какие-либо другие эле-
менты пользовательского интерфейса, в том числе флажки и счетчики, необходи-
мо сформировать хотя бы один свиток, в котором они будут находиться. Под
термином “свиток” в MAXScript подразумевается любой свиток, известный вам из
пользовательского интерфейса 3ds Мах, например панелей команд или диалого-
вых окон. Но, если требуется, свиток может быть отображен средствами
MAXScript, как отдельное диалоговое окно.
Правда, создать специальный свиток средствами MAXScript и заполнить его
элементами пользовательского интерфейса не составляет большого труда.
Для создания свитка используется следующая конструкция:
rollout <переменная> "Имя свитка"
(
79
Построение пользовательских интерфейсов
< Элементы пользовательского интерфейса, в том числе
флажки, кнопки н счетчики >
)
В переменной хранится внутреннее имя свитка, используемое в сценарии для
обращения к свитку. А строка “Имя свитка” определяет название, появляющееся
в заголовке свитка.
Код, находящийся в круглых скобках, называется выражением свитка. Внутри
выражения свитка определяются все элементы пользовательского интерфейса
и их функции.
Для начала в следующем упражнении будет создан самый простой свиток.
1. Откройте новое окно редактора MAXScript Editor и введите следующий
фрагмент кода:
rollout a "Something New"
(
spinner b "Enter a value: "
button c "Click Me"
)
В этом коде определяется свиток, обозначенный как “Something New”
(Нечто новое). Переменная а содержит внутреннюю ссылку на свиток, ко-
торую можно использовать в остальных частях сценария для обращения
к данному свитку.
Команды spinner и button создают соответственно счетчик и кнопку с мет-
ками. указанными в кавычках. А переменные b и с содержат внутренние
ссылки на счетчик и кнопку.
2. Выполните созданный сценарий.
При этом ничего особенного не произойдет, поскольку в данном сценарии
было задано лишь местоположение и внешний вид свитка.
3. Введите в конце сценария следующую строку кода:
createDialog а 20 50
4. Вычислите код сценария.
5. Свиток появится в виде диалогового окна Something New шириной 2 о и вы-
сотой 50 единиц. Он содержит два элемента пользовательского интерфейса:
счетчик и кнопку.
По команде createDialog создается новое перемещаемое диалоговое ок-
но с использованием команд создания свитка. В связи с тем, что а — это
внутреннее имя свитка, команда createDialog а обращается к определе-
нию свитка, сделанному ранее в данном сценарии.
Если изменить значение в счетчике и щелкнуть на кнопке, то ничего не
произойдет. Для того чтобы что-то произошло при взаимодействии пользо-
вателя с элементами интерфейса в данном диалоговом окне, в сценарий не-
обходимо ввести обработчики событий.
80
Глава 2
Для ввода обработчиков событий в сценарий выполните следующее упражнение
1. Закройте диалоговое окно Something New. Введите в окне редактора
MAXScript Editor следующий код после строки с определением счетчика:
on с pressed do
(
d = b.value
sphere pos.-[d,0,0]
)
Вычислите код сценария. Диалоговое окно появится, как и прежде.
2. Измените значение в счетчике и щелкните на кнопке. После каждого такого
щелчка создается сфера, расположенная по оси X так, как указано в счетчи-
ке. Рассмотрим более подробно, каким образом действует обработчик собы-
тий для кнопки с, указанный в строке кода on с pressed do. В этой
строке сценарию предписывается выполнить код в круглых скобках, когда
осуществляется щелчок на кнопке с.
Счетчик хранится в переменной Ь. А значение, введенное в его поле, может
быть получено с помощью свойства .value данной переменной. Следова-
тельно, b. value — это значение, введенное в поле счетчика Ь.
3. После щелчка на кнопке с значение из счетчика присваивается в сценарии
переменной d, а затем создается сфера, располагаемая по оси X так, как ука-
зано в счетчике.
Для того чтобы преобразовать данный сценарий в макросценарий, выполните
следующее упражнение. В этом упражнении вам предстоит перетащить исходный
код сценария на выбранную панель инструментов, чтобы организовать доступ
к нему на панели инструментов.
1. Закройте диалоговое окно Something New.
2. Выделите весь исходный код сценария в окне редактора MAXScript Editor,
нажав комбинацию клавиш <Ctrl+A>.
3. Перетащите выделенный текст на пустой участок между двумя кнопками
на основной панели инструментов. Как только курсор примет вид стрелки
со знаком “плюс”, отпустите кнопку мыши.
На основной панели инструментов появится новая кнопка. Кнопки сценариев
похожи на миниатюрные окна MAXScript Editor или MAXScript Listener.
4. Щелкните на новой кнопке.
Откроется диалоговое окно Something New, в котором можно создать сфе-
ру описанным выше образом.
5. Закройте диалоговое окно Something New.
6. Щелкните правой кнопкой мыши на кнопке New и выберите команду Edit
Macro Script (Править макросценарий).
Откроется новое окно редактора сценариев с новым вариантом создаваемо-
го вами сценария. В начале этого сценария введен ряд строк для его преоб-
81
Построение пользовательских интерфейсов
разования в макросценарий. Этот новый вариант сценария сохранен в фай-
ле DragAndDrop-Macro# .mcr, где # — порядковый номер текущей версии
сценария.
Примечание. Создание нового варианта сценария не оказывает никакого
влияния на его исходный вариант, который по-прежнему находится
в собственном окне редактора MAXScript Editor.
7. Закройте окно редактора MAXScript Editor с новым вариантом сценария,
который был перенесен на основную панель инструментов.
Созданный в данном упражнении сценарий является общим. Его нетрудно
преобразовать в утилиту, изменив лишь несколько строк кода.
Для преобразования сценария в утилиту выполните следующее упражнение.
1. Закройте диалоговое окно Something New.
2. Замените слово rollout словом utility в первой строке кода сценария.
3. Удалите последнюю строку кода с командой createDialog отображения
перемещаемого диалогового окна.
4. Вычислите код сценария.
5. Выберите кнопку MAXScript на панели Utilities. Затем выберите вариант
Something New из раскрывающегося списка Utilities в свитке MAXScript.
На панели Utilities появится свиток Something New, в котором можно вос-
пользоваться счетчиком и кнопкой таким же образом, как и ранее в пере-
мещаемом диалоговом окне.
Ввод элементов пользовательского интерфейса
Ранее в этой главе было показано, каким образом элементы пользовательского
интерфейса вводятся в свиток. Существует еще немало средств для ввода меток,
флажков, кнопок-переключателей и других элементов интерфейса. При этом
можно контролировать расположение элементов интерфейса справа, слева либо
по центру диалогового окна или в единственной строке свитка. Ниже перечислены
наиболее часто используемые элементы пользовательского интерфейса в том ви-
де, в каком они называются и применяются в сценариях MAXScript.
• Label (Метка) — статический элемент управления, предназначенный для
отображения текста. Пользователь не может изменить текст метки, однако
это можно сделать в сценарии.
82
Глава 2
Checkbox (Флажок) — элемент, который может быть включен или выклю-
чен пользователем.
Button (Кнопка) — элемент, который утапливается при нажатии и припод-
нимается обратно при отпускании.
Checkbutton (Фиксирующая кнопка) — элемент, который утапливается
при первоначальном нажатии и приподнимается при повторном нажатии.
Pickbutton (Кнопка выбора) — элемент выбора объектов на сцене.
Radiobuttons (Кнопки-переключатели) — ряд переключателей в свитке.
Одновременно можно выбрать лить один из них.
Spinner (Счетчик) — элемент, предназначенный для ввода числового зна-
чения в свитке. Он состоит из поля ввода и стрелок. У счетчика имеются
два параметра: диапазон значений и устанавливаемое по умолчанию значение.
83
Построение пользовательских интерфейсов
• Slider (Ползунковый регулятор) — альтернативный счетчику элемент.
Пользователь перемещает ползунок в ту или иную сторону. У ползунково-
го регулятора те же самые параметры: диапазон значений и устанавливае-
мое по умолчанию значение.
• Edittext (Поле редактирования текста) — текстовое поле, в котором
пользователь вводит и редактирует текст.
| - С*Т'йГГ
ЕЛ Тей |
• Listbox (Списковое окно) — список элементов, предоставляемых пользо-
вателю на выбор. Пользователь может прокручивать список для выбора
нужного элемента из списка.
• Combobox (Комбинированное окно) — комбинация списка выбора и поля
редактирования текста. Список всегда отображается в свитке полностью,
хотя длинные списки могут быть снабжены полосами прокрутки. В распо-
ложенном вверху поле редактирования отображается выделенный в данный
момент элемент списка.
84
Глава 2
• Dropdownlist (Раскрывающийся список) — аналогичен комбинирован-
ному окну, но в данном случае список раскрывается, когда пользователь
щелкает на кнопке со стрелкой вниз. Следует иметь в виду, что текст в рас-
крывающемся списке не вводится.
• Colorpicker (Селектор цвета) — элемент, предназначенный для отобра-
жения диалогового окна Color Selector (Селектор цвета). В свитке он пред-
ставлен образцом цвета. Пользователь может щелкнуть на образце цвета,
чтобы открыть диалоговое окно Color Selector.
• Progressbar (Индикатор выполнения) — элемент, предназначенный для
отображения хода действия или выполнения процесса.
• Mapbutton (Кнопка карты) и Materialbutton (Кнопка материала) —
элементы, предназначенные для отображения карт и материалов в диалого-
вом окне Material/Map Browser.
• Bitmap (Растр) — элемент, предназначенный для отображения растрового
изображения в свитке.
Для каждого элемента интерфейса, указываемого в выражении свитка, созда-
ется соответствующий объект со своими свойствами. Доступ к этим свойствам
осуществляется по имени данного элемента интерфейса. Имеются свойства, кото-
рые являются общими для всех элементов интерфейса (например, свойство поло-
жения), а также свойства, характерные только для элемента конкретного типа.
При создании в 3ds Мах элементы интерфейса размещаются на панели со
стандартными параметрами расположения. Если требуется другая схема их рас-
положения, конструктору каждого такого элемента можно передать ряд следую-
щих параметров.
85
Построение пользовательских интерфейсов
• align — указывается следующим образом: #left, #right или #center.
Знак “решетки” должен быть указан обязательно. Данный параметр опре-
деляет выравнивание элемента интерфейса по левому краю, по правому
краю или же по центру.
• pos — определяет положение элемента интерфейса в конкретной точке с ко-
ординатами х и у, указываемыми в пикселях. Значение этого параметра ука-
зывается с помощью типа данных Point2 ([х, у] ). Такое положение эле-
мента интерфейса определяется относительно левого верхнего угла свитка.
• width — задает ширину элемента интерфейса в пикселях.
• height — задает высоту элемента интерфейса в пикселях. Для спискового
и комбинированного окон высота задается в зависимости от числа элемен-
тов в списке. Так, для отображения N элементов в списковом окне его высо-
ту следует задать равной N. А для отображения N элементов в комбиниро-
ванном окне его высоту следует задать равной N+2.
• offset — задает смещение относительно устанавливаемого по умолчанию
положения элемента интерфейса. В качестве единиц изменения использу-
ются пиксели, а в качестве типа данных — Point2.
• across — задает положение элементов интерфейса по горизонтали, а не по
вертикали. Применяется к элементу и следующим за ним (N - 1) элемен-
там, где N — число, указываемое после слова across. Этот параметр более
подробно рассматривается в следующем разделе.
Как правило, лучше сначала предоставить 3ds Мах возможность расположить
элементы интерфейса с помощью устанавливаемых по умолчанию параметров,
азатем внести необходимые коррективы в расположение элементов. Текстовые
метки должны быть краткими, чтобы они не выходили за край свитка, а элементы
интерфейса не должны перекрываться.
Обработчики событий
Общая форма обработчика событий имеет следующий вид:
on <имя элемента интерфейса? <имя события? <аргументы? do
(
[выполняемые команды]
)
Ниже приведен перечень типичных событий, используемых в сценариях.
• pressed — вызывается после щелчка на кнопке.
• changed — вызывается при изменении состояния управляющего элемента,
например при установке флажка или правке значения в счетчике.
• picked— вызывается для кнопки выбора, когда пользователь выбирает
элемент в сцене.
86
Г лава 2
• entered — вызывается при вводе числа в поле редактирования счетчик?,
и последующем нажатии клавиши <Enter>.
• selected — вызывается при выборе элемента из списка в списковом или
комбинированном окне.
В версии 3ds Мах 8 событие Rightclick введено для следующих видов кнопок.
• Button
• CheckButton
• MapButton
• MaterialButton
• PickButton
• ImgTag
Многие элементы пользовательского интерфейса были усовершенствованы
в версии 3dsMax 7. Более подробно с перечнем подобных нововведений можно оз-
накомиться, перейдя к подразделу “User Interface Controls” (Элементы управле-
ния пользовательского интерфейса) в разделе “What was New in MAXScript in
3dsMax 8” (Нововведения в MAXScript версии 3dsMax 7) справочного руково-
дства no MAXScript.
Группы в свитке
По мере укрупнения и усложнения утилит возникает потребность сгруппиро-
вать элементы в свитке на панели Utilities. Элементы можно сгруппировать в ло-
гической последовательности, используя выражение группы. Независимо от того,
как и для чего группируются элементы, группирование должно разумно разграни-
чивать функции панели. Группа очерчивается на панели контуром с меткой в ле-
вом верхнем углу. А синтаксис группы следующий:
group "описание группы"
(
«элементы пользовательского интерфейса>
)
Создание рабочего сценария
А теперь вам предстоит написать сценарий для формирования Солнечной
системы на основании пользовательского ввода. Но прежде чем создавать пользо-
вательский интерфейс, необходимо выяснить, что именно должен делать сцена-
рий. В данном случае требуется написать сценарий, выполняющий следующее.
• Для того чтобы начать процесс формирования Солнечной системы, пользо-
ватель должен создать Солнце. В качестве Солнца может служить сфера,
расположенная в точке с координатами [0,0,0]. Пользователь должен задать
радиус сферы.
87
Построение пользовательских интерфейсов
• В версии 3ds Мах 8 введено новое свойство — возможность обрабатывать
для разных типов кнопок пользовательские события, связанные со щелчком
правой кнопкой мыши (см. перечень событий, приведенных в предыдущем
разделе). Для того чтобы воспользоваться этим свойством в сценарии, при-
дется организовать процесс создания сферы в зависимости того, какой
кнопкой мыши (левой или правой) пользователь щелкнет на кнопке созда-
ния Солнца. Так, если пользователь щелкнет левой кнопкой, будет создана
обычная сфера. А если он щелкнет правой кнопкой, будет создана геосфера.
• Как только будет создано Солнце, пользователь может сформировать допол-
няющие его планеты. У него должна быть возможность выбора числа планет.
• Как только пользователь щелкнет на кнопке Create Planets (Создать пла-
неты), в сценарии должны быть созданы планеты произвольного радиуса.
Для каждой планеты вокруг Солнца будет очерчен круг, обозначающий ее
орбиту, причем движение планеты будет ограничено этим кругом с помо-
щью ограничения по линии пути.
• После создания планет пользователь может выделить каждую планету
и изменить ее радиус и орбиту. На основании всей этой информации вы
можете построить такой пользовательский интерфейс, как на приведенном
ниже рисунке.
Создание пользовательского интерфейса
А теперь вы можете приступать к созданию и проверке пользовательского ин-
терфейса. В дальнейшем вам предстоит ввести обработчики событий в этот интер-
фейс для того, чтобы он выполнял конкретные функции.
Для создания пользовательского интерфейса выполните следующее упражнение.
1. Откройте окно редактора MAXScript Editor.
2. Введите в верхней части этого окна следующую строку:
-- SolarSystem.ms
Вы можете дополнить этот комментарий, например, своим именем и датой
создания сценария.
88
Глава 2
3. Введите следующий фрагмент кода:
rollout ssRoll "Solar System"
(
spinner spn_sunRadius "Sun Radius"
button but_createSun "Create Sun"
spinner spn_numPlanets "Number of Planets"
button but_createPlanets "Create Planets"
pickbutton pbt_pickPlanet "Pick Planet"
spinner spn_planetRadius "Planet Radius"
spinner spn_orbitRadius "Orbit Radius"
)
createDialog ssRoll 20 20
Многие программисты пользуются специальными условными обозначе-
ниями элементов пользовательского интерфейса. В приведенной ниже таб-
лице представлены префиксы, используемые для обозначения переменных
по типу элемента пользовательского интерфейса.
Префикс типа элемента Что обозначает
spn_ Счетчик
but_ Кнопка
pbt_ Кнопка выбора
После префикса типа элемента указывается имя переменной, содержащее
текстовую метку данного элемента пользовательского интерфейса, при-
чем первое слово должно быть введено строчными буквами, а все после-
дующие слова должны начинаться с прописной буквы. Так, переменная
для счетчика Sun Radius (Радиус Солнца) должна называться следую-
щим образом: spn_sunRadius.
Вы можете, конечно, выбрать другие условные обозначения в своих сцена-
риях. Главное — быть последовательным в их соблюдении.
4. Вычислите код сценария.
Откроется диалоговое окно с элементами пользовательского интерфейса,
указанными в коде данного сценария.
89
Построение пользовательских интерфейсов
Внешний вид этого диалогового окна можно усовершенствовать, выделив
в отдельную группу элементы пользовательского интерфейса, предназна-
ченные для правки внешнего вида планет.
5. Введите перед кодом первой кнопки выбора следующий фрагмент кода:
group "Planet s"
(
6. Введите закрывающую круглую скобку после кода последнего счетчика.
Код трех последних элементов пользовательского интерфейса должен вы-
глядеть следующим образом:
group "Planets"
(
pickbutton pbt_pickPlanet "Pick Planet"
spinner spn_planetRadius "Planet Radius"
spinner spn_orbitRadius "Orbit Radius"
)
Этот код выделяет три последних элемента пользовательского интерфейса
в отдельную группу.
7. Вычислите код сценария.
Элементы пользовательского интерфейса, предназначенные для правки
внешнего вида планет, теперь находятся в отдельной группе.
Для улучшения внешнего вида пользовательского интерфейса можно также
ввести пробел после метки каждого элемента, т.е. перед завершающими ка-
вычками.
8. Внесите изменения в строку кода каждого счетчика, содержащую метку,
чтобы ввести пробел после метки счетчика:
rollout ssRoll "Solar System"
(
spinner spn_sunRadius "Sun Radius "
button but_createSun "Create Sun"
spinner spn__numPlanets "Number of Planets "
button but_createPlanets "Create Planets"
pickbutton pbt_pickPlanet "Pick Planet"
spinner spn_planetRadius "Planet Radius "
spinner spn_orbitRadius "Orbit Radius "
90
Глава 2
group "Planets"
(
pickbutton pbt_pickPlanet "Pick Planet"
spinner spn_planetRadius "Planet Radius "
spinner spn_orbitRadius "Orbit Radius "
)
)
9. Вычислите код сценария.
Между меткой каждого счетчика и самим счетчиком должен быть пробел.
10. Сохраните вновь созданный сценарий в файле mySolarSystem. ms.
Примечание. Сохранять сценарий без лишних напоминаний полезно после
очередного этапа работы над ним — это общепринятая практика программирования.
Однако, начиная с версии 3ds Мах 8, при аварийном завершении работы 3ds Мах,
вызванном сбоями в MAXScript, должно появиться диалоговое окно, в котором
предлагается сохранить все открытые сценарии.
Ввод обработчиков событий
В следующем упражнении вам предстоит ввести обработчики событий для
создания Солнца и планет.
1. Введите следующий фрагмент кода перед последней закрывающей скобкой
в выражении свитка:
on but_createSun pressed do
(
)
on but_createSun rightclick do
(
)
В этом коде создаются два обработчика событий для кнопки Create Sun.
Если щелкнуть на ней левой кнопкой мыши, в сценарии должна быть соз-
дана сфера радиусом, определяемым параметром Sun Radius. Если же
щелкнуть на ней правой кнопкой мыши, в сценарии на этот раз должна
быть создана геосфера.
91
Построение пользовательских интерфейсов
2. Введите внутри обработчика событий pressed следующую строку кода:
sun = sphere radius:spn_sunRadius.value
Теперь данный обработчик событий должен иметь следующий вид:
on but_createSun pressed do
(
sun = sphere radius:spn_sunRadius.value
)
Значение переменной spn_sunRadius хранится в ее свойстве .value.
Выражение spn_sunRadius. value возвращает любое значение, находя-
щееся в поле редактирования счетчика Sun Radius в момент нажатия кноп-
ки Create Sun.
3. Введите внутри обработчика событий rightclick следующий фрагмент кода:
on but_createSun rightclick do
(
sun = geosphere radius:spn_sunRadius.value
)
4. Вычислите код сценария.
5. Измените значение параметра Sun Radius в открывшемся диалоговом окне,
введя в его поле число, большее нуля, а затем щелкните левой кнопкой мы-
ши на кнопке Create Sun. В сцене будет создана сфера с указанным радиу-
сом. Переместите сферу по сцене и попробуйте щелкнуть правой кнопкой
мыши, чтобы создать геосферу. Если сценарий не позволяет этого сделать,
проанализируйте его код в приемнике команд, выявите ошибку и исправьте
ее, прежде чем продолжить работу над данным сценарием.
6. Создайте обработчик событий для формирования планет и их орбит. Для
этого введите следующий фрагмент кода после только что введенного кода
обработчика событий:
on but_createPlanets pressed do
(
for i = 1 to spn_numPlanets.value do
(
- - Создание планеты
planet = sphere() -- Создать планету
- - Установить радиус планеты в виде случайного числа
- - в пределах от 10 до 30
planet.radius = random 10.0 30.0
- - Создать окружность для орбиты планеты
orbit = circle radius:(i*10)
- - Поместить планету на орбиту
planet.pos.controller = Path_Constraint()
planet.pos.controller.path = orbit
- - Повернуть орбиту, чтобы она заняла произвольное
- - исходное положение
orbit.rotation.z_rotation = random 0.0 360.0
)
)
92
Глаза 2
Этот обработчик событий создает ряд указанных планет с произвольной ор-
битой в виде окружности и ограничивает их движение по кругу с помощью
ограничения по линии пути. И наконец, он поворачивает орбиту каждой пла-
неты на случайную величину, чтобы исходное положение орбит было разным.
7. Вычислите код сценария.
Установите значение 3 в поле счетчика Number of Planets (Число планет)
и щелкните на кнопке Create Planets.
Вокруг Солнца будут созданы две планеты со своими орбитами.
Точная настройка пользовательского интерфейса
В поле счетчика Number of Planets отображается число с плавающей точкой в
пределах от 0 до 10. Это стандартный диапазон значений для всех счетчиков. Од-
нако для данного счетчика больше подходит диапазон целых чисел от 1 до 10.
1. Введите следующий код в конце строки spinner spn_numPlanets:
type:#integer range:[1,10,3]
Теперь эта строка кода должна иметь следующий вид:
spinner spn_numPlanets "Number of Planets" type:#integer
range: [1,10,3]
Данная строка кода предписывает отображать в счетчике Number of Planets
только целые числа в пределах от 1 до 10, причем по умолчанию отобража-
ется значение 3.
2. Вычислите код сценария.
3. Измените значение в счетчике Number of Planets. По умолчанию в этом
счетчике отображается значение 3, которое может изменяться лишь от 1 до 10.
В версии 3ds Мах 7 появилось новое свойство элемента управления
pickButton, позволяющее автоматически отображать имя выбранного
объекта в надписи кнопки выбора. Ранее это приходилось делать вручную.
93
Построение пользовательских интерфейсов
Итак, дополните строки кода для отображения кнопки выбора следующим
ключевым параметром:
autoDisplay: true
Автоматическое удаление диалоговых окон
В данный момент открыто несколько диалоговых окон Solar System (Солнечная
система). При каждом вычислении кода сценария появляется новое окно данного
типа, а старые не закрываются. Для того чтобы закрыть автоматически любые от-
крытые ранее варианты диалогового окна, когда приходится в очередной раз вычис-
лять код сценария, достаточно ввести в его начале следующий код:
destroyDialog ssRoll
Но при вычислении этой строки кода может возникнуть ошибка, если откры-
тое диалоговое окно ssRoll отсутствует. Следовательно, диалоговое окно
ssRoll нужно удалить в сценарии, если оно существует, и ничего не предприни-
мать, если оно отсутствует.
Для этого в начале сценария можно ввести следующий фрагмент кода:
if ((ssRoll != undefined) and (ssRoll.isdisplayed)) do
(destroyDialog ssRoll)
В этом коде сначала проверяется тот факт, что диалоговое окно ssRoll опре-
делено. Если затем обнаруживается, что данное окно отображается, оно удаляется
(т.е. закрывается). Следует иметь в виду, что для удаления диалогового окна
должны выполняться оба условия, т.е. результат их проверки должен быть истин-
ным (true). Если же не выполняется хотя бы одно из этих условий, т.е. результат
его проверки оказывается ложным (false), ничего не происходит.
Примечание. Приведенный выше условный оператор является относительно
новым и применяется благодаря внедрению в версии 3ds Мах 7 свойства свитков,
называемого . isdisplayed. Данное свойство возвращает логическое
значение true, если свиток отображается (или виден); в противном случае оно
возвращает логическое значение false. В предыдущем издании книги для
достижения того же результата в сценарии применялось следующее действие:
try (destroyDialog ssRoll) catch()
Для автоматического удаления диалоговых окон выполните следующее уп-
ражнение.
1. Закройте все варианты диалогового окна Solar System.
2. Введите в сценарии следующий фрагмент кода перед началом выражения
свитка:
if ((ssRoll != undefined) and (ssRoll.isdisplayed)) do
(destroyDialog ssRoll)
3. Вычислите код сценария.
Как видите, остается лишь один вариант данного диалогового окна.
Теперь код сценария должен иметь следующий вид:
94
Глава 2
-- SolarSystem.ms
if ((ssRoll != undefined) and (ssRoll.isdisplayed)) do
(destroyDialog ssRoll)
rollout ssRoll "Solar System"
(
spinner spn_sunRadius "Sun Radius"
button but_createSun "Create Sun"
spinner spn_NumPlanets "Number of Planets" type:#integer range: [1,10,3]
button but_createPlanets "Create Planets"
group "Planets"
(
pickbutton pbt_pickPlanet "Pick Planet" autoDisplay: true
spinner spn_planetRadius "Planet Radius"
spinner spn_orbitRadius "Orbit Radius"
)
on but_createSun pressed do
(
sun = sphere radius:spn_sunRadius.value
)
on but_createPlanets pressed do
(
for i = 1 to spn_numPlanets.value do
(
- - Создание планеты
planet = sphere() -- Создать планету
- - Установить радиус планеты в виде случайного числа
- - в пределах от 10 до 30
planet.radius = random 10.0 30.0
- - Создать окружность для орбиты планеты
orbit = circle radius:(i*10)
- - Поместить планету на орбиту
planet.pos.controller = Path_Constraint()
planet.pos.controller.path = orbit
- - Повернуть орбиту, чтобы она заняла произвольное
- - исходное положение
orbit.rotation.z_rotation = random 0.0 360.0
)
)
createDialog ssRoll 20 20
Ввод событий для кнопки выбора
Организуйте событие для кнопки Pick Planets, выполнив следующее упражнение.
1. Введите следующий код непосредственно перед последней круглой скобкой
в выражении свитка:
on pbt_pickPlanet picked aPlanet do
(
-- Установить радиус выбранной планеты в счетчике Planet Radius
95
Построение пользовательских интерфейсов
spn_planetRadius.value = aPlanet.radius
-- Установить радиус орбиты планеты в счетчике Orbit Radius
pOrbit = aPlanet.pos.controller.path
spn_orbitRadius.value = pOrbit.radius
)
Если щелкнуть на кнопке Pick Planet, выбранный объект сохранится в ло-
кальной переменной aPlanet. Имя выбранного объекта теперь автомати-
чески отображается в надписи кнопки выбора Pick Planet.
Примечание. Программирующие на MAXScript часто пользуются
переменной obj для обозначения того факта, что объект выбран. Имя
переменной obj не является ни ключевым словом, ни любым другим
именем специальной переменной. Это имя упоминается здесь лишь потому,
что оно часто встречается в сценариях.
2. Вычислите код сценария.
3. Щелкните сначала на кнопке Pick Planet, а затем на самой планете.
Независимо от того, какая планета выбрана, в поле счетчика Orbit Radius
появляется значение 10,0, хотя радиус орбиты может достигать и 10. На-
помним, что диапазон значений в счетчике ограничивается верхним преде-
лом 10. Для правильного отображения числовых значений в счетчике необ-
ходимо изменить этот предел.
4. Замените строку spn_orbitRadius следующей строкой кода:
spinner spn_orbitRadius "Orbit Radius” range:[0,100,0]
5. Вычислите код сценария.
6. Щелкните на кнопке Pick Planet и выберите планету. В поле счетчика Orbit
Radius появится правильно отображаемое значение радиуса орбиты.
Использование локальных переменных
В следующем упражнении вам предстоит ввести обработчики событий, изме-
няющие радиус выбранной планеты и ее орбиты в результате изменений в счетчи-
ках Planet Radius и Orbit Radius.
1. Введите следующий фрагмент кода после введенного последним обработ-
чика событий:
on spn_planetRadius changed value do
(
)
Данное событие возникает всякий раз, когда пользователь изменяет значе-
ние свойства .value в переменной счетчика, вводя новое значение с кла-
виатуры или настраивая счетчик с помощью мыши.
Но дело в том, что при вызове данного обработчика событий требуется изме-
нить радиус объекта, выбранного в предыдущем обработчике событий, а имя
этого объекта хранится в переменной aPlanet, которая является локаль-
ной для данного блока кода. Следовательно, для того чтобы использовать
96
Г лава 2
эту переменную в данном обработчике событий, нужно каким-то образом сде-
лать ее доступной вне области действия предыдущего обработчика событий.
Для этой цели необходимо объявить переменную pPlanet вне области
действия всех обработчиков событий и хранить в ней имя объекта. Это
даст возможность использовать ее в любом обработчике событий внутри
данного сценария.
2. Введите следующую строку кода перед обработчиком событий pbt_pickPlanet:
local pPlanet
3. Введите в начале кода обработчика событий pbt_pickPlanet следующую
строку:
pPlanet = aPlanet
В этой строке значение переменной pPlanet устанавливается в соответст-
вии с выбранной планетой. Теперь переменную pPlanet можно использо-
вать в остальных обработчиках событий.
4. Введите внутри обработчика событий spn_planetRadius следующую
строку кода:
pPlanet.radius = spn_planetRadius.value
Данный фрагмент кода теперь должен иметь следующий вид:
local pPlanet
on pbt_pickPlanet picked aPlanet do
(
pPlanet = aPlanet
-- Установить радиус выбранной планеты в счетчике Planet Radius
spn_planetRadius.value = aPlanet.radius
-- Установите радиус орбиты планеты в счетчике Orbit Radius
pOrbit = aPlanet.pos.controller.path
spn_orbitRadius.value = pOrbit.radius
)
on spn_planetRadius changed value do
(
pPlanet.radius = spn_planetRadius.value
)
5. Вычислите код сценария.
6. Щелкните сначала на кнопке Pick Planet, а затем на планете.
7. Измените значение в счетчике Planet Radius. Радиус планеты соответст-
венно изменится.
Сделайте то же самое для орбиты планеты. И в этом случае возникнет ана-
логичная проблема с переменными, поскольку переменная pOrbit являет-
ся локальной для обработчика событий pbt_pickPlanet. Для того чтобы
сделать доступной эту переменную, ее следует объявить локально вне обра-
ботчиков событий.
8. Введите следующую строку кода после строки объявления локальной пе-
ременной pPlanet:
local pOrbit
97
Построение пользовательских интерфейсов
9. Введите следующий фрагмент кода после введенного последним обработ-
чика событий:
on spn_orbitRadius changed value do
(
pOrbit.radius = spn_orbitRadius.value
)
10. Вычислите код сценария.
11. Щелкните сначала на кнопке Pick Planet, а затем на планете.
12. Измените значение в счетчике Orbit Radius. Радиус орбиты планеты соот-
ветственно изменится.
Включение и отключение элементов
пользовательского интерфейса
Итак, сценарий работает, хотя он и недостаточно защищен от ошибок. В част-
ности. кнопка Create Planets оказывается доступной даже в тот момент, когда
пользователь еще не создал Солнце. Всякая попытка создать планеты до Солнца
может привести к ошибке.
Во избежание пользовательских ошибок отдельные элементы интерфейса
включаются и отключаются в зависимости от конкретных действий пользователя
в интерфейсе. Например, при открытии диалогового окна Solar System можно от-
ключить все кнопки и счетчики до тех пор, пока пользователь не создаст Солнце.
1. Введите во всех строках, определяющих счетчики и кнопки, кроме первых
двух, следующую строку кода:
enabled:false
Измененный фрагмент кода сценария должен теперь выглядеть следующим
образом:
(
spinner spn_sunRadius "Sun Radius "
button but_createSun "Create Sun"
spinner spn_NumPlanets "Number of Planets " type:#integer \
range: [1, 10 , 3] enabled:false
button but_createPlanets "Create Planets" enabled:false
group "Planets"
(
pickbutton pbt_pickPlanet "Pick Planet" autoDisplay:true \
enabled:false
spinner spn_planetRadius "Planet Radius " enabled:false
spinner spn_orbitRadius "Orbit Radius " range: [0,100,0] \
enabled:false
)
При вычислении кода сценария в диалоговом окне становятся доступными
лишь два первых элемента пользовательского интерфейса. Остальные эле-
менты будут активизированы в обработчиках событий.
98
। Z
2. Введите следующий фрагмент кода внутри обработчика событ;:;-:
but_createSun для отображения элементов пользовательского интерфей-
са, предназначенных для создания планет:
spn_numPlanets.enabled = true
but_createPlanets.enabled = true
Оба элемента пользовательского интерфейса становятся доступными после
того, как пользователь создаст Солнце того или иного типа.
3. Введите следующий фрагмент кода внутри обработчика событий but_create -
Planets, но непременно вне цикла for, т.е. до или после него:
pbt_pickPlanet.enabled = true
spn_planetRadius.enabled = true
spn_orbitRadius.enabled = true
4. Сохраните сценарий.
5. Установите 3ds Max в исходное состояние и очистите сцену.
6. Вычислите код сценария.
Сначала доступными оказываются лишь два первых элемента. После соз-
дания Солнца появляется возможность создать планеты и далее изменить
радиус как отдельных планет, так и их орбит.
А теперь необходимо сделать еще одно, последнее изменение в сценарии,
чтобы он стал еще более защищенным от ошибок. При выполнении данного
сценария в первый раз значение параметра Sun Radius устанавливается по
умолчанию равным нулю. Если не изменить его, Солнце будет создано
с нулевым радиусом. Нетрудно представить, как неопытный пользователь
будет щелкать снова и снова на кнопке Create Sun, добиваясь того, чтобы
Солнце появилось на сцене. В итоге сцена заполнится десятками невиди-
мых Солнц, прежде чем пользователь поймет, в чем состоит ошибка.
Во избежание этого радиус сферы следует установить по умолчанию рав-
ным 50 или другому числовому значению, превышающему нуль.
7. Дополните строку кода, определяющую счетчик Sun Radius, следующим
кодом:
range: [1,100,50]
Эта строка должна теперь иметь следующий вид:
spinner spn_sunRadius "Sun Radius " range: [1,100,50]
8. Сохраните сценарий.
Вариант этого сценария можно найти в файле \chapter2\solar_System.ms
на прилагаемом к этой книге CD-ROM.
Для усовершенствования данного сценария в него можно внести целый ряд
дополнений. Например, пользователю можно разрешить следующее.
• Указывать начальные радиусы орбит с приращением вместо исходного зна-
чения 10. Для этого придется расширить диапазон значений параметра
Orbit Radius в сторону больших чисел.
99
Построение пользоввтельских интерфейсов
• Наклонить каждую орбиту или сделать ее эллиптической. Для этого потре-
буются навыки выполнения преобразований, которые более подробно рас-
сматриваются в главе 5.
Заключение
В этой главе вы научились строить пользовательские интерфейсы, создав свиток
и заполнив его элементами пользовательского интерфейса, а затем введя в него об-
работчики событий для вызова отдельных частей сценария с помощью элементов
управления пользовательского интерфейса. Кроме того, вы научились отличать об-
щий сценарий от макросценария и создавать каждый из них в отдельности.
100
Интерфейс 3ds Max
Глава 3
Пользовательский интерфейс 3ds Max
весьма обширен и сложен. Без MAXScript
работа в данном приложении
превращается в утомительное и довольно
скучное занятие. Более того, художники,
технические постановщики, аниматоры
и целые студии, не имеющие в своем
арсенале специальных сценариев,
работают менее эффективно и медленно,
а следовательно, им труднее соперничать
с теми, кто создает и регулярно
использует такие сценарии.
Интерфейс 3ds Max
Задание
После изучения этой главы вы должны уметь следующее.
• Создавать копии, экземпляры и ссылки на геометрические объекты, нахо-
дящиеся на сцене, и копировать массивы
• Пользоваться командами Мах, доступными в 3ds Мах
• Вызывать панели команд средствами MAXScript
• Получать доступ к основной панели инструментов средствами MAXScript
• Выбирать объекты на сцене из сценария
• Выбирать точки сцены из сценария
• Пользоваться инструментом отслеживания перемещений мыши
• Пользоваться интерфейсом раскраски
Введение
В 3ds Мах имеется немало элементов пользовательского интерфейса, включая
панели команд, свитки, диалоговые и обычные окна. Кроме того, в пользователь-
ском интерфейсе 3ds Мах можно выполнять немало тех действий, которые обычно
выполняются в видовых окнах, а также команды доступа к внешним файлам.
Столь глубокая структура пользовательского интерфейса 3ds Мах становится
причиной значительных потерь времени при решении сложных или часто повто-
ряющихся задач. Подобные задачи, как правило, автоматизируются полностью
или частично с помощью сценариев.
В MAXScript имеется достаточно функций и команд для работы практически
со всеми элементами пользовательского интерфейса. Поэтому в интересах инди-
видуальных пользователей или студий — уделить серьезное внимание вопросам
эффективного использования интерфейса 3ds Мах, чтобы найти пути повышения
производительности своего повседневного труда.
Тема доступа к пользовательскому интерфейсу средствами MAXScript слиш-
ком обширна, чтобы охватить ее в одной главе. Поэтому в данной главе рассмат-
риваются лишь самые важные вопросы.
Получение копии, экземпляра и ссылки
Одной из самых основных операций, выполняемых в видовом окне, является
дублирование, или клонирование, объектов. И большую часть этих операций
можно выполнять средствами MAXScript.
Следует, однако, иметь в виду, что копирование и получение экземпляра рас-
пространяется не только на объекты, находящиеся на сцене, в том виде, в каком
они представлены в MAXScript, но и на многие типы данных. Например, копиро-
вать можно строки, цвета, растры, значения угла поворота вокруг осей и т.д.
В этом разделе речь пойдет о копировании на сцене примитивных объектов. А что
102
Глава 3
касается копирования данных других типов, обращайтесь по этому вопросу за до-
полнительной справкой к справочному руководству по MAXScript.
Здесь и далее предполагается, что вы знаете, как пользоваться копией, экземп-
ляром и ссылкой в 3ds Мах вручную.
Копия
Синтаксис команды копирования следующий:
сору <узел>
Для копирования объекта выполните следующее упражнение.
1. Установите 3ds Мах в исходное состояние и откройте окно приемника ко-
манд MAXScript Listener. Введите в этом окне следующую строку кода:
Ь = box heightsegs: 8
В этой строке создается стандартный параллелепипед с 8 сегментами по
высоте.
2. Введите следующую строку кода:
с = сору Ь
В этой строке создается копия параллелепипеда. Она располагается в том
же месте, где и исходный параллелепипед Ь.
3. Введите следующую строку кода:
move с [25,0,0]
Анализ вновь скопированного параллелепипеда (хранящегося в перемен-
ной с) показывает, что он отделен от оригинала. Любые изменения в парал-
лелепипеде с не оказывают влияния на параллелепипед Ь. У скопированного
параллелепипеда имеются собственные свойства, модификаторы и прочие
атрибуты, которые могут быть изменены, не оказывая влияния на оригинал
или другие копии.
В данном случае была отдельно вызвана функция move, чтобы можно было
визуально различить оба параллелепипеда.
Но обе приведенные выше строки кода можно объединить в одну следую-
щим образом:
d = сору с pos: [50,0,0]
В этой строке создается копия параллелепипеда с в другом месте сцены.
Экземпляр
Синтаксис команды получения экземпляра следующий:
instance <узел>
Продолжите в следующем упражнении работу над предыдущим примером, но
на этот раз создайте экземпляр параллелепипеда Ь.
103
Интерфейс 3ds Max
1. Введите в окне приемника команд следующую строку:
i = instance b pos : [0,25,0]
В этой строке создается экземпляр исходного параллелепипеда, находяще-
гося в точке начала отсчета, т.е. параллелепипед i. Экземпляр располагает-
ся в точке, указанной в приемнике команд.
2. Введите следующую строку кода:
addmodifier i (bend())
3. Выделите полученный экземпляр параллелепипеда и перейдите к панели
команд Modify. Измените параметры сгибания модификатора Bend, наблю-
дая результаты в видовом окне.
Изменения, вносимые в параллелепипед i, сказываются и на параллелепи-
педе b. С другой стороны, изменения, вносимые в параллелепипед Ь, при-
водят к обновлению параллелепипеда i. Это классический пример поведе-
ния на сцене полученных экземпляров объектов. Экземпляры имеют общие
с исходным объектом свойства, модификаторы, материалы и карты, а также
контроллеры управления анимацией, но не преобразования, пространст-
венные исказители или путевые имена.
4, Продолжая предыдущий пример, удалите модификатор Bend. Для этого
введите в окне приемника команд следующую строку кода:
deletemodifier i 1
Функция deletemodifier воспринимает полученный экземпляр объекта
в качестве первого аргумента, а индекс удаляемого модификатора — в каче-
стве второго аргумента. Индекс модификатора, находящегося на вершине
стека, равен 1 и постепенно увеличивается в направлении дна стека моди-
фикаторов.
Ссылка
Синтаксис команды получения ссылки следующий:
reference <узел>
Продолжите в следующем упражнении работу над предыдущим примером,
создав на этот раз ссылку на объект.
1. Введите в окне приемника команд следующую строку кода:
г = reference b pos: [0,-25,0]
В этой строке создается ссылка на параллелепипед в стороне от исходного
параллелепипеда, находящегося в точке начала отсчета.
2. Введите следующую строку кода:
addmodifier г (bend О)
Как видите, параллелепипед г теперь содержит модификатор Bend, кото-
рый отсутствует у параллелепипеда Ь. Ссылочный параллелепипед г мож-
но рассматривать в качестве порожденного объекта по отношению к исход-
104
Глава 3
ному параллелепипеду Ь, как к родительскому объекту. Любые изменения,
вносимые в родительский объект, будут оказывать влияние на порожден-
ный объект. В то же время изменения в порожденном объекте не будут ока-
зывать влияния на родительский объект.
3. Выделите ссылочный параллелепипед и перейдите к панели команд Modify.
Измените параметры модификатора Bend, наблюдая за результатами в ви-
довом окне.
Изменения в модификаторе Bend не оказывают никакого влияния на па-
раллелепипед Ь, поскольку у этого объекта модификатор Bend отсутствует.
4. Введите следующую строку кода:
Ь.height = 40.0
Как видите, изменения распространяются на оба параллелепипеда. Это
классический пример поведения ссылочного объекта.
Клонирование узлов с помощью функции
maxOps.CloneNodes
В MAXScript имеется еще один, более сложный способ клонирования узлов.
Приведенные выше способы пригодны для простых объектов, но дают непредска-
зуемые результаты при клонировании таких объектов с иерархиями, как источни-
ки света с собственными целями. Для клонирования с сохранением взаимосвязей
между родительскими и порожденными объектами на сцене служит функция
maxOps . CloneNodes. Синтаксис этой функции следующий:
maxOps.CloneNodes <массив узлов> clonetype: <enum> newNodes:
<&массив узлов> actualNodeList: <&массив узлов> offset: <point3> ...
Данная функция возвращает логическое значение true при успешном выпол-
нении и логическое значение false при неудачном выполнении.
Примечание. У функции maxOps.CloneNodes имеется больше параметров, чем
перечислено выше. Для простоты здесь рассматривается лишь часть ее параметров.
Ниже приведены некоторые параметры функции maxOps. CloneNodes.
• <массив узлов> — это массив клонируемых узлов. Но если функции пе-
редается единственный объект, она обнаружит этот факт и автоматически
свернет объект в массив.
• clonetype: <enum> — этот параметр может принимать одно из трех сле-
дующих значений: #сору (копия), #instance (экземпляр) или
#ref erence (ссылка), а по умолчанию — #сору.
• newNodes: <&массив узлов > — этот массив узлов будет заполнен вновь
клонированными узлами.
• actualNodeList: <&массив узлов> — в качестве этого необязательно-
го параметра передается пустой массив, который будет заполнен конкретными
105
Интерфейс 3ds Max
клонированными узлами. Это объясняется тем, что между узлами возмож-
ны взаимосвязи, которые служат причиной появления в списке других уз-
лов, например взаимосвязи между целями источников света и камер, узло-
выми частями систем, членами групп или расширенных иерархий.
• offset: <point3> — этот параметр перемещает новый узел по указанно-
му вектору типа points. Он может быть использован для установления
различий между вновь клонированными и старыми узлами.
В следующем упражнении демонстрируются отличия между обычным копиро-
ванием и клонированием с помощью функции maxOps. Cl on eNodes.
1. Установите 3ds Max в исходное состояние и откройте окно приемника ко-
манд MAXScript Listener.
2. Создайте один нацеленный прожектор в сцене 3ds Мах.
3. Выделите этот источник света. Только не выделяйте его цель.
4. Введите в окне приемника команд следующий фрагмент кода:
а = $
с = сору а
move с [0,25,0]
В итоге будет получена копия источника света, которая имеет общую с ори-
гиналом цель. А для клонирования цели следует использовать функцию
maxOps.CloneNodes.
5. Введите следующий фрагмент кода:
maxops.cloneNodes a actualNodeList: &ANL clonetype: #сору \
offset: [-25,-25, 0] newNodes: &NN
В итоге будет создан новый источник света с собственной целью.
6. Введите следующую строку кода:
print ANL
В этой строке на печать выводятся два объекта: источник света и его цель.
В данном случае функции maxops. CloneNodes передан в качестве аргу-
мента один источник света, а также адрес неинициализированного массива
&ANL в качестве параметра actualNodeList. Функция заполнила массив
старым источником света и старой целью источника света. Массив ANL,
в общем, полезен лишь для проверки.
7. Введите следующую строку кода:
select NN
В сцене выделяются новый источник света и его цель. Кроме того, функции
maxops. CloneNodes в качестве параметра newNodes передан адрес не-
инициализированного массива &NN. А функция заполнила этот массив новым
источником света и новой целью источника света. После вызова данной
функции появляется возможность манипулировать новым узлом в массиве,
как обычно.
106
Главв 3
Дополнительные сведения о применении функции maxOps. CloneNodes при-
ведены в следующем разделе справочного руководства по MAXScript: MAXScript
Language Reference^3dsMax Objects^Interfaces^Core Interfaces^Core Interfaces
Pages^lnterface: MaxOps (Справочник по языку МАХБспрВ^Объекты 3ds Max^
Интерфейсы1^Базовые интерфейсы1^Страницы базовых интерфейсов^Ин-
терфейс: maxOps).
Копирование массивов
Массивы являются весьма эффективным и полезным средством MAXScript.
Они могут содержать практически все, что поддается записи. Например, можно
организовать массив чисел, строк, функций, структур, свитков и даже находящих-
ся на сцене объектов.
Время от времени массивы приходится копировать. В таком случае целесооб-
разно, казалось бы, воспользоваться следующим методом:
h = #(1,2,3)
m = copy h
Однако он непригоден. Ведь значение переменной m является не массивом,
а просто постоянным значением “ОК”. Это совершенно не то, что ожидалось по-
лучить. Для получения более предсказуемых результатов копирования массива
необходимо ввести в вызов функции дополнительный аргумент #поМар:
m = copy h ttnoMap
В ответ на введенную выше строку кода в приемнике команд будет выдан сле-
дующий результат:
#(1,2,3)
Благодаря дополнительному аргументу #поМар результаты копирования мас-
сива оказываются вполне предсказуемыми.
На прилагаемом к данной книге CD-ROM находится файл сценария
\chapter3\copy_instance_ref erence .ms с примером, иллюстрирующим
материал этого раздела.
Команды Мах
В MAXScript имеется ряд самых общих команд управления крупными частями
пользовательского интерфейса. Многие из них формируются автоматически в верх-
ней части окна приемника команд (называемого подокном макрорегистрации) в от-
вет на разные события, происходящие на сцене. В частности, имеется команда со-
хранения файла сцены “max file save”, команда фиксации выделенного “max freeze
selection” и команда развертывания видового окна на весь экран “max tool maximize”.
Более подробно с этими командами можно ознакомиться в следующем раз-
деле справочного руководства по MAXScript: MAXScript Tools and Interaction
with SdsMax^lnteracting with the 3dsMax User Interface^SdsMax Commands
(Инструменты MAXScript и взаимодействие c 3ds Max^Взаимодействие с поль-
зовательским интерфейсом 3ds Мах^Команды 3ds Мах).
107
Интерфейс 3ds Max
Панели команд
Панели команд являются наиболее важной частью интерфейса 3ds Мах. Пере-
ходя от одной панели к другой, пользователь получает доступ к разным командам.
Например, команды правки каркаса доступны только на панели Modify. Перехо-
дить от одной панели команд к другой можно и средствами MAXScript, используя
следующий синтаксис:
SetCommandPanelTaskMode [mode:] синя панели>
Для доступа к панели команд имеется также соответствующая функция:
GetCommandPanelTaskMode()
Эта функция возвращает следующие имена панелей.
• ttcreate
• ttmodify
• tthierarchy
• ttmotion
• ttdisplay
• #utility
Для того чтобы выбрать конкретную панель команд и задать режим ее работы,
выполните следующее упражнение.
1. Установите 3ds Мах в исходное состояние. Сцена открывается с выбранной
панелью Create. Для перехода к панели команд Modify введите одну из сле-
дующих строк кода.
• SetCommandPanelTaskMode ftmodify
• SetCommandPanelTaskMode mode:ttmodify
После ввода любой из приведенных выше строк кода отображается панель
Modify.
Еще один способ перехода от одной панели команд к другой состоит в примене-
нии команд Мах, упоминавшихся в предыдущем разделе. Эти команды следующие.
• max create mode
• max modify mode
• max hierarchy mode
• max motion mode
• max display mode
• max utility mode
Дополнительные сведения по данному вопросу приведены в следующем разде-
ле справочного руководства по MAXScript: MAXScript Tools and Interaction with
108
Глава 3
SdsMax^lnteracting with the 3dsMax User Interface^Command Panels (Инстру-
менты MAXScript и взаимодействие c 3ds MaxФВзаимодействие с пользователь-
ским интерфейсом 3ds МахФПанели команд).
Основная панель инструментов
Большинство самых важных команд доступно на основной панели инструментов.
В MAXScript имеются средства для доступа ко многим из этих команд. В частности,
программным путем можно выбрать кнопку отмены операции, открыть диалоговое
окно выбора объектов или активизировать инструмент перемещения объектов.
Дополнительные сведения по данному вопросу приведены в следующем разде-
ле справочного руководства по MAXScript: MAXScript Tools and Interaction with
SdsMax^lnteracting with the 3dsMax User Interface^Main Toolbar (Инструменты
MAXScript и взаимодействие c 3ds МахФВзаимодействие с пользовательским ин-
терфейсом 3ds МахФ Основная панель инструментов).
Выбор объектов на сцене
Одной из наиболее часто используемых функций расширенного набора
средств MAXScript является функция Pickobject, позволяющая выбрать объект
на сцене, используя стандартные инструменты выделения. Синтаксис данной
функции следующий:
Pickobject [message: <строка>] [count: n | #multiple] [filter:
<функция>] ...
Примечание. Синтаксис функции pickobject достаточно длинный, поэтому
для простоты и экономии места ниже поясняются лишь три необязательных
аргумента данной функции.
При вызове функции Pickobject курсор принимает вид пиктограммы выде-
ления объекта и происходит переход в режим ожидания от пользователя конкрет-
ных действий для выделения одного или более объектов в сцене 3ds Мах. Ниже
приведены некоторые необязательные параметры функции Pickob j ect.
• [message: <строка>] — это сообщение, появляющееся в строке состоя-
ния, расположенной в нижней части пользовательского интерфейса 3ds Мах.
• [count: п | #multiple] — этот параметр указывает количество выбирае-
мых объектов. Функции можно передать целое число (п) для выбора кон-
кретного количества объектов или же значение #mul tiple для того, чтобы
пользователь мог выбрать столько объектов, сколько потребуется, прежде
чем нажать клавишу <Esc> или щелкнуть правой кнопкой мыши. За до-
полнительной информацией о выделении нескольких объектов обращай-
тесь к справочному руководству по MAXScript.
• [filter: <функция>] — это функция, которая позволяет отфильтровать
разные виды объектов на сцене 3ds Мах. Такая функция может упростить вы-
бор объектов, если, например, требуется выделить только объекты формы на
109
Интерфейс 3ds Max
сцене, заполненной параллелепипедами. При этом фильтр вызывается и пе-
редается тому объекту на сцене, над которым находится курсор, например:
function mySphereFilter obj = ( ClassOf obj == Sphere )
В данном случае из тела функции возвращается логическое значение true,
если объект является сферой; в противном случае возвращается логическое
значение false. Эта функция фильтрации передается далее функции
Pickobject.
Для того чтобы воспользоваться функцией Pickobject, выполните следую-
щее упражнение.
1. Очистите сцену 3ds Мах и откройте новый файл сценария MAXScript по
команде MAXScriptdNew MAXScript из главного меню.
2. Откройте окно приемника команд MAXScript Listener.
3. Создайте в видовом окне пять параллелепипедов и две сферы, расположив
их в любом месте сцены.
4. Введите в файл сценария следующий фрагмент кода:
function mySphereFilter obj = ( ClassOf obj == Sphere )
sei = Pickobject message: "Pick any sphere" filter:
mySphereFilter
format "You selected: %\n" sei.name
5. Вычислите код сценария.
При перемещении в видовом окне курсор переходит в режим выделения объ-
ектов, когда он оказывается над сферой, и возвращается к исходному виду, ко-
гда он оказывается над параллелепипедом. В нижней части интерфейса 3ds Мах
появляется подсказка с указаниями относительно выделения сфер.
6. Попробуйте выделить любой из параллелепипедов. Как видите, это не уда-
ется сделать. Функция фильтрации препятствует выделению любых объек-
тов, кроме сферических.
7. Выделите любой из сферических объектов. Выделение сферы разрешается
и выполняется последняя строка сценария. В окне приемника команд появ-
ляется сообщение о выделении конкретной сферы и выводится ее наименова-
ние. После выбора сферы происходит возврат из данной функции, поскольку
по умолчанию она должна завершаться после выделения одного объекта. Ес-
ли бы функции было передано определенное количество выделяемых объек-
тов в качестве дополнительного аргумента, ее поведение было бы иным.
Дополнительные сведения по данному вопросу приведены в следующем разде-
ле справочного руководства по MAXScript: MAXScript Tools and User with 3dsMaxd
Interacting with the 3dsMax Interfaced Picking Scene Nodes (Инструменты MAXScript
и взаимодействие c 3ds MaxdВзаимодействие с пользовательским интерфейсом
3ds Maxd Выбор узлов сцены).
110
Глава 3
Выбор точек
В MAXScript имеется немало функций для работы с видовыми окнами. К ним,
в частности, относятся функции изменения схемы расположения видовых окон, об-
новления видовых окон, установки режимов привязки, изменения масштаба изо-
бражения, задания сеток и т.д. Вместо того чтобы рассматривать все подобные функ-
ции, в этом разделе основное внимание будет уделено одной очень важной функции,
pickPoint, с помощью которой пользователь выбирает точку или место в видовом
окне, а функция возвращает координаты этой точки в виде данных типа Point3.
Синтаксис функции pickPoint следующий:
pickPoint [ snap:#2D|#3D ] [ rubberBand:<start_point3> ] ...
Ниже приведены некоторые параметры данной функции.
• [snap: #2D | #3D] — этот аргумент определяет вид привязки, если он пере-
дается функции. В противном случае выделяемая точка будет находиться
на текущей плоскости построения.
Примечание. Для того чтобы данный параметр возымел действие,
необходимо сначала включить режим привязки в пользовательском
интерфейсе 3ds Мах.
• [rubberBand: <point3>] — этот аргумент определяет режим рисования
пунктирной линии от предоставляемой точки до местоположения курсора
до тех пор, пока данная функция активна. Данный режим обычно использу-
ется для визуального соединения ряда точек в видовом окне.
Для того чтобы воспользоваться функцией pickPoint, выполните следующее
упражнение.
1. Очистите сцену 3ds Мах и откройте новый файл сценария MAXScript по
команде MAXScript1^ New MAXScript из главного меню.
2. Откройте окно приемника команд MAXScript Listener.
3. Создайте ряд геометрических объектов в видовом окне и включите режим
трехмерной (3D), но не двухмерной (2D) или полуобъемной (2.5D) при-
вязки или же выберите любой другой вид привязки.
4. Введите в файл сценария следующий фрагмент кода:
pnt = points ООО
for i = 1 to 3 do
(
pnt = pickPoint snap.- #3D rubberband: pnt
)
5. Вычислите код сценария и выберите три точки в видовом окне.
Выделяя точки, обратите внимание на линию, проводимую от точки начала
отсчета до курсора, находящегося в первой точке, а затем к остальным вы-
бираемым точкам при последовательном перемещении курсора от одной
точки к другой. В более сложном сценарии такая линия проводится лишь
111
Интерфейс 3ds Max
после выбора первой точки. Обратите также внимание на то, что, прежде
чем выбирать точки, необходимо включить режим привязки, чтобы аргу-
мент привязки возымел действие. В данной функции режим привязки ав-
томатически не устанавливается.
Дополнительные сведения по данному вопросу приведены в следующем разде-
ле справочного руководства по MAXScript: MAXScript Tools and Interaction with
3dsMax^lnteracting with the 3dsMax User Interface^Viewports^Picking Points in
the ViewPorts (Инструменты MAXScript и взаимодействие c 3ds Мах^>Взаимо-
действие с пользовательским интерфейсом 3ds Мах>=> Видовые окна^ Выбор точек
в видовых окнах).
Функция mouseTrack
(дополнительный материал)
Функция mouseTrack позволяет отслеживать перемещения курсора мыши
в видовых окнах. В частности, она способна контролировать щелчки кнопками
мыши и перемещения курсора мыши, а также отслеживать пересечение курсора
мыши с геометрическими объектами на сцене. Для организации реакции на собы-
тие, связанное с мышью, можно написать функцию, которая вызывается, когда по-
добное событие наступает. Это так называемая функция обратного вызова. Она
имеет специальное обозначение и воспринимает определенные аргументы, пре-
доставляемые средствами MAXScript.
Синтаксис функции mouseTrack следующий:
mouseTrack [оп:<узел>] [prompt:"msg"] [snap:#2D|#3D]
[trackcallback:fn|#(fn,arg)]
Ниже приведены некоторые параметры функции mouseTrack.
• [оп:<узел>] — этот необязательный аргумент определяет находящийся на
сцене объект, реакция на который будет происходить в функции обратного
вызова. Если этот аргумент не предоставляется, функция mouseTrack будет
отслеживать перемещения курсора мыши на активной координатной сетке.
• [prompt: "msg"] — это текстовое сообщение, появляющееся в строке со-
стояния, расположенной в нижней части окна 3ds Мах.
• [snap: #2D | #3D] — этот аргумент активизирует привязки, но действует
лишь в том случае, если перемещение курсора мыши не отслеживается на
поверхности объекта.
• [trackcallback: fn] — это функция, которая вызывается в ответ на со-
бытия, связанные с мышью, а ее имя обозначает функцию обратного вызо-
ва. Такая функция должна возвращать значение ttcontinue для того, чтобы
продолжалась обработка событий, фиксируемых функцией mouseTrack. Ес-
ли же эта функция возвращает какое-то другое значение, она просто больше
не вызывается.
112
Глава 3
Реализуемая отдельно функция обратного вызова должна воспринимать ряд
аргументов следующим образом:
function CallBack message intRay obj faceNumber shift Ctrl alt = (...)
• message — это код, указывающий на действия мыши в виде одного из сле-
дующих четырех сообщений:
#f reemove — мышь перемещается, но кнопка мыши не нажимается;
ttmousepoint — нажата левая кнопка мыши;
#mousemove — курсор мыши перетаскивается при нажатой левой кнопке
мыши;
ttmouseabort — нажата правая кнопка мыши.
• intRay — пересечение с лучом, исходящим из курсора мыши и направленным
в сторону активной координатной сетки или отслеживаемого объекта. У такого
луча имеется свойство положения (. pos) и вектор направления (. dir).
• obj — это отслеживаемый объект. Он присваивается при вызове функции
mouseTrack с дополнительным аргументом [оп.-<узел>]. Если данный
аргумент не предоставляется, параметр obj не определен.
• faceNumber — порядковый номер грани, на которой находится курсор
мыши. Этот параметр действует только в том случае, если объект является
редактируемым каркасом. В противном случае он не определен.
• shift / Ctrl / alt — эти параметры указывают на нажатие соответст-
вующих модифицирующих клавиш. Они могут принимать лишь два логи-
ческих значения: true и false.
Для того чтобы воспользоваться функцией mouseTrack, выполните следую-
щее упражнение.
1. Очистите сцену 3ds Мах и откройте новый файл сценария MAXScript по
команде MAXScript1^ New MAXScript из главного меню. Затем откройте ок-
но приемника команд MAXScript Listener.
2. Введите в окне нового сценария следующий его код:
function myFooFunction message intRay obj faceNumber shift Ctrl alt =
(
print message
(♦continue
)
s = sphere()
mousetrack on: s prompt: "Tracking" trackcallback: myFooFunction
3. Сохраните введенный сценарий в файле и вычислите его код. Переместите
курсор мыши в видовом окне, попробовав щелкнуть и выполнить перетаски-
вание. Наблюдайте на результатами совершаемых действий в видовом окне.
4. Нажмите клавишу <Esc>, чтобы завершить действие.
113
Интерфейс 3ds Max
При перемещении курсора мыши в видовом окне появляется много сооб-
щений #freemove в приемнике команд, так что его окно быстро перепол-
няется и начинает прокручиваться. Поэтому нужно проявить определен-
ную сноровку, чтобы увидеть сообщение #mousepoint после нажатия
кнопки мыши. Экспериментируя с данным сценарием, вы должны увидеть
все сообщения о действиях мыши.
Далее вам предстоит видоизменить сценарий таким образом, чтобы пере-
мещать в диалоговом режиме чайник на поверхности сферы. Этот код будет
введен внутри функции обратного вызова myFooFunction. Используя
функцию mouseTrack, не забывайте о том, что, когда курсор мыши нахо-
дится над отслеживаемым объектом, определяются параметры intRay
и obj функции обратного вызова. Для перемещения чайника на поверхно-
сти сферы в диалоговом режиме следует использовать параметр intRay,
поскольку у пересекающего луча имеется очень удобное свойство положе-
ния, указывающее место, в котором луч попадает на отслеживаемый объект.
Именно это положение и следует присвоить чайнику.
5. Удалите любые находящиеся на сцене объекты.
6. Видоизмените сценарий следующим образом:
pot = teapot radius: 5 wirecolor: (color 255 0 0)
function myFooFunction message intRay obj faceNumber shift Ctrl alt =
(
case message of
(
#freeMove:
(
if (obj != undefined) and (intRay != undefined) do
(
pot.pos = intRay.pos
)
)
)
#continue
)
s = sphere segments: 48 wirecolor: (color 0 255 255)
mousetrack on: s prompt: "Tracking" trackcallback: myFooFunction
В начале этого сценария определен небольшой чайник (объект pot). А в функ-
ции обратного вызова перехватывается сообщение #f reemove. Кроме того,
в сценарии проверяется, были ли определены параметры obj и intRay.
Если они определены, положение луча, пересекающего каркас, присваива-
ется свойству положения чайника.
7. Сохраните сценарий и вычислите его код. Переместите курсор мыши по
сфере, обратив внимание, что именно происходит, когда вы продолжаете
перемещать курсор по ней. Для этого, возможно, удобнее свернуть текущее
видовое окно и наблюдать происходящее одновременно во всех четырех ви-
довых окнах.
114
Глава 3
8. Нажмите клавишу <Esc>, чтобы завершить действие.
Чайник перемещается, следуя за курсором мыши по сфере. А при переме-
щении курсора мыши в пустом пространстве экрана с чайником ничего не
происходит. Возможно, это не очень заметно в окне вида в перспективе, по-
скольку чайник не поворачивается. Но если завершить действие и повер-
нуть вид в перспективе, то можно заметить, как чайник буквально
“привязан” к поверхности сферы.
9. Для того чтобы сделать перемещение чайника по поверхности сферы вслед
за курсором мыши более очевидным, поверните его в направлении вектора
нормали в точке пересечения. Именно эта информация предоставляется
в функции обратного вызова с помощью параметра intRay. Пересекающий
луч (параметр intRay) исходит из точки пересечения и следует парал-
лельно вектору нормали к грани, которую он пересекает. Остается лишь
выровнять чайник по поверхности сферы. Для этого введите еще одну стро-
ку кода после строки присваивания положения внутри условного оператора if:
if (obj != undefined) and (intRay != undefined) do
(
pot.pos = intRay.pos
pot.dir = intRay.dir
)
10. Сохраните сценарий и вычислите его код. Переместите чайник по сфере.
115
Интерфейс 3ds Max
11. Нажмите клавишу <Esc>, чтобы завершить действие.
Теперь чайник выровнен по поверхности сферы.
12. Для того чтобы сделать данный сценарий более удобным для пользователя,
следует организовать прерывание действия, когда пользователь щелкнет
кнопкой мыши вместо того, чтобы нажимать клавишу <Esc>.
В настоящий момент функция возвращает значение ^continue независи-
мо от того, что происходит в операторе case. Это довольно простой, хотя
и грубый прием. Поэтому вам придется расширить оператор case для об-
работки поступающих сообщений, включая те, которые служат для уведом-
ления о преждевременном прекращении или отмене действия сценария.
13. Видоизмените функцию обратного вызова следующим образом:
function myFooFunction message intRay obj faceNumber shift Ctrl alt =
(
returnvalue = case message of
(
#freeMove:
(
if (obj != undefined) and (intRay != undefined) do
(
pot.pos = intRay.pos
pot.dir = intRay.dir
)
^continue
)
ttmouseAbort: ( undefined )
116
Главе 3
ttmousePoint: ( undefined )
ttmouseMove: ( ttcontinue )
)
returnvalue
)
14. Сохраните сценарий и вычислите его код. Переместите курсор мыши и на-
жмите любую ее кнопку, чтобы отменить действие сценария. Как видите,
взаимодействие функции mouseTrack и функции обратного вызова
служит удобным основанием для создания весьма интересных сцена-
риев. Окончательный вариант данного сценария можно найти в файле
\chapters\mouse_track.ms на прилагаемом к этой книге CD-ROM.
А дополнительные сведения по данному вопросу приведены в следующем раз-
деле справочного руководства по MAXScript: MAXScript Tools and Interaction
with SdsMax^lnteracting with the 3dsMax User Interface^MouseTrack (Инст-
рументы MAXScript и взаимодействие c 3ds Max^ Взаимодействие с поль-
зовательским интерфейсом 3ds Мах^Функция mouseTrack).
Интерфейс раскраски
(дополнительный материал)
Рассмотренные выше средства MAXScript, в том числе функции pickPoint,
Pickobject и mouseTrack, сами по себе весьма эффективны. А в этом разделе
речь пойдет об интерфейсе раскраски — самом совершенном средстве MAXScript
для организации работы в диалоговом режиме.
В 3ds Мах имеется ряд инструментов, использующих интерфейс раскраски,
в котором кисть оперирует объектом, раскрашивая его геометрическую форму,
выталкивая и втягивая вершины на каркасе или выполняя ряд других операций.
Все эти возможности раскрываются в интерфейсе раскраски MAXScript. У ин-
терфейса раскраски имеется немало функций и свойств, и поэтому он может пока-
заться слишком сложным для начинающих пользователей. Этот раздел служит
лишь в качестве краткого введения в данный интерфейс.
Как и в других интерфейсах, в интерфейсе раскраски используется глобальная
переменная thePainterlnterface. У этой переменной вообще нет значения,
а есть только свойства и методы, управляющие процессом раскраски.
Примечание. Дополнительные сведения об интерфейсах приведены в тех
разделах приложения к этой книге, в которых обсуждаются вопросы, связанные
с интерфейсами.
Работа интерфейса раскраски основана на использовании функций обратного
вызова. Как следует из приведенного выше примера применения функции
mouseTrack, функции обратного вызова определяются создателем сценария
(т.е. вами), а вызываются системой. Они называются так потому, что система де-
лает обратный вызов вашего кода через написанную вами функцию. Если в при-
мере применения функции mouseTrack из предыдущего раздела использовалась
лишь одна функция обратного вызова, то в интерфейсе раскраски — пять таких
117
Интерфейс 3ds Max
функций. Все эти функции вызываются во время разных событий типа раскраски.
Это следующие функции:
• Startstroke — вызывается в начале события раскраски;
• Paintstroke — вызывается в течение события раскраски;
• Endstroke — вызывается в конце события раскраски;
• Cancelstroke — вызывается при отмене пользователем события раскраски;
• SystemEnd — вызывается по окончании события раскраски.
Для регистрации этих функций в интерфейсе раскраски вызывается функция-
член (называемая также методом) глобальной переменной thePainterlnterface,
и ей передаются пять функций обратного вызова в указанном выше порядке. Это
нужно сделать после определения данных функций в сценарии. Ниже приведен
способ их инициализации:
thePainterlnterfасе.ScriptFunctions startstroke paintstroke endstroke
cancelstroke systemEnd
После инициализации функций интерфейсу раскраски указываются те объек-
ты (или узлы), которые требуется раскрасить. Эти объекты Можно рассматривать
как холст для картины, например:
canvasNodes = $
thePainterlnterface.initializeNodes 0 canvasNodes
В приведенном выше примере сначала все находящиеся на сцене объекты вы-
деляются, а затем раскрашиваются. Первый аргумент не используется и должен
оставаться равным нулю.
Для того чтобы начать сеанс раскраски, вызовите следующую функцию:
thePainterlnterface.startPaintSession()
А для того чтобы завершить сеанс раскраски, вызовите следующую функцию:
thePainterlnterface.endPaintSession()
В следующем упражнении вам предстоит написать сценарий, демонстрирую-
щий возможности интерфейса раскраски. В этом сценарии будет раскрашена пира-
мида, расположенная над сферой. В нем предусмотрен небольшой пользовательский
интерфейс, в котором пользователь нажимает фиксирующую кнопку, чтобы на-
чать раскраску, и отжимает ее, чтобы завершить раскраску. Этот интерфейс будет
помещен не в перемещаемое диалоговое окно, а в свиток на панели утилит.
1. Очистите сцену 3ds Мах и откройте новый файл сценария MAXScript по
команде MAXScript^New MAXScript из главного меню.
2. Откройте окно приемника команд MAXScript Listener.
3. Введите в окне нового сценария следующий его код:
global scatteredObject
-- функции обратного вызова
function Startstroke = (
118
Глава 3
)
function Paintstroke = (
)
function Endstroke = (
)
function Cancelstroke = (
)
function SystemEnd = (
)
- - определение утилиты
utility paintstuff "Paint Utility"
(
checkbutton ckb_paint "Paint"
on paintstuff open do
(
clearlistener()
delete $* -- удалить все существовавшие ранее объекты
si = sphere radius: 24 segments: 48
scatteredObject = Pyramid width:2 depth:2 height:20 pos:[0,25,0]
thePainterlnterface.ScriptFunctions startstroke paintstroke \
endstroke cancelstroke systemEnd
thePainterlnterface.initializeNodes 0 si
)
on ckb_paint changed state do
(
if state then
(
thePainterlnterface.startPaintSession()
)
else
(
thePainterlnterface.endPaintSession()
)
)
)
OpenUtility paintstuff
Примечание. Весь этот сценарий работает только в том случае, если
функции обратного вызова находятся в глобальной области действия.
4. Сохраните сценарий и вычислите его код.
В этом сценарии происходит переход к панели утилит, на которой отобра-
жается новый свиток. Со сцены удаляются любые геометрические объекты
и создаются два новых объекта.
119
Интерфейс 3ds Max
5. Щелкните на кнопке Paint (Раскрасить). Поместите курсор над сферой, об-
ратив внимание на появление над сферой пиктограммы инструмента рас-
краски. Раскрасьте поверхность сферы так, как показано на приведенном
ниже рисунке.
Средствами интерфейса раскраски на поверхности сферы автоматически
вычерчивается нарисованный вами контур. Как только вы отпустите кноп-
ку мыши, контур исчезнет и вам придется начать раскраску снова. В дан-
ный момент остроконечная пирамида еще не используется для раскраски.
6. Введите внутри функции Paintstroke следующий фрагмент кода:
function Paintstroke =
(
localHit = [0,0,0]
localNormal = [0,0,0]
worldHit = [0,0,0]
worldNormal = [0,0,0]
str = O.Of
radius = O.Of
thePainterlnterface.getHitPointData &localHit &localNormal \
&worldHit bworldNormal &radius &str 0
-- создать экземпляр пирамиды и переместить его
obj = instance scatteredObject
obj.pos = worldHit
obj.dir = worldNormal
)
7. Сохраните сценарий и вычислите его код. Как только раскроется свиток,
щелкните на кнопке Paint и начните раскраску сферы так, как показано на
приведенном ниже рисунке.
120
Глава 3
Итак, вы успешно раскрасили один объект на другом. Окончательный вариант
данного сценария можно найти в файле \chapter3\painter_interface .ms на
прилагаемом к этой книге CD-ROM. А дополнительные сведения по данному во-
просу приведены в следующих разделах справочного руководства по MAXScript.
• MAXScript Language Reference^3dsMax Objects^ Interfaces^Other Interfaces^
Other Interfaces^lnterface: thePainterlnterface (Справочник по языку MAXScript1^
Объекты 3ds Max1^ Интерфейсы1^Прочие интерфейсы1^Другие интерфейсы1^
Интерфейс: thePainterlnterface)
• MAXScript Tools and Interaction with 3dsMax^Creating MAXScript
Tools^Scripted Paint Tools (Инструменты MAXScript и взаимодействие
c3ds Мах^Создание инструментов MAXScript1^Сценарные инструменты
раскраски)
Заключение
В этой главе вы ознакомились со многими важными понятиями MAXScript
и пользовательского интерфейса. В частности, вы научились клонировать объекты
и массивы, а также освоили целый ряд команд MAXScript, доступных для выпол-
нения высокоуровневого доступа к пользовательскому интерфейсу, выбора пане-
лей команд и инструментов, узлов сцены и точек. Кроме того, вы научились поль-
зоваться функцией mouseTrack и интерфейсом раскраски.
121
Объекты и классы
Глава 4
MAXScript представляет собой весьма
эффективный язык создания сценариев,
в котором реализованы многие принципы
объектно-ориентированного
программирования. Усвоив эти принципы,
вы сможете лучше понять сам язык
MAXScript, а следовательно, стать на путь
профессионального написания сценариев.
Изучив основной материал этой главы,
вы научитесь попутно пользоваться
справочным руководством по MAXScript.
Глава 4
Задание
После изучения этой главы вы должны уметь следующее.
• Ясно представлять назначение объектов в контексте MAXScript
• Определять классы объектов
• Пользоваться справочным руководством по MAXScript для определения
свойств и методов объектов
• Понимать грамматику и синтаксис языка MAXScript
Введение
Для написания сценариев нужно, прежде всего, иметь ясное представление
о структуре класса, используемой в MAXScript. Вместо того чтобы обучать каж-
дой команде, необходимой для написания сценария, в этой главе показано, как
следует работать со структурой класса в MAXScript для поиска необходимой ин-
формации в справочном руководстве по MAXScript. Многие команды, представ-
ленные в этой главе, уже знакомы вам из материала предыдущих глав.
В этой главе вы изучите основные принципы применения этих команд, чтобы
в дальнейшем пользоваться ими постоянно.
Справочное руководство по MAXScript (MAXScript Reference Help), входящее
в состав 3ds Мах, периодически обновляется. Поэтому загрузите последнюю его
версию с Web-сайта компании Autodesk, прежде чем приступать к изучению ма-
териала этой главы.
Для этого обратитесь по адресу www.autodesk.com на Web-сайт компании
Autodesk и выберите в крупном заголовке вариант Media & Entertainment (Муль-
тимедиа и развлечения). Далее выберите вариант Training (Обучение) в левом боко-
вом поле открывшейся страницы, а затем вариант Autodesk 3ds Мах из раскрываю-
щегося списка. На следующей странице выберите вариант Documentation, Online
Tutorials, Sample Files (Документация, диалоговые учебные пособия, файлы приме-
ров). В нижней части открывшейся страницы появится ссылка MAXScript 8 Help.
Если вы не можете получить этот файл, воспользуйтесь справочным
руководством по MAXScript, которое предоставляется на прилагаемом к этой
книге CD-ROM в файле maxscript. chm. Вы можете просматривать это руково-
дство непосредственно на CD-ROM или же переписать его в папку 3dsmax8\help
на жестком диске своего компьютера, заменив существующую его версию.
Объектно-ориентированное
программирование
В MAXScript используется метод, называемый объектно-ориентированным
программированием (ООП). Термином “объект” описываются не только объекты,
находящиеся на сцене 3ds Мах. В MAXScript под объектом понимается любой
123
Объекты и классы
элемент, которым можно манипулировать, в том числе геометрическая форма, мо-
дификатор, контроллер, цвет и числовое значение.
Объект можно рассматривать в качестве контейнера для хранения информации.
Хранящаяся в объекте информация меняется в зависимости от типа объекта. Рас-
смотрим, например, сферу, находящуюся на сцене. В MAXScript сферический объект
не является собственно трехмерной сферой. Его следует, скорее, рассматривать в ка-
честве виртуального контейнера, обозначенного как сфера, для хранения наимено-
вания, радиуса, положения, ориентации и другой информации о трехмерной сфере.
Именно с этим контейнером и приходится работать в MAXScript.
В MAXScript можно создать множество подобных контейнеров с разной ин-
формацией, не прибегая непосредственно к созданию трехмерных сфер на сцене.
Если затем потребуется создать сферу на сцене, достаточно будет выполнить соот-
ветствующую команду MAXScript, чтобы взять всю необходимую информацию
в одном из контейнеров и создать трехмерный объект.
В MAXScript объекты могут служить контейнерами для хранения следующей
информации.
• Любого объекта, создаваемого на панели Create, включая параллелепипед,
окружность, свободно направленный прожекторный источник света, фик-
тивный объект или пространственный исказитель силы тяжести.
• Материалов, в том числе стандартных (Standard), смешанных (Blend), двух-
сторонних (Double Sided). Такой объект содержит всю информацию о кар-
тах и параметрах материала.
• Ограничений и контроллеров, например ограничений по линии пути (Path
Constraint) или контроллера управления по списку (Rotation List Controller).
Такой объект содержит все параметрические данные контроллера.
• Эффектов визуализации, включая размытость движения и зернистость
пленки. Такой объект содержит все параметрические эффекты.
• Цветов.
• Числовых типов данных, включая целые числа, числа с плавающей точкой
и данные типа Points. Такой тип объекта обычно является переменной.
Например, в строке кода х = 3 значение 3 присваивается переменной х.
В данном случае переменная х представляет собой объект.
• Строк.
• Значений true и false (т.е. логических типов данных).
• Массивов и совокупностей.
• Элементов пользовательского интерфейса, в том числе флажков, кнопок
и счетчиков.
Для простоты все эти элементы здесь и далее называются объектами, а объек-
ты 3ds Мах - объектами сцены.
Объект содержит не только свойства, но и методы. В этом и состоит фундамен-
тальное отличие ООП от традиционного, процедурного программирования.
124
Глава 4
Истинный потенциал ООП кроется именно в таком объединении свойств
(данных) и методов (функций) в объект.
В первой части этой главы вам придется поработать с объектами, которые яв-
ляются также объектами сцены, чтобы лучше усвоить сам язык MAXScript. Про-
работав материал этой главы, вы получите ясное представление о том, как прин-
ципы ООП применяются в MAXScript.
Иерархия классов
В ООП классы применяются для того, чтобы отнести каждый объект к опреде-
ленному классу. В свою очередь, классы организованы в иерархию.
Для того чтобы продемонстрировать принцип организации иерархии, рассмот-
рим часть иерархии классов в MAXScript. В частности, иерархия классов параллеле-
пипеда, капсулы и скошенного параллелепипеда организована следующим образом:
Value
MAXWrapper
Node
GeometryClass
Box
Capsule
ChamferBox
Эти три геометрических объекта выбраны потому, что они указаны первыми
в алфавитном порядке и служат удобным основанием для исследования особого
назначения иерархии классов.
Ниже классов Box, Capsule и ChamferBox отсутствуют другие классы. Эти
классы находятся в самом низу иерархии и представляют собой классы объектов,
из которых можно создавать объекты в MAXScript. Иными словами, класс гео-
метрического объекта (GeometryClass) не существует, но в то же время имеются
объекты класса Box, Capsule и ChamferBox.
В предыдущих главах такие классы объектов назывались типами данных, а в спра-
вочном руководстве по MAXScript они называются классами.
Примечание. Такие имена классов, как MAXWrapper и Node, не имеют какого-то
особого значения. Это просто имена, которые разработчики MAXScript придумали
для классов.
В следующем упражнении вам предстоит воспользоваться справочным руко-
водством по MAXScript, чтобы посмотреть, каким образом классы организованы
в MAXScript.
1. Откройте справочное руководство по MAXScript одним из следующих
способов.
• Выберите команду Help^MAXScript Reference из главного меню 3ds Мах.
• Откройте файл maxscript. chm из папки help на прилагаемом к этой
книге CD-ROM.
• Откройте файл maxscript .chm из папки 3dsmax8\help на жестком
диске своего компьютера.
125
Объекты и классы
Справочное руководство по MAXScript состоит из оперативно доступных
“книг”. Каждая такая книга помечена знаком “плюс” и пиктограммой книги
в подокне Contents (Содержание) программы просмотра справки. Для пе-
рехода к отдельным разделам книги необходимо открыть ее.
2. Перейдите к книге MAXScript Language Reference^3dsMax Objects^Node:
MAXWrapper^Node Subclasses (Справочник по языку MAXScript1^ Объекты
3ds Max1^Класс Node: MAXWrapper1^ Подклассы класса Node).
Книга Node Subclasses состоит из отдельных книг по подклассам, распо-
ложенным ниже класса Node. Их имена должны быть вам знакомы, по-
скольку они обозначают объекты сцены, которые вы можете создавать на
панели Create в 3ds Мах.
3. Раскройте книгу GeometryClass: Node.
Название этой книги указывает на то, что класс GeometryClass находится
в иерархии непосредственно под классом Node.
4. Откройте раздел “GeometryClass: Node.”
В этом разделе приведены все подклассы, расположенные ниже класса
GeometryClass.
5. Откройте раздел “Geometry — Standard and Extended Objects” (Геометрия —
стандартные и расширенные примитивы).
6. Щелкните на ссылке Box, чтобы открыть раздел “Box: GeometryClass”.
В этом разделе приведены конструктор и свойства класса объектов парал-
лелепипедов. Более подробно все эти термины рассматриваются в после-
дующих разделах данной главы.
126
Глава 4
Наследование классов
Помимо собственных свойств, каждый объект может наследовать свойства от
стоящего выше класса. Для того чтобы знать все свойства объекта, которыми можно
пользоваться, нужно знать также свойства класса, стоящего выше него в иерархии.
В MAXScript у класса Node имеются определенные свойства, которые насле-
дует класс Geometryclass. Эти же свойства, в свою очередь, наследуют классы
Box, Capsule и Chamf егВох.
Для изучения свойств узла выполните следующее упражнение.
1. Откройте раздел Node: MAXWrapper^Node Common Properties, Operators,
and Methods^General Node Properties (Node: MAXWrapper^O6niHe свой-
ства, операторы и методы^Общие свойства узла) справочного руководства по
MAXScript. Первый листинг в этом разделе выглядит следующим образом:
<node>.name
В этом листинге указано имя свойства (name), доступное для всех объектов
класса Node, включая все геометрические объекты, формы, источники све-
та, вспомогательные объекты и пространственные исказители.
Кроме того, в данном листинге приведено правило, указывающее, как поль-
зоваться данным свойством в MAXScript. О том, как истолковываются пра-
вила, речь пойдет далее в этой главе. А пока что достаточно сказать, что
<node> означает любой класс объектов, стоящий ниже класса Node.
Итак, рассмотрим свойства параллелепипеда, который будет создан в сцене.
2. Введите в окне приемника команд следующий фрагмент кода:
b = box()
b.name
Вторая строка этого фрагмента кода возвращает имя параллелепипеда. Это
свойство можно использовать для изменения имени параллелепипеда.
3. Введите следующую строку кода:
b.name = "Newbox"
В этой строке параллелепипед получает новое имя Newbox.
4. Перейдите в разделе “General Node Properties” справочного руководства
к заголовку “Viewport Related Properties” (Свойства, связанные с видовыми
окнами), прокрутив текст вниз почти наполовину. В этом разделе описы-
ваются некоторые уже знакомые вам свойства:
<node>.isSelected
<node>.isHidden
Эти свойства имеют логические значения (true или false), которые ука-
зывают, выделен объект или скрыт.
Они знакомы вам как параметры, которые вы устанавливаете в диалоговом
окне Object Properties (Свойства объекта). Многие, хотя и не все, свойства
объектов класса Node соответствуют свойствам объектов 3ds Мах.
127
Объекты и классы
5. Введите в окне приемника команд следующую строку кода:
b.isSelected = true
В этой строке установлено логическое значение true свойства . isSelected.
Таким образом, параллелепипед выделяется, а в приемнике команд воз-
вращается логическое значение true.
6. Введите следующую строку кода:
b.isHidden = true
Теперь параллелепипед скрыт. Опробуйте те же самые свойства на объекте
другого типа.
Примечание. Возможно, вы обратили внимание на то, что параллелепипед
по-прежнему выделен, хотя и скрыт. Такое отклонение от нормы может
быть достигнуто только средствами MAXScript.
7. Введите следующий фрагмент кода:
с = capsule()
с.isSelected = true
В этом коде создается, а затем выделяется капсула.
Эти свойства класса Node являются общими и для всех остальных классов,
стоящих ниже него в иерархии.
Наследование классов составляет саму суть объектно-ориентированного про-
граммирования. Благодаря этому свойства и прочие данные становятся в MAXScript
общими для классов.
Во время работы над сценариями MAXScript очень полезно мыслить катего-
риями классов. Для того чтобы получить или установить определенное свойство
объекта, нужно выяснить, какие свойства имеются и как ими пользоваться. Это
зачастую означает поиск в справочном руководстве по MAXScript информации
о свойствах классов, стоящих в иерархии выше класса данного объекта.
Определение типов классов
В MAXScript предоставляются средства высокого уровня для отображения
информации о классах объектов, доступных в 3ds Мах. В этом разделе рассматри-
ваются два метода определения класса и суперкласса, к которому относится любое
значение MAXScript. В программировании на C++ или С это называется опреде-
лением типов во время выполнения (RTTI — Run Time Type Identification).
Каждый класс передает свои свойства стоящим ниже классам, поэтому очень
важно уметь быстро находить классы, стоящие выше класса конкретного объекта.
Для поиска класса и суперкласса отдельного объекта выполните следующее
упражнение.
1. Введите в приемнике команд следующую строку кода:
ClassOf с
Объект с принадлежит классу Capsule, поэтому данная строка кода воз-
вращает класс Capsule.
128
Глава 4
2. Для поиска класса, которому принадлежит данный класс, воспользуйтесь
методом classOf, указав имя самого класса:
classOf Capsule
Эта строка кода возвращает класс Geometryclass, стоящий в иерархии
непосредственно над классом Capsule.
3. Для поиска следующего вверх по иерархии класса воспользуйтесь методом
superClassOf:
superClassOf Capsule
Эта строка кода возвращает класс Node.
Запросы классов делаются в сценариях для того, чтобы гарантировать пра-
вильное использование типов объектов. Допустим, например, что создается сце-
нарий, предоставляющий пользователю возможность выделить сферу, линию или
сплайн. Далее по сценарию выбирается радиус сферы, а линия используется в ка-
честве пути для ограничения по линии пути. Для того чтобы данный сценарий ра-
ботал правильно, необходимо убедиться в том, что пользователь выделяет объек-
ты нужного типа. Для проверки правильности такого выделения можно сделать
запросы соответствующих классов.
Ниже приведен краткий сценарий, демонстрирующий применение запросов
классов при определении пользовательского интерфейса в сценарии:
If ((spherePath != undefined) and (spherePath.isDisplayed == true)) do
(destroyDialog spherePath)
rollout spherePath "Sphere and Path"
(
pickbutton pick_sphere "Click to Pick Sphere"
pickbutton pick_path "Click to Pick Path"
on pick_sphere picked sphObject do
(
if classOf sphObject!=sphere then \
messagebox "Please pick a sphere."
)
on pick_path picked pathobject do
(
if classOf pathObject!=line and classOf pathobject!=SplineShape
then messagebox "Path must be a line or editable spline."
)
)
createDialog spherePath
Дополнительные сведения по данному вопросу приведены в следующих разде-
лах справочного руководства по MAXScript.
• MAXScript Language Reference^Values^Working with Values (Справочник
по языку МАХБспр^Значения1^Работа co значениями)
• MAXScript Language Reference^SdsMax Objects^ldentifying and Accessing
MAXScript Classes and Properties (Справочник по языку МАХБспр^Объекты
3ds Max1^ Определение и доступ к классам MAXScript и их свойствам)
129
Объекты и классы
Экземпляры
Объект, создаваемый средствами MAXScript, называется экземпляром данного
класса MAXScript. Так, созданные вами ранее объекты Ь и с являются экземпля-
рами классов Box и Capsule соответственно. Не путайте эту разновидность эк-
земпляра с клоном объекта сцены, поскольку это совсем разные вещи.
Свойства всегда используются с помощью экземпляра класса, а не самого
класса. В MAXScript свойства используются в переменной, хранящей экземпляр,
или в объекте, обозначаемом по имени.
Для изучения экземпляров выполните следующее упражнение.
1. Введите в приемнике команд следующую строку кода:
box.name
В ответ на эту строку кода в приемнике команд появится сообщение об
ошибке, поскольку в ней предпринята попытка воспользоваться свойством
с помощью класса, а не экземпляра данного класса.
2. Введите следующую строку кода:
b.name
Эта команда возвращает имя параллелепипеда и не приводит к ошибке.
Совет. Если BoxOl фактически является именем объекта сцены, его можно
также использовать следующим образом:
$Box01.name
Понятие экземпляров имеет очень большое значение в MAXScript. Класс
можно рассматривать в качестве типа объекта, а экземпляр — в качестве конкрет-
ного образца объекта данного типа. Класс — это концептуальное образование
группы объектов, тогда как экземпляр — это конкретный объект. В MAXScript
функции выполняются над экземплярами, а не над классами.
В справочном руководстве по MAXScript имя класса в угловых скобках о
обозначает экземпляр данного класса, указанного в этих скобках. Например,
<Capsule> означает экземпляр класса Capsule, тогда как <node> — экземпляр
любого объекта в классах, стоящих в иерархии ниже класса Node.
Свойства
Если объект — это какая-то вещь, то свойство — это сведения о вещи. Рассмот-
рим в качестве реального примера чашку, стоящую на столе. Если чашка — это
объект, то цвет, размер, текстура и температура являются свойствами чашки.
У каждого объекта в MAXScript имеются определенные свойства. С некото-
рыми свойствами объектов вам уже приходилось иметь дело в сценариях из пре-
дыдущих глав этой книги. В частности, у параллелепипедного объекта имеются
свойства, перечисленные в разделе “Box: GeometryClass” справочного руководства
по MAXScript. Эти же свойства появляются, когда к объекту применяется метод
showPrope гt i е s.
Более подробно свойства рассматриваются в конце этого раздела.
130
Глааа 4
Запрос свойств
Метод showProperties был представлен в качестве функции в главе 1. Дан-
ный метод полезен для вывода свойств объекта в окне приемника команд. В этом
подразделе представлены дополнительные способы доступа к свойствам объекта.
Довольно часто приходится решать задачу определения свойств объекта,
а главное — получать доступ к этим свойствам. Допустим, например, что требуется
сохранить в массиве все значения, описывающие параллелепипед. Для решения
такой задачи можно было бы, на первый взгляд, воспользоваться методом
showProperties и вывести свойства данного объекта в окне приемника команд.
Но в этом случае нельзя ни получить доступ к свойствам объекта, ни возвратить
их в строке. Следовательно, для возврата массива значений требуется специаль-
ный метод. Именно это и делает метод getPropNames. Его синтаксис следующий:
getPropNames <maxwrapper_object> [#dynamicOnly]
Данный метод возвращает массив значений в виде имен свойств, доступных
в указанном объекте.
Примечание. В этом подразделе необязательный аргумент #dynamicOnly
не рассматривается, поэтому за дополнительными сведениями обращайтесь
к справочному руководству по MAXScript.
Для получения имен свойств выполните следующее упражнение.
1. Установите 3ds Мах в исходное состояние и откройте новое окно редактора
сценариев.
2. Откройте окно приемника команд и введите следующий фрагмент кода:
b = box()
boxProps = getPropNames b
В приемнике команд выводится массив, содержащий свойства параллеле-
пипеда:
#(#height, #length, #lengthsegs, #width, #widthsegs, \
#mapcoords, #heightsegs, #realWorldMapSize)
Это те же самые свойства, которые отображаются для параллелепипеда на
панели Modify.
Примечание. В версии 3ds Мах 8 метод getPropNames (наряду с методом
showProperties) теперь применяется к свойствам интерфейса публикации
функций.
Получение и установка свойств
Итак, имея массив свойств параллелепипеда, можно воспользоваться метода-
ми getProperty и setProperty для получения и установки его свойств. Син-
таксис каждого из этих методов следующий:
getProperty cmaxwrapper object> «property_name>
setProperty cmaxwrapper object> <property_name> <value>
131
Объекты и классы
В качестве параметра <property_name> указывается имя свойства, например
#height, или же строка, например "height" (т.е. высота). А в качестве парамет-
ра «value> указывается значение, присваиваемое данному свойству.
Для получения и установки свойств объекта выполните следующее упражнение.
1. Введите в приемнике команд следующую строку кода:
getProperty b #height
В приемнике команд появится результат 25,0.
2. Выделите параллелепипед в видовом окне и перейдите к панели Modify.
Убедитесь в том, что высота параллелепипеда действительно составляет
25,0 единиц (это значение устанавливается по умолчанию).
3. Введите следующую строку кода:
setProperty b #height 40
4. Как видите, высота параллелепипеда в видовом окне изменилась и теперь
составляет 4 0,0 единиц. Эту последнюю строку кода можно было бы напи-
сать следующим образом:
Ь.height = 40.
Последний вариант короче и проще читается. Так в чем же преимущество ме-
тодов getProperty и setProperty? Если в коде сценария требуется доступ
только к одному свойству, для этого достаточно такой строки, как b. height
= 4 0. Но если требуется доступ ко всем свойствам объекта, для этой цели
лучше всего воспользоваться методами getPropNames и setProperty.
Примечание. При установке свойства следует убедиться в том, что
значение последнего аргумента соответствует типу устанавливаемого
свойства. Например, следующая строка кода приводит к ошибке:
setProperty b #height "foo" -- этот код приводит к ошибке
5. Продолжите текущий пример и выведите свойства параллелепипеда и их
значения на печать в приемнике команд, введя следующий фрагмент кода:
boxProps = getPropNames b
for prop in boxProps do format "% = %\n" prop (getProperty b prop)
В окне приемника команд выводятся следующие свойства параллелепипеда
и их значения:
#height =25.0
#length =25.0
#lengthsegs = 1
#width =25.0
#widthsegs = 1
#mapcoords = false
#heightsegs = 1
#realWorldMapSize = false
Дополнительные сведения по данному вопросу приведены в следующем разде-
ле справочного руководства по MAXScript: MAXScript Language Referenced
3dsMax Objectsdidentifying and Accessing MAXScript Classes and Properties.
132
Глава 4
Вложенные свойства
Некоторые свойства имеют собственные свойства. Например, как было пока-
зано выше, у свойства .pos имеются дополнительные свойства . х, .у и . z, обо-
значающие положение объекта по осям X, Y и Z. Эти дополнительные свойства
называются вложенными.
Следующая команда возвращает положение объекта по оси X, представленное
числом:
<node>.pos.х
Для того чтобы воспользоваться данным свойством, замените <node> экземп-
ляром объекта, как, например, в следующей строке кода:
b.pos.х
При этом возвращается положение объекта по оси X.
Следующая команда возвращает применяемый к объекту контроллер управле-
ния вращением:
<node>.rotation.controller
Дополнительные сведения по данному вопросу приведены в следующих разде-
лах справочного руководства по MAXScript.
• MAXScript Language Reference^SdsMax Objects^MAXWrapper: Valued
Nested Object Properties (Справочник по языку MAXScript^Объекты 3ds
Max О Класс MAXWrapper: Значение1^ Вложенные свойства объектов)
• MAXScript Language Reference^SdsMax Objects^Node: MAXWrapper1^
Node Common Properties, Operators, and Methods^Node Transform Properties
(Справочник по языку МАХЗспрС^Объекты 3ds МахФКласс Node:
MAXWrapper^OdiHHe свойства, операторы и методы класса Node^b
Свойства преобразования узла)
Класс MAXWrapper
Класс MAXWrapper включает в себя все объекты сцены 3ds Мах, а также мо-
дификаторы, материалы и эффекты. Ниже приведена часть иерархии класса
MAXWrapper.
Value
MAXWrapper
Node
Modifier
Atmospheric
Рассмотрим более подробно класс Modifier.
В MAXScript каждый модификатор, по существу, считается объектом. Для то-
го чтобы воспользоваться объектом-модификатором, необходимо получить его эк-
земпляр. Так, если требуется применить модификатор Bend к объекту, для этого
придется получить экземпляр данного модификатора.
Для ввода модификатора, выполните следующее упражнение.
133
Объекты и классы
1. Перейдите к разделу MAXScript Language Reference^SdsMax Objects1^
Modifier: MAXWrapper and SpacewarpModifier: MAXWrapperbModifier and
SpacewarpModifier Types ^Modifiers (Справочник по языку MAXScript1^
Объекты 3ds Max О Класс Modifier: Классы MAXWrapper и Spacewarp-
Modifier'. MAXWrapper1^Типы Modifier и SpacewarpModifier^Mo-
дификаторы) справочного руководства no MAXScript.
В этом разделе приведены все классы объектов, стоящие ниже класса
Modifier.
2. Введите в приемнике команд следующую строку кода:
cyl = cylinder heightsegs:5
Таким образом, получен экземпляр цилиндра с пятью сегментами по высоте.
3. Переместите цилиндр в любом видовом окне в сторону от параллелепипеда,
чтобы лучше его видеть.
4. Введите следующую строку кода:
myMod = bend()
Итак, получен экземпляр модификатора Bend.
5. Введите в приемнике команд следующую строку кода:
addmodifier cyl myMod
В этой строке модификатор Bend применяется к экземпляру цилиндра
и появляется в стеке модификаторов цилиндра. Для того чтобы ввести мо-
дификатор Bend в цилиндр, вам пришлось получить его экземпляр и затем
использовать этот экземпляр в последней строке кода, чтобы применить
данный модификатор к объекту.
Если вы являетесь опытным пользователем 3ds Мах, то такой принцип
применения модификаторов может показаться вам несколько запутанным.
Ведь когда вы работаете в пользовательском интерфейсе 3ds Мах, вам не
нужно создавать модификатор или контроллер в качестве отдельного объек-
та, прежде чем применять его к объекту. Вы просто выбираете его из меню
или панели команд. Но в MAXScript приходится создавать экземпляр каж-
дого элемента сцены, прежде чем делать с ним что-нибудь.
Впрочем, из данного правила имеются исключения; но, прежде чем уяснить
их, нужно как следует усвоить порядок получения экземпляров всех объек-
тов в MAXScript — даже таких, как модификаторы, которые не являются
объектами сцены.
Для изучения свойств модификаторов выполните следующее упражнение.
1. Откройте раздел “Bend: Modifier” (Модификатор Bend) справочного руко-
водства по MAXScript.
Свойства модификатора Bend совпадают с его параметрами, появляющи-
мися в момент применения данного модификатора в сцене 3ds Мах.
Экземпляр модификатора Bend, присвоенный переменной myMod, сохраня-
ет свою связь с конкретным модификатором в сцене 3ds Мах. Следовательно,
134
Главе 4
когда изменяются свойства переменной myMod, изменяются также пара-
метры модификатора Bend, применяемого на сцене к цилиндру.
2. Введите в приемнике команд следующую строку кода:
myMod.angle = 90
Параметр Angle (Угол сгибания) модификатора Bend, находящегося на
сцене, изменяется до 9 0 ° и цилиндр сгибается.
Когда модификатор применяется к объекту, а сам модификатор трактуется,
как свойство данного объекта. Например, в следующей строке кода уста-
навливается угол сгибания модификатора Bend:
с.bend.angle = 60
Методы
Метод представляет собой функцию, которая выполняет определенные дейст-
вия над объектом MAXScript. Аналогично свойствам, методы наследуются от од-
ного класса к другому вниз по иерархии. Иными словами, методы, доступные для
конкретного класса, доступны и для его подклассов.
Ниже перечислены некоторые методы класса Node.
• hide <node>
• select <node>
• distance <node> <node>
Поскольку эти методы доступны для класса Node, они доступны также для всех
объектов в классе GeometryClass, включая параллелепипеды, цилиндры и капсулы.
Методы hide и select выполняют ту же функцию, что и свойства
.isHidden и .isSelected. Во многих случаях действие в MAXScript может
быть выполнено как посредством метода, так и с помощью свойства.
Дополнительные сведения по данному вопросу приведены в следующем разделе
справочного руководства по MAXScript: MAXScript Language Reference^SdsMax
Objects^Node: MAXWrapper^Node Common Operators, Properties, and Methods.
Конструкторы
Конструктор представляет собой метод специального типа, создающий экзем-
пляр класса объектов. В сценариях из предыдущих глав вам уже приходилось
пользоваться некоторыми конструкторами.
В следующей строке кода конструктор box используется для создания парал-
лелепипеда, который затем присваивается переменной Ь:
b = box()
Вслед за конструктором должны быть указаны круглые скобки или же уста-
навливаемые свойства класса. В следующей строке кода приведен еще один впол-
не допустимый пример применения конструктора box:
box length:40 width:20
135
Объекты и классы
Конструкторы применяются также для создания других типов объектов, вклю-
чая модификаторы и контроллеры.
myMod = bend()
В этой строке кода создается экземпляр класса модификатора Bend в перемен-
ной myMod.
У каждого класса объектов имеется собственный конструктор. Для сравнения
такие методы, как hide <node>, являются общими для всех классов, стоящих
в иерархии ниже класса Node.
Для обнаружения конструкторов конкретного класса объектов найдите раздел,
посвященный данному классу объектов, в содержании справочного руководства
по MAXScript. Если у класса имеются конструкторы, они перечислены в начале
данного раздела.
Конструирование на ходу
Выше вам пришлось получить экземпляр модификатора, прежде чем приме-
нить его к объекту. Этого можно избежать, если воспользоваться конструктором
в выражении и тем самым избавить себя от необходимости создавать модифика-
тор (или другой объект) перед тем, как использовать его в сценарии.
Например, с помощью следующей команды можно применить модификатор
Bend к объекту с:
addmodifier с (bendO)
В данном примере конструктор bend () используется по ходу применения мо-
дификатора Bend к объекту. В этом случае конструктор должен быть указан в круг-
лых скобках. Недостаток такого подхода заключается в отсутствии отдельной пере-
менной (например, myMod), для которой можно получать и устанавливать свойства.
Методы типа get и set
Методы нередко начинаются с префикса get или set. Так, метод с префиксом
get используется для получения, а метод с префиксом set — для установки кон-
кретных свойств объекта.
Большая часть методов типа get и set применяется в классе Editable_Mesh,
который стоит в иерархии ниже класса GeometryClass.
Для изучения методов типа get и set выполните следующее упражнение.
1. Откройте раздел MAXScript Language Reference^SdsMax Objects^Editable
Meshes, Splines, Patches, and Polys^EditableJMesh and TriMesho
Editable_Mesh: GeometryClass and TriMesh: Value (Справочник по язы-
ку MAXScript^Объекты 3ds Max^Редактируемые каркасы, сплайны,
лоскуты и многоугольники1^ Классы Editable_Mesh и TriMesh^b Класс
Editable_Mesh: Классы GeometryClass и TriMesh: Значение) в спра-
вочном руководстве по MAXScript.
В этом разделе приведены все методы и свойства, характерные для редак-
тируемых каркасов. Вместо того чтобы создавать и править совершенно но-
вый каркас, можно преобразовать параллелепипед в редактируемый каркас.
136
Глава 4
2. Прокрутите текст справочного руководства до конца раздела “Constructors
(EditableMesh)” (Конструкторы класса Editable_Mesh). Два последних
метода в этом разделе преобразуют любой объект класса Node в редакти-
руемый каркас.
3. Введите в приемнике команд следующую строку кода:
m = convertToMesh b
Перейдя к панели Modify, вы можете обнаружить, что параллелепипед пре-
образован в редактируемый каркас.
4. Откройте следующий раздел справочного руководства, “Mesh Vertex
Methods’’ (Методы манипулирования вершинами каркаса). Первым в этом
разделе перечислен метод getNumVerts. Попробуйте применить его.
5. Введите в приемнике команд следующую строку кода:
getNumVerts m
В приемнике команд возвратится значение 8, обозначающее число вершин
в редактируемом каркасе.
Этот метод можно также использовать для присваивания числа вершин пе-
ременной:
numVerts = getNumVerts m
В этой строке кода число вершин (в данном случае — 8) присваивается пе-
ременной numVerts.
Отображаемые методы
Некоторые методы могут воздействовать на всю совокупность объектов одной
командой. Когда операция выполняется над целым рядом объектов, то говорят,
что она отображается на зти объекты.
Применяя метод к одному или нескольким объектам, можно воспользоваться
метасимволом для обозначения этих объектов либо организовать их в совокупность
или массив и затем применить данный метод к полученной совокупности объектов.
Для изучения отображаемых методов выполните следующее упражнение.
1. Вновь откройте раздел “Editable Mesh : GeometryClass and TriMesh: Value”
справочного руководства.
2. Прокрутите текст вниз и найдите правило для метода convertToMesh:
convertToMesh <node> -- mapped
Обозначение mapped (отображаемый метод), приведенное после этого пра-
вила, указывает на то, что данный метод можно применять к нескольким
объектам сразу. Попробуйте применить данный метод к находящимся на
сцене объектам.
3. Установите 3ds Мах в исходное состояние или удалите все объекты со сцены.
4. Введите в приемнике команд следующий фрагмент кода:
137
Объекты и классы
с = cylinder pos:[50,0,0]
Ь = box()
s = sphere pos:[-50,0,0]
В этом коде три объекта создаются в разных местах сцены.
5. Введите в приемнике команд следующую строку кода:
convertToMesh $*
В этой строке метасимвол * служит для обозначения всех преобразуемых
объектов сцены в редактируемые каркасы. Далее вам предстоит создать
массив для хранения этих объектов и применить к данному массиву соот-
ветствующий метод.
6. Введите в приемнике команд следующую строку кода:
objectArray = #(c,b,s)
В итоге создается массив obj ectArray, содержащий три объекта.
7. Введите в приемнике команд следующую строку кода:
hide objectArray
Все объекты скрываются на сцене. Метод hide, который может применять-
ся ко всем членам класса Node, является также отображаемым методом.
Работа со справочным руководством
по MAXScript
А теперь, когда вы ознакомились с объектами, классами, свойствами, методами
и их взаимными отношениями в MAXScript, рассмотрим ряд инструментов, помо-
гающих более эффективно пользоваться справочным руководством по MAXScript.
Грамматика MAXScript
Информация в каждом разделе справочного руководства по MAXScript распо-
ложена по определенным грамматическим правилам, указывающим, как пользо-
ваться конкретным методом или свойством в сценарии.
Выше уже были приведены некоторые примеры грамматики MAXScript. В ча-
стности:
<node>.name
hide <node>
convertToMesh <node> -- mapped
Из этих примеров можно вывести следующие правила.
• Полужирным выделен текст, который следует вводить в сценарии без изме-
нения.
• В угловых скобках <node > указывается класс объектов.
Имеются и другие грамматические правила, которые нужно знать, читая спра-
вочное руководство по MAXScript. Эти правила следующие.
138
Глава 4
• [...] — элементы в квадратных скобках являются необязательными. Их
можно указать один раз или вообще ни разу.
• {...}— элементы в одних только фигурных скобках являются необязатель-
ными. Их можно указать один или более раз либо вообще ни разу.
• {...}+— элементы в фигурных скобках со знаком “плюс” являются обяза-
тельными. Их можно указать один или более раз.
• {...|...|.„} — если элементы разделены вертикальной чертой, вводить можно
только один из них при условии, что данный вариант используется. Элемен-
ты, разделенные вертикальной чертой, могут быть заключены в квадратные
или фигурные скобки в зависимости от того, сколько раз они указываются.
• <> — элементы в угловых скобках обозначают правило синтаксиса, опреде-
ленное в другом месте, например:
• <node> — член класса Node;
• «digit> — целое число;
• «point 3 > — ряд из трех значений.
Определения правил
Многие правила определяются в разделе “MAXScript Grammar” (Грамматика
языка MAXScript) книги MAXScript Language Reference. В этом разделе знаком
: : = обозначается определение правила, например:
«point3> ::= [ «ехрг>, «ехрг>, «ехрг> ]
В данном примере определяется правило указания объекта типа points.
Квадратные скобки выделены полужирным, обозначая тот факт, что они вводятся
так, как показано в данном правиле. Иными словами, они не обозначают необяза-
тельный элемент.
Правило «ехрг> обозначает выражение. В MAXScript имеются самые разные
типы выражений, простейшим из которых является целое число.
Из этого правила можно сделать вывод, что следующая строка кода является
вполне допустимым способом выражения объекта типа Points в MAXScript:
х = [10, 20, 15]
Примечание. Еще один допустимый способ создания объекта типа Points
состоит в использовании конструктора, представленного ранее в этой книге:
х = points 10 20 15
В этой строке кода создается значение типа Points переменной х. Для этой
цели можно было бы также воспользоваться следующим выражением:
х = [j * 10, 8, myVar]
Эта строка кода является вполне допустимой при условии, что переменные j
и myVar определены в другом месте сценария, а в выражениях вычисляются дей-
ствительные значения составляющих отдельного значения типа Points.
139
Объекты и классы
Необязательные параметры
Во многих методах MAXScript используются необязательные параметры с клю-
чевыми словами. В этом разделе будет показано, как следует читать листинги
и как пользоваться такими параметрами в методах.
Для того чтобы научиться пользоваться необязательными параметрами, вы-
полните следующее упражнение.
1. Откройте раздел MAXScript Language Reference<>3dsMax Objects^Modifier:
MAXWrapper and SpacewarpModifier: MAXWrapper^Modifier Common
Properties, Operators, and Methods (Справочник по языку MAXScript1^
Объекты 3ds Max=>Классы MAXWrapper и SpacewarpModifier: Класс
MAXWrapper<>O6mHe свойства, операторы и методы модификаторов). Под
рубрикой “Associated Methods” (Связанные методы) приведен второй метод
в следующем виде:
addModifier <node> <modifier> [before:index] -- mapped
Вы уже пользовались этим методом со следующим синтаксисом:
addmodifier <node> <modifier>
Текст, заключенный в угловые скобки, вводить необязательно. В тексте,
приведенном ниже листинга этого метода в справочном руководстве, сооб-
щается, что данный аргумент может быть использован для указания в стеке
места, куда должен быть помещен модификатор. Так, индекс 2 означает, что
модификатор следует поместить на второй от вершины стека позиции.
Текст before является ключевым словом, которое следует ввести в код,
чтобы указать, что именно нужно сделать.
2. Далее создайте два экземпляра модификаторов:
myModl = bend()
myMod2 = twist(
3. Введите один модификатор в объект:
addmodifier с myModl
4. Введите следующую строку кода, чтобы применить в стеке модификатор
Twist ниже модификатора Bend:
addmodifier с myMod2 before:2
5. Попробуйте выполнить следующую команду:
addmodifier с myMod2 2
При этом возникает ошибка, поскольку для нормального выполнения дан-
ной команды ее необходимо дополнить ключевым словом before.
Возвращаемые значения
В справочном руководстве по MAXScript листингу метода иногда предшеству-
ет текст в угловых скобках. В этом случае текст в угловых скобках обозначает тип
данных, возвращаемых данным методом. Такой синтаксис характерен для методов
типа get и set.
140
Глава 4
Для того чтобы посмотреть пример указания возвращаемых значений, открой-
те раздел MAXScript Tools and Interaction with SdsMax^Interacting with the
3dsMax User Interface^Filters^Selection Filter (Инструменты MAXScript и взаимо-
действие c 3ds Max^ Взаимодействие с пользовательским интерфейсом 3ds Мах^
Фильтры1^ Фильтр выделения) справочного руководства. Четыре первых листин-
га в этом разделе следующие:
<int>GetSelectFilter
<void>SetSelectFilter <int_index>
<int>GetNumberSelectFilters
<BOOL>GetDisplayFilter <int_index)
Метод с предваряющим его текстом в угловых скобках обозначает, что команда
возвращает значение указанного типа:
• < int > — возвращает целое число;
• <void> — не возвращает значение;
• <Ьоо1> -- возвращает логическое значение true или false.
Если известен тип значения, возвращаемого командой, то можно выбрать пере-
менную соответствующего типа для хранения возвращаемого значения, например:
х = GetSelectFilter --в переменной х сохраняется целое значение
у = GetDisplayFilter 3 -- в переменной у сохраняется логическое
значение true или false
Присваивание ссылок
Когда переменной присваивается значение, то создается впечатление, будто
значение фактически сохраняется в переменной. На самом же деле в переменной
сохраняется ссылка на значение.
Рассмотрим, например, следующее выражение:
а = [0,20,45]
В этом выражении значение [0,20,45] типа Point3 в переменной а не со-
храняется. Вместо этого оно сохраняется в определенной ячейке оперативной па-
мяти, а указатель на эту ячейку помещается в переменной а. Иными словами, пе-
ременная а содержит ссылку на значение типа Point 3, а не само значение.
Казалось бы, такое различие не очень существенно, поскольку переменные
и их значения можно использовать, не заботясь о том, что и где хранится. Однако
данный принцип приобретает особую важность, если одно и то же значение при-
сваивается нескольким переменным.
Допустим, что в сценарий введена следующая строка кода:
а=Ь=с= [0,20,45]
Ссылка на одно и то же значение типа Point 3 делается в трех переменных: а, Ь и с.
Если полностью изменить значение типа Point 3 в одной из переменных, эта пе-
ременная уже не будет указывать на ту же самую ячейку памяти. Так, в приведенной
ниже строке изменяется значение типа Point3, на которое делается ссылка в пере-
менной Ь, поэтому она уже не указывает на ту же ячейку памяти, что и переменная с:
Ь = [0,0,30]
141
Объекты и классы
Что же касается переменных а и с, то в них по-прежнему делается ссылка на
исходное значение [0,20,45]. Но если изменить лишь одну составляющую дан-
ного значения, то ситуация окажется совсем иной. Допустим, что следующая
строка кода используется далее в сценарии для того, чтобы изменить положение
объекта по оси X:
а.х = 90
В этой строке изменяется первая составляющая значения типа Point3. Ее
значение становится равным 90. Но, помимо этого, в данной строке кода изменя-
ется значение, на которое делается ссылка в переменных а и с, а следовательно,
обе переменные теперь обращаются к значению [90,20,45].
Это же справедливо и для ссылочных массивов. Допустим, что созданы три
ссылочных массива следующим образом:
d = е = f = #(5,10,15,21)
Если изменить один элемент массива, это изменение коснется всех переменных:
е[4] = 20
Теперь в переменных d, е и f делается ссылка на массив #(5,10,15,20).
Заключение
В этой главе вы изучили самые важные принципы объектно-ориентированного
программирования и узнали, как они реализованы в MAXScript. В частности, вы
ознакомились с иерархией классов в MAXScript и узнали, как свойства, опреде-
ленные в родительском классе, реализуются в базовых классах. Кроме того, вы оз-
накомились с классом MAXWrapper и научились определять класс объектов сце-
ны, модификаторов и других типов данных во время выполнения сценария, чтобы
сценарий реагировал соответствующим образом. И наконец, что важнее всего, вы
научились пользоваться справочным руководством по MAXScript.
142
Преобразования и анимация
Глава 5
Эта глава посвящена реализации принципов
анимации средствами MAXScript. Анимация
организуется в 3ds Мах с помощью одного из
множества классов контроллеров,
доступных в окне Тrack View и на панели
Motion либо автоматически назначаемых
средствами 3ds Мах, когда пользователь
выбирает кнопку Animate для расстановки
ключевых кадров анимации. Все эти классы
контроллеров доступны и в MAXScript.
Преобразования и анимация
Задание
После изучения этой главы вы должны уметь следующее.
• Работать с преобразованиями перемещением, вращением и масштабирова-
нием в MAXScript
• Точно рассчитывать вращения
• Изменять точку опоры объекта или ось его вращения
• Создавать и удалять ключевые кадры анимации
• Работать с контроллерами
• Работать с разными типами касательных
Введение
В этой главе вы научитесь эффективно пользоваться преобразованиями при
написании сценариев. Объекты обычно требуется преобразовывать на основании
пользовательского ввода, а для их анимации устанавливаются ключевые кадры.
Кроме того, в этой главе вы научитесь устанавливать и применять контролле-
ры для специальной настройки анимации.
Свойства преобразований изменением
положения и масштабированием
Для всех геометрических объектов, независимо от их типа, имеются следую-
щие свойства положения и масштаба:
.pos
.position - то же, что и .pos
.scale
В этой главе сначала рассматриваются преобразования изменением положения
и масштабированием, поскольку они выполняются сходным образом. А у преобра-
зования вращением имеются ограничения, которые приходится принимать во
внимание при выполнении вращения по сценарию.
Преобразование изменением положения
Положение объекта может быть установлено двумя способами.
• Непосредственно с помощью свойства .pos или .position
• Косвенно с помощью метода move
В главе 1 вы научились устанавливать положение любого объекта непосред-
ственно с помощью свойства .posили .position:
144
Глава 5
s = sphere()
s.pos = [150, 10 , 0]
s.pos.x = 200
А с помощью метода move это делается следующим образом:
move s [10.0, 10.0, 10.0]
Перечень аргументов метода move состоит из ссылки на перемещаемый объект
и величины этого перемещения в виде данных типа Points. Следует, однако,
иметь в виду, что метод move перемещает объект не в точку с координатами [х, у, z],
а на величину [х, у, г]. Следовательно, если применить данный метод несколько
раз, объект будет непрерывно перемещаться на указанную величину.
Значение свойства положения задается явно и не увеличивается всякий раз.
Для того чтобы воспользоваться свойством pos и методом move, выполните
следующее упражнение.
1. Установите 3ds Мах в исходное состояние.
2. Введите в приемнике команд следующую строку кода:
s = sphere()
3. Введите следующий ряд строк кода:
s.pos.x = 25
s.pos.x = 25
s.pos.x = 25
При выполнении данной строки кода три раза подряд сфера устанавливает-
ся в точке с координатой х = 25.
4. Введите следующий ряд строк кода и нажмите клавишу <Enter> после ка-
ждой из них:
move s [25, 0, 0 ]
move s [25, 0, 0]
move s [25, 0, 0]
5. В итоге сфера переместится на 7 5 единиц по оси X.
Преобразование масштабированием
Свойство масштаба (scale) определяет сжатие или растяжение объекта вдоль
указанной оси. По умолчанию значение составляющих X, Y и Z свойства масшта-
ба равно 1,0, что соответствует масштабу 100% объекта по каждой из осей коор-
динат. Если установить значение одной из составляющих свойства масштаба рав-
ным 2,0, исходный масштаб объекта увеличится вдвое, а если установить ее
значение равным 0, 5, то исходный масштаб объекта сократится наполовину.
Масштаб объекта можно изменить по всем трем координатам следующим образом:
s.scale = [2.0, 1.0, 0.5]
Аналогично положению, масштаб указывается в виде данных типа Points.
В приведенном выше примере объект растягивается в два раза вдоль оси X, не изме-
няет свой размер вдоль оси Y и сокращается вдоль оси Z. Если же объект требуется
растянуть только вдоль оси X, для этого достаточно ввести следующую строку кода:
s.scale.х = 2.0
145
Преобразования и анимация
Для пропорционального масштабирования объекта достаточно умножить
свойство масштаба на требуемую величину:
s.scale = 3.0 * s.scale -- или
s.scale *= 3.0
Приведенный выше фрагмент кода означает следующее: “Установить новое
значение свойства масштаба, которое в 3 раза больше его текущего значения”. При
этом объект масштабируется по всем трем осям.
Аналогично свойству pos и методу move для свойства масштаба имеется соот-
ветствующий метод scale. Данный метод реализуется следующим образом:
b = box()
scale b [1.0, 2.0, 3.0]
В этом фрагменте кода параллелепипед масштабируется на разную величину
в направлении каждой из осей координат. Свойство . scale и метод scale дейст-
вуют таким же образом, как и свойство .position и метод move, а именно: зна-
чение свойства задается явно в виде данных типа Point3, а метод изменяет это
значение с указанным приращением.
Для масштабирования объекта выполните следующее упражнение.
1. Введите в окне приемника команд следующую строку кода:
b = box()
2. Для того чтобы установить свойство масштаба, введите и вычислите сле-
дующую строку кода:
b.scale = [2, 2, 2]
В качестве результата в приемнике команд возвращается значение [2, 2, 2 ]
данного свойства.
3. Для того чтобы вновь установить масштаб, введите следующую строку кода:
b.scale = [2, 2, 2]
В приемнике команд по-прежнему возвращается значение [2, 2, 2].
4. Примените метод scale, введя следующую строку кода:
scale b [2, 2, 2]
В приемнике команд возвращается значение [4, 4, 4].
Преобразование вращением
Вращение является более сложным видом преобразования, чем изменение по-
ложения и масштаба, поскольку требует более сложных математических расчетов.
Как и для изменения положения и масштаба, для вращения объектов в MAXScript
предусмотрены два способа.
• Установка свойства . rotation объекта явным образом
• Применение метода rotate
При изменении положения и масштаба значения по каждой из осей X, Y и Z
всегда выражаются одним числом, например 1, 0 или 34,5. А вращение на опре-
146
Глава 5
деленное количество градусов вокруг конкретной оси выражается несколькими
способами, причем с разной интерпретацией величины вращения. Итак, для вра-
щения объекта имеются следующие методы.
• EulerAngles
• Кватернионы
• AngleAxis
Метод EulerAngles
Метод EulerAngles является, вероятно, самым понятным и лучше всего со-
ответствующим тем операциям вращения, которые можно выполнять и наблюдать
в интерфейсе 3ds Мах.
Конструктор класса EulerAngles воспринимает три аргумента, выражаемые
в градусах (по одному для каждой из осей). Эти значения используются в данном
методе для вращения объекта на указанное число градусов вокруг заданной оси
в системе мировых координат:
b.rotation = eulerAngles 0 45 О
В приведенной выше строке кода объект поворачивается на 4 5 ° вокруг оси Y в сис-
теме мировых координат. Вращение по методу eulerAngles проще всего понять,
поскольку оно соответствует вращению объектов, наблюдаемому в видовых окнах.
Результат вращения по методу eulerAngles можно присвоить переменной,
чтобы затем использовать в другом объекте:
ang = eulerAngles 0 45 О
b.rotation = ang
Переменная ang в действительности представляет собой объект MAXScript,
имеющий тип данных вращения.
Углы вращения вокруг нескольких осей указываются следующим образом:
ang = eulerAngles 30 20 44
При установке ключевых кадров анимации с помощью метода eulerAngles
изменение вращения между двумя последовательными ключевыми кадрами огра-
ничивается углом 180°, поскольку в методе eulerAngles используется крат-
чайший путь перехода от одного ключевого кадра к другому.
Для того чтобы повернуть объект методом eulerAngles, выполните следую-
щее упражнение.
1. Введите в приемнике команд следующий фрагмент кода, чтобы создать ци-
линдр и переменную euAngle:
С = cylinder height:50
euAngle = eulerAngles 0 45 0
В итоге значение угла поворота типа eulerAngles присваивается пере-
менной euAngle.
2. Введите следующую строку кода, чтобы повернуть цилиндр:
rotate с euAngle
147
Преобразования и анимация
Когда объект поворачивается подобным методом, сначала происходит его
вращение вокруг оси X, затем вокруг оси Y и наконец вокруг оси Z. Это об-
стоятельство очень важно иметь в виду, потому что от перестановки поряд-
ка вращения меняется результат. Иными словами, вращение вокруг оси Y
после вращения вокруг оси X дает иной результат, чем вращение вокруг оси
X после вращения вокруг оси Y.
Свойство вращения
Составляющие свойства вращения объекта могут использоваться для задания
вращения вдоль конкретной оси. Например, выражения
euAngle = eulerAngles 30 45 60
rotate b euAng
можно заменить выражениями, в которых свойство вращения устанавливается
непосредственно:
b.rotation.x_rotation = 30
b.rotation.y_rotation = 45
b. rotation.z_rotation = 60
При таком способе установки свойства вращения угол поворота ограничивает-
ся величиной 360°.
Для проверки ограничения угла поворота величиной 360° выполните следую-
щее упражнение.
1. Установите 3ds Мах в исходное состояние.
2. Создайте стандартный параллелепипед, введя в приемнике команд сле-
дующую строку кода:
b = box()
3. Переместите ползунок временной шкалы к кадру 1 о, включите режим Auto Key
(Автоматическая расстановка ключевых кадров), а затем введите следую-
щую строку кода:
b.rotation.z_rotation = 720
4. Выключите режим Auto Key и воспроизведите анимацию.
Объект не вращается.
148
Глава 5
5. Переместите ползунок временной шкалы к кадру 10, включите режим Auto
Key, а затем введите следующую строку кода:
b.rotation.z_rotation = 450
6. Выключите режим Auto Key и воспроизведите анимацию.
Объект повернется только на 90°, поскольку полный его оборот на 3 60°
игнорируется (450 - 360 = 90).
Ограничения, присущие методу EulerAngies
Выполнение эйлерова вращения вызывает особые трудности как внутри 3ds
Мах, так и в MAXScript. Эти трудности связаны с тем, что при вращении объекта
вокруг одной оси соответствующие изменения происходят относительно осталь-
ных осей. Данный факт иллюстрирует следующее упражнение.
1. Установите 3ds Мах в исходное состояние.
2. Откройте окно приемника команд MAXScript Listener.
3. Создайте в окне вида сверху плоский и длинный параллелепипед, введя
следующую строку кода:
Ы = box length:100 width:75 height:25
4. Создайте копию параллелепипеда:
Ь2 = сору Ы
5. Переместите вновь созданную копию параллелепипеда в сторону от ори-
гинала:
b2.pos.x = 100
Такие размеры обоих параллелепипедов позволят вам лучше представить
себе вращения, выполняемые в данном упражнении.
6. Выберите команду Graph Editors^Track View - Dope Sheet (Редакторы
графических представлений1^ Вид трека — Подготовительная таблица) из
главного меню 3ds Мах. Разверните иерархию треков в окне Track View
вплоть до треков анимации вращения объекта BoxOl.
149
Преобразования и анимация
В итоге должны быть видны треки X Rotation, Y Rotation и Z
Rotation. В данный момент значения углов вращения данного объекта во-
круг всех трех осей равны нулю.
7. Выберите локальную систему опорных координат, введя в приемнике ко-
манд следующую строку кода:
set coordsys local
8. Введите в приемнике команд следующую строку кода:
Ы.rotation = eulerAngles 45 О О
Параллелепипед повернется на 4 5 ° вокруг оси X мировых координат. Со-
ответствующее значение на треке X Rotation в окне Track View изменит-
ся до -4 5.
Далее вам предстоит повернуть параллелепипед вокруг его оси Y.
9. Введите в приемнике команд следующую строку кода:
Ы.rotation = eulerAngles 0 45 О
10. Казалось бы, в результате этого вращения соответствующее значение на
треке Y Rotation должно было бы измениться до 45, однако вместо этого
значения на треках X Rotation, Y Rotation и Z Rotation стали равны
около - 54,74, -30,0 и 35,26 соответственно.
150
Глава 5
Рамочная система координат
Для того чтобы понять, что же произошло с параллелепипедом в предыдущем
упражнении, воспользуйтесь в следующем упражнении рамочной системой коор-
динат, в которой точнее всего представлены результаты эйлерова вращения объ-
ектов на сцене вокруг осей X, Y, Z.
1. Выделите второй параллелепипед (т.е. объект Вох02).
2. Разверните иерархию треков в окне Тrack View вплоть до треков анимации
вращения объекта Вох02.
3. Щелкните на кнопке Select and Rotate (Выделить и повернуть) и выберите
вариант Gimbal (Рамочная система координат) из раскрывающегося списка
Reference Coordinate System (Система опорных координат) на основной
панели инструментов 3ds Мах. Гизмо этой системы координат похож на
гизмо локальной системы координат, но это сходство заканчивается, как
только начинается вращение объекта.
4. Поверните второй параллелепипед в любом видовом окне на 45° вокруг
его оси X.
5. Затем поверните второй параллелепипед на 4 5 ° вокруг его оси Y.
На треках анимации вращения данного объекта в окне Тrack View появятся
значения 45, 45 и 0. Как видите, второй параллелепипед повернулся иначе,
чем первый параллелепипед в локальной системе координат.
При вращении объектов в любой системе координат значения из текущей
системы координат преобразуются внутри 3ds Мах в значения рамочной
системы координат для отображения на треках X Rotation, Y Rotation
и Z Rotation, причем это делается совершенно незаметно для пользова-
теля. А судить об этом можно лишь по соответствующим значениям на тре-
ках в окне Track View.
6. Перейдите от локальной к рамочной системе координат и обратно, повер-
нув в каждой из них оба параллелепипеда. Об отличиях во вращении в обо-
их системах координат можно судить по их гизмо. Так, в рамочной системе
координат происходит следующее.
151
Преобразования и анимация
• Вслед за вращением вокруг оси Y поворачивается также гизмо оси X.
• Вслед за вращением вокруг оси Z поворачи ваются также гизмо осей X и Y.
Объясняется это тем, что эйлерово вращение вокруг осей X, Y, Z должно
выполняться поочередно и в определенном порядке. По умолчанию
контроллер Euler XYZ выполняет соответствующие расчеты для вра-
щения в следующем порядке: XYZ.
Из приведенного выше упражнения следует, что единственный способ точного
расчета вращения вокруг нескольких осей состоит в использовании конкретных
значений, представленных в рамочной системе координат. Вращение вокруг толь-
ко одной оси (например, вокруг локальной оси Z параллелепипеда) можно доста-
точно точно выполнить в локальной системе координат. Но для вращения вокруг
нескольких осей необходимо выбрать рамочную систему координат, чтобы полу-
чить точные значения углов вращения вокруг осей X, Y и Z.
Блокировка рамки
Из предыдущих упражнений напрашивается вывод, что для представления
процесса вращения в MAXScript следует выбрать рамочную систему координат.
Однако у этой системы координат имеется один существенный недостаток, кото-
рый иллюстрирует следующее упражнение.
1. Выберите вариант Gimbal из раскрывающегося списка Reference Coordi-
nate System на основной панели инструментов 3ds Мах.
2. Выделите объект в любом видовом окне и поворачивайте его вокруг оси Y
до тех пор, пока гизмо оси X не совпадет с гизмо оси Z.
Итак, существенный недостаток рамочной системы координат состоит в том,
что при вращении вокруг оси Y на 90° положение гизмо осей X и Z совпа-
дает, а следовательно, они обозначают одну и ту же ось вращения. Такая си-
туация называется блокировкой рамки и в значительной степени ограничи-
вает выбор видов вращения, которые можно выполнять.
3. Подобного осложнения можно в какой-то степени избежать, изменив поря-
док следования осей вращения. Так, если заранее известно, что объект должен,
152
Глава 5
скорее всего, повернуться на 90° вокруг оси Y, порядок следования осей
можно изменить на следующий: YZX или YXZ, чтобы первым выполнялось
вращение вокруг оси Y. Это позволяет исключить блокировку рамки при
вращении объекта на 90° вокруг оси Y. Но если затем повернуть объект на 90°
вокруг оси Z или X, блокировки рамки избежать не удастся.
Это основная причина, ограничивающая применение рамочной системы
координат для представления процесса вращения.
Локальные вращения
Во всех приложениях трехмерного моделирования и анимации, включая 3ds
Мах, имеется собственное представление локального вращения, т.е. поворота во-
круг локальных осей объекта. Но как было только что показано, вращение в ло-
кальной системе координат не дает истинных значений для треков X Rotation,
Y Rotation и Z Rotation в окне Track View. В этом смысле локальное враще-
ние не позволяет правильно судить о происходящем.
С другой стороны, рамочная система координат дает более точное представление
об истинных значениях вращения вокруг осей X, Y и Z, хотя вращение в этой систе-
ме вокруг нескольких осей рассчитывается в определенном порядке. Если изменить
порядок расчетов, конечная ориентация объекта, скорее всего, окажется другой.
Таким образом, точного способа представления конкретного локального вращения
с помощью значений эйлерова вращения вокруг осей X, Y и Z не существует. В силу
особого характера расчетов вращения в трехмерном пространстве этим недостатком
страдают буквально все приложения трехмерного моделирования и анимации.
Кватернионы
Во время работы с объектами сцены непосредственно в пользовательском ин-
терфейсе 3ds Мах ограничения, присущие эйлерову представлению вращения во-
круг осей X.Y и Z, зачастую никак не мешают поворачивать объекты и получать
вполне предсказуемые результаты. Для этого просто выбирается система коорди-
нат, наиболее подходящая для конкретной ситуации, и далее вращение выполня-
ется визуально для достижения желаемого результата.
При написании сценариев возможность манипулировать моделью визуально
отсутствует. Вращение объекта приходится обозначать точно с помощью конкрет-
ных чисел, чтобы добиться искомого результата.
И в этом случае на помощь приходит метод представления процесса вращения
с помощью кватернионов. Кватернионы явно обозначают всякое возможное вра-
щение, что позволяет точно и однозначно задать вращение вокруг осей X, Y и Z.
Значение кватерниона выражается в виде угла и значения типа Point3, опи-
сывающего некий вектор:
quat <угол> <вектор>
Векторная часть данного выражения относится к выражению типа Point3.
Отдельные значения в выражении типа Point3 всегда находятся в пределах от -1
до 1. Ниже приведены некоторые примеры обозначения кватернионов:
Преобразования и анимация
quat 30 [1, 0, 0]
quat 30 [0.266917, 0.534798, 0.801715]
Для того чтобы лучше понять кватернионы, представьте себе сферу с вектором,
направленным от центра сферы к ее поверхности. Векторная часть кватерниона
обозначает направление вектора, в угол — количество градусов, на которое объект
должен повернуться вокруг данного вектора.
Если векторное значение состоит из единицы и двух нулей, то вектор нетрудно
себе представить направленным вдоль одной из осей X, Y или Z. При этом 1 опре-
деляет ось, вдоль которой вектор направлен. Так, векторное значение [1, 0, 0]
направляет вектор вдоль оси X.
В более сложном вектором выражении, как, например, [0.266917, 0.534798,
0.801715], вектор направлен из воображаемого центра сферы к точке поверхности,
определяемой данным выражением типа Point3. Объект будет вращаться вокруг
данного вектора на количество градусов, определяемых угловым значением кватер-
ниона. В приведенных выше примерах это угловое значение равно 3 0.
Как правило, используются векторы, направленные вдоль оси X, Y или Z.
А для того чтобы использовать векторы, имеющие другое направление, нужно
знать, как их строить.
Векторные значения
Векторные значения кватернионов следует рассчитывать очень аккуратно.
Квадратный корень из суммы квадратов всех составляющих должен быть равен 1.
Так, из приведенного выше примера кватерниона quat 30 [0.266917, 0.534798,
0.801715] можно установить, что квадратный корень из суммы (0.266917)2 +
(0.534798)2 + (0.801715)2 = 1
Это ограничение объясняется тем, что длина вектора должна быть всегда равна 1.
Следовательно, длина вектора всегда равна квадратному корню из суммы х2 + у2 + z2.
Правильное определение векторных значений кватерниона — занятие долгое
и утомительное. Поэтому для упрощения расчетов применяется метод normalize.
rot_vect = normalize [10, 14, 5]
q = quat 90 rot_vect
Предопределенные значения углов вращения
В MAXScript имеется ряд предопределенных глобальных переменных. К ним
относятся три следующие переменные: x axis, у axis и z axis. Они представляют
значения типа Point 3, обозначающие вращение вокруг соответствующих осей:
x_axis представляет [ 1, 0, 0]
y_axis представляет [ 0, 1, 0]
z_axis представляет[0, 0, 1]
В любом выражении, описывающем вращение, выражение типа Point 3 можно
заменить соответствующей переменной. Зная это, данное выражение можно ис-
пользовать для составления следующего выражения:
q = quat 45 x_axis
154
Глава 5
Аналогично методу eulerAngles, объект кватернионного вращения может
быть присвоен любому вращаемому объекту,
b = box()
q = quat 45 xaxis
rotate b q
Выражения в качестве аргументов
Нередко оказывается удобнее сократить два или более оператора сценария до
одного. В MAXScript это нетрудно сделать при вызове функций. Во всех приве-
денных выше примерах переменные или явно указываемые числовые значения
были приведены в качестве аргументов. Но в этом качестве можно использовать
и выражения. Выражение представляет собой конструкцию для вычисления зна-
чения. Так, если в приемнике команд ввести quat 2 0 x_axis и нажать клавишу
<Enter>, в ответ появится сообщение об успешном выполнении команды.
Во веденном выше выражении было вычислено значение, хотя оно и не было
присвоено переменной. В данном случае создается кватернионный объект, а вы-
численное значение хранится во внутренней переменной MAXScript, которая не-
доступна для пользователя. Оба приведенных ниже сценария выполняют одно
и то же действие.
В первом сценарии сначала создается кватернионный объект, а затем паралле-
лепипед, который далее поворачивается на следующую величину:
rot = quat 30 y_axis
b = box rotation:rot
А во втором сценарии то же самое делается с помощью выражения в конструкторе:
b = box rotation:(quat 30 y_axis)
В выражении quat 3 0 y_axis вычисляется кватернион, поэтому его можно
ввести вместо аргумента функции. Данное выражение сначала вычисляется внут-
ри 3ds Мах, а затем его значение присваивается свойству вращения. Такое выра-
жение следует указывать в круглых скобках, чтобы 3ds Мах было проще распо-
знать его начало и конец. Где и как часто следует использовать подобные
выражения, зависит от ваших целей и стиля программирования.
Кватернионы имеют свои ограничения. В частности, углы можно указывать
только в пределах от -180° до 180°. Если же требуется повернуть объект на угол,
который превышает данный 360-градусный диапазон, придется воспользоваться
методом AngleAxis.
155
Преобразования и анимация
Метод AngleAxis
Если объект нужно повернуть на угол более 360°, в таком случае можно вос-
пользоваться объектами класса AngleAxis. Такие объекты реализуются подобно
кватернионам следующим образом:
ang = angleaxis 30 [1, 0, 0]
ang = angleaxis 30 x_axis
Оба приведенных выше выражения равнозначны, поскольку в обоих случаях
создается объект ang, который обеспечивает вращение на 3 0 0 вокруг оси X.
Для вращения объекта по методу AngleAxi s выполните следующее упражнение.
1. Установите 3ds Мах в исходное состояние.
2. Введите следующую строку кода в приемнике команд, чтобы создать стан-
дартный параллелепипед:
b = box()
3. Включите режим Auto Key и переместите ползунок временной шкалы ани-
мации к кадру 10. Введите в приемнике команд следующую строку кода:
b.rotation.x_rotation = 720
4. Воспроизведите анимацию.
Объект не вращается.
5. Переместите ползунок временной шкалы анимации к кадру 10. Если режим
Auto Key все еще включен, введите в приемнике команд следующий фраг-
мент кода:
ang = angleaxis 720 [1, 0, 0]
rotate b ang
6. Выключите режим Auto Key и воспроизведите анимацию.
Объект совершит два полных оборота.
Контексты
У всякого геометрического объекта имеется своя точка опоры, которая пред-
ставляет собой точку, вокруг которой происходит перемещение, вращение и мас-
штабирование объекта. До сих пор в этой главе преобразования рассматривались
лишь относительно устанавливаемой по умолчанию точки опоры объекта.
Для преобразования точки опоры объекта вручную выполните следующее уп-
ражнение.
1. Создайте любой объект.
2. Перейдите к панели команд Hierarchy.
3. Если объект выделен, активизируйте кнопку Affect Pivot Only (Оказывать
влияние только на точку опоры).
Точка опоры перемещается и вращается, когда выполняются преобразова-
ния перемещением и вращением. На приведенном ниже рисунке показана
156
Глава 5
точка опоры параллелепипеда после того, как он был преобразован произ-
вольным образом.
Г-----------------------г
I Hvot к i 1-lr*,nto I
I---------------------------Г
I Hlvot к i Liric ln!o I
4- _ ; '. 8 ' |
г Move/Rotate^Scate:--------
? Аад PYSlQrfe' J
Affect Object Only ]
Affect HieioictjyOnC |
»- Alignment: ——-—
Center to Object
Align to Object
Align to World
-< I ..
Г Pivot:--------------*-
Reset Pivot
Для изменения точки опоры объекта в MAXScript воспользуйтесь свойст-
вом . pivot, чтобы установить или переместить точку опоры, например:
object.pivot = [0, 0, 10.0]
или
object.pivot.z = 10.0
Любые последующие преобразования объекта будут происходить относи-
тельно нового центра преобразования.
Для преобразования точки опоры средствами MAXScript выполните следую-
[ее упражнение.
1. Создайте параллелепипед. Введите следующую строку кода и нажмите кла-
вишу <Enter>:
b = box()
2. Переместите точку опоры данного объекта. Введите следующую строку ко-
да и нажмите клавишу <Enter>:
b.pivot.z = 40.0
3. Перейдите к панели команд Hierarchy. Активизируйте кнопку Affect Pivot
Only.
Убедитесь в том, что параллелепипед выделен. Как видите, точка опоры па-
раллелепипеда смещена по оси Z.
157
Преобразования и анимация
4. Установите точку опоры в центре параллелепипеда с помощью свойства
. center. Введите следующую строку кода и нажмите клавишу <Enter>:
b.pivot = b.center
Как видите, точка опоры перемещается в центр параллелепипеда.
Если выполняется вращение, в 3ds Мах предполагается, что это делается
в системе мировых координат относительно точки опоры. Преобразования
можно выполнять и относительно других точек объекта или же в иной сис-
теме координат. Это делается с помощью контекстов, где указывается
ссылка на выполняемую операцию. К наиболее важным контекстам
относятся coordsys и about.
• coordsys указывает систему координат для операции.
• about указывает точку опоры (или центр преобразования) для операции.
Контекст about применяется к операциям вращения и преобразования.
158
Глава 5
Для того чтобы воспользоваться контекстом about, выполните следующее уп-
ражнение.
1. Создайте два цилиндра на сцене. Для этого введите следующие строки кода,
нажав после каждой из них клавишу <Enter>:
cl = cylinder height:50
c2 = cylinder pos:[40, 0, 0]
Далее попробуйте выполнить два разных вращения цилиндра cl.
2. Введите следующую строку кода и нажмите клавишу <Enter>:
rotate cl (quat 45 y_axis)
По умолчанию используется система мировых координат, а точка опоры
находится в основании цилиндра. Далее вам предстоит ознакомиться с кон-
текстом about и его применением.
3. Щелкните правой кнопкой мыши в любом видовом окне и нажмите комбина-
цию клавиш <Ctrl+Z>, чтобы отменить только что выполненное вращение.
4. Введите в приемнике команд следующую строку кода и нажмите клавишу
<Enter>:
about с2 rotate cl (quat 45 y_axis)
159
Преобразования и анимация
Теперь результат вращения будет иным, поскольку на этот раз центр пре-
образования находится в точке опоры цилиндра с2.
Префикс контекста about указывается в начале, а не в конце выражения,
как можно было бы ожидать. В 3ds Мах операторы интерпретируются слева
направо, поэтому контекст следует применять до операции вращения. Если
поместить префикс контекста about в конце выражения, он будет приме-
нен к следующей вводимой операции.
Ниже приведены другие примеры применения контекста about:
• about [х, у, z] — выполняет вращение определенной точки;
• about selection— выполняет вращение вокруг центра выделенных
в данный момент объектов.
Контекст coordsys
Для изменения текущей системы координат служит контекст coordsys.
В этом случае префикс контекста coordsys следует указывать перед операторами
в начале выражения, например:
in coordsys local rotate cl (quat 45 y_axis)
В этом примере локальная система опорных координат выбирается для после-
дующего кода, указанного в круглых скобках. Если же систему координат требу-
ется установить для всех команд вплоть до особого уведомления, то используется
следующая конструкция:
set coordsys local
С помощью контекста coordsys можно установить систему мировых коорди-
нат, локальную, родительскую, сеточную, экранную систему координат, а также
локальную систему координат другого объекта.
Ранее было показано, что при установке свойств .pos, . rotation и . scale
с помощью оператора значения этих свойств присваиваются непосредственно
и в абсолютном виде, а при повторе оператора они не подлежат приращению. Это
160
Глава 5
справедливо для всех систем координат, кроме локальной. Если выбрана локаль-
ная система координат, она изменяет свое положение, ориентацию и масштаб вся-
кий раз, когда устанавливается свойство. Следовательно, при повторе одного и то-
го же оператора преобразование вновь повторяется, но в относительном виде.
Анимация
Анимация в 3ds Мах осуществляется с помощью контроллеров управления анима-
цией. Контроллеры рассчитывают значения оживляемых свойств объекта с помощью
самых разных методов интерполяции в зависимости от типа выбранного контроллера.
Чаще всего применяются контроллеры управления положением, вращением и мас-
штабированием, называемые также контроллерами управления преобразованием.
Анимация сцены организуется по трекам. Трек содержит информацию об из-
менениях, происходящих в объекте, модификаторе, параметре или другом элемен-
те в ходе анимации. С каждым оживляемым элементом сцены связан отдельный
трек анимации, для которого может быть назначен контроллер.
Треки анимации сцены и их свойства доступны для правки в окне Track View.
Кроме того, контроллеры управления преобразованием можно назначать и пра-
вить на панели Motion. Для того чтобы извлечь максимальную пользу из материа-
ла этого раздела, вы должны уметь пользоваться окном Track View, чтобы про-
сматривать и править треки анимации, а также назначать контроллеры на панели
Motion и в том же окне Track View.
Контроллеры
Для каждого создаваемого объекта автоматически назначаются контроллеры
управления преобразованием. А для остальных оживляемых параметров объекта
контроллер назначается, как только для анимации параметра устанавливается
ключевой кадр.
Конкретные типы контроллеров указываются в подсвойстве .controller
всякого оживляемого свойства объекта:
s = sphere()
s.pos.controller
При выполнении этого фрагмента кода возвращается значение
Controller: Position_XYZ, указывающее на то, что для трека анимации поло-
жения сферы назначен контроллер Postion_XYZ.
Свойство .controller имеет подсвойство .value. Как только для параметра
будет назначен контроллер, значение этого контроллера может быть установлено
следующим образом:
s.pos.controller.value = [20,0,50]
Некоторые контроллеры, например Position_XYZ, имеют три составляющие,
каждая из которых имеет свой контроллер. Доступ к этим контроллерам осущест-
вляется по индексу 1,2 и 3:
s.pos.controller[1].controller
При выполнении этой строки кода возвращается контроллер, назначенный для
составляющей X стандартного контроллера Position_XYZ, в качестве которого
161
Преобразования и анимация
служит Bezier_Float, т.е. контроллер управления по кривой Безье с плавающей
точкой. Подсвойство . value может быть использовано и для этого подконтроллера:
s.pos.controller[1].controller.value
При выполнении этой строки кода возвращается значение составляющей X
контроллера Position_XYZ.
У каждого контроллера имеются свои подсвойства. Так, если для объекта на-
значен контроллер Position_XYZ в качестве контроллера анимации его положе-
ния, следующая строка окажется равнозначной предыдущей строке кода:
s.pos.controller.X_Position.controller.value
Доступ к контроллеру, состоящему из подконтроллеров, а также к его значени-
ям может быть всегда осуществлен несколькими способами. Многие программи-
сты предпочитают конструкцию controller [1] .controller вместо более яв-
но выраженной конструкции controller.X Position, поскольку это дает им
возможность работать с любым назначенным для объекта контроллером при ус-
ловии, что он имеет три составляющие. Если в сценарии используется первая кон-
струкция, используемый в объекте контроллер можно изменить без ошибок.
Для того чтобы назначить новый контроллер для оживляемого параметра объ-
екта, достаточно создать сначала экземпляр этого контроллера, а затем присвоить его:
с = linear_float()
s.radius.controller = с
В дальнейшем экземпляр контроллера можно использовать для изменения
свойств данного контроллера.
с.value = 40
Если контроллер из переменной с назначается для других параметров в сцене,
при изменении значения переменной с изменяются также все экземпляры с. value
подобно тому, как это происходит с экземплярами других элементов сцены.
Во многих случаях вместо свойства .controller может быть использовано
подсвойство .track. Тем не менее рекомендуется пользоваться свойством
. controller, чтобы ваши сценарии работали при любых обстоятельствах.
Ключевые кадры анимации
В MAXScript имеются средства для создания ключевых кадров на треках ани-
мации и установки их значений.
• Ключевые кадры анимации можно создавать с помощью контекста
animate. Этот контекст равнозначен включению режима Auto Key и вы-
полнению последующих команд (при этом кнопка Auto Key в пользова-
тельском интерфейсе 3ds Мах не активизируется):
animate on
(
[команды]
)
В данном контексте можно также использовать контекст at time для ука-
зания места для установки ключевых кадров:
162
Глава 5
s = sphere()
animate on
(
at time 50 s.radius = 10
at time 100 s.radius = 60
)
В этом фрагменте кода создаются ключевые кадры анимации радиуса сфе-
ры в кадрах 50 и 100, где устанавливаются значения радиуса 10 и 60 соот-
ветственно.
Если контекст animate используется для установки ключевых кадров, то в
нулевом кадре автоматически создается ключевой кадр, даже если это не
указано явно. При этом повторяются те же действия, что и при активизации
кнопки Auto Key: если ключевой кадр устанавливается не в нулевом кадре,
а в последнем он отсутствует, то ключевой кадр автоматически создается
в нулевом кадре с исходным значением трека.
Когда создается сфера, контроллер для трека анимации ее радиуса не на-
значается. Если ключевые кадры устанавливаются с помощью контекста
animate, то по умолчанию для трека анимации радиуса сферы назначается
контроллер Bezier_Float. После расстановки ключевых кадров на треке
можно отобразить тип назначенного контроллера, введя в приемнике ко-
манд следующую строку кода:
s.radius.controller
• Кроме того, ключевые кадры анимации могут быть созданы с помощью мето-
да addNewKey. Если контроллер уже назначен для трека, то, используя метод
addNewKey, можно добавить ключевой кадр непосредственно к контроллеру:
с = s.radius.controller
addNewKey с 20
В данном примере ключевой кадр добавляется к контроллеру, управляю-
щему анимацией радиуса сферы, в кадре 20. Значение контроллера в дан-
ном кадре не меняется, а просто устанавливается ключевой кадр.
Если ключевые кадры вводятся с помощью метода addNewKey, ключевой
кадр не создается автоматически в нулевом кадре.
Для удаления всех ключевых кадров конкретного контроллера можно вос-
пользоваться следующей строкой кода:
deleteKeys s.radius.controller
Значения ключевых кадров
Для изменения значений ключевых кадров в конкретном кадре имеются сле-
дующие возможности.
• Использовать контекст animate, чтобы установить значения ключевых
кадров непосредственно для контроллера или же самого параметра. Обе
приведенные ниже строки кода совершенно равнозначны:
animate on ( at time 30 s.radius = 50 )
animate on ( at time 30 s.radius.controller.value = 50 )
163
Преобразования и анимация
При написании сценариев предпочтительнее использовать более короткую
запись. Но при установке ключевых кадров анимации вращения может воз-
никнуть потребность присвоить значение угла поворота свыше 360° непо-
средственно контроллеру, не прибегая к методу angleAxis. Рассмотрим
для примера две следующие строки кода:
at time 50 s.rotation.z_rotation = 720
at time 50 s.rotation.controller[3].controller.value = 720
Допустим, что в качестве контроллера управления вращением назначен
контроллер Euler XYZ. При выполнении первой строки кода вращения не
происходит, поскольку угол поворота определяется в виде остатка от деле-
ния на 360. А во второй строке кода устанавливается ключевой кадр, выну-
ждающий объект совершить два полных оборота вокруг своей оси Z.
• Использовать свойство . keys, содержащее массив ключевых кадров, уста-
новленных для конкретного контроллера.
s.radius.keys [2] .value = 40
В этой строке кода изменяется значение второго ключевого кадра, установ-
ленного для контроллера, управляющего анимацией радиуса сферы.
Если значения ключевых кадров изменяются с помощью свойства .keys,
нужно точно знать контроллер, которому эти значения присваиваются.
Присваиваемое значение определяется для ключевых кадров контроллера.
Если создать контроллер в виде экземпляра и назначить его для нескольких
оживляемых параметров в сцене, то изменение отдельного значения с по-
мощью свойства .keys коснется всех параметров, для которых назначен
данный контроллер.
Для создания простой анимации выполните следующее упражнение.
1. Установите 3ds Мах в исходное состояние.
2. Создайте чайник, введя в окне приемника команд следующую строку кода:
t = teapot()
3. В этом упражнении вам предстоит осуществить анимацию радиуса чайника
от нулевого до сотого кадра, установив ключевые кадры в кадрах 0, 50 и 10.
Сделайте это в окне приемника команд, чтобы видеть реакцию на выполне-
ние каждого пункта данного упражнения.
По умолчанию для анимации радиуса чайника назначен контроллер
Bezier Float, но его придется заменить.
4. Создайте объект контроллера 1 inear_f loat:
с = linear_float()
Контроллер linear_float обеспечивает плавное, линейное изменение
значения параметра в промежутке между ключевыми кадрами. Поэтому его
можно применять к таким параметрам объектов, как радиус чайника, кото-
рый описывается единственным числовым значением с плавающей точкой.
164
Глааа 5
5. А теперь, когда имеется чайник и соответствующий контроллер, назначьте
этот контроллер для радиуса чайника:
t.radius.controller = с
Далее вам предстоит установить ключевые кадры с помощью контекста
animate. При вводе каждого ключевого кадра в свойство .keys контрол-
лера, управляющего анимацией параметра объекта (в данном случае радиу-
са чайника), добавляется очередной элемент массива.
6. Создайте три ключевых кадра, используя контекст animate:
animate on
(
for i = 0 to 100 by 50 do
(
at time i t.radius = ((i * 0.5) + 10)
)
)
7. В этом фрагменте кода устанавливаются значения 1 о, 3 5 и 6 о радиуса чай-
ника соответственно в кадрах о, 5 о и 10.
8. Воспроизведите анимацию, наблюдая за изменением радиуса чайника.
Существует несколько способов доступа к ключевым кадрам анимации.
9. Введите следующую строку кода:
print с.keys[2]
В приемнике команд появится результат ttLinear Float key (2 ® 50f).
Для перехода к отдельным ключевым кадрам в данном случае можно вос-
пользоваться непосредственно параметром радиуса чайника, поскольку для
него назначен контроллер.
10. Введите следующую строку кода:
print t.radius.keys[2]
В приемнике команд будет получен тот же результат, что и в п. 7 данного
упражнения.
11. Вновь воспроизведите анимацию, наблюдая за изменением радиуса чайника.
Типы контроллеров
Контроллер линейного управления с плавающей точкой (linear_float)
достаточно прост и понятен. К другим часто применяемым контроллерам отно-
сятся следующие.
• Группа контроллеров линейного управления. Включает контроллеры
linear_float,linear_position, linear_rotationиlinear_scale.
• Группа контроллеров управления по кривой Безье. Включает контроллеры
bezier_f loat, bezier^position, bezier_j?oint3, bezier_rotation,
bezier_scale и bezier_color.
• Группа контроллеров управления по натяжению, непрерывности и смеще-
нию. Включает контроллеры tcb_float, tcb_position, tcb_point3,
tcb_rotation и tcb_scale.
165
Преобразования и анимация
Каждый контроллер из группы контроллеров линейного управления обеспечи-
вает простую линейную интерполяцию в промежутке между ключевыми кадрами.
Линейная интерполяция означает, что оживляемый параметр или свойство объекта
изменяется постепенно и равномерно. Так, посредине промежутка между кадрами
значение параметра изменяется наполовину и т.д. Контроллеры в каждой упомяну-
той выше группе отличаются лишь типом переменной, которой они управляют.
Контроллер Bezier предоставляет больше возможностей для определения
анимации. Он обладает следующими свойствами:
• . inTangent — значение с плавающей точкой или типа Point3;
• . outTangent — значение с плавающей точкой или типа Point3;
• .inTangentType и .outTangentType— #smooth, #linear, #step,
fast, ttslow, #custom или #auto;
• . x_locked — логическое значение;
• . y_locked — логическое значение;
• . z_locked — логическое значение;
• . constantvelocity — логическое значение.
Свойства . inTangent и . outTangent используются в том случае, если соз-
дается касательная специального типа. Если это анимация положения объекта, то
эти свойства будут иметь тип данных Point3, определяя значения координат X, Y
и Z касательной в ключевом кадре.
Если вы не знакомы с контроллерами Bezier, обратитесь за дополнительны-
ми сведениями к справочному руководству по MAXScript.
Для того чтобы воспользоваться контроллером Bezier, выполните следующее
упражнение.
1. Установите 3ds Мах в исходное состояние.
2. Введите в окне сценария MAXScript следующую строку кода:
s = sphere showTrajectory:true
В этой строке кода создается сфера и активизируется режим отображения
траектории ее движения.
3. Продолжите создание сценария, введя следующий фрагмент кода:
s.pos = [-100, -100, 0]
с = bezier_position()
s.pos.controller = с
4. Организуйте движение сферы, установив ключевые кадры анимации ее по-
ложения:
animate on
(
at time 0 s.pos = [-50, -60, 0]
at time 35 s.pos = [-10, -50, 0]
at time 70 s.pos = [20, 50, 0]
at time 100 s.pos = [80, 10, 0]
)
166
Глава 5
5. Вычислите сценарий.
Для определения характера интерполяции между ключевыми кадрами про-
анализируйте траекторию движения сферы в видовых окнах.
6. Воспроизведите анимацию.
По умолчанию касательная для свойств . inTangentType и .outTangentType
имеет плавный вид. Оставьте без изменения ключевые кадры, установлен-
ные по умолчанию в нулевом и сотом кадрах, но измените тип касательных
в ключевых кадрах 35 и 70.
7. Выберите команду Graph Editors^Track View - Curve Editor (Редакторы
графических представлений1^ Вид трека — Редактор кривых). Как только
откроется редактор кривых, выделите трек анимации положения сферы,
чтобы просмотреть соответствующие функциональные кривые.
8. Введите в приемнике команд следующий фрагмент кода, чтобы изменить
касательные к ключевым кадрам на функциональных кривых:
с.keys[2].inTangentType = #fast
с.keys[2].outTangentType = #fast
167
Преобразования и анимация
с.keys[3].inTangentТуре = #slow
с.keys[3].outTangentType = #slow
Соответствующие изменения в функциональных кривых можно наблюдать
в окне Track View.
9. Воспроизведите анимацию.
Для того чтобы создать сценарий, организующий вращение колеса, выполните
следующее упражнение.
1. Вооружившись полученными в этой главе знаниями о характере вращения
и системах координат, вы можете теперь написать сценарий, в котором ключе-
вые кадры устанавливаются на основании пользовательского ввода и данных,
взятых из сцены. В этом упражнении вам предстоит создать сценарий, в кото-
ром устанавливаются ключевые кадры анимации вращения колеса автомоби-
ля. Количество оборотов колеса будет определяться дальностью передвиже-
ния автомобиля. Загрузите файл сцены \chapter5\Roadster_start.max,
находящийся на прилагаемом к этой книге CD-ROM.
Эта сцена содержит простую модель четырехколесного автомобиля.
2. Воспроизведите анимацию.
168
Глава 5
Движение автомобиля ограничивается путем, проходящим вдоль дороги,
причем автомобиль движется с постоянной скоростью. Колеса, представ-
ляющие собой цилиндрические примитивы, связаны с кузовом автомобиля.
Напишите сценарий, выполняющий следующее.
• Разрешить пользователю выбрать колесо и путь, по которому движется
автомобиль.
• Проверить, является ли выбранное пользователем колесо цилиндром,
а путь — линией или редактируемым сплайном.
• Определить длину пути.
• Использовать длину окружности колеса и длину пути для расчета ко-
личества оборотов, которое должно совершить колесо.
• Установить ключевые кадры анимации вращения колеса на соответст-
вующее количество градусов вокруг оси Z.
3. Начните со сценария, в котором уже частично организован пользователь-
ский интерфейс. Для этого выберите команду MAXScript^Open Script из
главного меню и откройте файл сценария WheelRollStarter .ms на при-
лагаемом к этой книге CD-ROM.
Этот сценарий содержит элементы пользовательского интерфейса, необхо-
димые для написания готового сценария, а также ряд обработчиков собы-
тий. Последний обработчик событий, в котором вычисляются ключевые
кадры, пока еще пуст.
В первой строке сценария проверяется, открыто ли диалоговое окно. Если
это так, то диалоговое окно закрывается. Это делается для того, чтобы не
множить многочисленные копии диалогового окна при проверке сценария.
try (closeRolloutFloater wheelFloater) catch()
В ряде следующих строк сценария организуется его пользовательский ин-
терфейс:
rollout setRoll "Wheel Roll"
(
label lab_wheel "Pick Wheel: "
pickbutton pbt_obj "Click to Pick Wheel" width:105
autoDisplay:true
169
Преобразования и анимация
label lab_path "Pick Path: "
pickbutton pbt_path "Click to Pick Path" width:105
autoDisplay:true
spinner spn_startFrame "Start Frame: " type:ttinteger \
range: [0,1000,0] fieldwidth:40
spinner spn_endFrame "End Frame: " type:#integer \
range:[1,1000,100] fieldwidth:40
button but_setkeys "Set Wheel Keys" enabled:false
В остальных строках из выражения свитка определяется, что происходит
после щелчков на кнопках в пользовательском интерфейсе. Последний об-
работчик событий, в котором должны устанавливаться ключевые кадры,
в данный момент пуст. Вам предстоит его заполнить в этом упражнении:
local wheelobject, wheelpath
on pbt_obj picked wheel do
(
-- Проверить, является ли выбранный объект цилиндром
if classOf wheel!=cylinder then \
messagebox "Please pick a cylinder."
-- Если это цилиндр:
else
(
-- Поместить выбранный объект в переменной wheelobject
-- для использования вне данного блока кода
wheelobject = wheel
-- Если выбран также путь, активизировать кнопку "Set Wheel Keys"
if wheelPath != undefined then but_setkeys.enabled = true
)
)
on pbt_path picked pth do
(
-- Проверить, является ли путь линией или редактируемым сплайном
if classOf pth != line and classOf pth != SplineShape then \
messagebox "Please pick a line or editable spline."
-- Если это линия или редактируемый сплайн,:
else
(
- - Поместить выбранный путь в переменной wheelPath для
- - использования вне данного блока кода
wheelPath = pth
- - Если выбрано также колесо, активизировать кнопку "Set
Wheel Keys"
if wheelobject != undefined then but_setkeys.enabled = true
)
)
on but_setkeys pressed do
(
)
)
wheelFloater = newRolloutFloater "Wheel Roll" 200 195
addrollout setRoll wheelFloater
170
Глава 5
4. Выполните сценарий.
В этом сценарии отображается диалоговое окно, в котором можно выбрать
колесо и путь, а затем щелкнуть на кнопке Set Wheel Keys (Установить
ключевые кадры анимации колеса).
5. Попробуйте выбрать другие объекты на сцене, чтобы проверить, какие из
них могут быть выбраны по данному сценарию. Когда объект воспринима-
ется сценарием как допустимый, обратите внимание на автоматическое об-
новление названия кнопки выбора в соответствии с именем выбранного
объекта сцены. Этот режим появился в версии 3ds Мах 7. Он активизирует-
ся благодаря передаче логического значения true свойству autoDisplay
при объявлении элемента управления pickButton в определении свитка.
А до этого имя объекта приходилось присваивать надписи кнопки (в обра-
ботчике событий pickButton) следующим явным образом:
pbtjath. text = pth.name
Кнопка Set Wheel Keys пока еще ничего не делает. Ее функции по установ-
ке ключевых кадров вам предстоит ввести в сценарий.
Примечание. Если у вас нет желания вводить исходный код сценария
вручную, но в то же время есть желание продолжить выполнение данного
упражнения, откройте файл сценария \chapter5\WheelRollFinished.ms,
находящийся на прилагаемом к этой книге CD-ROM.
6. Введите в круглых скобках внутри обработчика событий but_setkeys
pressed do из файла сценария WheelRollStarter .ms следующие стро-
ки кода:
local pathLength, numRotations, totalDegrees, startAngle, endAngle
- - Получить длину пути
pathLength = curveLength wheelPath
- - Получить количество оборотов, исходя из длины окружности 2piR
numRotations = pathLength / (2 * pi * wheelobject.radius)
- - Умножить на 360, чтобы получить общее число оборотов
totalDegrees = numRotations * 360
print totalDegrees
171
Преобразования и анимация
7. Выполните сценарий, чтобы открыть диалоговое окно. Выберите колесо
WheellOl и путь, а затем щелкните на кнопке Set Wheel Keys.
8. Обратите внимание на значение переменной totalDegrees, выводимое
в приемнике команд при выполнении последнего оператора в сценарии.
Теперь вам известно количество градусов, на которое должно повернуться
колесо. Это общее количество градусов оказывается больше 360, и поэтому
вращение колеса придется организовать одним из двух следующих способов.
• Методом angleAxis
• Явно задав значение контроллера управления вращением
В данном упражнении вам предстоит воспользоваться вторым способом.
9. Введите после строки вывода на печать значения переменной totalDegrees
следующий фрагмент кода:
with animate on
(
at time spn_startFrame.value
wheelobject.rotation.controller. \
z_rotation.controller.value = 0
at time spn_endFrame.value
wheelObject.rotation.controller. \
z_rotation.controller.value = totalDegrees
)
10. Выполните сценарий, выберите колесо WheellOl и путь, а затем щелкните
на кнопке Set Wheel Keys.
11. Воспроизведите анимацию.
При перемещении автомобиля его колесо поворачивается на нужное коли-
чество градусов.
Это довольно простой сценарий, однако его можно изменить или улучшить
самыми разными способами. Ряд усовершенствований данного сценария
находится в файле \chapter5\WheelRollComplete.ms на прилагаемом
к этой книге CD-ROM.
Ось вращения
Написанный выше сценарий можно было бы сделать более удобным для поль-
зователя, чтобы он мог выбрать также ось вращения колеса с помощью кнопок-
переключателей, которые следует ввести в определение пользовательского интер-
фейса данного сценария. Для этого введите следующие строки кода после строки
определения кнопки button but_setkeys:
label lab_rotAxis "Local Rotation Axis: "
radiobuttons rbt_rotAxis labels:#("X","Y","Z") default:!
Если ввести эти элементы пользовательского интерфейса, то для их размеще-
ния в диалоговом окне придется соответственно изменить его высоту (сделайте
это в предпоследней и последней строках сценария). Далее в той части кода, где
172
Глава 5
устанавливаются ключевые кадры анимации колеса, можно воспользоваться со-
стоянием кнопки rotAxis. state, чтобы задать конкретную ось вращения. Итак,
замените код из блока контекста with animate on в обработчике событий on
but_setKeys pressed следующим фрагментом кода:
rAxis = rbt_rotAxis.state
at time spn_startFrame.value
wheelObj ect.rotation.controller[rAxis] \
.controller.value =0
at time spn_endFrame.value wheelObject.rotation.controller[rAxis] \
.controller.value = totalDegrees
Временные интервалы
Созданный только что сценарий вполне работоспособен для анимации автомо-
биля, преодолевающего весь путь с одинаковой скоростью. Но если скорость или
направление движения автомобиля может измениться в любой момент, то придет-
ся установить ключевые кадры через определенные интервалы и рассчитать вра-
щение колеса для каждого ключевого кадра.
Для того чтобы предоставить пользователю возможность устанавливать кон-
кретные интервалы времени, сценарий можно дополнить счетчиком Time Step
(Временной интервал), введя следующую строку кода перед определением кнопки
button but_setkeys:
spinner spn_timeStep "Time Step: " range: [1,10,5]
Если ввести этот элемент пользовательского интерфейса, то для его размеще-
ния в диалоговом окне придется соответственно изменить высоту данного окна.
Для получения в любой момент длины пройденного пути в процентах необхо-
димо знать, какой объект следует по этому пути. Для выбора этого объекта можно
предоставить соответствующую кнопку или же предположить, что это родитель-
ский объект выбранного колеса. Для доступа к родительскому объекту колеса
можно воспользоваться следующим оператором:
wheelObj ect.parent
А длину пути, пройденного автомобилем, в процентах можно рассчитать с по-
мощью следующего выражения:
wheelObject.parent.controller.percent / 100
Для установки только двух ключевых кадров вместо контекста animate лучше
организовать цикл. На каждом шаге цикла выбирается значение из счетчика Time
Step и по нему определяется конкретный кадр анимации для установки ключевого
кадра. Итак, замените весь блок кода с контекстом with animate on следую-
щим фрагментом кода:
local rAxis = rbt_rotAxis.state
local curDeg, curPerc, distTraveled, numRotations
for t = spn_startFrame.value to spn_endFrame.value \
by spn_timeStep.value do
(
at time t
173
Преобразования и анимация
(
curPerc = wheelobject.parent.position.controller.percent / 100
distTraveled = curPerc * pathLength
numRotations = distTraveled / (2 * pi * wheelobject.radius)
curDeg = numRotations * 360.0
animate on wheelobject.rotation.controller[rAxis]. \
controller.value = curDeg
)
)
Для того чтобы сделать вращение колеса более привлекательным визуально,
установите режим Show Trajectory (Показать траекторию) для объекта Wheel 01-
Motionindicator.
А для проверки данного метода воспользуйтесь сценой из файла \chapter5\
Roadster_reverse.max на прилагаемом к этой книге CD-ROM. В этой сцене
автомобиль проезжает весь путь, а затем возвращается назад, останавливаясь на
полпути. За ним, соответственно, следует камера.
Удаление ключевых кадров
Если для установки ключевых кадров используются временные интервалы, то
предыдущие ключевые кадры можно удалить с помощью следующего оператора:
deleteKeys wheelobject.rotation.controller
Касательные к ключевым кадрам
При установке ключевых кадров касательные к ним на функциональных кри-
вых, отображаемых в редакторе кривых, могут оказаться нелинейными. Доступ
к таким касательным можно организовать в цикле, используя следующие свойства
(в данном случае это делается для объекта b только для примера):
b.rotation.controller[1].controller.keys -- Все ключевые кадры на
треке анимации вращения вокруг оси X
b.rotation.contгоIler[2].controller.keys -- Все ключевые кадры на
треке анимации вращения вокруг оси Y
b.rotation.controller[3] .controller.keys -- Все ключевые кадры на
треке анимации вращения вокруг оси Z
Например, для доступа к входящей касательной (In) к заданному ключевому
кадру на треке X Rotat ion используется следующее выражение:
b.rotation.controller[1].controller.keys[i].inTangentType
А задать линейный тип касательной можно с помощью следующего выражения:
b.rotation.controller[1].controller.keys[i].inTangentType = #linear
В сценарии для вращения колеса все касательные к ключевым кадрам можно
сделать линейными в конце блока кода обработчика событий on but_setkeys
pressed. В данном случае лучше подходит устанавливаемый по умолчанию тип
#auto касательных, однако линейные касательные служат хорошим примером
для демонстрации доступа и задания типов касательных:
174
Глааа 5
for i = 1 to 3 do
(
for к in wheelObject.rotation.controller [i] .controller.keys do
(
k.inTangentType = k.outTangentType = #linear
)
Заключение
В этой главе вы научились выполнять преобразования средствами MAXScript.
Вы ознакомились с разными видами вращения и особенностями их организации
в сценарии. Кроме того, вы научились устанавливать ключевые кадры анимации
и применять контроллеры. И наконец вы создали рабочий сценарий для вращения
объекта на основании пользовательского ввода и элементов сцены.
175
Работа с объектами в MAXScript
Глава 6
В MAXScript имеется возможность
манипулировать самыми разными типами
объектов щены. В этой главе показано,
как работать с некоторыми основными
объектами щены, в том числе
с модификаторами, источниками света
и камерами. Кроме того,
здесь рассматриваются важные
вопросы визуализации, организации
обратных вызовов и формирования
случайных значений.
Глава 6
Задание
После изучения этой главы вы должны уметь следующее.
• Работать с модификаторами
• Создавать источники света и камеры
• Работать с материалами
• Управлять средством визуализации
• Организовывать обратные вызовы
• Пользоваться случайными числами
Введение
Итак, вы уже умеете создавать геометрические объекты средствами MAXScript.
В этой главе вы научитесь создавать и модифицировать источники света, камеры
и материалы.
Приступая к работе в пользовательском интерфейсе 3ds Мах, вы обычно на-
страиваете средство визуализации и пользуетесь его настройками в течение всей
работы. В этой главе поясняется, как средство визуализации настраивается
в MAXScript для автоматизации процесса визуализации.
Кроме того, вы ознакомитесь с обратными вызовами и методом вызова сцена-
рия, когда на сцене происходит определенное событие. И наконец вы научитесь
формировать случайные значения средствами MAXScript.
Применение модификаторов
Все, что создается в MAXScript, считается объектом или элементом опреде-
ленного типа, даже при отсутствии физического проявления. Модификаторы
также считаются объектами, хотя они и не являются трехмерными объектами,
аскорее относятся к элементам, обладающим определенными свойствами, кото-
рые можно устанавливать и изменять аналогично трехмерным объектам сцены.
Об этом различии уже упоминалось в главе 4.
Сначала создается объект-модификатор, а затем устанавливаются его свойства.
Для того чтобы создать и применить модификатор, выполните следующее уп-
ражнение.
1. Установите 3ds Мах в исходное состояние.
2. Создайте модификатор Bend с помощью конструктора bend и укажите
угол сгибания, введя в приемнике команд следующую строку кода:
b = bend angle:90
Переменная ь содержит ссылку на модификатор Bend, тогда как угол сги-
бания (angle) относится к свойствам данного модификатора. Теперь мо-
дификатор можно применить к любому трехмерному объекту.
177
Работа с объектами в MAXScript
3. Создайте цилиндр и установите число его сегментов по высоте равным 2С.
чтобы лучше видеть воздействие на него модификатора. Для этого введите
следующую строку кода:
с = cylinder height:50 heightsegs:20
4. Примените модификатор Bend к цилиндру. Для этого введите следующую
строку кода:
addmodifier с Ь
В этой строке кода модификатор применяется к цилиндру с помощью ме-
тода addmodifier, после имени которого указываются ссылка на цилиндр
и ссылка на данный модификатор. А поскольку конкретная ось действия мо-
дификатора не указывается, то по умолчанию в 3ds Мах используется ось Z.
5. Этот же сценарий можно было бы написать короче. Введите следующий
фрагмент кода:
сс = cylinder pos: [100,0,0] height:50 heightsegs:20
addmodifier cc (bend angle:90)
В последнем пункте предыдущего упражнения конструктор модификатора
был помещен в круглые скобки. Это еще один пример передачи выражения в виде
аргумента функции. В данном выражении создается объект-модификатор, кото-
рый затем применяется к цилиндру.
Свойства модификатора можно изменить тремя способами.
• Присвоить явную ссылку на модификатор. В приведенном выше упражне-
нии переменной Ь была присвоена ссылка на модификатор. После этого
свойства переменной Ь могут быть установлены с помощью таких выраже-
ний. как следующее:
i:. angle = 80
178
Глава 6
При установке свойства объект автоматически обновляется в видовом окне.
Так, в приведенном выше упражнении это оказало влияние не на новый,
а на исходный цилиндр, поскольку к нему был применен модификатор Bend,
ссылка на который делается в переменной Ь.
• Изменить свойства модификатора посредством объекта, к которому он
применяется. Если используется метод addmodifier, модификатор вы-
полняет роль свойства геометрического объекта. Изменения могут быть
внесены в модификатор следующим образом:
сс.bend.angle = 75
Доступ в этой строке кода осуществляется сначала к свойству bend цилиндра
сс, а затем к свойству angle модификатора Bend. Таким способом удобно
пользоваться в отсутствие явной ссылки на модификатор, как в примере со-
кращенной записи кода сценария из п. 5 приведенного выше упражнения.
• Получить доступ к массиву свойств модификаторов, применяемых к объек-
ту. Каждый объект имеет свойство .modifiers, возвращающее массив мо-
дификаторов, применяемых к данному объекту. Первым элементом данного
массива является модификатор, находящийся на вершине стека в том виде,
в каком он представлен на панели команд Modify. Вторым элементом мас-
сива является следующий вниз по стеку модификатор и так далее до по-
следнего элемента массива, который соответствует модификатору, находя-
щемуся на дне стека. Если воспользоваться упоминавшимся ранее
примером цилиндра, то можно написать следующее:
с.modifiers[1].angle
В этой строке кода осуществляется доступ к свойству angle модификатора
Bend. Такой способ доступа к свойствам модификатора удобен для выпол-
нения операций над всеми модификаторами, применяемыми к объекту.
Источники света и камеры
Источники света и камеры являются подклассами класса Node. Все, что было
сказано в главе 4 в отношении наследования классов, распространяется и на ис-
точники света, камеры и геометрические объекты.
Источники света
В MAXScript можно создать любой тип источника света из тех, которые до-
ступны в пользовательском интерфейсе 3ds Мах. У каждого типа источника света
имеется свой конструктор. Например, конструктор свободно направленного ис-
точника света выглядит следующим образом:
directionalLight()
179
Работа с объектами в MAXScript
MAXScript Listener CD®®
Rb at Search MacroRecorder lebugg Help
directionalLightО
?Free__Directional_LiQht:FDirect01 6 [0.000000/0.006000,0.000000]
У1
Если ввести приведенную выше строку кода в окне приемника команд, в ответ
появится результат, очень похожий на тот, который был получен для геометриче-
ского объекта:
$Free_Directional—Light:FDirectOl @ [0.000000, 0.000000, 0.000000]
В этом результате представлены класс объектов Free_Directional_Light
(обозначаемый также как Directionallight), путевое имя объекта $FDirect01
и местоположение объекта в точке мирового пространства с координатами [0,0,0].
Полный перечень типов источников света, которые можно создавать средст-
вами MAXScript, приведен в следующем разделе справочного руководства по
MAXScript: MAXScript Language Reference^SdsMax Objects^Node: MAXWrapper1^
Node Subclasses^Light: Node (Справочник по языку МАХБспр^Объекты 3ds Max1^
Класс Node: MAXWrapper1^ Подклассы класса Node1^ Класс Light: Node).
Все доступные типы источников света перечислены в книгах Standard Lights
и Photometric Lights данного справочного руководства, посвященных стандартным
и фотометрическим источникам света соответственно.
Многие свойства источников света являются общими для них. К ним относят-
ся следующие свойства:
dight>.rgb - цвет RGB
<light>.excludeList - массив узлов, исключаемых из световых эффектов
dight>.projectorMap - карта, хранящаяся в объекте textureMap
Полный перечень общих свойств источников света приведен в разделе “Light
Common Properties, Operators, and Methods” (Общие свойства, операторы и мето-
ды источников света) справочного руководства по MAXScript.
Для того чтобы исключить объекты из сферы влияния источника света, вы-
полните следующее упражнение.
1. Установите 3ds Мах в исходное состояние.
2. Введите в новом окне редактора MAXScript Editor следующий фрагмент
кода, чтобы создать па сцене несколько объектов:
for i = -1 to 1 do
(
box poS:[i*40, 0, 0]
sphere pos:[i*40, 0, 60]
180
Глава 6
)
myPlane = plane length:150 width:150
3. Создайте всенаправленный источник света с устанавливаемыми по умол-
чанию свойствами и задайте его положение:
myLight = omnilight pos:[0, -100, 100] castshadows:on
Свойство excludeList воспринимает массив узлов. В данном упражне-
нии необходимо исключить сферы из освещения всенаправленным источ-
ником света.
4. Создайте массив сферических узлов:
sphereArray = for obj in objects \
where (classof obj == sphere) collect obj
В приведенном выше цикле for возвращается массив сферических объек-
тов. В данном случае использована специальная форма синтаксиса цикла
for, в которой вместо ключевого слова do, указывающего тело цикла, вве-
ден оператор collect, предписывающий создать совокупность объектов,
удовлетворяющих заданному условию. Это условие также указывается
в специальной форме цикла for, где оно является частью определения дан-
ного цикла. Нетрудно заметить, в чем именно состоит проверка: если объ-
ект является сферой, возвращается логическое значение true. Это доволь-
но компактная и удобочитаемая форма цикла for.
5. Установите свойство excludeList источника света следующим образом:
myLight.excludeList = sphereArray
6. Вычислите сценарий.
7. Визуализируйте сцену.
Теперь на сцене видны только параллелепипеды.
181
Работа с объектами a MAXScript
Как упоминалось выше, каждый источник света имеет свойство . pro j ectorMap.
Далее вам предстоит присвоить этому свойству текстурную карту. Сущест-
вует более 30 типов текстурных карт, в том числе карты планеты, мрамора
и клетчатого рисунка. Как только будет создан объект textureMap, его
можно присвоить свойству . pro j ectorMap источника света.
Примечание. В свойствах источников света можно также указывать растровые
текстуры, но из-за большого числа свойств объекта BitmapTexture с ними
нелегко обращаться. Более подробные сведения об этом приведены в разделе
“BitmapTexture: TextureMap” справочного руководства по MAXScript.
Для изучения свойства .proj ectorMap выполните следующее упражнение.
1. Продолжите работу с предыдущим примером сценария, удалив со сцены
все объекты. Введите две следующие строки кода в конце предыдущего сце-
нария, чтобы создать текстурную карту и назначить ее для источника света:
marbleMap = marble Vein_Width:0.1 size:12
myLight.projectorMap = marbleMap
В этих строках кода изменены свойства ширины и размера карты, чтобы
сделать мраморный эффект более заметным. Все свойства объекта
textureMap могут быть установлены по отдельности. В данном случае ус-
тановлены только два из них, а остальные используются в том виде, в каком
они установлены по умолчанию.
В видовом окне текстурная карта не наблюдается, но после визуализации
сцены она должна выглядеть так, как показано на приведенном ниже рисунке.
С объектами textureMap вам еще предстоит поработать в этой главе, когда
речь пойдет о материалах.
182
Глава 6
Камеры
Управление камерами осуществляется в MAXScript достаточно просто. Ниже
приведены некоторые конструкторы для свободных и нацеленных камер:
targetCamera()
freeCamera()
Для создания нацеленной камеры выполните следующее упражнение.
1. Продолжите работу с предыдущим примером сценария. Вместо того чтобы
удалять вручную все объекты со сцены всякий раз, когда выполняется сце-
нарий, вам предстоит организовать их удаление автоматически. Введите
следующую строку кода в самом начале своего сценария:
delete $*
2. Введите следующую строку кода в самом конце сценария:
tobj = targetobject pos:[7,15,31]
В этой строке создается целевой объект для нацеленной камеры. У данного
объекта, выполняющего роль цели камеры, отсутствуют собственные свойства.
3. Создайте нацеленную камеру и укажите ее цель:
tc = targetcamera pos:[0, 0, 40.0] target:tobj
4. Когда камера перемещается, она остается постоянно направленной на цель.
Введите в окне приемника команд следующую строку кода:
move tc [-121,-166,60]
Камера постоянно направлена на цель.
183
Работа с объектами в MAXScript
Для того чтобы назначить текущее видовое окно для камеры, выполните сле-
дующее упражнение.
1. Активизируйте окно вида в перспективе, выделив в этом окне любой нахо-
дящийся на сцене объект. Введите в свой сценарий следующую строку кода:
viewport.setcamera tc
2. Активизируйте безопасные кадры в этом видовом окне, введя следующую
строку кода:
max safeframe toggle
А теперь сохраните сценарий в файле, поскольку вам еще предстоит вер-
нуться к нему.
Материалы
Средствами MAXScript можно получить доступ к редактору материалов, а также
к отдельным материалам, применяемым к объектам. В частности, для доступа
к материалу, назначенному для объекта, служит свойство . material или . mat:
<node>.material
<node>.mat
А для доступа к материалу в редакторе материалов служит виртуальный мас-
сив meditMaterials. Этот массив организуется в 3ds Мах автоматически и ин-
дексируется номерами соответствующих позиций образцов в редакторе материа-
лов, например:
meditmaterials[3]
При выполнении этой строки кода возвращается материал, находящийся на
третьей позиции образца в редакторе материалов.
184
Глава 6
Предупреждение. Массив meditMaterials состоит только из 24 элементов,
поэтому будьте внимательны, чтобы не выйти за пределы этого массива во время
его индексации. Так, обращение meditMaterials [25] к данному массиву
приведет к ошибке.
Материалы можно создавать, как отдельные объекты, и назначать их для объ-
ектов сцены. Каждый тип материала имеет свой конструктор. Например, конст-
руктор стандартного материала имеет следующий вид:
standard()
Как только стандартный материал создан, его карты становятся доступными
в виде свойств данного материала:
sm = standard()
sm.diffusemap
Разные виды карт можно также создавать, как отдельные объекты, и назначать
их для отдельных каналов проецирования:
ch = checker()
sm.diffusemap = ch
Для отображения карты в видовом окне служит метод showTextureMap:
showTextureMap sm ch on
В этой строке кода активизируется режим отображения карты клетчатого ри-
сунка ch в материале sm.
Управление средством визуализации
В MAXScript имеется возможность устанавливать ряд параметров для автома-
тического управления средством визуализации. Визуализацию проще всего орга-
низовать с помощью метода render. Его синтаксис следующий:
render [ camera: <camera_node> ] [ frame: <number> | ([current ] ...
Примечание. Метод render имеет около 45 необязательных параметров. В этом
разделе приводятся лишь самые важные из них.
Ниже перечислены некоторые устанавливаемые по умолчанию параметры и ре-
жимы визуализации.
• Визуализация в активном видовом окне
• Использование текущих настроек визуализации
• Визуализация в виртуальный буфер кадров
Устанавливаемые по умолчанию параметры могут быть переопределены. Ни-
же приведены некоторые необязательные параметры визуализации.
• camera: <camera>— после создания камеры визуализацию можно вы-
полнять с точки зрения камеры, используя объект камеры.
• frame: <number> или #current — для визуализации конкретного кадра,
например кадра 10, достаточно ввести следующую строку кода:
render f rame:10
185
Работа с объектами в MAXScript
Для указания средству визуализации текущего номера кадра служит обо-
значение #current:
render fгame:#current
• frameRange: <interval> или #active — этот параметр задает диапа-
зон кадров анимации в следующем виде:
frameRange:(interval 0 100)
С помощью обозначения #active средству визуализации указывается ак-
тивный в данный момент временной интервал:
render frameRange:#active
• fromframe: <number> и toframe: <number>- если используется
только свойство fromframe, визуализация начинается с указанного кадра
и продолжается до последнего кадра. Если же используется только свойст-
во toframe, визуализация начинается с текущего кадра и завершается
в кадре с номером toframe.
• nthframe: <number> — устанавливает режим визуализации через каж-
дые п кадров.
• outputfile: <string> — указывает путь к файлу вывода.
• outputwidth: <number> — задает выходную ширину.
• outputheight: <number> — задает выходную высоту.
• pixelaspect: «number> — задает выходные пропорции элемента изо-
бражения.
В версии 3ds Мах 8 появились следующие дополнительно указываемые пара-
метры визуализации.
• renderElements: <Ьоо1> — если передается логическое значение true
этого параметра либо его значение вообще не передается, визуализации
подлежат любые визуализируемые элементы сцены.
• renderMultiPassEf fects: <bool> — если передается логическое значе-
ние true этого параметра либо его значение вообще не передается, а для
текущей камеры активизирован эффект многопроходной визуализации, то
визуализируется именно этот эффект.
• renderElementBitmaps: <&var>— если визуализация выполняется по
элементам, растровые изображения отдельно выводимых элементов визуа-
лизации помещаются в массив, который возвращается в переменной, ука-
зываемой по ссылке.
Дополнительные сведения об управлении средством визуализации приведены
в следующем разделе справочного руководства по MAXScript: MAXScript Tools
and Interaction with SdsMax^Miscellaneous Functions^Controlling the Renderer
(Инструменты MAXScript и взаимодействие c 3ds Max1^ Взаимодействие с поль-
зовательским интерфейсом 3ds Мах^Разные функции1^Управление средством
визуализации).
186
Глава 6
В следующем упражнении будет создана простая сцена и визуализирован ряд
ее кадров. В этом упражнении вы продолжите работу с предыдущим примером
сценария. Сначала вам предстоит оживить ряд параллелепипедов, чтобы в анима-
ции было заметно некоторое движение.
1. Введите следующий фрагмент кода в конце сценария, над которым вы ра-
ботали в предыдущем упражнении:
boxArray = for obj in objects where (classof obj == box)
collect obj
with animate on
(
at time 10 move tc [50,0,0]
for i = 1 to 3 do
at time 10 ( rotate boxArrayti] (quat (i * 98) z_axis))
)
Если переместить ползунок временной шкалы анимации от кадра 1 к кадру 10,
то можно заметить, как переместится камера и повернутся параллелепипеды.
2. Визуализируйте сцену в файл формата AVI. Для этого введите в окне ре-
дактора сценариев следующий фрагмент кода:
render camera:tc \
outputwidth:320 \
outputheight:240 \
fromframe:0 \
tof rame -.10 \
outputfile:"c:\\teapot.avi"
Если вы предпочитаете вывести результаты визуализации в другую папку
или на другой диск, замените имя диска или введите другую папку перед
именем файла формата AVI в последней строке данного фрагмента кода.
3. Выведите следующее сообщение об окончании визуализации:
messagebox "Finished Rendering!"
Когда визуализация начнется, видно будет лишь содержимое буфера
видеокадра, поэтому вам придется немного подождать, пока она не завер-
шится. Для того чтобы проверить правильность выполнения визуализиро-
ванной анимации, воспроизведите сформированный файл формата AVI на
своем компьютере.
Примечание. Вариант сценария из данного упражнения находится в файле
\chapter6\animate_boxes.ms на прилагаемом кэтой книге CD-ROM.
Обратные вызовы
Обратный вызов представляет собой сценарий, указываемый для выполнения
всякий раз, когда наступает некоторое событие. Например, можно организовать
обратный вызов конкретной функции в любой момент, когда наступает одно из
следующих событий.
187
Работа с объектами в MAXScript
• Визуализируется сцена
• Перемещается ползунок временной шкалы или воспроизводится анимация
• Сохраняется, импортируется или объединяется файл сцены
• Вводится в стек или удаляется из стека модификатор
• Скрывается, фиксируется или удаляется объект
Это лишь некоторые примеры событий, для которых создаются функции об-
ратного вызова. Все возможные при этом события приведены в следующем разде-
ле справочного руководства по MAXScript: MAXScript Tools and Interaction with
SdsMax^Change Handlers and Callbacks (Инструменты MAXScript и взаимодей-
ствие c 3ds Max1^Обработчики изменений и обратные вызовы).
В следующем упражнении вам предстоит организовать обратный вызов сцена-
рия всякий раз, когда изменяется положение ползунка временной шкалы анимации.
1. Загрузите сцену из файла \chapter6\obstacles.max, находящегося на
прилагаемом к этой книге CD-ROM.
2. Воспроизведите анимацию.
Эта сцена содержит камеру, которая следует по пути, проложенному между
несколькими примитивами. Для каждого примитива назначен отдельный
материал.
Далее вам предстоит организовать обратный вызов сценария, в котором
проверяется расстояние между камерой и каждым объектом и изменяется
прозрачность объекта в зависимости от расстояния до камеры. Объекты по-
степенно проявляются на сцене по мере приближения к ним камеры, как бы
выплывая из тумана.
3. Выберите команду MAXScript1^New Script из главного меню.
4. Введите в начале сценария строку комментария с названием сценария:
-- Revealer.ms
Вы можете дополнить этот комментарий своим именем, датой создания
сценария или любыми другими сведениями, которые вы сочтете нужным
сообщить.
188
Глава 6
Создайте следующую функцию для проверки расстояния между камерой
и объектами:
-- Определить непрозрачность
fn calcOpacity =
(
for i in objects do
(
if superclassof i == geometryclass then
(
closeness = distance i $Camera01
- - Если камера отдалена от объекта, сделать его прозрачным
if closeness > 900 then i.material.opacity = 0
- -По мере приближения камеры изменить прозрачность
- - в зависимости от расстояния
- - Сделать объект совершенно непрозрачным,
- - когда расстояние окажется меньше 100
else
(
if closeness > 400 then
i.material.opacity = '900 - closeness)/5.0
else
i.material.opacity = ICQ
)
)
)
)
5. В этом фрагменте кода объекты, находящиеся близко к камере (т.е. на расстоя-
нии менее 40 единиц), оказываются совершенно непрозрачными. Объекты, от-
даленные от камеры (на расстояние более 90 единиц) оказываются совер-
шенно прозрачными. А объекты, находящиеся в промежутке между этими
точками, становятся менее прозрачными по мере приближения к камере.
Теперь необходимо организовать обратный вызов данной функции всякий
раз, когда перемещается ползунок временной шкалы анимации.
6. Введите в конце сценария следующую строку кода:
registerTimeCallback calcOpacity
7. Вычислите сценарий.
8. Переместите ползунок временной шкалы анимации.
При перемещении ползунка по временной шкале анимации камера прохо-
дит мимо объектов, и каждый из них становится менее прозрачным по мере
приближения к нему камеры.
По завершении сценария, содержащего обратный вызов, необходимо отме-
нить регистрацию обратного вызова. В противном случае функция будет
вызываться всякий раз, когда в сцене наступит указанное событие. Напри-
мер, в созданном только что сценарии функция calcOpacity будет вызы-
ваться при всяком изменении положения ползунка на временной шкале
анимации, если не отменить регистрацию этой функции обратного вызова.
189
Работа с объектами в MAXScript
9. После того как функция обратного вызова будет использована, введите
в приемнике команд следующую строку кода:
unRegisterTimeCallback calcOpacity
В этой строке отменяется регистрация функции обратного вызова
calcOpacity.
Примечание. Вариант сценария из данного упражнения находится в файле
\chapter6\revealer .ms на прилагаемом к этой книге CD-ROM.
Внесение элемента случайности
С помощью метода random в MAXScript можно сформировать случайные зна-
чения следующих типов данных: integer, float, color, quat, eulerAngles,
angleAxis, time, Point2 и Point3. Эти случайные значения можно использо-
вать для изменения любого свойства, имеющего заданный тип данных. Ниже при-
веден простой пример применения метода random.
190
Глава 6
for i = 0 to 5 do
(
s = sphere pos: [i*40, 0, 0]
s.radius = random 10.0 30.0
)
Метод random дает произвольные значения. Его синтаксис следующий:
random (наименьшее значение) (наибольшее значение)
Метод random возвращает случайное значение, которое находится в проме-
жутке между минимальным и максимальным значениями, указанными при вызо-
ве данного метода. В приведенном выше примере радиус каждой сферы получает
случайное значение в пределах от 10,0 до 30,0. Если в качестве аргументов ме-
тода random указываются числовые значения с плавающей точкой, возвращаемое
случайное значение также будет числом с плавающей точкой. Если же в качестве
аргументов указываются целочисленные значения
s.radius = random 10 30,
то возвращаемое случайное значение будет целым числом (в данном примере это
ряд случайных значений 25, 27,35 и т.д.)
Метод random реализован достаточно гибко, и если передать ему значения ти-
па Points, то с его помощью можно внести случайный элемент в положение, цвет
и прочие свойства объектов. Так, для произвольного расположения сфер из упо-
минавшегося выше примера можно написать следующий фрагмент кода:
for i = 0 to 5 do
(
s = sphere()
s.pos = random [0.0, 0.0, 10.0] [25.0, 30.0, 100.0]
)
Метод random может полностью воспринимать в качестве аргумента значение
типа Points. В приведенном выше фрагменте кода положение сфер по оси X из-
меняется произвольно в пределах от 0,0 до 25,0, по оси Y — в пределах от 0,0 до
30,0 и по оси Z — в пределах от 10,0 до 100,0.
Допустим, что в начале сценария имеется следующая строка кода: s . pos . х =
random 0.0 10.0. При ее выполнении получается случайное значение в преде-
лах от 0,0 до 10,0. Если перезапустить 3ds Мах и сразу же выполнить данный
сценарий без каких-либо других функций 3ds Мах, указанная строка кода даст то
же самое “случайное” значение. Но при каждом последующем выполнении данно-
го сценария в том же самом сеансе работы в 3ds Мах это значение будет иным.
Внутри метода random используется некоторое начальное случайное значение.
Это значение служит в качестве отправной точки для выполнения внутренней про-
цедуры формирования случайных чисел. При запуске 3ds Мах всегда используется
одно и то же начальное случайное значение. Поэтому метод random формирует одну
и ту же последовательность “случайных” значений всякий раз, когда он вызывается.
Именно по этой причине метод random называется псевдослучайным. Если такой
режим формирования случайных значений вас не устраивает, измените начальное
случайное значение с помощью метода seed следующим образом:
191
Работа с объектами в MAXScript
seed <number> -- где <number> - любое целое число
-- или же число с плавающей точкой
Этот метод может быть связан с функцией New Seed (Новое начальное случай-
ное значение) таких элементов 3ds Мах, как вспомогательный объект SphereGizmo.
Заключение
В этой главе вы научились делать много полезных вещей средствами
MAXScript. Сначала вы научились применять модификаторы, а затем создавать
источники света и камеры и манипулировать ими, а также создавать материалы
и назначать их для объектов сцены. И наконец вы научились управлять средством
визуализации по сценарию, организовывать в сценарии обратный вызов и форми-
ровать случайные значения с помощью метода random.
Используя инструментальные средства, освоенные в главах этой книги, и нау-
чившись пользоваться иерархией классов по справочному руководству
MAXScript, мы можете теперь приступить к созданию собственных сценариев.
192
Приложение
В этом приложении представлен
дополнительный материал по MAXScript.
По мере приобретения опыта
программирования на языке MAXScript
и написания все более сложных сценариев
у вас может возникнуть потребность
в инструментальных средствах,
представленных в данном приложении.
Если же вы только начинаете изучать
MAXScript, этот дополнительный материал
принесет вам пользу лишь после того,
как вы накопите некоторый опыт
программирования в MAXScript.
Приложение
Отладка, перехват и обработка ошибок
При написании сценария, содержащего несколько строк, в нем нередко возни-
кают ошибки. В этом разделе рассматривается процесс поиска и исправления
ошибок в сценариях.
Отладка представляет собой общий процесс обнаружения и исправления
ошибок в сценарии. Перехват ошибок означает выявление ошибок в сценарии,
а обработка ошибок — привлечение средств для манипулирования ошибками. На-
пример, для отладки сценария в него можно ввести ряд строк кода, в которых про-
веряется конкретное условие (перехват ошибок), и предписать MAXScript ото-
бражать диалоговое окно при появлении ошибки (обработка ошибок).
Отладка и обработка ошибок является неотъемлемой частью процесса напи-
сания сценариев. Помимо вновь внедренного отладчика сценариев (MAXScript
Debugger), в MAXScript имеется целый ряд других средств и способов отладки
кода. К ним относятся цветовое кодирование сценария, проверка уравновешен-
ности скобок, применение внутрипроцессных операторов вывода (на печать или
в заданном формате), а также интерпретация сообщений об ошибках и обратное
отслеживание по стеку.
Виды ошибок
В сценарии может возникнуть несколько видов ошибок. Ниже приведены ти-
пичные ошибки.
• Syntax — имя переменной или функции введено неверно либо предприня-
та попытка воспользоваться функцией недозволенным способом.
• Logic — часть сценария выполняет не то. что нужно, поскольку она по-
строена неверно.
• User error — эта ошибка возникает при взаимодействии пользователя со
сценарием. Так, если в сценарии требуется, чтобы пользователь выделил
объект со свойством . radius, в самом сценарии должна быть выполнена
проверка соответствия выбранного объекта заданному критерию. Если же
объект не соответствует критерию выбора, в сценарии может быть выведено
сообщение, предлагающее пользователю выбрать другой объект.
Если возникающая ошибка приводит к сообщению об ошибке, это сообщение
обычно выводится в приемнике команд, даже если сценарий выполняется из ре-
дактора MAXScript Editor или другого места.
Синтаксическая ошибка происходит при попытке использовать функции, зна-
ки, зарезервированные слова, переменные и прочие элементы языка MAXScript не-
дозволенным способом. Ниже приведено выражение, которое не соответствует
правилам языка MAXScript и поэтому приводит к синтаксической ошибке:
for i = 1 to 10 print i
В приемнике команд появляется следующее сообщение об ошибке:
- - Syntax error: at end, expected "do" or "collect"
194
Приложение
Это сообщение означает, что в приведенной выше строке кода пропущено клю-
чевое слово do после числового значения 10.
Ошибка периода выполнения возникает при попытке осуществить в выражении
недопустимую операцию во время выполнения сценария, например:
агг = #(1);агг[0]
В приемнике команд появляется следующее сообщение об ошибке:
- - Runtime error: array index must be +ve number, got: 0
Это сообщение означает, что в выражении предпринята попытка доступа
к элементу массива по индексу 0, но поскольку индексирование массивов начина-
ется с 1, в данном выражении возникает ошибка.
Логическая ошибка возникает в том случае, если предполагаемый результат
не получается, несмотря на соблюдение всех синтаксических правил, например:
у = if х<0 then 0
В этом выражении нулевое значение безошибочно присваивается переменной у,
если х меньше нуля. Но допустим, что на самом деле переменной у нужно было
присвоить нулевое значение, если х больше нуля. Причиной данной ошибки явля-
ется неверная логика программирования. Обнар} жш ь такие ошибки очень труд-
но, поскольку они не формируют сообщения об ошибкЛх. а их последствия могут
проявиться в других местах сценария. В таких случаях рекомендуется писать код
с выводом значений переменной в разных частях сценария, чтобы обнаружить ме-
сто возникновения логической ошибки.
Ошибка периода компиляции возникает еше до начала выполнения кода, на-
пример:
(
у = (1/(х as float)
)
- - Compile error: Unexpected end-of-script
В данном выражении отсутствует закрывающая круглая скобка. И хотя фор-
мально эта ошибка не является синтаксической, она происходит во время компи-
ляции и поэтому различается как таковая.
Ниже приведен еще один пример ошибки периода компиляции. И эта ошибка
не является синтаксической:
local х=0
В приемнике команд появляется следующее сообщение об ошибке:
- - Compile error: no local declarations at top level x
На первый взгляд, приведенное выше простое выражение выглядит правильно.
Где же в нем ошибка? В данном выражении предпринята попытка объявить пере-
менную х как локальную на верхнем уровне сценария, а не в блоке кода. Но локаль-
ная переменная может быть объявлена только в блоке кода. Все переменные верхне-
го уровня считаются глобальными независимо от того, объявлены ли они таковыми.
Пользовательская ошибка возникает в том случае, если пользователь выполняет
действие, не соответствующее текущему состоянию сценария. Допустим, что поль-
зователь щелкнул на кнопке, в обработчике событий которой проверяется выбор
объектов определенного типа, однако такие объекты не были выбраны. Во избе-
195
Приложение
жание ошибки и возможного аварийного сбоя в сценарий следует включить код
для проверки данной ситуации (т.е. перехвата ошибки) и совершения соответст-
вующего действия (т.е. обработки ошибки). В дополнение к этому, возможно, потре-
буется отобразить окно сообщения, в котором пользователю предлагается выбрать
сначала какой-нибудь другой объект. Дополнительные сведения по данному вопросу
приведены в разделе “Перехват и обработка ошибок” далее в этом приложении.
Периоды компиляции и выполнения
Вообще говоря, MAXScript является интерпретируемым языком программи-
рования. Это означает, что код читается построчно и далее формируются и вы-
полняются (т.е. интерпретируются) все необходимые базовые команды. С другой
стороны, в таком транслируемом языке, как C++, код компилируется в выполняе-
мый файл, например, с расширением . ехе. На этапе компиляции выполняемого
файла сначала анализируется исходный код и затем выполняется его преобразо-
вание в необходимые базовые команды, которые уже не нужно формировать по-
вторно всякий раз, когда выполняется программа. Благодаря этому программа
выполняется быстрее, но в то же время усложняется ее разработка.
Несмотря на то что MAXScript является интерпретируемым языком програм-
мирования, в нем все же предусмотрен этап компиляции. На этом этапе выполня-
ется ряд проверок, а код преобразуется в форму, удобную для интерпретации, од-
нако необходимые базовые команды по-прежнему не формируются. Это процесс
периода компиляции. А период выполнения наступает после этапа компиляции,
когда команды фактически формируются и выполняются.
Методы отладки сценариев
Для отладки сценариев имеется целый ряд вспомогательных инструменталь-
ных средств.
Цветовое кодирование
Отдельные части сценария могут кодироваться в редакторе MAXScript Editor
разными цветами, чтобы выделить, например, комментарии, ключевые слова и т.д.
Как правило, цветовое кодирование выполняется автоматически. Исключени-
ем из этого правила являются копирование и вставка текста. Для принудительно-
го обновления цветового кодирования достаточно нажать комбинацию клавиш
<Ctrl+D>. Цветовое кодирование осуществляется следующим образом.
• Зеленым цветом выделяются комментарии
• Голубым цветом выделяются ключевые слова (for, do, if, then и т.д.)
• Красным цветом выделяется текст в кавычках (строковые литералы)
Цветовое кодирование удобно, например, для обнаружения пропущенных за-
крывающих кавычек в строковом литерале.
196
Приложение
Проверка уравновешенности скобок
Данная проверка позволяет выявить неуравношенность таких скобок, как (), []
и {}. В крупных блоках кода иногда трудно определить, соответствует ли каждой
открывающей скобке аналогичная закрывающая скобка.
Для проверки уравновешенности скобок достаточно поместить курсор внутрь
блока кода, заключенного в скобки, и нажать комбинацию клавиш <Ctrl+B>,
чтобы выделить весь текст внутри проверяемых скобок. Если нажать комбинацию
клавиш <Ctrl+B> еще раз, выделится следующий блок, находящийся вне данного
блока кода. Продолжая нажимать комбинацию клавиш <Ctrl+B>, можно посте-
пенно дойти до внешних скобок. Если обнаружится неуравношенность скобок,
раздастся предупреждающий сигнал и текст уже нельзя будет выделить.
Внутрипроцессные операторы вывода
В код сценария можно включить операторы вывода для проверки значений пе-
ременных и других элементов сценария. Это делается с помощью функций вывода
на печать и форматирования.
Вывод на печать
Функция вывода на печать (или метод print) отображает текст в приемнике
команд. Вам уже приходилось пользоваться этим методом при написании сцена-
риев в этой книге.
С помощью метода print можно вывести на печать строку или же содержимое
переменной:
b = box()
print "Box position"
print $Box01.pos
Метод print может быть отображен и на совокупности объектов, например:
arr=#(l, "two", (sqrt 9))
print arr
При выполнении этого фрагмента кода в приемнике команд выводится сле-
дующее:
1
"two"
3.0
У функции вывода на печать имеются определенные ограничения. В частности,
она позволяет выводить только одну строку или переменную в каждом операторе
print. Поэтому для отображения описательного текста или содержимого пере-
менных лучше воспользоваться функцией форматирования.
Форматирование
Функция форматирования выводит текст и содержимое переменных в прием-
ник команд или же в файл указанного формата:
а = 5
format "The variable a is equal to %\n" a
При выполнении данного фрагмента кода в приемнике команд появится сле-
дующее:
The variable a is equal to 5
197
Приложение
Первым параметром функции format является строка. Помимо текста,
в строке можно указать знак процента (%) на том месте, где должно появиться со-
держимое переменной. После строки перечисляются значения в том порядке,
в каком они должны появляться в строке, например:
а = 2
Ь = 3
format "% times % equals %" a b (a*b)
Как видите, последний параметр данной функции представляет собой матема-
тическое выражение. Напомним, что во всяком выражении вычисляется опреде-
ленное значение и поэтому оно может быть использовано везде, где данное значе-
ние оказывается действительным.
Вызов функции format в приведенном выше примере приводит к выводу сле-
дующего результата в приемнике команд:
2 times 3 equals 6
Кроме того, в функции format могут быть использованы последовательности
переключения кода. К наиболее распространенным последовательностям пере-
ключения кода относятся \t (табуляция) и \п (новая строка):
format "\t% times % equals %\n" a b (a*b) to:theFile
В данном примере сначала вводится табуляция, а затем новая строка, поэтому
все остальное форматирование начинается со следующей строки. Параметр to
keyword направляет вывод в файл вместо приемника команд.
В отличие от метода print, метод format не отображается на совокупности
объектов. Если, например, вновь вычислить квадратный корень
arr=#(l, "two", (sqrt 9))
format "arr = %\n" arr
то на этот раз в приемнике команд появится следующий результат:
arr = #(1, "two", 3.0)
Интерпретация сообщений об ошибках
В ответ на выполнение сценария в MAXScript формируются сообщения об
ошибках, помогающие определить вид ошибки и место ее возникновения. Приме-
ры сообщений об ошибках уже приводились в предыдущем разделе, посвященном
видам ошибок, в частности следующее сообщение:
for i=l to 10 print i
-- Syntax error: at end, expected "do" or "collect"
В этом сообщении указывается, что синтаксическая ошибка произошла в конце
сценария, где предполагалось обнаружить зарезервированное слово do или collect.
А теперь рассмотрим пример сообщения об ошибке периода выполнения:
arr=#(1);arr[0]
- - Runtime error: array index must be +ve number, got: 0
В этом сообщении указывается, что ошибка времени выполнения возникла
в связи с тем, что индекс массива должен быть положительным целым числом, ко-
торое больше нуля, однако он оказался равным нулю.
198
Приложение
Далее рассмотрим пример ошибки времени компиляции:
(
у=(1/(х as float)
)
- - Compile error: Unexpected end-of-script
В этом сообщении указывается, что произошла ошибка времени компиляции.
В частности, обнаружено неожиданное окончание сценария. Это произошло из-за
пропуска круглой скобки в строке line у=(1/(х as float).
Системное исключение Unknown указывает на серьезную ошибку, которая
может привести к нарушению устойчивой работы 3ds Мах.
Сообщения об ошибках помогают отнюдь не всегда и могут даже ввести в заблу-
ждение. Ведь сообщение об ошибке — это всего лишь попытка MAXScript распо-
знать и обнаружить ошибку. Решению этой задачи препятствуют присущие данному
процессу ограничения. Иногда MAXScript просто не в состоянии правильно распо-
знать и обнаружить ошибку. Поэтому сообщение об ошибке может быть неопреде-
ленным, а место ошибки — указанным неверно. Но несмотря на подобные ограниче-
ния, сообщения об ошибках являются важным элементом отладки сценариев.
Обратное отслеживание по стеку
Сообщения об ошибках появляются в приемнике команд, а иногда и в переме-
щаемом диалоговом окне предупреждения. Текст сообщения в приемнике команд
включает в себя информацию из окна предупреждения, а также результаты обратно-
го отслеживания по стеку. В таком стеке отслеживается вся предыстория вызовов
функций, обработчиков ошибок и выполнения циклов, включая ошибки, к которым
это привело. Подобные сведения приводятся в обратном порядке по отношению
к происходившим событиям, причем самое последнее из них находится в начале от-
слеживаемой предыстории. Помимо этого, выводятся локальные переменные, пара-
метры функций и их значения. Тщательный анализ подобной информации позволя-
ет выявить подозрительные переменные и определить место возникновения ошибки.
Ниже приведен пример сценария, выполнение которого приводит к ошибке
и появлению окна предупреждения вместе с результатами обратного отслежива-
ния по стеку. В данном сценарии создается простое окно с единственной кнопкой.
В обработчике событий данной кнопки вызывается простая функция, восприни-
мающая один параметр. Эта функция содержит цикл, индекс которого умножает-
ся на параметр функции и неопределенную локальную переменную. Именно эта
переменная дает ошибку.
Откройте приемник команд и выполните приведенный ниже сценарий в окне
редактора MAXScript Editor. Щелкните на кнопке Click Me (Щелкни на мне).
fn testFunction n =
(
for i=ltolOdox=i*n* undefinedLocalVariable
)
try destroyDialog rol_test catch()
rollout rol_test "Test”
(
199
Приложение
button but_test "Click Me!"
on but_test pressed do
(
clearListener()
testFunction 123
)
)
createDialog rol_test
После того как вы щелкнете на кнопке Click Me, появится приведенное ниже
предупреждающее окно, в котором указывается ошибка несовместимости типов
данных.
MAXScript Rollout Handler Exception [Xj
A
Эта ошибка возникла из-за того, что обработчик событий кнопки вызвал функцию
и передал ей числовое значение 12 3 в качестве параметра. Затем в цикле данной функ-
ции была предпринята попытка умножить неопределенную переменную на 123.
Ниже приведены результаты обратного отслеживания по стеку, выводимые
в окне приемника команд. В этом окне красным выделено место возникновения
ошибки и само сообщение об ошибке, а синим выделены параметры и локальные
переменные с соответствующими значениями.
- - Error occurred in i loop
- - Frame:
- - X: undefined
- - undefinedLocalVariable: undefined
- - i : 1
- - called in testFunction()
- - Frame:
- - n: 123
- - called in but_test.pressed ()
- - Frame:
>> MAXScript Rollout Handler Exception: -- Incompatible types: 123, and
undefined <<
Предыстория выполнения сценария отображается в обратном порядке. В пер-
вой строке указывается, что ошибка произошла в цикле. В строках, которые сле-
дуют после строки "Frame", перечислены локальные переменные цикла и их зна-
чения (обратите внимание на то, что индекс цикла i считается локальной
переменной). В связи с тем что i = 1, ошибка возникла на первом же шаге цикла.
Затем в предыстории указывается на то, что ошибка произошла в функции. В ин-
формации под заголовком "Frame" также перечисляются параметр функции
и его значение. И наконец, обратите внимание, что ошибка началась с обработчика
событий кнопки, а в последней строке содержатся заголовок предупреждающего
окна и сообщение об ошибке.
200
Приложение
Кроме того, курсор помещается рядом с ошибочной строкой кода. В данном
случае он находится рядом с закрывающей круглой скобкой, следующей сразу же
после цикла, в котором произошла ошибка. Иногда MAXScript не в состоянии
точно определить ошибочную строку кода, но, как правило, результат оказывается
достаточно близким к истине, чтобы начать отладку кода сценария.
Обратное отслеживание по стеку может показаться поначалу не очень удоб-
ным средством обнаружения ошибок, хотя оно не очень сложное. В то же время
оно дает немало важной и полезной информации для отладки. Если уделить не-
много времени, чтобы научиться правильно интерпретировать обратно отслежи-
ваемую предысторию, это позволит значительно упростить отладку сценариев.
Перехват и обработка ошибок
Перехват и обработка ошибок подразумевает наличие и использование средств
для обнаружения ошибок и манипулирования ими. Пользователи часто допуска-
ют ошибку, пытаясь обрабатывать объекты, которые не выделены. Ниже приведен
пример кода для перехвата и обработки подобных ошибок:
if selection.count==0
then messagebox "Please select one or more objects."
else (/‘Обработать объекты*/; for obj in selection do obj.pos.x+=10)
В операторе if проверяется условие выделения нуля объектов (т.е. ни одного
объекта). Если это условие выполняется, то по условному переходу then отобра-
жается диалоговое окно, в котором пользователю предлагается выделить какие-
нибудь объекты. В противном случае по условному переходу else выделенные
объекты обрабатываются.
Следует заметить, что обработка пустой совокупности выделения объектов не
приводит к ошибке. Такая совокупность содержит нуль объектов, и поэтому цикл
вообще не выполняется. Этот фрагмент кода успешно перехватывает ошибку, свя-
занную с тем, что объекты не выделяются, и обрабатывает ее, предлагая пользова-
телю выделить объекты.
Попытка обработать удаленный объект также приводит к ошибке, например:
obj =box ()
delete obj
print obj.name
-- Runtime error: Attempt to access deleted scene object
-- (Ошибка периода выполнения: попытка доступа к
удаленному объекту сцены)
Для перехвата такой ошибки следует заменить последнюю строку кода сле-
дующей:
if NOT isDeleted obj then print obj.name else messagebox "Deleted object!"
Функцию isDeleted можно применять к модификаторам, контроллерам
и прочим объектам.
201
Приложение
Как правило, для перехвата и обработки ошибок служит пара операторов try/
catch. В блоке кода try предпринимается попытка выполнить операцию, и если
при этом возникает ошибка, то выполняется блок кода catch, например:
try (print obj.name) catch (messagebox "Deleted object!")
В этой строке предпринимается попытка вывести на печать имя объекта. Если
эта операция терпит неудачу, то отображается окно соответствующего сообщения.
Даже если операция в блоке кода try завещается неудачно, данная строка кода не
приведет к ошибке периода выполнения.
Выражения try и catch заключаются в круглые скобки лишь для ясности, но
формально скобки не требуются.
Операция try/catch выполняется относительно медленно, поэтому ее следу-
ет избегать в циклах или функциях, которые вызываются многократно. Основной
критерий выбора такого метода перехвата и обработки ошибок - - скорость выпол-
нения сценария. Если код выполняется достаточно быстро, значит, операцию
try/catch целесообразно применять.
Отладчик MAXScript Debugger
Отладчик MAXScript Debugger, внедренный в версии 3ds Мах 8, предназначен
для оказания помощи в выявлении и устранении программных ошибок в сцена-
рии. Такой отладчик состоит из нескольких инструментов, помогающих анализи-
ровать сценарии.
Этот раздел служит лишь введением в отладчик MAXScript Debugger, а сама
отладка, в целом, представляет собой сложный процесс и требует некоторого опы-
та для полного освоения.
Раньше при аварийном завершении сценария приходилось полагаться на вы-
вод результатов обратного отслеживания по стеку для определения состояния пе-
ременных и последовательности вызовов функций и обработчиков событий. Од-
нако обратное отслеживание по стеку не всегда помогало. Например, можно было
получить ошибку "Unknown property: "cproperty name> in undefined"
(Неизвестное свойство <имя свойства> неопределенной переменной). Обнаружить
неопределенную переменную было очень трудно, особенно если у функции было
много таких переменных. Для разрешения подобных затруднений и отслеживания
программных ошибок можно было бы попытаться использовать в сценарии не-
сколько операторов print или format. Но это лишь усложнило бы код сценария.
В новом отладчике имеются инструменты, позволяющие решать упомянутые
выше проблемы. Но сначала нужно научиться получать доступ к этому отладчику.
Доступ к отладчику
Окно отладчика MAXScript Debugger открывается из следующих меню.
• Из главного меню 3ds Мах по команде MAXScript^Debugger Dialog
• Из меню Debugger приемника команд
• Из меню Debugger любого окна редактора сценариев
202
Приложение
Когда окно отладчика MAXScript Debugger открывается в первый раз, оно
имеет небольшие размеры. Но размеры этого окна можно изменить и сохранить
вместе с его положением для последующего использования. Отладчик работает
в автономном режиме по отношению к 3ds Мах.
Параметры настройки отладчика
Для доступа к параметрам настройки отладчика выберите кнопку Config...
(Настройка) в нижней части его окна. Откроется диалоговое окно MAXScript Debugger
Parameters (Параметры отладчика).
Параметры настройки в этом диалоговом окне управляют отладчиком как при
его открытии, так и в других режимах его работы. Непременно установите флажок
Stay On Тор (Оставить сверху), чтобы окно отладчика случайно не оказалось по-
зади окна 3ds Мах. Дополнительные сведения о настройке параметров отладчика
приведены в книге MAXScript Debugger справочного руководства по MAXScript.
Команда прерывания
Как правило, выполнение сценария прекращается при появлении ошибки, ис-
ключительной ситуации или при срабатывании оператора throw. Например, вся-
кая попытка получить доступ к свойству неопределенной переменной приводит
к ошибке, а попытка выполнить деление на нуль — к исключительной ситуации
и останову сценария. Метод throw также приводит к приостановке выполнения
203
Приложение
сценария. В отладчике внедрен новый метод, позволяющий останавливать или
прерывать выполнение сценария вручную. Это так называемая функция прерыва-
ния, или контрольного останова. Ее синтаксис довольно прост:
<ok> Break()
Данная функция возвращает постоянное значение "ок" и не воспринимает па-
раметры, а просто останавливает выполнение сценария в данной точке. Если окно
отладчика настроено на открытие по команде прерывания, то оно открывается при
останове сценария.
Окно вывода из отладчика
Если выполнение сценария прекращается по ошибке или контрольному остано-
ву, информация о сценарии выводится из отладчика в специальное окно Debugger
Output Window. При этом отладчик запрещает доступ к пользовательскому ин-
терфейсу 3ds Мах, приемнику команд и любым открытым окнам редактора
MAXScript Editor.
Для того чтобы использовать отладчик, выполните следующее упражнение.
1. Установите 3ds Мах в исходное состояние.
2. Откройте сначала отладчик, а затем диалоговое окно Debugger Parameters.
3. Установите флажок Stay On Top.
4. Откройте новое окно редактора сценариев и введите следующий фрагмент кода:
(
а = О
for i = 1 to 10 do
(
a += 1.5
ss = i * 2
if ss == 18 do break()
)
)
5. Сохраните сценарий в файле debugger. ms.
6. Вычислите сценарий.
Когда индекс цикла for достигнет 9, значение переменной ss станет рав-
ным 18 и будет вызвана команда прерывания. Затем в окне вывода из от-
ладчика появится следующая информация:
#
♦♦thread data: threadID. 2848
** [stack level: 0]
♦ ♦In i loop; filename: C:\Program
Files\3DSMax8\Scripts\debugger.ms;
position: 89
♦♦member of: anonymous codeblock
- -Parameters:
- -i: 9
- -Locals:
- -SS: 18
204
Приложение
- -i: 9
- -Externals:
- -owner: cCodeBlock:anonymous>
- -a: 13.5
--Owner:
- -Locals:
- -a: 13.5
- -Externals:
* *[stack level: 1]
♦ ♦called from anonymous codeblock; filename: C:\Program
Files\3DSMax8\Scripts\debugger.ms; position: 93
- -Locals:
- -a: 13.5
- -Externals:
* *[stack level: 2]
♦ ♦called from top-level
Первая строка результатов отладки содержит идентификационный номер
2 84 8 текущего потока (у вас этот номер может быть другим). Чаще всего иденти-
фикационные номера потоков не нужны для отладки, поэтому они здесь и не рас-
сматриваются. Далее выводятся все уровни и кадры стека, называемые также бло-
ками кода, заключенного в круглые скобки. Для каждого блока кода в MAXScript
создается отдельный кадр стека, располагаемый в том порядке, в каком данный
блок кода вызывается. Каждый кадр стека нумеруется начиная с нуля, соответст-
вующего вершине стека (или последнему блоку кода). Таким образом, результаты
отладки показывают, что прерывание сценария произошло в следующей строке кода:
** [stack level: 0]
Этот кадр стека связан с циклом for. Поэтому цикл for указывается во вто-
рой строке результатов отладки:
♦♦In i loop; filename: C:\Program
Files\3DSMax8\Scripts\debugger.ms;
position: 89
В этой строке указываются имя файла сценария и местоположение знака отно-
сительно начала файла, в котором произошло прерывание.
В последующих строках результатов отладки перечисляются различные пере-
менные, используемые в данном цикле for.
• Под заголовком Parameters перечисляются любые параметры текущего
блока кода. В данном случае индекс цикла i считается параметром блока
кода, и поэтому указывается его значение 9.
• Под заголовком Locals перечисляются любые локальные переменные, оп-
ределенные внутри текущего блока кода. В данном случае перечислены пе-
ременные i и ss, а также их значения 9 и 18 соответственно.
• Под заголовком Externals перечисляются любые внешние переменные из
более обширной области действия, которые используются внутри текущего
цикла for. В данном случае внешняя переменная а имеет локальную об-
ласть действия и получает приращение на каждом шаге цикла for (ее зна-
чение равно 13,5).
205
Приложение
• Под заголовком Owner указывается владелец текущего блока кода. В дан-
ном случае сценарий выполнялся внутри пары круглых скобок. Такой
блок кода называется анонимным, поскольку у него нет имени. Если бы
это был конкретный сценарий MacroScript, у него было бы имя категории
MacroScript и присоединяемое к нему через символ подчеркивания имя
сценария MacroScript.
После содержимого кадра стека нулевого уровня перечисляется содержимое
выполнявшегося ранее кадра стека уровня 1, т.е. того блока кода, из которого вы-
зывался цикл for:
**[stack level: 1]
Об этом свидетельствует следующая строка:
♦♦called from anonymous codeblock; filename: C:\Program
Files\3DSMax8\Scripts\debugger.ms; position: 93
Далее указывается содержимое второго уровня стека, который соответствует
глобальной области действия и называется верхним уровнем:
**[stack level: 2]
♦♦called from top-level
Командная строка отладчика
Итак, вам должно быть ясно, что собой представляют выводимые результаты
отладки сценария. А теперь вам нужно ознакомиться с назначением командной
строки. Именно в этой строке вы можете вводить команды отладчика для переме-
щения по блокам кода, запроса и изменения содержимого переменных и выполне-
ния команд MAXScript. Все это можно делать лишь в том случае, если выполне-
ние сценария остановлено, т.е. в режиме прерывания (Break). На первый взгляд,
в командной строке отладчика можно вводить все, что угодно, как и в приемнике
команд. Но на самом деле в этой строке воспринимаются лишь некоторые пере-
численные ниже команды.
• threads - перечисляет все потоки.
• setThread сцелочисленный литерал? — задает указанный поток в ка-
честве активного. По этой команде выводится также содержимое стека ак-
тивного потока.
• setFrame сцелочисленный литерал? - задает указанный кадр стека
в качестве активного.
• locals {сстроковый литерал?} — выводит содержимое переменных
из активного потока и кадра стека либо содержимое отдельно указанной
переменной.
• getVar сстроковый литерал? — получает значение указанной пере-
менной из активного или глобального кадра стека.
• setVar сстроковый литерал? свыражение? — задает значение ука-
занной переменной из активного или глобального кадра стека. Указанное
выражение вычисляется в области действия активного кадра стека.
206
Приложение
• eval <выражение>— вычисляет выражение. Указанное выражение вы-
числяется в области действия активного кадра стека.
• ? — выводит список команд отладчика.
Если сценарий находится в режиме прерывания, содержимое переменных мо-
жет быть изменено с помощью перечисленных выше команд. Примеры их выпол-
нения приведены в следующем разделе.
Окно диспетчера наблюдения
При выборе кнопки Watch... (Наблюдение) в нижней части окна отладчика
открывается окно Watch Manager (Диспетчер наблюдения). В этом окне выводит-
ся текущее значение любой переменной, введенной в столбце Variable.
Содержимое переменных выводится в этом окне после того, как сценарий ока-
жется в режиме прерывания. При этом кнопка Break (Прервать) в нижней части
окна отладчика недоступна, а кнопки Run (Выполнить) и Stop (Остановить) дос-
тупны. Щелкните на кнопке Run, чтобы возобновить выполнение сценария. А для
остановки выполнения сценария щелкните на кнопке Stop. Кнопка Clear
(Очистить) доступна всегда и просто очищает окно вывода из отладчика.
В окне Watch Manager можно запрашивать и изменять содержимое переменных,
чтобы не делать этого из командной строки. В этом окне выводится содержимое
только указанных вами переменных, чтобы не искать их в окне вывода из отладчика.
В сценариях иногда встречаются логические переходы, которые выполняются
редко или не выполняются вообще. Например, длинный оператор if-then-else
или case может содержать переходы к колу, который выполняется очень редко.
(Оператор case реализует еще один способ управления ходом программы и может
быть использован вместо условного оператора if-then-else.) В итоге получа-
ется плохо проверенный код сценария. Подобный недостаток устраняется путем
изменения содержимого переменной условия непосредственно перед оператором
if-then-else или case и последующей проверки каждого логического перехода
в коде сценария. Благодаря этому существенно упрощается отладка сценария, осо-
бенно если условное выражение глубоко скрыто внутри вызовов функций.
Аналогично командной строке отладчика окно Watch Manager может быть ис-
пользовано для изменения содержимого переменных в режиме прерывания
207
Приложение
сценария. Для этого достаточно дважды щелкнуть на ячейке, в которой отобража-
ется значение искомой переменной, а затем изменить его вручную.
В следующем упражнении показано применение окна Watch Manager для из-
менения значения переменной во время выполнения сценария с целью проверки
всех вариантов выполнения кода в операторе case.
1. Установите 3ds Мах в исходное состояние. Откройте окно отладчика и вы-
берите кнопку Watch, чтобы открыть окно Watch Manager. Откройте новое
окно редактора сценариев и введите следующий сценарий:
h = 1
г = undefined
break()
г = case h of
(
1: (h * 2)
5: (h * 3)
"a": (h + "pple")
"b": (h + "at”)
)
break()
2. Введите h и г в столбце Variable диалогового окна Watch Manager.
3. Сохраните сценарий и вычислите его. В окне Watch Manager сообщается,
что переменная h имеет значение 1, а значение переменной г не определено.
Выполнение сценария остановлено непосредственно перед оператором
case, и отладчик находится в ожидании ввода данных от пользователя. Вы
можете изменить значение переменной h прямо сейчас, но прежде просмот-
рите результат выполнения данного сценария по умолчанию.
4. Щелкните на кнопке Run в окне отладчика.
Как видите, выполнение сценария вновь остановлено. Это было сделано
в последнем операторе break, введенном в конце данного сценария, чтобы
вы могли просмотреть значение (в данном случае 2) переменной г в окне
Watch Manager.
208
Приложение
5. Щелкните на кнопке Run, чтобы завершить сценарий.
Примечание. Если вы дошли по последнего оператора break в конце
сценария, когда вывод результатов в приемнике команд завершился,
значение переменной г будет по-прежнему выводиться как
неопределенное. В таком случае вы можете просто выбрать кнопку Break,
чтобы обновить содержимое окна Watch Manager.
6. Вычислите сценарий.
7. Как только выполнение сценария приостановится, воспользуйтесь команд-
ной строкой отладчика вместо окна Watch Manager, чтобы изменить значе-
ние переменной h.
Сначала запросите значение переменной h. Для этого введите в командной
строке следующую команду и нажмите клавишу <Enter>:
getVar h
Введенная команда отображается в окне вывода из отладчика (Debugger
Output Window). А в следующей строке этого окна выводится значение 1
указанной переменной.
8. Установите значение 5 переменной h. Для этого введите в командной стро-
ке следующую команду и нажмите клавишу <Enter>:
setVar h 5
Обратите внимание на то, что значение переменной h автоматически об-
новляется в окне Watch Manager.
9. Щелкните на кнопке Run.
Теперь значение переменной г равно 15.
Итак, вы успешно изменили ход сценария, организовав принудительное
выполнение второго оператора case с помощью отладчика.
10. Щелкните на кнопке Run, чтобы завершить сценарий.
И. Вычислите сценарий. Измените значение переменной h в окне Watch Manager,
введя строку "а". Присваивая строковый литерал переменной, обязательно
указывайте его в кавычках.
209
Приложение
12. Щелкните на кнопке Run.
Теперь переменная г содержит значение "apple" (яблоко).
13. Щелкните на кнопке Run, чтобы завершить сценарий.
14. Вычислите сценарий. Измените значение переменной h, введя на этот раз
строку "Ь".
15. Щелкните на кнопке Run.
Теперь переменная г содержит значение "bat" (летучая мышь).
Область действия диспетчера наблюдения
В окне Watch Manager может выводиться содержимое только тех переменных,
которые оказываются действительными в области действия той части сценария,
на которой было остановлено его выполнение. Рассмотрим для примера следую-
щий сценарий:
function foo х =
(
у = X * X
)
function start =
(
у = foo 5
г = start()
break()
Если попытаться запросить значение переменной у в точке прерывания, в окне
Watch Manager появится следующее сообщение о необъявленной переменной:
"** Undeclared variable: у.Дело в том, что обе переменные у оказались
вне области действия данного блока кода.
Для запроса значения любой из переменных у придется видоизменить сцена-
рий следующим образом:
function foo х =
(
у = X * X
break()
У
)
function start =
(
у = foo 5
210
Приложение
break()
У
)
г = start ()
break()
Оператор break возвращает значение ОК. Следовательно, для возврата пра-
вильного значения нужно явно указать переменную у в конце каждой функции.
В противном случае функция возвратит неверное значение.
Исправление ошибок в отладчике
Итак, вы научились останавливать выполнение сценариев вручную, используя
метод break. Кроме того, вы научились запрашивать значения переменных с по-
мощью того же метода break вместо методов print и format. А теперь покажем, как
в отладчике MAXScript Debugger исправляются настоящие ошибки типа "Unknown
property: <insert property name here>" (Неизвестное свойство:
<укажите здесь имя свойства>). Такая ошибка знакома всякому опытному созда-
телю сценариев. Она обычно приводит к вопросу “Чье неизвестное свойство?”.
Для перехвата подобных ошибок откройте сначала отладчик, а затем диалого-
вое окно Debugger Parameters и установите флажки Break On Error (Прервать
при ошибке) и Break On Exception (Прервать при исключительной ситуации).
Далее откройте новое окно редактора MAXScript Editor, введите и вычислите сле-
дующий фрагмент кода:
function bazz a b = а.х * b
bazz undefined 5
При выполнении этого фрагмента кода в окне вывода из отладчика появляется
следующая ошибка:
#
-- Unknown property: "х" in undefined
**thread data: threadID:1812
**[stack level: 0]
**In bazz();
--Parameters :
--a: undefined
--b: 5
--Locals:
--a: undefined
--b: 5
--Externals:
--owner: undefined
**[stack level: 1]
“called from top-level
Примечание. Вывод результатов обратного отслеживания по стеку в приемнике
команд также усовершенствован. Теперь он частично отражает информацию,
появляющуюся в окне вывода из отладчика. (Напомним, что вывод результатов
обратного отслеживания по стеку в приемнике команд недоступен в режиме
прерывания сценария.)
211
Приложение
В данном случае о самой ошибке сообщается во второй строке, а затем в окне
вывода из отладчика появляется содержимое стека обратного отслеживания. Ана-
лизируя содержимое этого окна, можно прийти к выводу, что параметр а не опре-
делен. Аналогичную информацию о переменных можно было бы с тем же успехом
вывести в окне Watch Manager. Преимущество вывода из отладчика над выводом
результатов обратного отслеживания по стеку в приемнике команд состоит в том,
что значения переменных могут быть введены в окне Watch Manager даже после
аварийного останова в режиме прерывания. Теперь вместо поиска в длинном переч-
не из стека обратного отслеживания достаточно лишь ввести искомую переменную.
Установка активного кадра стека
Во время выполнения сценария возможны многочисленные вызовы функций
или переходы к выполнению разных блоков кода. Как пояснялось выше, такие вы-
зовы отслеживаются в стеке. Когда выполнение сценария останавливается, в окне
вывода из отладчика появляется соответствующая информация из стека. Нулевой
уровень стека соответствует верхнему кадру стека, а на каждом последующем
уровне стека находится предыдущий вызов, и так до самого начала сценария.
В отладчике имеется весьма эффективная команда setFrame, позволяющая воз-
вращаться обратно по сценарию в режиме его прерывания. Ее синтаксис следующий:
setFrame <целое число
В этой команде указанный кадр стека задается в качестве активного. Если вве-
сти команду setFrame в командной строке отладчика, точка выполнения сцена-
рия сместится к предыдущему коду. Нетрудно заметить, что после того как будет
задан активный кадр стека, переменные из кадра стека с меньшим номером ока-
жутся вне заданной области действия, тогда как переменные из нового кадра стека
окажутся в этой области действия.
Так, если выполнение сценария остановлено в точке, находящейся на глубине
трех вызовов функций, и при этом требуется запросить значение локальной пере-
менной, которая установлена в первой функции, достаточно вернуться к данной
функции, просмотреть ее значение и возобновить выполнение сценария в отладчике.
В следующем упражнении приведен пример задания активного кадра стека.
1. Установите 3ds Мах в исходное состояние и откройте новое окно редактора
MAXScript Editor.
2. Введите и сохраните следующий сценарий:
function terrier с =
(
d = 2 * с
break()
212
Приложение
return d
)
function dog b =
(
tr = 2 * terrier b
)
function quadroPed a =
(
dg = 2 * dog a
)
function mammal =
(
h = [1,2,3]
qp = quadroPed h
)
mammal()
3. Вычислите сценарий.
Откроется окно отладчика, а в окне вывода из отладчика появится отладоч-
ная информация.
4. Откройте окно Watch Manager и введите все переменные и параметры, ис-
пользуемые в сценарии:
В данный момент определены только переменные end.
5. Введите в командной строке отладчика следующую команду:
setFrame 1
Содержимое окна Watch Manager обновляется и в нем отображаются пере-
менные b и tr, а переменные end обозначаются как необъявленные
(Undeclared), поскольку они оказываются вне данной области действия.
213
Приложение
Если требуется, вы можете изменить значение переменной Ь в окне Watch
Manager, но с определенными ограничениями. В частности, переменной Ь
можно присвоить значение типа integer или float.
А вот значения типа points нельзя изменить в окне Watch Manager. Ес-
ли изменить значение переменной Ь в окне Watch Manager, а затем во-
зобновить выполнение сценария, новое значение этой переменной не бу-
дет передано функции terrier. Вместо него будет использовано старое
значение, т.е. [1,2,3].
Для того чтобы изменить значение типа points переменной Ь, необходимо
ввести команду eval в командной строке отладчика:
eval <выражение MAXScript>
6. Введите в командной строке отладчика следующую команду и нажмите
клавишу <Enter>:
eval b = [1,1,3]
Обратите внимание на обновление содержимого окна Watch Manager и ок-
на вывода из отладчика. В них появилось новое значение [1,1,3] пере-
менной Ь. Если возобновить выполнение сценария, выбрав кнопку Run,
старое значение переменной Ь будет по-прежнему передаваться функции
terrier, поскольку в этой функции все еще используется старое значение
переменной с. Тем не менее с помощью команды eval можно вычислять
отдельные части сценария.
7. Введите в командной строке отладчика следующую команду и нажмите
клавишу <Enter>:
eval tr = 2 * terrier b
Вновь обратите внимание на обновление содержимого окна Watch Manager
и окна вывода из отладчика. В них появилось новое значение [4,4,12] пе-
ременной tr.
Тем не менее это значение переменной tr остается временным. Если щелк-
нуть на кнопке Run, чтобы завершить сценарий, функция mammal будет по-
прежнему возвращать устанавливаемое по умолчанию значение [8,16,24].
Дополнительные сведения об отладчике приведены в следующих разделах
справочного руководства по MAXScript.
• MAXScript Debuggerri>The MAXScript Debugger
• MAXScript Debuggers Using the MAXScript Debugger
Интерфейс отладчика
Программное управление всеми свойствами отладчика можно организовать с по-
мощью интерфейса MXSDebugger. Этот интерфейс позволяет устанавливать с помо-
щью кода параметры и режимы, доступные в диалоговом окне Debugger Parameters.
У данного интерфейса имеется немало устанавливаемых свойств, например:
MXSDebugger.stayOnTop = true
214
Приложение
или
MXSDebugger.breakOnException = false
Примечание. Полный перечень свойств интерфейса MXSDebugger приведен
в справочном руководстве no MAXScript.
Кроме того, у данного интерфейса имеются следующие четыре метода, предна-
значенные для управления отладчиком: openDialog, closeDialog, writeString
и writeLine.
Примечание. Все эти методы полностью описаны в справочном руководстве
по MAXScript.
Ниже приведен пример применения метода openDialog для открытия отлад-
чика программным путем:
MXSDebugger.openDialog break:true message:"Welcome to the \
MAXScript Debugger" setfocus:true
• Необязательный параметр break определяет, будет ли отладчик прерывать
выполнение сценария.
• Необязательный параметр message выводит сообщение в окне Debugger
Output перед тем, как остановить выполнение сценария.
• Необязательный параметр setFocus определяет, будет ли окно отладчика
располагаться поверх всех остальных выбираемых окон.
Дополнительные сведения об интерфейсе MXSDebugger приведены в следующем
разделе справочного руководства по MAXScript: MAXScript Language Referenced
3dsMax ObjectsdCore InterfacesdCore Interfaces Documentationdlnterface:
MXSDebugger (Справочник по языку MAXScriptdO6i>eKTbi 3ds Мах^Базовые ин-
терфейсы^ЬДокументация по базовым интерфейсам^Интерфейс: MXSDebugger).
Файловый ввод-вывод
Иногда информацию приходится читать или записывать в текстовый файл.
Ниже приведены характерные примеры применения файлового ввода-вывода.
• Запись данных для считывания в игровом механизме
• Доступ к данным вне 3ds Мах для создания сцены
Файловый ввод-вывод организуется в MAXScript достаточно просто и под-
держивается целым рядом функций, позволяющих работать с файлами и манипу-
лировать ими.
При чтении или записи данных приходится иметь дело с объектом filestream,
который открывается или создается специально для ввода-вывода. Такой объект
представляет собой своего рода информационный канал для входящих и исходящих
данных. В MAXScript данные можно читать и записывать в текстовые и двоичные
файлы. Каждый текстовый символ занимает один байт информации, поэтому дан-
ные читаются или записываются в файлы байтовыми потоками.
215
Приложение
Для выполнения любой операции файлового ввода-вывода необходимо снача-
ла открыть информационный канал к файлу. Это можно сделать двумя способами
в зависимости от того, существует ли файл. Если файл существует, он открывает-
ся с помощью функции openFile. Если же файл не существует, он создается
с помощью функции createFile.
fs = openFile "с:\\temp\\myfile.txt"
или
fs = createFile "c:\\temp\\myfile.txt"
Обе функции возвращают ссылку на объект filestream в переменной fs.
После этого объект filestream может быть использован для чтения из файла,
записи в файл или получения сведений о нем.
Для того чтобы открыть файл и прочитать его содержимое, выполните сле-
дующее упражнение.
1. Откройте текстовый редактор Windows Notepad и введите несколько строк
текста:
это первая строка,
это вторая строка
и наконец это последняя строка
2. Сохраните этот текст в файле test. txt и поместите данный файл в любой
удобный для вас каталог. Для выполнения данного упражнения вы можете
выбрать каталог с : \3dsmax8\scripts.
3. Введите в окне приемника команд следующую строку кода:
fs = openFile "с:\\3dsmax8\\scripts\\test.txt"
В итоге создан объект filestream, присвоенный переменной fs.
В ответ в приемнике команд появится сообщение «File : с : \3dsmax6\
maxscriptest. txt>. которое свидетельствует об успешном выполнении
данной операции.
4. Введите в приемнике команд следующие строки кода:
readLine fs
readLine fs
readLine fs
Всякий раз, когда выполняется функция readLine, из файла читается но-
вая строка. Если вы введете строку кода readLine f s еще раз, в приемнике
команд появится ошибка периода выполнения - - Runtime error: Read
past end of file, указывающая на попытку чтения за пределами файла.
5. По завершении операции чтения из файла вызовите функцию закрытия
файла следующим образом:
close fs
Если у вас есть большой файл, содержащий много текстовых строк, чтение
из этого файла можно организовать в цикле while.
216
Приложение
6. Введите следующий фрагмент кода:
fs = openFile "с:\\3dsmax8\\scripts\\test.txt"
while NOT eof fs do readLine fs
close fs
7. Функция eof позволяет определить конец файла. Она возвращает логиче-
ское значение true, если достигнут конец файла; в противном случае — ло-
гическое значение false. В коде чтения из файла функция eof применяет-
ся во избежание упомянутой выше ошибки выхода за пределы файла.
Указатель файла и смещение
Всякий раз, когда вызывается функция readLine, в начале следующей строки
автоматически помещается указатель файла. Смещение указателя файла — это чис-
ло, обозначающее местоположение этого указателя относительно начала файла. При
открытии файла его указатель помещается в начало файла с нулевым смещением.
Несмотря на то что указатель файла устанавливается автоматически по мере
чтения содержимого файла, его положением можно управлять, если в этом есть
необходимость. Это делается с помощью функции seek. А смещение указателя
файла определяется с помощью функции f ilePos.
Для того чтобы воспользоваться функциями seek и f ilePos. выполните сле-
дующее упражнение.
1. Скопируйте файл seek. txt из каталога appendix на прилагаемом к этой кни-
ге CD-ROM в удобный для вас каталог на жестком диске вашего компьютера.
Этот файл содержит ряд двузначных чисел, разделенных пробелом.
2. Введите в приемнике команд следующий фрагмент кода, используя соот-
ветствующий путь к файлу seek . txt:
fs = openFile "с:\\3dsmax8\\scripts\\seek.txt"
seek fs 6
readchars fs 2
В качестве результата в приемнике команд появится значение 53, которое
означает, что двумя символами, прочитанными из данного файла на пози-
ции 6, оказались числа 5 и 3.
3. Введите в приемнике команд следующую строку кода:
filePos fs
В качестве результата в приемнике команд появится значение 8. После чте-
ния двух упомянутых выше символов указатель файла переместился на две
позиции вперед и теперь его смещение равно 8.
4. Введите в приемнике команд следующую строку кода, чтобы закрыть файл:
close fs
Итак, для чтения из файла отдельных символов в приведенном выше упраж-
нении была использована функция readChars. Если же воспользоваться функ-
цией readLine, будет прочитана вся строка начиная с позиции 6. Для чтения
единственного символа служит функция readchar.
217
Приложение
Для перемещения по файлу имеются еще две полезные функции:
skipToNextLine и skipToString. В частности, функция skipToNextLine
осуществляет переход к следующей строке, а функция skipToString - поиск
конкретной строки символов и установку сразу же после нее указателя файла
с соответствующим смещением. Функция skipToString оказывается полезной
в том случае, если файл содержит дескрипторы — текстовые ограничители, кото-
рые вводятся в файл для того, чтобы упростить поиск в нем отдельных элементов.
Для того чтобы применить функцию skiptoString к размеченному дескрип-
торами файлу, выполните следующее упражнение.
1. Установите 3ds Мах в исходное состояние.
2. Скопируйте файл skiptostring.txt из каталога appendix на прила-
гаемом к этой книге CD-ROM в удобный для вас каталог на жестком диске
вашего компьютера.
3. Откройте файл skiptostring. txt в текстовом редакторе Windows Notepad.
Он содержит следующее:
$$hsegs 10
$$height 50
$$radius
20
В трех первых строках находятся знаки денежной единицы, текстовое опи-
сание и число. Знаки денежной единицы служат в качестве дескрипторов,
обеспечивающих правильное обнаружение текста в файле. Это очень ко-
роткий файл, но в более крупных файлах такие дескрипторы, как $$, помога-
ют без труда находить многочисленные значения, текст и прочие элементы.
4. Закройте текстовый редактор Windows Notepad.
5. Введите в окне редактора сценариев MAXScript Editor следующую строку
кода, правильно указав в ней путь к файлу skiptostring. txt:
fs = openFile "с:\\3dsmax8\\scripts\\skiptostring.txt"
Указанный файл откроется.
6. Введите следующий фрагмент кода для чтения и поиска текста в откры-
том файле:
skipToString fs "$$height"
h = readvalue fs
seek fs 0
skipToString fs "$$hsegs"
hs = readvalue fs
seek fs 0
skipToString fs "$$radius"
r = readvalue fs
Функция skipToString обнаруживает дескриптор файла. Но она отнюдь
не всегда начинает поиск с текущего смещения указателя файла. Поэтому
сначала нужно установить указатель в начало файла с помощью функции
seek, а затем начать поиск. Дескрипторы можно искать в любом порядке.
218
Приложение
6. Введите следующий фрагмент кода:
fs = openFile "с:\\3dsmax8\\scripts\\test.txt"
while NOT eof fs do readLine fs
close fs
7. Функция eof позволяет определить конец файла. Она возвращает логиче-
ское значение true, если достигнут конец файла; в противном случае — ло-
гическое значение false. В коде чтения из файла функция eof применяет-
ся во избежание упомянутой выше ошибки выхода за пределы файла.
Указатель файла и смещение
Всякий раз, когда вызывается функция readLine, в начале следующей строки
автоматически помещается указатель файла. Смещение указателя файла — это чис-
ло, обозначающее местоположение этого указателя относительно начала файла. При
открытии файла его указатель помещается в начало файла с нулевым смещением.
Несмотря на то что указатель файла устанавливается автоматически по мере
чтения содержимого файла, его положением можно управлять, если в этом есть
необходимость. Это делается с помощью функции seek. А смещение указателя
файла определяется с помощью функции f ilePos.
Для того чтобы воспользоваться функциями seek и f ilePos, выполните сле-
дующее упражнение.
1. Скопируйте файл seek. txt из каталога appendix на прилагаемом к этой кни-
ге CD-ROM в удобный для вас каталог на жестком диске вашего компьютера.
Этот файл содержит ряд двузначных чисел, разделенных пробелом.
2. Введите в приемнике команд следующий фрагмент кода, используя соот-
ветствующий путь к файлу seek . txt:
fs = openFile "с:\\3dsmax8\\scripts\\seek.txt"
seek fs 6
readChars fs 2
В качестве результата в приемнике команд появится значение 53, которое
означает, что двумя символами, прочитанными из данного файла на пози-
ции 6, оказались числа 5 и 3.
3. Введите в приемнике команд следующую строку кода:
filePos fs
В качестве результата в приемнике команд появится значение 8. После чте-
ния двух упомянутых выше символов указатель файла переместился на две
позиции вперед и теперь его смещение равно 8.
4. Введите в приемнике команд следующую строку кода, чтобы закрыть файл:
close fs
Итак, для чтения из файла отдельных символов в приведенном выше упраж-
нении была использована функция readchars. Если же воспользоваться функ-
цией readLine, будет прочитана вся строка начиная с позиции 6. Для чтения
единственного символа служит функция readChar.
217
Приложение
Для перемещения по файлу имеются еще две полезные функции:
skipToNextLine и skipToString. В частности, функция skipToNextLine
осуществляет переход к следующей строке, а функция skipToString — поиск
конкретной строки символов и установку сразу же после нее указателя файла
с соответствующим смещением. Функция skipToString оказывается полезной
в том случае, если файл содержит дескрипторы — текстовые ограничители, кото-
рые вводятся в файл для того, чтобы упростить поиск в нем отдельных элементов.
Для того чтобы применить функцию skiptoString к размеченному дескрип-
торами файлу, выполните следующее упражнение.
1. Установите 3ds Мах в исходное состояние.
2. Скопируйте файл skiptostring.txt из каталога appendix на прила-
гаемом к этой книге CD-ROM в удобный для вас каталог на жестком диске
вашего компьютера.
3. Откройте файл skiptostring. txt в текстовом редакторе Windows Notepad.
Он содержит следующее:
$$hsegs 10
$$height 50
$$radius
20
В трех первых строках находятся знаки денежной единицы, текстовое опи-
сание и число. Знаки денежной единицы служат в качестве дескрипторов,
обеспечивающих правильное обнаружение текста в файле. Это очень ко-
роткий файл, но в более крупных файлах такие дескрипторы, как $$, помога-
ют без труда находить многочисленные значения, текст и прочие элементы.
4. Закройте текстовый редактор Windows Notepad.
5. Введите в окне редактора сценариев MAXScript Editor следующую строку
кода, правильно указав в ней путь к файлу skiptostring. txt:
fs = openFile "с:\\3dsmax8\\scripts\\skiptostring.txt"
У казанный файл откроется.
6. Введите следующий фрагмент кода для чтения и поиска текста в откры-
том файле:
skipToString fs "$$height"
h = readvalue fs
seek fs 0
skipToString fs "$$hsegs"
hs = readValue fs
seek fs 0
skipToString fs "$$radius"
r = readvalue fs
Функция skipToString обнаруживает дескриптор файла. Но она отнюдь
не всегда начинает поиск с текущего смещения указателя файла. Поэтому
сначала нужно установить указатель в начало файла с помощью функции
seek, а затем начать поиск. Дескрипторы можно искать в любом порядке.
218
Приложение
7. Закройте файл и создайте цилиндр, используя считанные из него данные:
close fs
с = cylinder radius:г height:h heightsegs:hs
8. Выполните сценарий.
В этом сценарии считываются данные из файла и создается цилиндр с па-
раметрами, указанными в файле. Несмотря на то что значение 2 0 радиуса
находится в строке файла skiptostring. txt после текста $$radius, это
значение читается в сценарии правильно.
Запись в файлы
В следующем упражнении вы научитесь записывать данные в файл.
1. Создайте в сцене цилиндр:
с = cylinder()
2. Введите в новом окне редактора MAXScript Editor следующий фрагмент
кода и выполните его:
fs = createFile "с:\\3dsmax8\\scripts\\cylinderData.txt"
format "radius %" c.radius to:fs
close fs
В итоге будет сформирована текстовая строка "radius 15,0", которая за-
тем записывается в файл.
3. Откройте в текстовом редакторе Windows Notepad файл cylinderdata. txt,
чтобы проверить его содержимое, а затем закройте его в том же текстовом
редакторе.
4. Перейдите в редактор сценариев, внесите изменения в строку форматирования,
чтобы отформатировать два элемента в одной строке, и выполните сценарий:
format "radius % heightsegs %" с.radius с.heightsegs to:fs
5. Откройте в текстовом редакторе Windows Notepad файл cylinderdata. txt,
чтобы проверить его содержимое, а затем закройте этот файл в том же тек-
стовом редакторе.
В этом файле должна быть записана строка " radius 15.0 heightsegsl".
Весь автоматически сформированный текст находится в одной строке. Это по-
ложение вам предстоит изменить в следующем пункте данного упражнения.
6. Перейдите в редактор сценариев и внесите изменения в строку форматиро-
вания следующим образом:
format "radius = %\nheightsegs = %" с.radius с.heightsegs to:fs
Итак, в файле будет записано следующее:
radius = 15.0
heightsegs = 1
Символ новой строки выглядит так: \п. Между символом п и началом сле-
дующей строки не должно быть пробела, иначе пробел станет частью строки.
7. Откройте в текстовом редакторе Windows Notepad файл cylinderdata. txt,
чтобы проверить его содержимое, а затем закройте этот файл в том же тек-
стовом редакторе.
219
Приложение
Если в файл необходимо записать очень длинный перечень данных, все эти
данные необязательно записывать в одной отформатированной строке.
Ведь всегда можно ввести символ новой строки. Приведенный ниже сцена-
рий формирует тот же текст, что и предыдущий:
fs = createFile "с:\\3dsmax8\\scripts\\cylinderData.txt"
format "radius = %" c.radius to:fs
format "\n" to:fs
format "segments = %" c.heightsegs to:fs
close fs
Для записи чисел без текста просто опустите текст:
format "%" с.radius to:fs
Доступ к файлам на уровне системы
Иногда управлять файлами или каталогами приходится на уровне системы,
например, для того, чтобы создать новый каталог, получить список всех файлов
в этом каталоге или скопировать файлы. Для решения подобных задач в MAXScript
имеется целый ряд функций.
Ниже приведен перечень этих функций и краткие сведения о том, как они реа-
лизованы. Введите каждую из них в приемнике команд, чтобы просмотреть ре-
зультаты их выполнения.
• getFiles — возвращает массив строковых значений в виде имен файлов,
соответствующих указанному имени файла или обозначению любых сим-
волов. В приведенном ниже примере осуществляется поиск в каталоге
с : \temp всех файлов с расширением . max:
fileList = getFiles "с:\\temp\\*.max"
В этом примере fileList представляет собой массив строковых значений
в виде имен файлов, соответствующих заданному критерию поиска. Используя
свойство . count данного массива, можно определить число таких файлов:
numFiles = fileList.count
Примечание. Свойство . count, обозначающее число элементов данного
массива, позволяет определить наличие найденных файлов. Если это
число равно нулю, значит, файлы, соответствующие заданному критерию
поиска, отсутствуют.
• getDirectories — возвращает такой же массив каталогов, как и у функ-
ции getFiles. Так, приведенная ниже строка кода возвращает все катало-
ги, находящиеся на корневом уровне диска С: \:
directories = getDirectories "с:\\*"
• makeDir — создает каталог. Синтаксис этой функции следующий:
makeDir "c:\\newDir"
• deleteFile — удаляет из системы указанный файл. Синтаксис этой
функции следующий:
deleteFile "с:\\temp\\dontneedit.max"
220
Приложение
• renameFile — изменяет имя файла. В качестве первого аргумента этой
функции указывается текущее имя файла, а в качестве второго аргумента —
новое имя файла:
renameFile "с: Wnameidontlike .max" "с: Wbettemame .max"
• copyFile— копирует файл. Синтаксис этой функции такой же, как
и у функции renameFile:
copyFile "с:\\oldfile.max" "с:\\newfile.max"
Дополнительные сведения о применении перечисленных выше функций при-
ведены в следующем разделе справочного руководства по MAXScript: MAXScript
Tools and Interaction with SdsMax^File Access^External File Access^External File
Methods (Инструменты MAXScript и взаимодействие c 3ds Max1^ Доступ к файлам^
Доступ к внешним файлам “^Методы доступа к внешним файлам).
Диалоговые окна открытия и сохранения файлов
Для того чтобы сохранить в файле данные, введенные пользователем, необхо-
димо получить доступ к диалоговым окнам открытия и сохранения файлов.
В следуюшем упражнении демонстрируется применение диалогового окна Open.
1. Введите в приемнике команд следующую строку кола:
getOpenFileName()
Откроется диалоговое окно, представленное на приведенном ниже рисунке.
В этом окне отображается рабочий каталог, т.е. последний каталог, к кото-
рому осуществлялся доступ при выполнении предыдущей операции откры-
тия или сохранения в 3ds Мах. Если же такие операции еще не выполня-
лись, то в качестве рабочего служит каталог с файлом 3dsmax. ехе.
Поле File name (Имя файла) пусто, в поле раскрывающегося списка Files
Of type (Тип файла) по умолчанию выбран вариант All Files (*.*), т.е. все
221
Приложение
файлы, а в заголовке диалогового окна указано слово Open, обозначающее
открытие файлов.
2. Выберите файл или введите его в поле File name. Щелкните на кнопке
Open, расположенной в правом нижнем углу данного диалогового окна.
В приемнике команд появится путь к файлу.
3. Введите в приемнике команд функцию getOpenFileName(). Щелкните
в открывшемся диалоговом окне на кнопке Cancel.
В приемнике команд появится сообщение undefined, указывающее на от-
мену операции открытия файла.
В сценарии данная функция применяется следующим образом:
fileName = getOpenFileName()
В этой строке кода переменной fileName присваивается путь к выбранно-
му файлу. Функция getOpenFileName не открывает файл. Она лишь воз-
вращает путь к выбранному пользователем файлу. А для открытия файла
служит рассмотренная выше функция openFile.
В качестве дополнительного параметра функции getOpenFileName мож-
но указать другой заголовок диалогового окна.
4. Введите следующую строку кода:
fileName = getOpenFileName caption:"Select a File"
Заголовок Select a File (Выбрать файл) появится в строке заголовка диало-
гового окна.
5. Закройте диалоговое окно.
6. Второй дополнительный параметр данной функции определяет строковое
значение, появляющееся в поле File name диалогового окна.
7. Введите в приемнике команд следующую строку кода:
fileName = getOpenFileName filename:"test.txt"
222
Приложение
8. Закройте диалоговое окно.
Третий дополнительный параметр также определяет строковое значение,
появляющееся в поле раскрывающегося списка Files of type и обозначаю-
щее тип файла. С помощью этого параметра можно указать сколько угодно
типов файлов.
9. Введите в приемнике команд следующий фрагмент кода:
fileName = getOpenFileName \
caption:"Select a File" \
filename:"test.txt" \
types:"Text(*.txt) |*.txt|Script(*.ms) |*.ms| All(*.*) |* . * | "
В свойстве types каждая последовательность начинается с текста, появ-
ляющегося в поле раскрывающегося списка Files of type, после чего следует
тип файла, который отображается, когда сделан соответствующий выбор.
Открытие диалогового окна сохранения файлов
Диалоговое окно сохранения файлов (Save) открывается с помощью функции
getSaveFileName:
fileName = getSaveFileName \
caption:"Select a File Name" \
types:" Text(*.txt)|(*.txt)|"
Функция getSaveFileName возвращает имя выбранного файла. Если файл
уже существует, пользователю предлагается подтвердить продолжение операции
сохранения данных в этом файле. Аналогично функции getOpenFileName
функция getSaveFileName на самом деле не сохраняет данные в файле. Она
лишь извлекает имя выбранного файла. Этот файл следует открыть в сценарии,
записать в него данные и закрыть его с помощью рассмотренных ранее функций.
223
Приложение
Ввод-вывод в двоичные файлы
Числа хранятся в компьютере в компактном двоичном формате. Такой формат
дает ряд преимуществ при сохранении числовых данных в файлах.
Прежде всего, файл получается компактным. Так, если для хранения числово-
го значения с плавающей точкой в двоичном формате требуется четыре байта, то
для его сохранения в текстовом формате с помощью упоминавшихся выше функций
требуется по одному байту на каждую цифру плюс еще один байт на десятичную
точку. Например, для сохранения числа 1,4565 в текстовом файле требуется 6 байт.
Следует, однако, иметь в виду, что не все числовые значения, сохраняемые
в двоичном формате, приводят к сокращению размера файла. Для сохранения
в двоичном формате любого целого числа требуется, по крайней мере, четыре бай-
та, поэтому строковое представление целых чисел от 0 до 100 получается более
компактным, чем двоичное.
Еще одно преимущество сохранения в двоичном формате состоит в том, что
в сценарии не нужно преобразовывать строки в числа при чтении данных из файла.
В рассмотренной выше функции readvalue строковые данные читаются из файла
и автоматически преобразуются в числовые значения для того, чтобы их можно бы-
ло использовать при выполнении числовых операций на компьютере. А при чтении
двоичных данных из файлов необходимость в таком преобразовании отпадает.
Запись в двоичный файл
Для открытия файла с целью чтения или записи двоичных данных служит
функция fopen. Эта функция возвращает значение BinStream, которое исполь-
зуется для последующего доступа к файлу.
В следующем упражнении вам предстоит создать сферу, записать в файл коор-
динаты ее вершин, а затем установить 3ds Мах в исходное состояние и прочитать
из файла сохраненные координаты вершин.
1. Установите 3ds Мах в исходное состояние.
2. Создайте в любом видовом окне сферу радиусом около 50 единиц. Этой
сфере должно быть присвоено имя Sphere 01.
3. Преобразуйте сферу в редактируемый каркас.
4. Введите в окне редактора MAXScript Editor приведенную ниже строку кода
сценария. Если на диске С вашего компьютера отсутствует каталог temp,
выберите любой другой каталог по своему усмотрению, соответственно ви-
доизменив сценарий:
stream = fopen "с:\\temp\\bintest.bin" "wb"
Параметр wb в этой строке кода означает только запись двоичных данных.
Этот режим будет использован в сценарии для записи данных в файл.
5. Продолжите ввод кода сценария:
-- Получить число вершин сферы
num = getNumVerts $Sphere01
for i = 1 to num do
224
Приложение
-- Получить координаты положения вершин
pos = getVert $Sphere01 i
-- Записать координаты х, у, z в файл
writeFloat stream pos.x
writeFloat stream pos.у
writeFloat stream pos.z
Метод getNumVerts возвращает число вершин редактируемого каркаса,
а метод getVert воспринимает каркасный объект в качестве своего перво-
го параметра и число вершин в качестве своего второго параметра. Он воз-
вращает значение типа Points, обозначающее координаты х, у и z отдель-
ной вершины.
6. Закройте файл, введя следующую заключительную строку кода сценария:
fclose stream
7. Выполните сценарий.
В итоге будет создан файл.
8. Попробуйте открыть созданный файл bintest. bin в текстовом редакторе
Notepad или Wordpad.
Данные в этом файле записаны в двоичном формате. Их можно прочитать
средствами MAXScript, но не текстового редактора. Поэтому измените тип
вывода данных в файл, чтобы прочитать их.
9. Внесите приведенные ниже изменения в сценарий, используя на этот раз
строковые данные. И в этом случае указывается параметр wb, поскольку
строковые данные также состоят из отдельных байтов. Кроме того, необхо-
димо изменить имя файла.
stream = fopen "с:\\temp\\bintest2.bin" "wb"
num = getNumVerts $Sphere01
for i = 1 to num do
(
pos = getVert $Sphere01 i
writeString stream (pos.x as string)
writeString stream (pos.у as string)
writeString stream (pos.z as string)
)
fclose stream
10. Откройте файл bintest2.bin в текстовом редакторе Notepad или
Wordpad. На этот раз данные записаны в стандартном текстовом формате.
Как показывает Проводник Windows, размер данного файла больше, чем
предыдущего. Если же добавить символ перевода строки после каждого
элемента данных, размер файла bintest2 . bin станет еще больше.
При записи данных в двоичном формате могут быть использованы самые раз-
ные их представления. В частности, читать и записывать можно длинные цело-
численные значения, хотя для их хранения потребуется больше байтов. Если ко-
роткие целочисленные значения записываются с помощью функции writeShort
225
Приложение
и хранятся в двух байтах, то для записи длинных целочисленных значений с по-
мощью функции writeShort требуется уже четыре байта. Кроме того, целочис-
ленные значения могут храниться со знаком (плюс или минус) или без знака
(только положительные значения).
Ниже приведены диапазоны для чисел, сохраняемых с помощью функций
writeByte, writeShort и writeLong. Соответствующие значения указаны
приближенно.
• Числа, сохраняемые с помощью функции writeByte
• Однобайтовое целое число со знаком: +/-127
• Однобайтовое целое число без знака: 0-255
• Числа, сохраняемые с помощью функции writeShort
• Двухбайтовое целое число со знаком: +/-32000
• Двухбайтовое целое число без знака: 0-65000
• Числа, сохраняемые с помощью функции writeLong
• Четырехбайтовое целое число со знаком: +/-2000000000
• Четырехбайтовое целое число без знака: 0-4000000000
Полный перечень представлений чисел, доступных в MAXScript, можно найти
в следующем разделе справочного руководства по MAXScript: MAXScript Tools
and Interaction with SdsMax^File Access4>Text and Binary File Input and Outputs
BinStream for Binary Reading and Writing (Инструменты MAXScript и взаимодей-
ствие c 3ds МахЧ>Доступ к файламЧ>Ввод-вывод в текстовые и двоичные фай-
лы1^ Методы класса BinStream для чтения и записи двоичных данных).
Чтение из двоичного файла
Процедура чтения данных из двоичного файла аналогична процедуре их запи-
си в двоичный файл. Для этого достаточно организовать последовательное чтение
данных из файла, а их тип будет автоматически распознаваться в MAXScript.
В следующем упражнении вам предстоит создать сферу и видоизменить ее вер-
шины на основании данных, считанных из файла.
1. Установите 3ds Мах в исходное состояние.
2. Создайте в любом видовом окне сферу радиусом около 10. Этой сфере
должно быть присвоено имя Sphere01.
3. Преобразуйте сферу в редактируемый каркас.
4. Начните сценарий с открытия файла для чтения:
stream = fopen "с:\\temp\\bintest.txt" "rb"
5. Прочитайте данные из файла и примените их к сфере для ее видоизменения:
num = getnumVerts $Sphere01
pos = [0, 0, 0]
for i = 1 to num do
226
Приложение
(
pos.x = readFloat stream
pos.у = readFloat stream
pos.z = readFloat stream
setVert $sphere01 i pos
)
fclose stream
-- Обновить сферу, чтобы увидеть изменения
update $sphere01
6. Выполните сценарий.
Сфера перемещается в то место, где она была создана в предыдущем уп-
ражнении. Кроме того, размер сферы становится таким же, как и в преды-
дущем упражнении.
Если вас интересуют дополнительные сведения о манипулировании карка-
сами и их вершинами для написания сценариев экспорта и импорта дан-
ных, обратитесь к следующему разделу справочного руководства по
MAXScript: MAXScript Language Reference^SdsMax Objects^Editable
Meshes, Splines, Patches, and Polys^Editable_Mesh: GeometryClass and
TriMesh: Value (Справочник по языку МАХЗспрг^Объекты 3ds Max>=>
Редактируемые каркасы, сплайны, лоскуты и многоугольники^Класс
Editable_Mesh: классы GeometryClass и TriMesh: Значение).
Дополнительные функции двоичного
ввода-вывода
Ниже приведены функции, манипулирующие двоичными файлами и эквива-
лентные функциям установки указателя текстового файла.
• f Tell - возвращает текущее положение указателя файла.
• f Seek — перемещает указатель файла в указанное положение. В качестве
аргументов этой функции указываются величина, на которую следует пе-
реместить указатель файла, а также начальное положение, которое может
быть установлено в начале файла (#seek_set). внутри файла (#seek_cur)
или же в конце файла (#seek_end). Не путайте эту функцию с функцией
seek для файлового ввода-вывода в коде ASCII.
Редактор Visual MAXScript
В MAXScript предоставляются удобные средства для построения пользова-
тельских интерфейсов. В частности, визуальный редактор Visual MAXScript
(VMS) позволяет интуитивно строить панели на основании готовых форм, на-
блюдая за их внешним видом по ходу данного процесса и не заботясь о располо-
жении отдельных элементов пользовательского интерфейса программным путем.
Кроме того, редактор VMS автоматически формирует код для обработчиков собы-
тий, которые требуется включить в сценарий. Разумеется, написание кода, состав-
227
Приложение
ляющего тело самих обработчиков событий, по-прежнему возлагается на вас как
на автора сценария.
С помощью редактора Visual MAXScript можно создать панель, которая дейст-
вует таким же образом, как и свиток. А если потребуется, то панель можно будет
затем отобразить как диалоговое окно.
Для доступа к редактору Visual MAXScript выполните следующее упражнение.
1. Перейдите к панели Utilities, щелкните на кнопке More, а затем выберите из
списка вариант Visual MAXScript.
Откроется окно визуального редактора VMS Editor. По умолчанию в левой
части этого окна отображается панель с черными маркерами, с помощью
которых можно изменить ее размеры. При стандартных размерах панель
правильно вписывается в панель команд.
С другой стороны, доступ к редактору Visual MAXScript можно получить
из окна редактора MAXScript Editor.
2. Закройте редактор Visual MAXScript.
3. Откройте окно редактора MAXScript Editor и выберите из его меню коман-
ду Edit^New Rollout (Правка1^Новый свиток).
{£) Untitled MAXScript
Edit
05®
Search Debugger Help
Undo
Redo
Ctrl+Z
Ctrl+/
Copy
Райе
Delete
Clear All
Qi1+ s
Ctrl+C
Chl+V
Del
Edit Rollout F2
New Rollout
Select All Ctrl+A
Команда New Rollout позволяет создать совершенно новый свиток, тогда
как команда Edit Rollout открывает созданную ранее панель. Это удобно для
формирования свитка в процессе написания сценария.
Вдоль нижнего края окна редактора VMS располагается ряд пиктограмм,
обозначающих все доступные для построения элементы интерфейса. Если
поместить над пиктограммой курсор, появится всплывающая подсказка
с обозначением данного элемента. А его краткое описание появляется в
строке состояния, расположенной в нижней части окна данного редактора.
228
Приложение
Для построения элементов пользовательского интерфейса выполните следую-
щее упражнение.
1. Щелкните на третьей слева пиктограмме кнопки.
После щелчка на пиктограмме выбранного элемента интерфейса курсор
примет вид перекрестья, как только вы поместите его над областью размет-
ки панели.
2. Перетащите курсор на панели, чтобы создать кнопку.
Маркеры вокруг изображения кнопки позволяют изменять размеры и поло-
жение кнопки визуально. При этом в правой части окна редактора VMS по-
являются вкладки Value (Значение) и Event Handlers (Обработчик событий).
3. Щелкните на вкладке Value.
229
Приложение
На этой вкладке можно установить любое значение, перейдя к соответ-
ствующему столбцу и введя нужное значение или же выбрав это значение
из раскрывающегося списка. Дополнительные сведения по данному вопросу
приведены в следующем разделе справочного руководства по MAXScript:
MAXScript Tools and Interaction with 3dsMaxd>Creating MAXScript Tools'^
Scripted Utilities and Rollouts1^ Rollout User-Interface Controls1^ I mage Buttons
(Инструменты MAXScript и взаимодействие c 3ds Мах^Создание инстру-
ментов MAXScript1^ Сценарные утилиты и свитки1^Элементы управления из
пользовательского интерфейса свитка "^Кнопки с изображением).
В поле toolTip можно ввести текстовую строку, которая появится в виде
всплывающей подсказки, как только пользователь поместит курсор над
данным элементом пользовательского интерфейса.
4. Выберите вкладку Event Handlers. Для кнопки имеется лишь один обра-
ботчик событий pressed, предназначенный для реакции на событие, свя-
занное со щелчком на кнопке.
Value | EvarlHendters | f
Event Handlers
□ pressed
5. Поместите курсор над словом pressed и щелкните.
Откроется диалоговое окно Edit Event Handler (Правка обработчика событий).
6. Введите в окне правки этого диалогового окна код сценария, который дол-
жен быть выполнен после щелчка на кнопке, например:
Messagebox "Here is the message!"
В этом примере обработчик событий отображает окно сообщения после
щелчка на кнопке.
7. Щелкните на кнопке ОК, чтобы вернуться в редактор VMS. Теперь обра-
ботчик событий pressed выбран. Итак, вы создали панель и сценарий для
ее функционирования. Далее вам предстоит узнать, как эта панель приво-
дится в действие.
Сохранение и активизация панелей, созданных
в редакторе Visual MAXScript
По завершении правки вы можете сохранить свой проект VMS двумя способа-
ми: в файле с расширением . vms и в файле сценария MAXScript с расширением . ms.
При открытии файла формата VMS открывает и редактор VMS. Если же ре-
зультаты правки сохранены в файле с расширением . ms, в MAXScript фактически
создается сценарий, который может быть затем выполнен. Прежде чем продол-
жить работу с панелью, измените ее имя.
230
Приложение
Для того чтобы сохранить и активизировать панель, созданную в редакторе
Visual MAXScript, выполните следующее упражнение.
1. Щелкните на панели в редакторе VMS, чтобы выделить ее.
2. Щелкните на вкладке Value.
3. Измените значение в поле name на message, а значение в поле caption —
на Message Box.
4. Выберите команду File^Save из меню в окне редактора Visual MAXScript.
В ответ на запрос разорвать связь с редактором сценариев MAXScript,
щелкните на кнопке Yes.
5. Выберите вариант MAXScript Files из раскрывающегося свитка, располо-
женного в нижней части открывшегося диалогового окна Save.
6. Выберите удобный каталог для сохранения файла.
7. Закройте редактор Visual MAXScript.
8. Откройте файл формата MS в окне редактора сценариев MAXScript Editor.
В этом окне появится следующий сценарий:
rollout message "Message Box" width:162 height:300
(
button btnl "Button" pos:[41, 27] width:76 heights0
on btnl pressed do messagebox "Here is the message!"
)
Ваш сценарий может выглядеть несколько иначе, отражая другое положе-
ние и размеры кнопки.
9. Заключите этот сценарий в оболочку утилиты следующим образом:
utility test "Message Test"
(
rollout message "Message Box" width:162 height:300
(
button btnl "Button" pos:[41, 27] width:76 height30
on btnl pressed do messagebox "Here is the message!"
)
)
231
Приложение
Осталось сделать лишь один шаг, чтобы привести сценарий в рабочее со-
стояние. По умолчанию панели со свитками не вводятся в утилиту, если не
указать на их существование явно. Следовательно, для ввода данной панели
со свитком на панели команд Utilities необходимо добавить в код сценария
обработчик событий open.
10. Добавьте в сценарий следующие строки кода:
utility test "Message Test"
(
rollout message "Message Box" width:162 height:300
(
button btnl "Button" pos: [41,27] width:76 height:30
on btnl pressed do messagebox "Here is the message!"
)
on test open do
(
addRollout message
)
)
11. Нажмите комбинацию клавиш <Ctrl+E>, чтобы выполнить сценарий.
12. Перейдите к панели Utilities и выберите кнопку MAXScript.
13. Выберите утилиту Message Test из раскрывающегося списка Utilities. Вид
панели Utilities изменится так, как показано на приведенном ниже рисунке.
Итак, на панели Utilities появятся два отдельных свитка. Появление нового
свитка на панели Utilities обеспечивает функция addRollout. Для того
чтобы свернуть небольшой свиток Message Test, щелкните на кнопке
Close. При этом останется другой свиток — Message Box. Несмотря на то
что свиток Message Box введен внутри утилиты Message Test, он является
совершенно независимым объектом.
232
Приложение
Другое применение редактора VMS
В следующем упражнении показан другой пример применения редактора VMS
во время работы над сценарием. Находясь в окне редактора сценариев MAXScript
Editor, вы можете перейти в редактор VMS и вставить сформированный в нем код
в текущую позицию курсора в окне редактора сценариев.
1. Введите следующий фрагмент кода в окне редактора MAXScript Editor:
utility vms_insert "VMS Insert"
(
)
2. Убедитесь в том, что курсор установлен в строке, находящейся между от-
крывающей и закрывающей круглыми скобками.
3. Выберите команду Editri>New Rollout из меню в окне редактора сценариев.
Откроется окно редактора VMS.
4. Создайте кнопку аналогично описанной выше и выберите команду
File^Save.
5. Код сценария для вновь созданного свитка автоматически появится в пози-
ции курсора в окне редактора сценариев. Фон окна редактора сценариев
станет серым, и править код в нем нельзя будет до тех пор, пока не закроет-
ся окно редактора VMS.
Вы можете продолжить ввод элементов пользовательского интерфейса,
используя редактор Visual MAXScript. По завершении выберите команду
File^Save из меню в окне редактора VMS, чтобы поместить соответствую-
щий код в окне редактора сценариев, а затем закройте окно редактора VMS.
6. Код, переносимый из редактора VMS в окно редактора сценариев MAXScript
Editor, вставляется без отступа, поэтому вам придется добавить отступы
вручную. А для того чтобы автоматически сформированный свиток поя-
вился на панели, придется, как и прежде, ввести обработчик событий open
в код сценария вручную.
Примечание. После ввода определений свитка в сценарий этот свиток
можно ввести или удалить где угодно, используя соответственно функцию
addRollout или removeRollout.
233
Приложение
Встраивание элементов управления
ActiveX в свитки средствами MAXScript
В MAXScript имеется возможность встраивать элементы управления ActiveX®
независимых производителей непосредственно в свиток. Для этого совершенно
необязательно разбираться в технологии ActiveX, которая разработана компанией
Microsoft и позволяет применять в приложениях независимые программные мо-
дули для решения специальных задач. Многие элементы управления ActiveX вы
можете обнаружить в своей системе. В частности, электронные таблицы Excel,
универсальный проигрыватель Windows Media Player и даже Web-браузер могут
быть реализованы в виде элементов управления ActiveX.
Для того чтобы воспользоваться элементом управления ActiveX, нужно уметь
его распознать. Этой цели в MAXScript служит ряд специальных функций.
Для того чтобы научиться обнаруживать и распознавать элементы упражнения
ActiveX, выполните следующее упражнение.
1. Откройте окно редактора MAXScript Editor и введите следующий фраг-
мент кода:
ws = newscript()
ShowAllActiveXControls to:ws
Функция newscript () открывает новое окно сценария. Значение, возвра-
щаемое данной функцией, обозначает это окно как поток windowstream.
Анри выполнении метода ShowAllActiveXControls указывается, что
вывод направляется в данное окно. Если бы пришлось открыть файл, вывод
нужно было бы направить в поток filestream.
2. Выполните сценарий.
Откроется новое окно сценария, в котором появляются все элементы
управления ActiveX, доступные в вашей системе. Многие из них не свя-
заны с пользовательским интерфейсом, и поэтому ими нельзя воспользо-
ваться в MAXScript.
3. Прокрутите список элементов управления ActiveX или же выберите из
строки меню команду Search (Поиск) и найдите элемент Windows
Media Player.
"CAdEPlotViewerCommandMap Object" "EPlotViewer.AdEPlotViewerCommandMap.1" "(679A16FB-49EB-45A
"TeamWrapper2x.TDGanttWrapper" "TeamWrapper2x.TDGanttWrapper" "(68879CE6-84AD-4484-8542-C3053
"Microsoft DirectAnimation Windowed Control" "DirectAnimation.DirectAnimationWindowedlntegrat
"DTC Surrogate 7.1" "VSDTC.Surrogate?!.1" "(6A02123S-2EB0-49F8-8036-38CECD06DB5D}"
"Microsoft StatusBar Control, version 5.0 (SP2)" "COMCTL.SBarCtrl.1" "(6B7E638F-850A-101B-AFC
"Pegasus Ima$<press Control v7.0" "ImagXpr7. ImagXpress. 1" "{6D3CF4F3-C2F3-46E7-A126-3E53102A6
"ActorBvr Class" "(null)" "{6DDE3061-736C-11D2-A5E8-00A0C967A25F}"
"Microsoft Forms 2.0 Frame" "Forms.Frame.1" "{6E182020-F460-llCE-9BCD-00AA00608E01}"
"InstallEngineCtl Object" "ASControls.InstallEngineCtl.1" "(6E449683-C509-11CF-AAFA-00AA00B60
"CMissingFontsCtrl Object" "EPlotViewer.MissingFontsCtrl.1" "{6F59AA1D-7896-4E38-88E7-53FA9CB
4. В этом списке указаны имена элементов управления ActiveX, зарегистри-
рованных в вашей системе, наряду с их идентификационными номерами.
Это так называемые идентификаторы класса, по которым распознаются
отдельные элементы управления ActiveX, в том числе и в MAXScript.
234
Приложение
5. Запишите идентификатор класса для элемента управления Windows
Media Player. Идентификатор класса этого элемента управления ActiveX
будет одним и тем же на всех компьютерах. Для универсального проигры-
вателя он следующий:
{6BF52A52-394А-11D3-B153-0C04F79FAA6}
Для того чтобы встроить элемент управления ActiveX в свиток, выполните
следующее упражнение.
1. Откройте новое окно редактора MAXScript Editor и введите следующие
строки кода:
utility ActiveXDemo "ActiveX Demo"
(
2. Установите курсор на последней строке (после круглой скобки). Выберите
команду Edit^New Rollout из меню в окне редактора сценариев. Откроется
окно редактора VMS.
3. Измените имя свитка на MovieDemo, введя его без пробелов, а заголовок
свитка — на Movie Demo (Демонстрационный ролик).
4. Щелкните на пиктограмме OLE в нижнем ряду доступных элементов поль-
зовательского интерфейса.
“OLE” означает “связывание и встраивание объектов”. Это старое, но все
еще применяемое название технологии ActiveX.
5. Перетащите курсор, чтобы создать элемент управления на используемой по
умолчанию панели свитка. Точные размеры этого элемента особого значе-
ния не имеют, тем не менее он должен занимать большую часть панели.
й 0 4 |
₽
235
Приложение
6. Щелкните на вкладке Value.
Теперь необходимо указать тип элемента управления, т.е. упоминавшийся
выше идентификатор его класса.
7. Введите (или вставьте) записанный ранее идентификатор класса в поле
controlType, не забыв заключить его в фигурные скобки.
V*e : .-ж
______!_________ _< 1
Рта, в'*. Vaiue. ,
dess ActiveXCorrtrot
name. actx
I controlTypB {63F52A52-394A-11D3-815MCC04F79FAA6}
! x-pos 3
iypos S
8. Введите в свиток кнопку с надписью Get Movie (Получить фильм).
9. Выберите команду File^Save из меню в окне редактора VMS, чтобы сфор-
мировать код сценария для данного свитка. Закройте окно редактора VMS.
10. Введите круглую скобку, закрывающую блок кода утилиты. Теперь сцена-
рий должен иметь следующий вид:
236
Приложение
utility ActiveXDemo "ActiveX Demo"
(
rollout movieDemo "Movie Demo" width:162 height:300
(
ActiveXControl actx "{6BF52A52-394A-11D3-B153-00C04F79FAA6}" \
pos:[3,5] width:156 height:191
button btnl "Get Movie" pos: [24,231] width:110 height:27
)
)
11. Введите обработчик событий open, чтобы дополнить утилиту свитком
с элементом управления ActiveX.
utility ActiveXDemo "ActiveX Demo"
(
rollout movieDemo "Movie Demo" width:162 height:300
(
ActiveXControl actx "{6BF52A52-394A-11D3-B153-00C04F79EAA6}" \
pos: [3,5] width:156 height:191
button btnl "Get Movie" pos: [24,231] width:110 height:27
)
on ActiveXDemo open do
(
addRollout MovieDemo
)
)
12. Выполните сценарий.
13. Перейдите к панели Utilities, выберите сначала кнопку MAXScript, а затем
утилиту ActiveX Demo из раскрывающегося списка Utilities. Появится сви-
ток Movie Demo.
Остается лишь организовать реакцию на выбор кнопки Get Movie.
237
Приложение
14. Введите обработчик событий pressed в код сценария следующим образом:
utility ActiveXDemo "ActiveX Demo"
(
rollout movieDemo "Movie Demo" width:162 height:300
(
ActiveXControl actx "{6BF52A52-394A-11D3-B153-00C04F79FAA6}" \
pos: [3,5] width:156 height:191
button btnl "Get Movie" pos:[24,231] width:110 height:27
on btnl pressed do
(
file = getOpenFileName caption:"Choose An Avi File" \
types:"AVI(*.avi)"
if file ! = undefined do
actx.URL = file
)
)
on ActiveXDemo open do
(
addRollout MovieDemo
)
)
15. Вновь выполните сценарий и щелкните на кнопке Get Movie. Выберите
любой файл формата AVI в своей системе и воспроизведите его. Обратите
внимание на выражение actx.URL = file, где URL — это свойство эле-
мента управления ActiveX. У всех элементов управления ActiveX имеется
целый ряд свойств и методов (вызываемых функций). В MAXScript имеет-
ся функция showProperties, которая выдает перечень свойств указанно-
го элемента управления ActiveX.
Завершенный вариант данного сценария находится в файле \appendix\
activeXDemo .ms на прилагаемом к этой книге CD-ROM.
Дополнительные сведения об элементах управления ActiveX приведены
в следующем разделе справочного руководства по MAXScript: MAXScript
Tools and Interaction with 3dsMax^ActiveX Controls in MAXScript Rollouts
(Инструменты MAXScript и взаимодействие c 3ds Max1^Элементы управ-
ления ActiveX в свитках, создаваемых средствами MAXScript).
Система публикации функций
и интерфейсы
Подключаемые модули 3ds Мах позволяют создавать новые типы объектов.
Одни подключаемые модули входят в стандартный комплект 3ds Мах, а другие
разрабатываются независимыми производителями с помощью набора инструмен-
тальных средств разработки программ (SDK — Software Developer Kit). Анало-
гично остальным типам объектов такие объекты обладают рядом свойств и мето-
дов. Система публикации функций (FPS — Function Publishing System)
предоставляет средства для запроса подобных объектов в MAXScript с целью оп-
ределить их свойства, методы и связанные с ними действия.
238
Приложение
Система публикации функций была разработана и внедрена в версии 3ds Мах 4.
С тех пор все свойства и методы для новых и уже имеющихся объектов MAXScript
публикуются с помощью данной системы, а не встраиваются непосредственно
в объекты.
С точки зрения публикации функций интерфейс представляет собой ряд
свойств, методов и связанными с ними действий, доступных для объекта. Это по-
нятие не следует путать с пользовательским интерфейсом. Доступные для объекта
интерфейсы определяются с помощью функции getlnterf aces:
getlnterfaces <объект>
Данная функция выводит перечень интерфейсов для указанного объекта. Обна-
ружив нужный интерфейс, вы можете запросить свойства, методы и связанные с ним
действия, доступные посредством данного интерфейса, введя следующую команду:
showinterface <объект>.синтерфейо
Эта команда сродни функции showProperties. Если функция showProperties
выводит свойства, встроенные в объект, то команда showinterface выводит свой-
ства, методы и действия, введенные в объекты, существующие с версии 3ds Мах 4,
или же в новые объекты, созданные с помощью подключаемых модулей.
Для вывода всех интерфейсов, доступных для объектов, стоящих ниже класса
Node, служит следующая команда:
showinterfaces node
С помощью любой из этих команд можно вывести интерфейсы наиболее удоб-
ным для написания сценариев способом. Так, функция getlnterfaces и коман-
да showinterface отображают интерфейсы для отдельного объекта независимо
от их доступности для всех остальных узлов. А команда showinterfaces (с бук-
вой “s” в конце) отображает интерфейсы для всех узлов.
Рассмотрим некоторые свойства и методы, доступные посредством системы
публикации функций.
Для доступа к интерфейсам выполните следующее упражнение.
1. Установите 3ds Мах в исходное состояние и очистите приемник команд.
2. Введите в приемнике команд следующий фрагмент кода:
b = box()
getlnterfaces b
В итоге будут выведены все интерфейсы для параллелепипедного объекта:
#(<MixinInterface:IAssembly>,
<MixinInterface:INodeGIProperties>,
<MixinInterface:INode>,
<MixinInterface:INodeLayerProperties>,
<MixinInterface:INodeBakeProperties>,
<MixinInterface:SkinPose>)
Эти интерфейсы могут быть использованы для обнаружения дополнитель-
ных свойств, методов и действий, доступных для параллелепипеда. Далее
вам предстоит ознакомиться с интерфейсом Inode.
3. Введите в приемнике команд следующую строку кода:
showinterface b.INode
239
Приложение
По этой команде выводится ряд свойств и методов применительно к парал-
лелепипеду. Так, свойство .handle предоставляет уникальный идентифи-
кационный номер, связанный с объектом.
4. Введите в приемнике команд следующую строку кода:
b.INode.handle
При выполнении этой строки кода возвращается идентификационный но-
мер 1 в качестве дескриптора параллелепипедного объекта. Смена имени
параллелепипеда никак не сказывается на свойстве .handle. С его помо-
щью параллелепипед остается по-прежнему доступным на сцене.
Кроме того, многие свойства интерфейса можно использовать, не указывая
перед ними сам интерфейс.
5. Введите в приемнике команд следующую строку кода:
b.handle
При выполнении этой строки кода возвращается идентификационный но-
мер 1. В данном случае свойство . handle использовано без указания перед
ним интерфейса . INode. Если свойство интерфейса не вступает в кон-
фликт с имеющимся в MAXScript свойством, сам интерфейс можно не ука-
зывать между именем объекта и свойством интерфейса.
6. Введите в приемнике команд следующую строку кода:
showinterfaces node
При выполнении этой строки выводится каждый интерфейс, а также его
свойства, методы и действия. Третьим выводится интерфейс INode. В этой
части листинга приведены те же свойства, методы и действия, что и при вы-
полнении команды showinterface b . INode.
Для применения интерфейса на практике выполните следующее упражнение.
1. В этом упражнении вам предстоит воспользоваться интерфейсом, который
обнаруживается с помощью системы публикации функций, чтобы получить
дополнительные методы для ограничения по линии взгляда. Установите
3ds Мах в исходное состояние и очистите приемник команд.
2. Введите в приемнике команд следующий фрагмент кода:
clearListener()
lookAtObj = cone pos:[50,0,0]
lookAtTarg = dummy()
c = lookat—Constraint()
lookAtObj.rotation.controller = c
В двух последних строках кода в переменной с создается экземпляр огра-
ничения по линии взгляда и затем он присваивается конусу.
3. Введите в приемнике команд следующую строку кода:
showproperties с
По этой команде выводятся встроенные свойства ограничения по линии
взгляда.
240
Приложение
4. Введите в приемнике команд следующую строку кода:
с.target_axis = 2
В этой строке кода встроенное свойство используется для выбора оси Y
ориентации цели.
По команде showProperties выводятся свойства, используемые для по-
лучения и установки разных параметров осей, но не свойства для получе-
ния и установки параметров цели. Такие свойства и методы обнаруживают-
ся посредством интерфейса.
5. Введите в приемнике команд следующую строку кода:
getlnterfaces с
По этой команде выводятся интерфейсы для ограничения по линии взгля-
да. В данном случае это единственный интерфейс constraints.
6. Введите в приемнике команд следующую строку кода:
showinterface с.constraints
По этой команде выводятся свойства, методы и связанные с ними действия,
доступные для данного интерфейса. Это, в частности, метод appendTarget
для присоединения целей.
7. Введите в приемнике команд следующую строку кода:
с.constraints.appendTarget lookAtTarg 50
С помощью метода из интерфейса в этой строке кода цель по линии взгляда
вводится в список целей с весом 50.
8. Переместите конус, обратив внимание на то, что он нацелен на фиктивный
объект.
Интерфейс constraints — это специальный вид интерфейса, называемо-
го Mixininterface. Это означает, что интерфейс является средством дос-
тупа к множеству элементов. Иными словами, в одном интерфейсе совме-
щается множество элементов.
Если для решения конкретной задачи требуется найти подходящее свойст-
во или метод, воспользуйтесь функцией getlnterfaces и командами
showinterface и showinterfaces, чтобы получить перечень свойств
и методов, доступных для любого объекта.
Контроллеры управления по выражению
и по сценарию
Контроллер управления по выражению позволяет управлять свойствами объекта
по математическому выражению, а контроллер управления по сценарию — по коду.
Каждый из этих способов находит применение и имеет свои достоинства и недостатки.
В версии 3ds Мах 8 контроллер управления по выражению был переработан и
теперь доступен для сценариев MAXScript посредством интерфейса lExprCtrl.
241
Приложение
А контроллер управления по сценарию использует общий базовый код и имеет
почти такое же диалоговое окно, как и контроллер управления по выражению. Он
доступен для сценариев MAXScript посредством интерфейса iScriptCtrl. По-
мимо изменений в диалоговом окне, контроллер управления по сценарию был
значительно усовершенствован.
В следующем упражнении оба контроллера сравниваются и противопоставля-
ются на конкретном примере.
1. Введите в новом окне редактора MAXScript Editor следующий фрагмент
кода и вычислите его:
delete objects
clearListener()
objE=box name:"objE"
objS=box name:"objS" pos: [50,0,0]
2. Назначьте контроллер управления по выражению с плавающей точкой для
свойства length объекта objE следующим образом:
obj ECtrl=objЕ.length.controller=float_expression()
3. Назначьте контроллер управления по сценарию с плавающей точкой для
свойства length объекта obj S следующим образом:
obj SCtrl=obj S.length.controller=float_script()
4. Откройте приемник команд и вычислите следующую строку кода:
showinterfaces objECtrl
В итоге выводится только один интерфейс, называемый lExprCtrl.
5. Откройте приемник команд и вычислите следующую строку кода:
showinterfaces objSCtrl
В итоге выводится только один интерфейс, называемый IScriptCtrl.
При ближайшем рассмотрении обнаруживается, что у каждого интерфейса
имеется ряд следующих общих методов: GetExpression,
SetExpression, GetDescription, SetDescription, GetOffset,
SetOffset, GetValue, DeleteVariable, RenameVariable, Update
и VariableExists. У них также имеется общее свойство ThrowOnError.
6. Вычислите следующие строки кода:
objECtrl.setExpression "F"
objSCtrl.setExpression "currentTime"
7. Воспроизведите анимацию.
Продолжительность анимации соответствует числу кадров. " F" — это спе-
циальный символ, используемый в выражениях для обозначения номера
текущего кадра. Анимация обоих параллелепипедов получается практиче-
ски одинаковой.
8. Откройте редактор кривых в окне Тrack View. Перейдите к треку свойства
length объекта objE. Выделите его, щелкните правой кнопкой мыши
и выберите команду Properties из контекстного меню, чтобы открыть диа-
242
Приложение
логовое окно свойств данного объекта. Сделайте то же самое для объекта
obj S. Обратите внимание на большое сходство диалоговых окон.
9. Далее внесите некоторую произвольность в увеличение размеров паралле-
лепипеда. Этого нельзя добиться с помощью контроллера управления по
выражению, но можно сделать с помощью контроллера управления по сце-
нарию. Вычислите следующую строку кода:
objSCtrl.setExpression "currentTime + random 0 20"
10. Воспроизведите анимацию.
Окончательный код сценария должен выглядеть следующим образом:
delete objects
clearListener()
objE=box name:"objE"
objS=box name:"objS" pos: [50,0,0]
objECtrl=obj E.length.controller=float_expression()
obj SCtrl=obj S.length.controller=float_script()
showinterfaces objECtrl -- Имеется один интерфейс: lExprCtrl.
showinterfaces objSCtrl -- Имеется один интерфейс: IScriptCtrl.
objECtrl.setExpression "F"
objSCtrl.setExpression "currentTime"
objSCtrl.setExpression "currentTime + random 0 20"
И. Для обратной совместимости сценарий из контроллера управления по сце-
нарию можно получить и установить с помощью свойства . script. На-
пример, для получения сценария вычислите следующую строку кода:
obj S.length.controller.script
В приемнике команд появится следующий результат:
"currentTime + random 0 20"
12. Для установки сценария вычислите следующую строку кода:
objSCtrl.script="random -20 20"
Параллелепипед начнет подрагивать.
Это было очень краткое введение в контроллеры управления по выраже-
нию и сценарию. Дополнительные сведения по данному вопросу можно
найти в справочном руководстве по MAXScript.
243
Предметн ы й указател ь
А
Анимация
вращения колеса по сценарию, 168
простая, создание, 164
с помощью контроллеров, 161
Б
Блок кода, 44
Блокировка рамки, 152
В
Ввод-вывод в двоичные файлы, 224
Вращение
в локальной системе координат, 153
в рамочной системе координат, 151
методом AngleAxis, 156
методом Euler Angles, 147
с помощью кватернионов, 153
Выбор
объектов на сцене, 109
точек в видовом окне, 111
Вызов функции, 23
Выражение свитка, 80
Г
Грамматические правила MAXScript, 138
Д
Доступ
к касательным, 174
к материалам, 184
к окнам открытия и сохранения
файлов, 221
к панелям команд, 108
к файлам на уровне системы, 220
3
Запись в двоичный файл, 224
И
Идентификаторы класса, 234
Индекс
массива, 55
цикла, 53
Интерфейсы
constraints, 241
lExprCtrl, 241
1No&e,240
IScriptCtrl, 242
MXSDebugger, 214
доступ, 239
определение, 239
применение, 240
раскраски, 117
К
Кватернионы, 153
Классы
MAXWrapper, 133
Modifier, 133
запросы,129
иерархия, 125
конструкторы, 135
методы, 135
наследование свойств, 127
определение, 125
экземпляры, 130
Клонирование
объектов, 102
узлов, 105
Ключевые кадры анимации, 162
Команды
button, 80
Предметный указатель
createDialog, 80
Max, 108
showinterface, 239
spinner, 80
копирования объектов, 103
отладчика MAXScript Debugger, 206
получения ссылок, 104
получения экземпляров, 103
Комментарии
блочные, 17
назначение, 16
Контексты
about, 158
animate, 162
at time, 162
coordsys, 160
области действия, 46
Контроллеры
назначение, 161
типы, 165
управления
по выражению, 241
по сценарию, 241
Кэш, 25
Л
Линейная интерполяция, 166
м
Макрорегистратор
назначение, 29
применение, 29
свойства, 29
Макросценарии, 78
Массивы
вывод на печать, 58
доступ по индексу, 55
копирование, 107
многомерные, 59
определение, 55
создание, 55
элементы, 55
Метасимволы, 61
Методы
addmodifier, 179
addNewKey, 163
format, 198
getNumVerts, 225
getProperty, 131
getPropNames, 131
getVert, 225
move, 145
normalize, 154
print, 197
random, 190
render, 185
scale, 146
seed, 191
SetProperty, 131
showAHActiveXControls, 234
showProperties, 131
showTextureMap. 185
возвращаемые значения. 140
вращения, 147
назначение, 135
необязательные параметры, 140
отображаемые. 137
типа get и set. 136
управления отладчиком MAXScript
Debugger. 215
О
Обработка ошибок, 194
Обработчики событий, 86
Обратное отслеживание по стеку, 199
Обратные вызовы, 187
Общие сценарии, 78
Объектно-ориентированное
программирование, 123
Объекты
MAXScript. 123
вложенные свойства, 133
классы. 125
свойства. 130
сцены,124
Операторы
as float, 69
as integer, 69
as string, 69
case, 207
if-then, 47
245
Предметный указатель
if-then-else, 49
MAXScript, 17
try и catch, 202
логические, 47
ссылки, 42
сценария, 17
условные, 47
Отладка
назначение, 194
сценариев, методы, 196
Отладчик MAXScript Debugger
доступ, 202
исправление ошибок, 211
командная строка, 206
назначение, 202
Окно
Debugger Output Window, 204
Watch Manager, 207
параметры настройки, 203
применение, 204
установка кадра стека, 212
Относительные имена объектов, 32
Ошибки
виды, 194
логические, 195
перехват и обработка, 201
периода
выполнения, 195
компиляции, 195
пользовательские, 195
синтаксические, 194
п
Переменные
глобальные, 44
значение, 18
индексные, 51
локальные, 44
назначение, 18
определение, 45
предопределенные, глобальные, 154
присваивание ссылок, 141
присвоение, 18
строковые, 67
Перехват ошибок, 194
Периоды
выполнения, 196
компиляции, 196
Пользовательский интерфейс
включение и отключение элементов, 98
группирование элементов, 87
построение, 77
свитки, 79
типы, 77
элементы, 82
Преобразования
вращением, 146
изменением положения, 144
контексты, 158
масштабированием, 145
строк и чисел, 69
сценариев
в макросценарии, 81
в утилиты,82
Приемник команд MAXScript
доступ, 20
назначение, 20
область Mini Listener, 21
применение, 22
Применение модификаторов, 177
Проверка уравновешенности скобок, 197
Путевые имена, 24
Р
Редактор VMS
доступ, 228
назначение, 227
сохранение результатов, 230
формирование и вставка кода
в сценарий, 233
Руководство по MAXScript
назначение, 12
поиск информации, 12', 24
применение, 125
С
Свойства
вращения, 148
источников света, 180
контроллера, 161
246
Предметный указатель
масштаба, 145
модификатора, 178
объектов, 25
положения, 27\ 144
цвета, 28
элементов интерфейса, 85
Система публикации функций, 238
Смещение указателя файла, 217
Совокупности, 55
Создание
источников света, 180
камер, 183
карт, 185
материалов, 185
Сообщения об ошибках, 198
Ссылки, 23
Строки, 67
Структуры
инициализация, 64
определение, 63
правила создания, 63
функции-конструкторы, 64
функции-члены, 66
Сценарии
ввод обработчиков событий, 81
виды, 77
для вращения колеса, 168
для раскраски пирамиды, 118
для формирования Солнечной
системы, 87
определение, 16
организация, 16
пример создания и выполнения, 70
стиль написания, 12
типичные ошибки, 194
файлы, 79
факторы для написания, 12
Сценарная утилита, 78
Сценарная функция, 77
Сценарный подключаемый модуль, 77
Сцепление, 67
т
Типы данных
Point3,35
логические, 19
приведение, 58
строковые, 19
числовые, 18
Треки анимации сцены, 161
У
Указатель файла, 217
Управление
камерами, 183
средством визуализации, 185
Ф
Файловый ввод-вывод, 215
Формирование случайных значений, 190
Функции
box, 26
createFile, 216
deletemodifier, 104
filePos, 217
findString, 68
fopen, 224
getlnterfaces, 239
getOpenFileName, 222
getSaveFileName, 223
maxOps. CloneNodes, 105
mouseTrack, 112
newscript, 234
openFile, 216
PickObject, 109
pick Point, 111
read Char, 217
readChars, 217
readLine, 217
replace, 68
seek, 217
showProperties, 26\ 238
skipToNextLine, 218
skipToString, 218
writeByte, 226
writeLong, 226
writeShort, 226
аргументы, 34
возвращаемые значения, 39
возвращающие значения, 43
247
Предметный указатель
вывода на печать, 197
для массивов, 57
имена, 23
ключевые параметры, 40
манипулирования двоичными
файлами, 227
назначение, 34
не возвращающие значения, 43
обозначение, 35
обратного вызова, 112', 117
определение, 23
передача аргументов
по значению, 41
по ссылке, 42
способы,34
позиционные параметры, 40
прерывания, 204
публикация, 239
пустые, 43
создание, 37
способы вызова, 36
управления файлами, 220
форматирования, 197
ц
Цветовое кодирование, 196
Целое число, 18
Циклы
for, 51
while, 54
определение, 50
с многими операторами, 52
ч
Число с плавающей точкой, 18
Чтение из двоичного файла, 226
э
Элементы управления ActiveX
встраивание в свиток, 235
распознавание, 234
Я
Явные имена объектов, 32
248
Научно-популярное издание
Autodesk Inc.
Основы 3ds Max 8 MAXScript
учебный курс от Autodesk
Литературный редактор
Верстка
Художественный редактор
Корректоры
Л.Н. Красножон
В.И. Бордюк
В.Г. Павлютин
ЛА. Гордиенко
Издательский дом “Вильямс”
101509, г. Москва, ул. Лесная, д. 43, стр. 1
Подписано в печать 08.05.2006. Формат 70x100/16.
Гарнитура Times. Печать офсетная.
Усл. печ. л. 16,0. Уч.-изд. л. 12,8.
Тираж 3000 экз. Заказ № 1474.
Отпечатано по технологии CtP
в ОАО “Печатный двор” им. А. М. Горького.
197110, Санкт-Петербург, Чкаловский пр., 15.