Выбор точек

В MAXScript имеется немало функций для работы с видовыми окнами. К ним, в частности, относятся функции изменения схемы расположения видовых окон, об­новления видовых окон, установки режимов привязки, изменения масштаба изо­бражения, задания сеток и т.д. Вместо того чтобы рассматривать все подобные функции, в этом разделе основное внимание будет уделено одной очень важной функции, pickPoint, с помощью которой пользователь выбирает точку или место в видовом окне, а функция возвращает координаты этой точки в виде данных типа Point3. Синтаксис функции pickPoint следующий:

pickPoint [snap:#2D|#3D] [rubberBand: <start_point3>] ...

Ниже приведены некоторые параметры данной функции.

• [snap: #2D|#3D] — этот аргумент определяет вид привязки, если он передается функции. В противном случае выделяемая точка будет находиться на текущей плоскости построения.

Примечание. Для того чтобы данный параметр возымел действие, необходимо сначала включить режим привязки в пользовательском интерфейсе 3dsMax.

• [rubberBand: <point3>] — этот аргумент определяет режим рисования пунктирной линии от предоставляемой точки до местоположения курсора до тех пор, пока данная функция активна. Данный режим обычно используется для визуального соединения ряда точек в видовом окне.

Для того чтобы воспользоваться функцией pickPoint, выполните следующее упражнение.

1. Очистите сцену 3dsMax и откройте новый файл сценария MAXScript по команде MAXScript ⇨ NewMAXScript из главного меню.

2. Откройте окно приемника команд MAXScript Listener.

3. Создайте ряд геометрических объектов в видовом окне и включите режим трехмерной (3D), но не двухмерной (2D) или полуобъемной (2.5D) привязки или же выберите любой другой вид привязки.

4. Введите в файл сценария следующий фрагмент кода:

pnt = point3 0 0 0

for i = 1 to 3 do

(

pnt = pickPoint snap: #3D rubberband: pnt

)

5. Вычислите код сценария и выберите три точки в видовом окне.

Выделяя точки, обратите внимание на линию, проводимую от точки начала отсчета до курсора, находящегося в первой точке, а затем к остальным выбираемым точкам при последовательном перемещении курсора от одной точки к другой. В более сложном сценарии такая линия проводится лишь


Интерфейс 3dsMax

после выбора первой точки. Обратите также внимание на то, что, прежде чем выбирать точки, необходимо включить режим привязки, чтобы аргумент привязки возымел действие. В данной функции режим привязки автоматически не устанавливается.

Дополнительные сведения по данному вопросу приведены в следующем разделе справочного руководства по MAXScript: MAXScript Tools and Interaction with 3dsMax ⇨ lnteracting with the 3dsMax User Interface ⇨ Viewports ⇨ Picking Points in the ViewPorts (Инструменты MAXScript и взаимодействие с 3dsMax ⇨ Взаимодействие с пользовательским интерфейсом 3dsMax ⇨ Видовые окна ⇨ Выбор точек в видовых окнах).

Функция mouseTrack (дополнительный материал)

Функция mouseTrack позволяет отслеживать перемещения курсора мыши в видовых окнах. В частности, она способна контролировать щелчки кнопками мыши и перемещения курсора мыши, а также отслеживать пересечение курсора мыши с геометрическими объектами на сцене. Для организации реакции на событие, связанное с мышью, можно написать функцию, которая вызывается, когда по­добное событие наступает. Это так называемая функция обратного вызова. Она имеет специальное обозначение и воспринимает определенные аргументы, пре­доставляемые средствами MAXScript.

Синтаксис функции mouseTrack следующий:

mouseTrack [on:<узел>] [prompt:"msg"] [snap:#2D|#3D] [trackCallback: fn | #(fn,arg)]

Ниже приведены некоторые параметры функции mouseTrack.

• [on: <узел>] — этот необязательный аргумент определяет находящийся на сцене объект, реакция на который будет происходить в функции обратного вызова. Если этот аргумент не предоставляется, mouseTrack будет отслеживать перемещения курсора мыши на активной координатной сетке.

• [prompt: "msg"] — это текстовое сообщение, появляющееся в строке состояния, расположенной в нижней части окна 3dsMax.

• [snap: #2D|#3D] — этот аргумент активизирует привязки, но действует лишь в том случае, если перемещение курсора мыши не отслеживается на поверхности объекта.

• [trackCallback: fn] — это функция, которая вызывается в ответ на события, связанные с мышью, а ее имя обозначает функцию обратного вызова. Такая функция должна возвращать значение #continue для того, чтобы продолжалась обработка событий, фиксируемых функцией mouseTrack. Если же эта функция возвращает какое-то другое значение, она просто больше не вызывается.


Глава 3

Реализуемая отдельно функция обратного вызова должна воспринимать ряд аргументов следующим образом:

function CallBack message intRay obj faceNuxnber shift Ctrl alt = (...)

• message — это код, указывающий на действия мыши в виде одного из следующих четырех сообщений:

#freemove — мышь перемещается, но кнопка мыши не нажимается; #mousepoint — нажата левая кнопка мыши;

#mousemove — курсор мыши перетаскивается при нажатой левой кнопке мыши;

#mouseabort — нажата правая кнопка мыши.

• intRay — пересечение с лучом, исходящим из курсора мыши и направленным в сторону активной координатной сетки или отслеживаемого объекта. У такого луча имеется свойство положения (.pos) и вектор направления (.dir).

• obj — это отслеживаемый объект. Он присваивается при вызове функции mouseTrack с дополнительным аргументом [on:<узел>]. Если данный аргумент не предоставляется, параметр obj не определен.

• faceNumber — порядковый номер грани, на которой находится курсор мыши. Этот параметр действует только в том случае, если объект является редактируемым каркасом. В противном случае он не определен.

• shift/ Ctrl/ alt— эти параметры указывают на нажатие соответствующих модифицирующих клавиш. Они могут принимать лишь два логических значения: true и false.

Для того чтобы воспользоваться функцией mouseTrack, выполните следующее упражнение.

1. Очистите сцену 3dsMax и откройте новый файл сценария MAXScript по команде MAXScript⇨NewMAXScript из главного меню. Затем откройте окно приемника команд 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>, чтобы завершить действие.


Интерфейс 3dsMax

При перемещении курсора мыши в видовом окне появляется много сообщений #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). А в функции обратного вызова перехватывается сообщение #freemove. Кроме того,
в сценарии проверяется, были ли определены параметры objи intRay.
Если они определены, положение луча, пересекающего каркас, присваивается свойству положения чайника.

7. Сохраните сценарий и вычислите его код. Переместите курсор мыши по
сфере, обратив внимание, что именно происходит, когда вы продолжаете
перемещать курсор по ней. Для этого, возможно, удобнее свернуть текущее
видовое окно и наблюдать происходящее одновременно во всех четырех видовых окнах.


Глава 3

8. Нажмите клавишу <Esc>, чтобы завершить действие.

Чайник перемещается, следуя за курсором мыши по сфере. А при перемещении курсора мыши в пустом пространстве экрана с чайником ничего не
происходит. Возможно, это не очень заметно в окне вида в перспективе, поскольку чайник не поворачивается. Но если завершить действие и повернуть вид в перспективе, то можно заметить, как чайник буквально
"привязан" к поверхности сферы.

 

 

 

 


9. Для того чтобы сделать перемещение чайника по поверхности сферы вслед
за курсором мыши более очевидным, поверните его в направлении вектора
нормали в точке пересечения. Именно эта информация предоставляется
в функции обратного вызова с помощью параметра intRay. Пересекающий
луч (параметр intRay) исходит из точки пересечения и следует параллельно вектору нормали к грани, которую он пересекает. Остается лишь
выровнять чайник по поверхности сферы. Для этого введите еще одну строку кода после строки присваивания положения внутри условного оператора if:

if (obj != undefined) and (intRay != undefined) do
(

pot.pos = intRay.pos
pot.dir = intRay.dir

)

 

10. Сохраните сценарий и вычислите его код. Переместите чайник по сфере.


Интерфейс 3dsMax

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

)

#mouseAbort: ( undefined )

#mousePoint: ( undefined )

#mouseMove: (#continue )

)

returnValue

)


Глава 3

14. Сохраните сценарий и вычислите его код. Переместите курсор мыши и нажмите любую ее кнопку, чтобы отменить действие сценария. Как видите, взаимодействие функции mouseTrack и функции обратного вызова служит удобным основанием для создания весьма интересных сценариев. Окончательный вариант данного сценария можно найти в файле \chapter3\mouse_track.ms на прилагаемом к этой книге CD-ROM. А дополнительные сведения по данному вопросу приведены в следующем разделе справочного руководства по MAXScript: MAXScript Tools and Interaction with 3dsMax ⇨ lnteracting with the 3dsMax User Interface ⇨ MouseTrack (Инструменты MAXScript и взаимодействие с 3dsMax ⇨ Взаимодействие с пользовательским интерфейсом 3dsMax ⇨ Функция mouseTrack).

Интерфейс раскраски (дополнительный материал)

Рассмотренные выше средства MAXScript, в том числе функции pickPoint, PickObject и mouseTrack, сами по себе весьма эффективны. А в этом разделе речь пойдет об интерфейсе раскраски — самом совершенном средстве MAXScript для организации работы в диалоговом режиме.

В 3dsMax имеется ряд инструментов, использующих интерфейс раскраски, в котором кисть оперирует объектом, раскрашивая его геометрическую форму, выталкивая и втягивая вершины на каркасе или выполняя ряд других операций. Все эти возможности раскрываются в интерфейсе раскраски MAXScript. У интерфейса раскраски имеется немало функций и свойств, и поэтому он может показаться слишком сложным для начинающих пользователей. Этот раздел служит лишь в качестве краткого введения в данный интерфейс.

Как и в других интерфейсах, в интерфейсе раскраски используется глобальная переменная thePainterInterface. У этой переменной вообще нет значения, а есть только свойства и методы, управляющие процессом раскраски.

Примечание. Дополнительные сведения об интерфейсах приведены в тех разделах приложения к этой книге, в которых обсуждаются вопросы, связанные с интерфейсами.

Работа интерфейса раскраски основана на использовании функций обратного вызова. Как следует из приведенного выше примера применения функции mouseTrack, функции обратного вызова определяются создателем сценария (т.е. вами), а вызываются системой. Они называются так потому, что система делает обратный вызов вашего кода через написанную вами функцию. Если в примере применения функции mouseTrack из предыдущего раздела использовалась лишь одна функция обратного вызова, то в интерфейсе раскраски — пять таких


Интерфейс 3dsMax

функций. Все эти функции вызываются во время разных событий типа раскраски. Это следующие функции:

• StartStroke — вызывается в начале события раскраски;

• PaintStroke — вызывается в течение события раскраски;

• EndStroke — вызывается в конце события раскраски;

• CancelStroke — вызывается при отмене пользователем события раскраски;

• SystemEnd — вызывается по окончании события раскраски.

Для регистрации этих функций в интерфейсе раскраски вызывается функция-член (называемая также методом) глобальной переменной thePainterinterface, и ей передаются пять функций обратного вызова в указанном выше порядке. Это нужно сделать после определения данных функций в сценарии. Ниже приведен способ их инициализации:

thePainterinterface.ScriptFunctions startStroke paintStroke endStroke cancelStroke systemEnd

После инициализации функций интерфейсу раскраски указываются те объекты (или узлы), которые требуется раскрасить. Эти объекты можно рассматривать как холст для картины, например:

canvasNodes = $

thePainterInterface.initializeNodes 0 canvasNodes

В приведенном выше примере сначала все находящиеся на сцене объекты вы­деляются, а затем раскрашиваются. Первый аргумент не используется и должен оставаться равным нулю.

Для того чтобы начать сеанс раскраски, вызовите следующую функцию: thePainterInterface.startPaintSession()

А для того чтобы завершить сеанс раскраски, вызовите следующую функцию: thePainterInterface.endPaintSession()

В следующем упражнении вам предстоит написать сценарий, демонстрирующий возможности интерфейса раскраски. В этом сценарии будет раскрашена пирамида, расположенная над сферой. В нем предусмотрен небольшой пользовательский интерфейс, в котором пользователь нажимает фиксирующую кнопку, чтобы начать раскраску, и отжимает ее, чтобы завершить раскраску. Этот интерфейс будет помещен не в перемещаемое диалоговое окно, а в свиток на панели утилит.

1. Очистите сцену 3dsMax и откройте новый файл сценария MAXScript по команде MAXScript ⇨ NewMAXScript из главного меню.

2. Откройте окно приемника команд MAXScript Listener.

3. Введите в окне нового сценария следующий его код:

 

Глава 3

 

global scatteredObject

-- функции обратного вызова

function StartStroke = (

)

function PaintStroke = (

)

function EndStroke = (

)

function CancelStroke = (

)

function SystemEnd = (

 

-- определениеутилиты

utility paintStuff "Paint Utility"

(

checkbutton ckb_paint "Paint"
on paintStuff open do

(

clearlistener()

delete $* -- удалить все существовавшие ранее объекты
s1 = sphere radius: 24 segments: 48

scatteredObject = Pyramid width:2 depth:2 height:20 pos:[0,25,0]

thePainterInterface.ScriptFunctions startStroke paintStroke \

endStroke cancelStroke systemEnd

thePainterInterface.initializeNodes 0 s1

)

on ckb_paint changed state do

(

if state then

(

thePainterInterface.startPaintSession()

)

else

(

thePainterInterface.endPaintSession()

)

)

)

OpenUtility paintStuff

Примечание.Весь этот сценарий работает только в том случае, если
функции обратного вызова находятся в глобальной области действия.

4. Сохраните сценарий и вычислите его код.

В этом сценарии происходит переход к панели утилит, на которой отобра-
жается новый свиток. Со сцены удаляются любые геометрические объекты
и создаются два новых объекта.


Интерфейс 3dsMax

5. Щелкните на кнопке Paint (Раскрасить). Поместите курсор над сферой, обратив внимание на появление над сферой пиктограммы инструмента раскраски. Раскрасьте поверхность сферы так, как показано на приведенном ниже рисунке.

 

 


Средствами интерфейса раскраски на поверхности сферы автоматически вычерчивается нарисованный вами контур. Как только вы отпустите кнопку мыши, контур исчезнет и вам придется начать раскраску снова. В данный момент остроконечная пирамида еще не используется для раскраски.

6. Введите внутри функции PaintStrokeследующий фрагмент кода:

function PaintStroke =

(

localHit = [0,0,0]

localNormal = [0,0,0]

worldHit = [0,0,0]

worldNormal = [0,0,0]

str = 0.0f

radius = 0.0f

thePainterInterface.getHitPointData &localHit &localNormal \

&worldHit &worldNormal &radius &str 0

-- создать экземпляр пирамиды и переместить

obj = instance scatteredObject

obj.pos = worldHit

obj.dir = worldNormal

)

7. Сохраните сценарий и вычислите его код. Как только раскроется свиток, щелкните на кнопке Paint и начните раскраску сферы так, как показано на приведенном ниже рисунке.


Глава 3

 

 

 


Итак, вы успешно раскрасили один объект на другом. Окончательный вариант данного сценария можно найти в файле \chapter3\painter_interface.ms на прилагаемом к этой книге CD-ROM. А дополнительные сведения по данному вопросу приведены в следующих разделах справочного руководства по MAXScript.

• MAXScript Language Reference ⇨ 3dsMax Objects ⇨ Interfaces ⇨ Other Interfaces ⇨ Other Interfaces ⇨ Interface: the Painter Interface (Справочник по языку MAXScript ⇨ Объекты 3dsMax ⇨ Интерфейсы ⇨ Прочие интерфейсы ⇨ Другие интерфейсы ⇨ Интерфейс: the Painter Interface)

• MAXScript Tools and Interaction with 3dsMax ⇨ Creating MAXScript Tools ⇨ Scripted Paint Tools (Инструменты MAXScript и взаимодействие с 3dsMax ⇨ Создание инструментов MAXScript ⇨ Сценарные инструменты раскраски)

Заключение

В этой главе вы ознакомились со многими важными понятиями MAXScript и пользовательского интерфейса. В частности, вы научились клонировать объекты и массивы, а также освоили целый ряд команд MAXScript, доступных для выполнения высокоуровневого доступа к пользовательскому интерфейсу, выбора панелей команд и инструментов, узлов сцены и точек. Кроме того, вы научились пользоваться функцией mouseTrack и интерфейсом раскраски.


Объекты и классыГлава 4

MAXScript представляет собой весьма эффективный язык создания сценариев, в котором реализованы многие принципы объектно-ориентированного программирования. Усвоив эти принципы, вы сможете лучше понять сам язык MAXScript, а следовательно, стать на путь профессионального написания сценариев. Изучив основной материал этой главы, вы научитесь попутно пользоваться справочным руководством по MAXScript.

Глава 4

Задание

После изучения этой главы вы должны уметь следующее.

• Ясно представлять назначение объектов в контексте MAXScript

• Определять классы объектов

• Пользоваться справочным руководством по MAXScript для определения свойств и методов объектов

• Понимать грамматику и синтаксис языка MAXScript