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.
Defining SimpleObject plug-ins
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
|
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
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.
Mid Topic ID: Parameter_block2
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.
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.
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.
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.
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.
The tool create handles the mouse controls on object creation.
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.
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.
The on mouseMove handler is executed each time the user moves the mouse in the viewport. The variable click counts the number of clicks.
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.
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.
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.
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.
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.