MAXScript allows you to register callback scripts for all of the notification events supported by 3ds Max, such as pre/post scene file open, new, reset, scene file save, pre/post render, selection change, etc.
You can specify any number of callback scripts per notification event.
Callback scripts can be bundled into sets with user-defined IDs and can be deleted by type, by ID or by both.
Callback scripts can be specified as persistent so that they are saved and loaded with the currently open file.
The callbacks are added using the following syntax:
callbacks.addScript <callback_type_name> (<function> | <script_string> | <script_stringstream> | fileName:<filename_string>) [id:<name>] [persistent:<boolean>]
This method is used to register a new callback script. Requires as the first argument a name that specifies which type of notify event this script is associated with. The list of valid callback_type_name
values is listed below.
The script is supplied as a MAXScript function. Any type of function may be supplied: global functions, struct methods, and plug-in methods. Only functions that do not take any parameters, or all parameters have default values, should be registered as callbacks. The addScript()
call will fail if you attempt to add a function that takes parameters. Functions passed as callbacks cannot be persisted, and attempting to call with persisted:true
will fail.
addScript()
, it is effectively held as a unique instance. If the function is later re-defined, it does not change the code executed during the callback. To update the function, it needs to be removed and added again.The script can also be a direct String or StringStream value containing the text of the script to run, or as a fileName:
keyword argument, in which case the named file is loaded and run whenever the event notification callback occurs.
If the full path of the script is not specified, the script is searched for in the user scripts directory and the 3ds Max system scripts directory. As of 3ds Max 2022.1 Update, Windows system directories and directories in the PATH are no longer searched. See File Access Function Search Behavior for a list of directories the filename_string
is searched for if the full path is not specified.
NEW in 3ds Max 2024.2 Update:
The fileName:
keyword argument can be a Python script.
The optional id:
parameter lets you tag one or a group of callbacks with a unique name so that you can remove them all as a group without interfering with other callbacks, perhaps registered by other scripted tools.
The optional persistent:
parameter lets you control whether the script is saved permanently in the currently open scene file or is a global callback script that remains in place no matter what file opening and closing is performed. A true
value for the parameter specifies that the script should be stored in the current file and loaded and registered for callback whenever that file is opened again. Persistent callback scripts are always removed when a new file is loaded or a reset is performed so that persistent scripts in one file don't accidentally get copied to a later file. The default for this parameter is false
, indicating the script is a global script and is not persistent. Function-based callbacks cannot be persisted, and passing with persistent:true
will fail.
EXAMPLES:
callbacks.addScript #preRender "setUpRenderGeom()" id:#jbwRender
This registers a new callback script that will be called just before a render is performed. The script invokes a function (that has presumably already been set up). A unique ID has been assigned to the script for later selective removal.
-- in 3ds Max 2021 and higher
fn myCallback = print "hello"
callbacks.addScript #nodeCreated myCallback id:#myCallbacks
This registers a new callback that is called whenever a node is created. The callback is a previously defined function.
-- in 3ds Max 2024.2 Update and higher
script_name = @"C:\My Documents\scripts\my_python_script.py"
callbacks.addScript #nodeCreated filename:script_name id:#myCallbacks
This is similar to the previous example, except that the callback is a Python script.
callbacks.removeScripts [<callback_type_name>] [id:<name>]
This method is used to unregister and remove one or more callback scripts.
Specifying just a callback event type name removes all the callback scripts for that event type.
Specifying just an id:
removes all callback scripts in all events with that ID.
Specifying both limits the ID-based removal to the specified event type.
callbacks.show [<callback_type_name>] [id:<name>] [to:<stream>] \
[asArray: <boolean>]
This method lists out the current callback scripts or functions in the Listener window, or to an optional stream. Callbacks are listed with their ID, persistent setting, and whether they are loaded from a scene file. If the callback is defined in a string, stringStream or file, the script or filename in which they are defined is also listed. If the callback is defined as a function, the function name, including the struct or plugin it is defined in, is listed.
If the optional callback type name argument is specified in 3ds Max 2009 and higher, only callbacks of that type will be shown.
If the optional keyword argument id:
is specified, only callbacks with that ID will be shown.
If type name and ID are both specified, only callbacks of the type with the given ID will be shown.
Available in 3ds Max 2018.4 and higher: If the optional keyword argument to:
is specified, output from the method is sent to the specified stream.
If the callback definition was loaded from a scene file they are listed as SceneFileEmbedded:true
, and considered embedded scripts. If the Safe Scene Script Execution feature is enabled these types of callbacks are inspected and potentially unsafe commands are blocked from execution.
Available in 3ds Max 2021.3 Update and higher.
If the optional keyword argument asArray:
is specified, the output is returned as an array, with an element for each callback. Available in 3ds Max 2019.3 Update and higher. Each element is an array that contains information about the callback, in this order:
(callback type, callback ID, persistent, is filename, script name, scene file embedded)
Example
-- show callbacks of type #filePreOpen
callbacks.show #filePreOpen
-- output:
filePreOpen:
id:#PhysXPlugin, persistent:false, SceneFileEmbedded:false, script:"px_filePreOpen()"
id:#ALC_SecurityTool, persistent:false, SceneFileEmbedded:false, script:"::ALC_SecurityTool.scenePreOpen()"
id:#ALC2_SecurityTool, persistent:false, SceneFileEmbedded:false, script:"::ALC2_SecurityTool.scenePreOpen()"
id:#CRP_SecurityTool, persistent:false, SceneFileEmbedded:false, script:"::CRP_SecurityTool.m_in_file_open = true;::CRP_SecurityTool.register_post_load_check()"
id:#ADSL_SecurityTool, persistent:false, SceneFileEmbedded:false, script:"::ADSL_SecurityTool.m_in_file_open = true;::ADSL_SecurityTool.register_post_load_check()"
OK
-- the same thing, but as an array:
callbacks.show #filePreOpen asArray:true
-- output:
#(#(#filePreOpen, #PhysXPlugin, false, false, "px_filePreOpen()", false), #(#filePreOpen, #ALC_SecurityTool, false, false, "::ALC_SecurityTool.scenePreOpen()", false), #(#filePreOpen, #ALC2_SecurityTool, false, false, "::ALC2_SecurityTool.scenePreOpen()", false), #(#filePreOpen, #CRP_SecurityTool, false, false, "::CRP_SecurityTool.m_in_file_open = true;::CRP_SecurityTool.register_post_load_check()", false), #(#filePreOpen, #ADSL_SecurityTool, false, false, "::ADSL_SecurityTool.m_in_file_open = true;::ADSL_SecurityTool.register_post_load_check()", false))
-- function defined in a struct:
callbacks.show #nodeCreated
-- output:
nodeCreated:
id:#myCallbacks, persistent:false, SceneFileEmbedded:false, script:"myStruct.myCallback()"
callbacks.broadcastCallback <callback_type_name>
This method provides a way for you to simulate one of the events and have all the callback scripts for it executed.
Within 3ds Max, the #preRenderFrame
and #postRenderFrame
callbacks can only be called by the renderer. These callbacks can not be called by using this method.
callbacks.notificationParam()
This method can be called in a callback script to provide additional information on the callback. The value returned by this method varies based on the callback type. If no additional information was present for the callback, a value of 'undefined' is returned.
EXAMPLE:
--Remove any existing callbacks with this ID.
callbacks.removeScripts id:#MXSHelp
--Add a new callback script which will call
--callbacks.notificationParam() before selected nodes are deleted
--and thus will print the deleted objects to the Listener:
callbacks.addScript #selectedNodesPreDelete" print (callbacks.notificationParam())" id:#MXSHelp
These are all supported the Callback Event Names and the callbacks.notificationParam()
values typically returned. Depending on how the broadcast is generated, a value of 'undefined' may be returned by this method instead of the value shown.
Two functions are still exposed in MAXScript for adding scene open or save callbacks, but are obsolete / deprecated, and should not be used:
setOpenSceneScript()
is replaced by callbacks.addScript()
and #filePreOpen
setSaveSceneScript()
is replaced by callbacks.addScript()
and #filePreSave