Menu Manager

MAXScript has full access to the menu manager and menu creation system.

Note: Be very careful when using or testing this API. It makes permanent changes to the menu database, and it is very easy to mess things up quite badly. For example, if you "unRegister" the main menu bar, 3ds Max won't start.

Anyone using this API should make a copy of the "..\UI\MaxStartUI.mnu" file before running any of the scripts. If anything messes up, just copy the backup version back on to MaxMenu.mnu.

There are 4 exposed interfaces to MAXScript: the menu manager, menu objects, quad menu objects and menu items.

Menu Manager

menuMan.loadMenuFile "file.mnu"

This loads a new menu file with the given name. It looks in the current "UI" directory for the file. It return true if successful, and false if not.

menuMan.saveMenuFile "file.mnu"

This saves a new menu file with the given name. It saves it in the current "UI" directory.

menuMan.getMenuFile()

Returns the full path to the current menu file.

menuMan.updateMenuBar()

This updates the main menu bar with any changes that have been made. This MUST be called after changing anything on the main menu bar.

menuMan.registerMenuContext contextId

This call is used to register menu extensions. The "contextId" is a random 32-bit integer. It can be generated using the "genclassid()". This function registers an extension with the menu manager that is remembered permanently. It returns true the first time the extension is registered, and false every time thereafter. This is saved in the MaxMenu.mnu file, so it is sticky from session to session. This is used so that scripts can add items and sub-menus MAX's main menu bar and quad menus. See the sample scripts below for the proper usage.

menuMan.findMenu "menuName"

This function returns the menu with the given name. It returns "undefined" if no menu exists in the menu manager with the given name. This requires the full name of the menu, including and "&" characters that might be in the name.

EXAMPLE:

   helpMenu = menuMan.findMenu "&Help" -- Retrieve3ds Max’shelp menu.
menuMan.findQuadMenu "quadMenuName"

This method works like "findMenu" but it gets quad menus instead of menus.

menuMan.unRegisterMenumenu

This method removes a menu from the menu manager.

WARNING! USE EXTREME CAUTION WHEN USING THIS METHOD!

If you unregister a menu that is used as a sub-menu, or in a quad menu, or the main menu bar, you will corrupt your 3ds Max installation.

menuMan.unRegisterQuadMenuquadMenu

This method works like "unregisterMenu" but for quad menus.

menuMan.createMenu "name"

This method creates a new, empty menu with the given name.

menuMan.createQuadMenu "name" "quad1Name" "quad2Name" "quad3Name" "quad4Name"

This method creates a new, empty quad menu. It contains, 4 empty menus, one for each quad.

menuMan.createSubMenuItem "name" subMenu

This method creates a new sub-menu item that can be added to a menu. It uses the given "name" and it displays the given sub-menu.

menuMan.createSeparatorItem()

This method creates a new menu separator that can be added to a menu.

menuMan.createActionItem "macroScriptName" "macroScriptCategory"

This method creates a new menu item that can be added to a menu. The item is an action that executes the macro script with the given name and category. This returns "undefined" if there is no macroScript with the given name and category.

menuMan.setViewportRightClickMenu which quadMenu

This method sets the viewport right click menu to be the given quad menu. The value of "which" can be one of the following:

#nonePressed #shiftPressed #altPressed #controlPressed #shiftAndAltPressed #shiftAndControlPressed #controlAndAltPressed #shiftAndAltAndControlPressed

The following example sets the default (no keys pressed) quad menu the "Modeling 2". The menu name must be a quad menu that is listed in the "Quads" customization dialog, and the name must match exactly, including capitalization. menuMan.SetViewportRightClickMenu returns FALSE if you try to set the viewport right-click menu to a menu that is not allowed.

EXAMPLE:

   menuMan.setViewportRightClickMenu #nonePressed "Modeling 2"
menuMan.getViewportRightClickMenu which

