MAXScript supports sophisticated user interaction. The mouse tracking tool, and the painter interface are two examples.
In this chapter, you will use the mouse tool to drag a mesh along the surface of another mesh. And you will use the painter interface to "paint" geometry on the surface of a mesh.
Objectives
After completing this chapter, you should be able to:
• Use the mouse tracking tool.
• Use the painter interface.
Introduction
MAXScript allows sophisticated interaction with the viewport and scene objects. MouseTrack and the painter interface implement advanced MAXScript interfaces. MouseTrack tracks mouse events like click and drag, etc, then executes a function based on the particular event. The painter interface exposes the 3ds Max paint capabilities. This includes "painting" objects on surfaces, pushing and pulling sub-objects, etc.
MouseTrack
The MouseTrack Function lets you track the mouse in the viewports. For instance it can monitor mouse clicks, mouse movement, and track the intersection of the mouse with scene geometry. You can respond to the mouse events by writing a function that will get called whenever a mouse event happens. This function is called a callback function. A callback function has a certain signature, and takes certain arguments that are supplied by MAXScript.
The syntax is as follows:
mouseTrack [on:<node>] [prompt:"msg"] [snap:#2D|#3D] [trackCallback:fn|#(fn,arg)]
Some of the MouseTrack parameters are:
• [on:<node>]—This optional argument is a scene object that the function will respond to in your callback function. If you don’t supply this, the MouseTrack function will operate on the active grid.
• [prompt:"msg"]—This is a text message that will be displayed in the status bar at the bottom of the 3ds Max window.
• [snap:#2D|#3D]—This enables snaps, and only works when an object is tracking on an object surface.
• [trackCallback:fn]—This is the function that gets called in response to mouse events and is the name of your callback function.This callback function should return a value of #continue to keep processing MouseTrack events. If the return value is anything else, the function will simply get called once and stop.
The callback function you implement should take seven arguments as follows:
function CallBack message intRay obj faceNumber shift ctrl alt = (...)
• message— This is a code that tells what the mouse is doing. It is one of four different enumerated messages:
#freemove—The mouse is moving and no mouse buttons are pressed.
#mousepoint—The left mouse button was pressed.
#mousemove—The mouse is being dragged with the left mouse button pressed.
#mouseabort—The right mouse button was pressed.
• intRay : The intersection from a ray starting at the mouse cursor and aiming towards the active grid or tracked object.
A ray has a position property (.pos), and a direction vector (.dir).
• obj—This is the object that is getting tracked. It was assigned when the MouseTrack function was called in the optional [on:<node>] argument. If the optional [on:<node>] argument was unsupplied, then the obj parameter is undefined.
• faceNumber—The index number of the face the mouse is over. This only works if the object is an editable mesh. If not, this parameter is undefined.
• shift / ctrl / alt—These values tell whether these keys are depressed. Values are true or false.
To use the MouseTrack function:
1. Reset the 3ds Max scene, and open a new MAXScript file (Choose MAXScript > New MAXScript from the Menu). Also open the MAXScript Listener.
MouseTrack ■
171
2. In the new Script window type the following:
function myFooFunction message intRay obj faceNumber shift ctrl alt = (
print message
#continue )
s = sphere()
mousetrack on: s prompt: "Tracking" trackCallback: myFooFunction
3. Save the file, and evaluate the script. Move the mouse around the viewport, and experiment with clicking and dragging.
Be sure to watch the viewport as you perform your actions.
4. Press the ‘ESC’ key to exit the action.
As you move the mouse around the viewport, many #freemove messages are sent to the MAXScript Listener so that the Listener window starts scrolling very quickly. You have to be quick to observe a #mousepoint message when you press the mouse button. You should see all the mouse messages as you experiment with this tool.
Next, modify the script so you can interactively drag a teapot on the surface of the sphere. This code will be written in the myFooFunction callback function. When MouseTrack function is running, it is helpful to remember that when a mouse is over the tracked object, the intRay and obj parameters of the callback function are defined. To interactively drag the teapot on the sphere’s surface, use the intRay parameter—a ray has a very handy position property that tells you where the ray hits the tracked object. You will assign this position to the teapot.
5. Delete any objects in the scene.
6. Modify your script to look like this:
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 (
s = sphere segments: 48 wirecolor: (color 0 255 255)
mousetrack on: s prompt: "Tracking" trackCallback: myFooFunction
Notice that you defined a small teapot (pot) at the top of the script. In the callback function, you now trap the #freemove message. You also test to make the sure the obj and intRay parameters are defined. When the two previously mentioned parameters are defined, you assign the position of the intersecting ray with mesh to the position property of the teapot.
7. Save and evaluate the script. Move your mouse over to the sphere, and notice the behavior as you continue to move your cursor over it. It may help to minimize your window so you can see four viewports at the same time.
8. Press the ‘ESC’ key to exit the action.
The teapot moves and follows your mouse as it tracks over the sphere. When you move your mouse over empty screen space, nothing happens to the teapot. In a perspective viewport it may not look like much because the teapot is not rotating.
However if you end the action and rotate the perspective view, you can see that the teapot is ‘attached’ to the surface of the sphere.
9. To make it apparent that the teapot is following the surface of the sphere, rotate the teapot to follow the normal vector at the intersection point. This data is precisely given in the callback function with the intRay parameter. The intersection ray (intRay) is from the point of intersection and is parallel to the normal vector of the face it intersects with. Now, it is a small matter to align the teapot with the surface of the sphere. Within the if statement, add a line of code after the position assignment:
...
if (obj != undefined) and (intRay != undefined) do (
pot.pos = intRay.pos pot.dir = intRay.dir )
...
10.Save and evaulate the script. Move the mouse over the sphere.
MouseTrack ■
173
11.Press the ‘ESC’ key to exit the action.
The teapot is now aligned with the surface of the sphere.
To make this script more user friendly, it should abort the command when the user clicks a mouse button rather than when the user presses the escape key.
Currently, the function returns a #continue value, no matter what happens in the case statement. This is rather crude, but simple. Next, expand the case statement to handle the other messages, including the messages you will use to abort or cancel the script.
12.Modify your callback function to look like the following:
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 )
13.Save and evaluate the script. Move the mouse around and press any button to cancel the script.
As you can see, the MouseTrack and callback function working together can make some very interesting scripts. The final version of this script called mouse_track.ms can be found on the CD. For reference information, see the following section in the MAXScript Reference Help:
MAXScript Tools and Interaction with 3ds Max > Interacting with the 3ds Max User Interface > MouseTrack.