MAXScript has full access to the menu manager and menu creation system.
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.
The menu manager is a database of menus and quad menus.
The main menubar and all sub-menus are menu objects.
A quad menu object holds 4 menu objects, one for each quad.
A menu object is a container for menu items.
A menu item can be a separator, an action that invokes a macroScript or a sub-menu that pops up a cascading menu.
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 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.
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!" )
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 ) )