General Event Callback Mechanism

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.

Adding Callbacks

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.

Note: When a function is passed to 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.

Note:

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.

Removing Callbacks

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.

Inspecting Callbacks

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.

Additional Notification Information on the Callback:

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

Callback Event Names and notificationParam Return Values

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.

ActionItem Notifications Named Selection Set Notifications
Animation Notifications Node Related Notifications
Direct3D Device Notifications Plug-in Notifications
FileLink Notifications Radiosity Notifications
File Notifications Rendering Notifications
Image Viewer Display Notifications Render Dialog and Renderer Plugin Notifications
Layer System Notifications Schematic Notifications
Manipulate Mode Notification System Notifications
Modifier Panel Notifications Undo System Notifications
Modifier Notifications Xrefs Notifications
Material Library Notifications Other Notifications
Material Notifications

Obsolete Callback Functions

Two functions are still exposed in MAXScript for adding scene open or save callbacks, but are obsolete / deprecated, and should not be used: