This is part 2 of our series on MaxScript. I'll cover some simple ways you can start to use maxscript in your every day workflow.
Even if you have never touched code before, there are some simple ways you can start using maxscript that will help you automate tasks and remove some of the time wasting steps you have to take time and time again.
To answer that head over to part one of this series and also check out www.scriptspot.com or wonder over to our post about GhostTown to get an idea of what is possible.
Cool stuff huh?
We won't be getting that crazy complex, but someday you might! You won't get there unless you start somewhere.
The next thing to keep in mind is, did someone already do what I'm about to?
Check www.scriptspot.com and other technically minded artists sites like James Haywood, Neil Blevins, Paul Neale or the MaxScripting giant Borislav Petrov better known as Bobo (not the seal) who's written the majority of the max script help files.
Next, ask yourself, will writing this script help me (and potentially others) later?
Or is this a one shot thing that will take more time to write then the time it saves? With that said...
Lets say you need to collapse a bunch of objects in your scene. You could select all the objects, then apply edit poly, and then right click and collapse the stacks? That works pretty well but why not have a one button solution? Here's how:
Open the listener window. Right click either the white or pink box in the lower right corner of max and choose open listener.
Or press F11
Or go Main Menu > MAXScript > Open Listener
Click MacroRecorder in the menu and turn on:
Enable, show command panel switching, show tool selections and show menu item selections.
Now most of what you do in 3dmax will be reported in the pink window in one way or another.
Note: If you have just a white box when the listener pops up, click and drag on the separator just under the menu to reveal the pink recorder section.
Repeat after me:
Click in each plane and hit ctrl-D (or edit >clear all) to clear out both windows.
Select an object, collapse it and check out the maxscript listener it will look something like this:
It shows that we selected the box "select $Box023" and then collapsed "maxOps.CollapseNode $ off".
Note: The $ in the command, that means selection. If we wanted to collapse a specific item we would say "maxOps.CollapseNode $box23 off" but with the way it is "$" it will collapse whatever is selected, exactly what we want, awesome.
Now you could drag the chunk of code from the listener into the tool bar to make a button and call it done... Or we can start to expand on it and make the script a little smarter, copy the command "maxOps.CollapseNode $ off" from the listener window go File > New Script, paste.
We should explore one of the basic building blocks of scripting. Typically you use the for loop to run a series of commands over a selection of objects. For the objects in this group do these commands.
The "for loop" looks something like this:
1 meshes = $ --stores the currently selected objects in a group(array) called meshes.
2 for i in meshes do ( --Each time you find a command with "i" in it, insert an object from meshes.
3 maxOps.CollapseNode i off --we replace $ with i so the for loop inserts the objects into the command.
4 ) --this closes the for loop
If we have 6 objects in our meshes array it will run the collapse command 6 times inserting each object into the command every time it runs.
Note: We could define meshes as anything, it could be objects on a specific layer or only objects that are named a specific way, or it can be set up to exclude splines. We're doing the easiest thing possible right now and making an array out of the selected objects but you could chase the rabbit further down the hole...
This is good, pat yourself on the back and bask in your genius. Just don't get too comfortable it breaks easily. WHAT? NO! HOW!? If nothing is selected, the script crashes and the listener yells at us in red text... that's bad.
So lets add a check to see if anything is selected and complain if there isn't anything selected.
If this condition is met, Then do this, otherwise do something Else.
1 (-- start script
2 local meshes = $ -- define meshes as local so we don't confuse max (or other scripts) globally
3 if meshes != undefined then ( -- if meshes "does not equal" undefined then carry on and collapse
4 for i in meshes do (-- here is our for loop from before
5 maxOps.CollapseNode i off
6 ) -- close for loop
7 ) -- close then statement
8 else ( --this is used if meshes does equal undefined
9 messagebox "Nothing selected, nothing collapsed." title: "Selection Failure"
10 ) -- close else
11 ) -- end script
So there we go, our script is pretty much bullet proof, nice going! You can drag the code from the window into the tool bar to make a button, I'll cover binding it to a key a little later on when I cover MacroScripts in example #3.
Note: You can use this same method to change the default settings of modifiers. For example If you like Edit Poly applied with specific settings and to start in edge mode? You could record yourself applying that modifier, making those changes and use listener to create a new button that does all that.
See how those little annoying, time wasters are starting to disappear?
Lets say you want one button that toggles the Field of View from 45, to 60 to 90. We do this with two "if, then, else" statements.
This kind of circular thinking can be a real brain bender, especially for artists so lets look at the logic:
With the logic squared away, lets find our commands and begin piecing this together. Lets change the FOV and see what the listener spits out... Humm it looks like the listener doesn't record the change in FOV so we need to look the commands up in the maxscript help file, with either the script editor or the listener active press F1 (this will bring up the maxscript help file which is different than the standard F1 help file).
Search for "FOV" in the second search result, we find the commands we're looking for: viewport.GetFOV() and viewport.SetFOV()
We string it all together like this:
1 ( -- start script
These are functions, they are defined like array's but you tack on fn at the beginning so instead of storing information it will run whatever is defined and return something. Functions can be long complicated commands but we'll keep it simple for now.
2 fn SetFOV90 = viewport.setFOV 90 -- creates a function called SetFOV90
3 fn SetFOV45 = viewport.setFOV 45 -- creates a function called SetFOV45
4 fn SetFOV60 = viewport.setFOV 60 -- creates a function called SetFOV60
5 local FOVis = viewport.GetFOV() as integer -- collects and stores the FOV
Note: we use "as integer" so it returns 45 instead of 45.0 making it easier to deal with
This is the beginning of the first if statement, this answers the "yes/true" side of the question.
7 if FOVis == 45 then ( -- Compares the FOV to 45, if its yes/true it does...
8 SetFOV60() -- sets the FOV to 60 by calling our function
9 print "fov is 60" -- prints to the listener window the new FOV, just to be nice
10 completeRedraw() -- redraws the viewport forcing the FOV change to take effect
11 ) -- closes the yes/true part of the FOV 45 question
This handles the "no/false" part of the first if statement.
12 else ( -- opens the no part of the FOV 45 question
13 if FOVis == 60 then ( -- This begins the second if statement, we're asking another question, if it wasn't 45, is it 60?
14 SetFOV90() ( -- if it was 60 yes/true, set it to 90
15 print "fov is 90" -- print the change
16 completeRedraw() -- redraw the viewport
17 ) -- closes the yes part of the FOV 60 question
This handles the no/false part of the 2nd if statement.
18 else ( -- opens the no part of the FOV 60 question
19 SetFOV45() -- It wasn't 45, it wasn't 60 so whatever it must be set it to 45
20 print "fov is 45" -- print the change
21 completeRedraw() -- redraw the viewport
22 ) -- end 2nd if
23 ) -- end 1st if
24 ) -- end script
So this asked 2 questions and if they both are no/false and the FOV is none of the settings we want, then the final no/false answer will set the FOV to 45 so the next time the script is run it will answer true and work its way through the options. You can do this with a lot of things and turn what used to be 3-4 separate buttons into 1. This is very handy when you start setting up your own keyboard shortcuts.
Macroscripts are not much more than a header at the top of your script that tells max, instead of running this code like you would if you hit Evaluate (Ctrl-E) to install the script and make it accessible from the Main Menu > Customize > Customize UI menu.
The Macroscript header looks like this:
1 macroScript toggleFOV -- The name of the script that is saved internally
2 category:" MyTools" -- the category it shows up under in the Customize UI menu. Note, I put a space at the beginning so it shows up first in the list.
3 toolTip:"Toggle FOV 45/90" -- the text that pops up when hovering
4 buttonText:"TogFOV" -- the text on the button if one is created
Then you wrap your script in parenthesis () and evaluate it. It will appear as if nothing happened but if you check the Customize UI menu it now appears there. From there you can bind it to keys, assign it to a new toolbar, stick it in the main menu or stuff it in a quad menu.
Note: These scripts are saved deep into the bowels of max typically:
C:/Users/USERNAME/AppData/Local/Autodesk/3dsMax2012/ - 64bit/enu/scripts/
Also know that you can stack a few macroscripts together in one file and when you run it, they will all be added, this is a handy way to get all of your custom scripts installed in one shot, like say... when the yearly upgrade of 3dsmax rolls out. Also know that there are other ways to package scripts together such as drag and drop .mzp files (my personal preference) but that is a discussion for another day.
Below you'll find some helpful links and books that will help you dive deeper. One of the biggest things that has helped me and that I've seen suggested about every time it comes up, is to crack open working scripts and see how they did things. This doesn't mean butcher and steal code without giving credit but to broaden your understanding and figure out how to tackle problems.
I hope that helps you, start to understand something pretty complex but very very helpful to your every day life. You can start to see how some of the annoying little things can be cleared up and minimized. For example it shouldn't be too hard to develop a script that moves your object to the world 0 0 0 point and triggers the FBX export option with your favorite settings and then moves your object back... That would probably save some time when working with UDK...
Related links:
http://www.scriptspot.com/3ds-max/tutorials/maxscript-101-free-online-training
http://www.maxforums.org/threads/dub_maxscript_tutorial_index/0001.aspx
http://www.allanmckay.com/site/index.php/3ds-max/68-maxscript-for-beginners-1
http://www.amazon.com/MAXScript-Essentials-Second-Autodesk-Maxscript/dp/0240809327
Replies
This will get me to give it another shot.
This is so awesome, it made me laught while being informative