Retrieves the quad menu used for right-clicking in the viewport. The "which" parameter can be one of the following:

 #nonePressed #shiftPressed #altPressed #controlPressed #shiftAndAltPressed #shiftAndControlPressed #controlAndAltPressed #shiftAndAltAndControlPressed menuMan.getMainMenuBar()

Returns the menu being used as MAX's main menu bar.

menuMan.setMainMenuBar menu

Sets the menu being used as MAX's main menu bar. You must call "menuMan.updateMenuBar()" in order to see the result.

menuMan.getShowAllQuads quadMenu

Gets the "show all quads" setting for the given quad menu.

menuMan.setShowAllQuads quadMenu value

This sets the "show all quads" flag for the given quad menu. "value" can be true or false .

menuMan.getQuadMenuName quadMenu

This returns the name of the given quad menu.

menuMan.setQuadMenuName quadMenu "name"

This sets the name of the give quad menu.

menuMan.numMenus()

Returns the total number of menus in registered with the menu manager.

menuMan.getMenu index

Retrieves the "index"th menu in the menu manager. This is a 1-based index.

menuMan.numQuadMenus()

Returns the total number of quad menus registered with the menu manager.

menuMan.getQuadMenu index

Retrieves the "index"th quad menu in the menu manager. This is a 1-based index.

Quad Menu objects

Quad menu objects have the following functions available:

quadMenu.getMenu quadIndex

Retrieves the menu object associated with the 4 quads of the menu. "quadIndex" can take the value 0, 1, 2, or 3. Quad 0 is the lower-right, and they are numbered counter-clockwise from there.

quadMenu.trackMenu showAllQuads

This displays the quad menu. If "showAllQuads" is true, then all 4 quads are shows at once. It is displayed at the current cursor position.

Menus are containers for menu items, and have the following functions:

menu.setTitle "title"

Sets the title of the menu to the give string.

menu.getTitle()

Returns the current title of the menu.

menu.numItems()

Returns the number of items the menu holds.

menu.getItem index

Retrieves the menu item at the given index.

Note:

The index is 0-based.

menu.addItem menuItem position

This inserts an item in the menu at the given position, which is 0-based. If the position is -1, then the item is appended to the end of the menu.

menu.removeItemByPosition position

This removes the item at the given position.

menu.removeItem menuItem

This removes the given item from the menu, if it is in the menu.

A menu item can be a separator, a sub-menu or an action that is connected to a macroScript. The following functions are available for menuItems:

menuItem.setTitle "title"

Sets the name associated with the item.

menuItem.getTitle()

Returns the name associated with the item.

menuItem.setUseCustomTitle value

When value is true, this tells an item that is associated with a macroScript to use the item title when displaying the menu. Otherwise it will use the name of the macro or the "buttontext" of the macroScript.

menuItem.getUseCustomTitle()

Returns the current value of the custom title flag.

menuItem.setDisplayFlat value

This is for sub-menu items. When value is true, it tells the menu to display the sub-menu in-line, rather than as a cascading sub-menu.

menuItem.getDisplayFlat()

Returns the current value for the "display flat" flag.

menuItem.getIsSeparator()

Return true if the item is a separator, and false otherwise.

menuItem.getSubMenu()

If the item is a sub-menu item, this returns the menu associated with the sub-menu.

Included below is a script that shows how to use the menuMan interface to register menu extensions. This script should go in the "stdplugs\stdscripts" folder.

EXAMPLE:

   -- Sample menu extension script
   -- If this script is placed in the "stdplugs\stdscripts"
   -- folder, then this will add the new items to MAX's menu bar
   -- when MAX starts.
   -- A sample macroScript that we will attach to a menu item
   macroScript MyTest
   category: "Menu Test"
   tooltip: "Test Menu Item"
   (
   on execute do print "Hello World!"
   )
Note: The macroScript above must be present before running the example below.

