How To ... Create Scripted Geometry Plug-in

MAXScript lets you create scripted geometry plug-ins that can generate procedural mesh objects on the fly just like regular C++plug-ins.

We are going to use the simple mesh code from the How To ... Create Custom Mesh Object topic and extend it to a scripted plug-in.

Related Topics:

Defining SimpleObject plug-ins

Scripted mouse tools

Mouse tool clauses

NATURAL LANGUAGE

Define a simpleObject scripted plug-in.

Convert the basic parameters of the mesh object created in the first tutorial to parameter block parameters.

Define a UI and link to the parameter block values.

Paste the original mesh code into the buildMesh handler of the plug-in.

Create a mouse tool to place the object and define the parameters.

MAXSCRIPT

plugin simpleObject AntiStar
name:"AntiStar"
category:"HowTo"
classID:#(0xe855567c, 0xbcd73b8b)
(
parameters main rollout:params
(
num_faces type:#integer ui:num_faces default:10
radius1 type:#float ui:radius1 default:0
radius2 type:#float ui:radius2 default:0
width type:#float ui:width default:1
)
rollout params "AntiStar"
(
spinner num_faces "# Faces"range:[2,100,10] type:#integer
spinner radius1 "Radius 1 "range:[0,10000,0]
spinner radius2 "Radius 2 "range:[0,10000,0]
spinner width "Width "range:[0,90,1]
)

on buildMesh do
(
--Note: The code below has been taken from the
--How To – Create Custom Mesh Object 
--topic and is identical.

vert_array = #()
face_array = #()
vert_count = 0
for a = 0 to 360 by 360.0/num_faces do
(
v1 = [radius1*cos(a+width), radius1*sin(a+width), 0]
v2 = [radius1*cos(a-width), radius1*sin(a-width), 0]
v3 = [radius2*cos(a),radius2*sin(a),0]
append vert_array v1
append vert_array v2
append vert_array v3

append face_array [vert_count+1,vert_count+3,vert_count+2]
vert_count += 3
)
setMesh mesh verts:vert_array faces:face_array
)--end buildMesh
tool create
(
on mousePoint click do
(
case click of
(
1: coordsys grid (nodeTM.translation = gridPoint)
)
)
on mouseMove click do
(
case click of
(
2: (radius1 = abs(gridDist.y))
3: (radius2 = abs(gridDist.y))
4: (width = abs(gridDist.x))
5: (#stop)
)
)
)--end create
)--end plugin

Step-By-Step

plugin simpleObject AntiStar
name:"AntiStar"
category:"HowTo"
classID:#(0xe855567c, 0xbcd73b8b)
(

A scripted plug-in starts with the constructor plugin followed by the superclass of the scripted plug-in ( simpleObject ) and the new class name of the plug-in ( AntiStar ). In addition, you have to provide the name that appears in the effects list and a unique classID .

The classID is used by 3ds Max to recognize the plug-in class when loading the scene. To generate a new unique ID, you can use the GenclassID () method in the Listener and copy the result into the script.

To keep all versions of this plug-in compatible around the world, it is recommended to copy the above classID .

Scripted SimpleObject Plug-ins

classID

parameters main rollout:params
(

The scripted plug-in stores its parameters in a so-called Parameter Block. The ParamBlock2 format has been introduced in 3ds Max 3 and allows for easy properties and tracks management, automatic animation brackets in the UI, and more. In this case, we will store the same values used in the first mesh script (number of faces, the two radii and the width (offset) value) in the ParamBlock.

All parameters in the block have their counterparts in the plug-ins rollout in the UI. By providing the rollout name, you allow the ParamBlock to establish an automatic connection between the internal values and the UI elements.

Parameter_block2

num_faces type:#integer ui:num_faces default:10

The num_faces object property controls the number of "rays" in the object, actually the number of faces. It is an integer and corresponds to a spinner in the UI with the same name. The default number of faces are 10.

radius1 type:#float ui:radius1 default:10

The radius1 object property controls the outer radius of the object. It is a floating point value and corresponds to a spinner in the UI with the same name. The default radius on creation is 10. If you create an object using MAXScript by calling the constructor antiStar(), the object uses this value as the default outer radius.

radius2 type:#float ui:radius2 default:0

The radius2 object property controls the inner radius of the object. It is a floating point value and corresponds to a spinner in the UI with the same name. The default radius on creation is 0.

width type:#float ui:width default:1

The width object property controls the offset of the outer vertices and defines the width of the rays. It is a floating point value and corresponds to a spinner in the UI with the same name. The default width on creation is 1.

)
rollout params "AntiStar"
(
spinner num_faces "# Faces" range:[2,100,10] type:#integer
spinner radius1 "Radius 1" range:[0,10000,0]
spinner radius2 "Radius 2" range:[0,10000,0]
spinner width "Width" range:[0,90,1]
)

Now, you can provide the rollout with UI elements referenced by the Parameter Block. The UI elements can limit the input values using the optional range: parameter, but the default value is taken from the ParamBlock2.

Rollout Clauses

Spinner

on buildMesh do (

The buildMesh is the main handler of scripted simpleObject plug-ins. It is called each time the geometry needs to be updated. Inside the handler, you can use our existing mesh generation code from the other tutorial to generate the vertices and faces of the mesh.

vert_array = #()
face_array = #()
vert_count = 0
for a = 0 to 360 by 360.0/num_faces do
(
v1 = [radius1*cos(a+width),radius1*sin(a+width),0]
v2 = [radius1*cos(a-width),radius1*sin(a-width),0]
v3 = [radius2*cos(a),radius2*sin(a),0]
append vert_array v1
append vert_array v2
append vert_array v3
append face_array [vert_count+1,vert_count+3,vert_count+2]
vert_count += 3
)
setMesh mesh verts:vert_array faces:face_array

The buildMesh handler accepts the setMesh method that feeds the mesh generation data into a fast routine, which regenerates the object on the fly.

)--end buildMesh
tool create
(

The tool create handles the mouse controls on object creation.

Scripted Mouse Tools

on mousePoint click do
(

The on mousePoint handler is executed each time the user clicks with the mouse in the viewport. The variable click counts the number of clicks.

Mouse_Tools_Event_Handlers

case click of
(
1: coordsys grid (nodeTM.translation = gridPoint)

In case the user has clicked for the first time, you can set the translation part of the Node Transformation Matrix of the object to the grid point the user specified. This repositions the center of the object to the clicked point in the active grid.

Mouse_Tools_nodeTM

Mouse_Tools_gridPoint

)
)
on mouseMove click do
(

The on mouseMove handler is executed each time the user moves the mouse in the viewport. The variable click counts the number of clicks.

Mouse_Tools_Event_Handlers

Case click of
(

The case expression allows the selection of options based on the value of the supplied variable. It is similar to using multiple if statements to compare the same variable with multiple values.

Case Expression

2: (radius1 = abs(gridDist.y))

If the user has clicked twice so far, set the outer radius to the Y distance from the center of the object to the current mouse position.

Mouse_Tools_gridDist

3: (radius2 = abs(gridDist.y))

If the user has clicked tree times, set the inner radius to the Y distance from the center of the object to the current mouse position.

4: (width = abs(gridDist.x))

If the user has clicked four times, set the offset to the outer vertices by measuring the X distance from the center of the object to the current mouse position.

5: (#stop)

Finally, finish the creation. A new object is created.

)
)
)--end create
)--end plugin

Using the Script

This is a scripted plug-in and it is handled by 3ds Max as a real C++ plug-in.

To install it permanently on your system, copy the file to the \plugins folder or to any other folder listed in the plug-in paths.

To try the plug-in without installing it permanently, evaluate the code and look under Create panel>Geometry>HowTo category in the drop-down list. The plug-in is only available for the single session and will not be there after restarting 3ds Max.

Any MAX files saved with the plug-in in the scene will require the script to be installed and evaluated in order to load correctly.

To use the plug-in, click the AntiStar button in the Create panel > Geometry > HowTo. Click in the viewport to define the center, drag to define the outer radius, click and drag again to define the inner radius, and click and drag again to define the width. Click to finish or right-click to cancel.

Play with the controls in the UI under the Modify panel and note how quickly the mesh is updated by the script.

Back to

"How To" Tutorials Index Page