Not that I’m doing it right, but I’ve taken inspiration from python package structure to organize my maxscript content.
I’ve got a script which gets called from Max upon startup (You need to point Max to this via installer or by manually editing configs). This file is always executed upon every launch (think “sitecustomize.py”). In the startup script, I define a few global variables which define relative directories from which I know the entire install base for everything contained therein. I personally store:
[LIST=3]
[li]The location of the currently running startup script so I know where the user installed my external source files[/li][li]A path to the root of my tools based on parsing the result of #1[/li][li]A path to the actual folder which is the root of all Max scripts (since the tools folder doesn’t just contain Max only content)[/li][/LIST]
For example:
-- Packages paths based on introspection of "RobotArtTools"
ROBOT_STARTUP_ROOT = getFilenamePath(getThisScriptFilename())
ROBOT_ARTTOOLS_ROOT = substring ROBOT_STARTUP_ROOT 1 ((findString ROBOT_STARTUP_ROOT "RobotArtTools")+"RobotArtTools".count)
ROBOT_SCRIPTS_ROOT = pathConfig.appendPath ROBOT_ARTTOOLS_ROOT "MAX/Scripts/"
Once I know where each of these directories live, I know the entire layout of my custom library, and can get to anywhere by starting from one of the variables above. Also in the startup script is a function to load any package (folder of max scripts) I tell it to assuming package modules end with a valid .ms or .mcr extension.
fn load_package root =
--
-- Discovers all ".ms" files recursively below the provided root directoy
-- and loads them into memory for immediate use.
--
-- :param root: Path to the package directory
-- :type root: String
--
(
-- TODO: Type load logic here :)
)
The last part of the startup script uses an array of hard coded packages names which I always load at startup. This could be configured via .ini or likewise and located via instrospection if so desired, but I haven’t done that as of yet. I call the “load_package” function and that tears through all the folders, locates the script files, and pulls them into memory using filein command.
packages = #()
append packages (pathConfig.appendPath ROBOT_SCRIPTS_ROOT "robotools/")
append packages (pathConfig.appendPath ROBOT_SCRIPTS_ROOT "external/")
append packages (pathConfig.appendPath ROBOT_SCRIPTS_ROOT "legacy/")
for package in packages do
(
load_package package
)
In order for this to work, all modules in a package (maxscript in a folder) are unqiuely named as to not name clash. I name them after the type of functions they hold, IE: “roboanim.ms” holds functions related to animation tasks. Each function (def) in my module (maxscript file) have names which are prefixed to match the name I used for the package (folder that holds the scripts), IE: def roboanim_bake() is found in module (script) roboanim.ms in package (folder) “robotools”.
At the top of each modules (maxscript) I have a few calls to other modules which must be sourced into memory so that the current module functions run properly (think python includes). For example, module roboanim.ms has a first line that reads:
filein (ROBOT_SCRIPTS_ROOT + "/robotools/lib/robonode.ms")
because there are a bunch of calls to functions related to node manipulation.
I haven’t done much with UI yet, but I can tell you that it’s fantastic to separate code used to generate UI from code driven by UI callbacks. Then when your UI crashes it’s a matter of rebuilding the UI and not having to restart max because the whole function is borked.
Hope this helps. I’d like to hear other input as well as I’ve arrived here coming from a Maya python background.
-csa