EXAMPLE:

   -- This example adds a new entry to MAX's main "Help" menu.
   -- Register a menu context. This returns true the first time it
   -- is registered, and we can add things to the menu. If
   -- it returns false, then the context is already registered,
   -- and the items are already in the menu.
   -- The number 0x246c6dbe is random, and can be generated
   -- using the genClassID() function. 
   if menuMan.registerMenuContext 0x246c6dbe then
   (
   -- Get the main menu bar
   local mainMenuBar = menuMan.getMainMenuBar()
   -- The help menu is always the last menu.
   local helpMenuIndex = mainMenuBar.numItems()
   -- Get the menu item that holds the help menu
   local helpMenuItem = mainMenuBar.getItem(helpMenuIndex)
   -- Get the menu from the item
   local helpMenu = helpMenuItem.getSubMenu()
   -- create a menu separator item
   local sepItem = menuMan.createSeparatorItem()
   -- create a menu items that calls the sample macroScript
   local testItem = menuMan.createActionItem "MyTest" "Menu Test"
   -- Add the separator to the end of the help menu.
   -- the position of -1 means add it to the end.
   helpMenu.addItem sepItem -1
   -- Add the action item to the end of the help menu.
   helpMenu.addItem testItem -1
   -- redraw the menu bar with the new item
   menuMan.updateMenuBar()
   )

EXAMPLE:

   -- This example adds a new sub-menu to MAX's main menu bar.
   -- It adds the menu just before the "Help" menu.
   if menuMan.registerMenuContext 0x1ee76d8e then
   (
   -- Get the main menu bar
   local mainMenuBar = menuMan.getMainMenuBar()
   -- Create a new menu
   local subMenu = menuMan.createMenu "Test Menu"
   -- create a menu item that calls the sample macroScript
   local testItem = menuMan.createActionItem "MyTest" "Menu Test"
   -- Add the item to the menu
   subMenu.addItem testItem -1
   -- Create a new menu item with the menu as it's sub-menu
   local subMenuItem = menuMan.createSubMenuItem "Test Menu" subMenu
   -- compute the index of the next-to-last menu item in the main menu bar
   local subMenuIndex = mainMenuBar.numItems() - 1
   -- Add the sub-menu just at the second to last slot
   mainMenuBar.addItem subMenuItem subMenuIndex
   -- redraw the menu bar with the new item
   menuMan.updateMenuBar()
   )

EXAMPLE:

   -- This example adds a new command to MAX's default right-click quad menu
   if menuMan.registerMenuContext 0x36690115 then
   (
   -- Get the default viewport right-click quad menu
   local quadMenu = menuMan.getViewportRightClickMenu #nonePressed
   -- Get the lower-left menu from the quad
   local menu = quadMenu.getMenu 3
   -- create a menu item that calls the sample macroScript
   local testItem = menuMan.createActionItem "MyTest" "Menu Test"
   -- Add the item to the menu
   menu.addItem testItem -1
   )

Here are two macroScripts that set and reset two of the right-click menus:

   macroScript SetQuads
   category:"Custom UI"
   tooltip:"Set Quad"
   (
   on execute do
   (
   quadmenu = menuMan.findQuadMenu "Modeling 2"
   if quadmenu != undefined do menuMan.setViewportRightClickMenu #nonePressed quadmenu
   quadmenu = menuMan.findQuadMenu "Sample 4x1"
   menuMan.setViewportRightClickMenu #controlPressed quadmenu
   )
   )
   macroScript ResetQuads
   category:"Custom UI"
   tooltip:"Reset Quads"
   (
   on execute do
   (
   quadmenu = menuMan.findQuadMenu "Default Viewport Quad"
   if quadmenu != undefined do menuMan.setViewportRightClickMenu #nonePressed quadmenu
   quadmenu = menuMan.findQuadMenu "Modeling 1 [Cntrl+RMB]"
   if quadmenu != undefined do menuMan.setViewportRightClickMenu #controlPressed quadmenu
   )
   )