Pārlūkot izejas kodu

Merge pull request #1118 from Areloch/MenuBuilderUpdates

Expands functionality of MenuBuilder to act as primary API for building out menus
Brian Roberts 1 gadu atpakaļ
vecāks
revīzija
0a9ba692ed

+ 41 - 939
Engine/source/gui/editor/guiMenuBar.cpp

@@ -143,945 +143,6 @@ IMPLEMENT_CALLBACK( GuiMenuBar, onMenuItemSelect, void, ( S32 menuId, const char
    "@see GuiTickCtrl\n\n"
 );
 
-//------------------------------------------------------------------------------
-// console methods
-//------------------------------------------------------------------------------
-
-/*DefineEngineMethod( GuiMenuBar, clearMenus, void, (),,
-   "@brief Clears all the menus from the menu bar.\n\n"
-   "@tsexample\n"
-   "// Inform the GuiMenuBar control to clear all menus from itself.\n"
-   "%thisGuiMenuBar.clearMenus();\n"
-   "@endtsexample\n\n"
-   "@see GuiTickCtrl")
-{
-   object->clearMenus();
-}
-
-DefineEngineMethod( GuiMenuBar, setMenuMargins, void, (S32 horizontalMargin, S32 verticalMargin, S32 bitmapToTextSpacing),,
-   "@brief Sets the menu rendering margins: horizontal, vertical, bitmap spacing.\n\n"
-   "Detailed description\n\n"
-   "@param horizontalMargin Number of pixels on the left and right side of a menu's text.\n"
-   "@param verticalMargin Number of pixels on the top and bottom of a menu's text.\n"
-   "@param bitmapToTextSpacing Number of pixels between a menu's bitmap and text.\n"
-   "@tsexample\n"
-   "// Define the horizontalMargin\n"
-   "%horizontalMargin = \"5\";\n\n"
-   "// Define the verticalMargin\n"
-   "%verticalMargin = \"5\";\n\n"
-   "// Define the bitmapToTextSpacing\n"
-   "%bitmapToTextSpacing = \"12\";\n\n"
-   "// Inform the GuiMenuBar control to set its margins based on the defined values.\n"
-   "%thisGuiMenuBar.setMenuMargins(%horizontalMargin,%verticalMargin,%bitmapToTextSpacing);\n"
-   "@endtsexample\n\n"
-   "@see GuiTickCtrl")
-{
-   object->mHorizontalMargin = horizontalMargin;
-   object->mVerticalMargin = verticalMargin;
-   object->mBitmapMargin = bitmapToTextSpacing;
-}
-
-DefineEngineMethod(GuiMenuBar, addMenu, void, (const char* menuText, S32 menuId),,
-   "@brief Adds a new menu to the menu bar.\n\n"
-   "@param menuText Text to display for the new menu item.\n"
-   "@param menuId ID for the new menu item.\n"
-   "@tsexample\n"
-   "// Define the menu text\n"
-   "%menuText = \"New Menu\";\n\n"
-   "// Define the menu ID.\n"
-   "%menuId = \"2\";\n\n"
-   "// Inform the GuiMenuBar control to add the new menu\n"
-   "%thisGuiMenuBar.addMenu(%menuText,%menuId);\n"
-   "@endtsexample\n\n"
-   "@see GuiTickCtrl")
-{
-   if(dIsdigit(menuText[0]))
-   {
-      Con::errorf("Cannot add menu %s (id = %s).  First character of a menu's text cannot be a digit.", menuText, menuId);
-      return;
-   }
-   object->addMenu(menuText, menuId);
-}
-
-DefineEngineMethod(GuiMenuBar, addMenuItem, void, (const char* targetMenu, const char* menuItemText, S32 menuItemId, const char* accelerator, int checkGroup, const char *cmd),
-                                     ("","",0,nullAsType<const char*>(),-1,""),
-   "@brief Adds a menu item to the specified menu.  The menu argument can be either the text of a menu or its id.\n\n"
-   "@param menu Menu name or menu Id to add the new item to.\n"
-   "@param menuItemText Text for the new menu item.\n"
-   "@param menuItemId Id for the new menu item.\n"
-   "@param accelerator Accelerator key for the new menu item.\n"
-   "@param checkGroup Check group to include this menu item in.\n"
-   "@tsexample\n"
-   "// Define the menu we wish to add the item to\n"
-   "%targetMenu = \"New Menu\";  or  %menu = \"4\";\n\n"
-   "// Define the text for the new menu item\n"
-   "%menuItemText = \"Menu Item\";\n\n"
-   "// Define the id for the new menu item\n"
-   "%menuItemId = \"3\";\n\n"
-   "// Set the accelerator key to toggle this menu item with\n"
-   "%accelerator = \"n\";\n\n"
-   "// Define the Check Group that this menu item will be in, if we want it to be in a check group. -1 sets it in no check group.\n"
-   "%checkGroup = \"4\";\n\n"
-   "// Inform the GuiMenuBar control to add the new menu item with the defined fields\n"
-   "%thisGuiMenuBar.addMenuItem(%menu,%menuItemText,%menuItemId,%accelerator,%checkGroup);\n"
-   "@endtsexample\n\n"
-   "@see GuiTickCtrl")
-{
-   if(dIsdigit(menuItemText[0]))
-   {
-      Con::errorf("Cannot add menu item %s (id = %s).  First character of a menu item's text cannot be a digit.", menuItemText, menuItemId);
-      return;
-   }
-   GuiMenuBar::Menu *menu = object->findMenu(targetMenu);
-   if(!menu)
-   {
-      Con::errorf("Cannot find menu %s for addMenuItem.", targetMenu);
-      return;
-   }
-   object->addMenuItem(menu, menuItemText, menuItemId, accelerator != NULL ? accelerator : "", checkGroup == -1 ? -1 : checkGroup, cmd);
-}
-
-DefineEngineMethod(GuiMenuBar, setMenuItemEnable, void, (const char* menuTarget, const char* menuItemTarget, bool enabled),,
-   "@brief sets the menu item to enabled or disabled based on the enable parameter.\n"
-   "The specified menu and menu item can either be text or ids.\n\n"
-   "Detailed description\n\n"
-   "@param menuTarget Menu to work in\n"
-   "@param menuItemTarget The menu item inside of the menu to enable or disable\n"
-   "@param enabled Boolean enable / disable value.\n"
-   "@tsexample\n"
-   "// Define the menu\n"
-   "%menu = \"New Menu\";  or  %menu = \"4\";\n\n"
-   "// Define the menu item\n"
-   "%menuItem = \"New Menu Item\";  or %menuItem = \"2\";\n\n"
-   "// Define the enabled state\n"
-   "%enabled = \"true\";\n\n"
-   "// Inform the GuiMenuBar control to set the enabled state of the requested menu item\n"
-   "%thisGuiMenuBar.setMenuItemEnable(%menu,%menuItme,%enabled);\n"
-   "@endtsexample\n\n"
-   "@see GuiTickCtrl")
-{
-   GuiMenuBar::Menu *menu = object->findMenu(menuTarget);
-   if(!menu)
-   {
-      Con::errorf("Cannot find menu %s for setMenuItemEnable.", menuTarget);
-      return;
-   }
-   GuiMenuBar::MenuItem *menuItem = object->findMenuItem(menu, menuItemTarget);
-   if(!menuItem)
-   {
-      Con::errorf("Cannot find menu item %s for setMenuItemEnable.", menuItemTarget);
-      return;
-   }
-   menuItem->enabled = enabled;
-}
-
-DefineEngineMethod(GuiMenuBar, setCheckmarkBitmapIndex, void, (S32 bitmapindex),,
-   "@brief Sets the menu bitmap index for the check mark image.\n\n"
-   "@param bitmapIndex Bitmap index for the check mark image.\n"
-   "@tsexample\n"
-   "// Define the bitmap index\n"
-   "%bitmapIndex = \"2\";\n\n"
-   "// Inform the GuiMenuBar control of the proper bitmap index for the check mark image\n"
-   "%thisGuiMenuBar.setCheckmarkBitmapIndex(%bitmapIndex);\n"
-   "@endtsexample\n\n"
-   "@see GuiTickCtrl")
-{
-   object->mCheckmarkBitmapIndex = bitmapindex;
-}
-
-DefineEngineMethod(GuiMenuBar, setMenuItemChecked, void, (const char* menuTarget, const char* menuItemTarget, bool checked),,
-   "@brief Sets the menu item bitmap to a check mark, which by default is the first element in\n"
-   "the bitmap array (although this may be changed with setCheckmarkBitmapIndex()).\n"
-   "Any other menu items in the menu with the same check group become unchecked if they are checked.\n\n"
-   "@param menuTarget Menu to work in\n"
-   "@param menuItem Menu item to affect\n"
-   "@param checked Whether we are setting it to checked or not\n"
-   "@tsexample\n"
-   ""
-   "@endtsexample\n\n"
-   "@return If not void, return value and description\n\n"
-   "@see References")
-{
-   GuiMenuBar::Menu *menu = object->findMenu(menuTarget);
-   if(!menu)
-   {
-      Con::errorf("Cannot find menu %s for setMenuItemChecked.", menuTarget);
-      return;
-   }
-   GuiMenuBar::MenuItem *menuItem = object->findMenuItem(menu, menuItemTarget);
-   if(!menuItem)
-   {
-      Con::errorf("Cannot find menu item %s for setMenuItemChecked.", menuItemTarget);
-      return;
-   }
-   if(checked && menuItem->checkGroup != -1)
-   {
-      // first, uncheck everything in the group:
-      for(GuiMenuBar::MenuItem *itemWalk = menu->firstMenuItem; itemWalk; itemWalk = itemWalk->nextMenuItem)
-         if(itemWalk->checkGroup == menuItem->checkGroup && itemWalk->bitmapIndex == object->mCheckmarkBitmapIndex)
-            itemWalk->bitmapIndex = -1;
-   }
-   menuItem->bitmapIndex = checked ? object->mCheckmarkBitmapIndex : -1;
-}
-
-DefineEngineMethod(GuiMenuBar, setMenuText, void, (const char* menuTarget, const char* newMenuText),,
-   "@brief Sets the text of the specified menu to the new string.\n\n"
-   "@param menuTarget Menu to affect\n"
-   "@param newMenuText New menu text\n"
-   "@tsexample\n"
-   "// Define the menu to affect"
-   "%menu = \"New Menu\";  or %menu = \"3\";\n\n"
-   "// Define the text to change the menu to\n"
-   "%newMenuText = \"Still a New Menu\";\n\n"
-   "// Inform the GuiMenuBar control to change the defined menu to the defined text\n"
-   "%thisGuiMenuBar.setMenuText(%menu,%newMenuText);\n"
-   "@endtsexample\n\n"
-   "@see GuiTickCtrl")
-{
-   if(dIsdigit(menuTarget[0]))
-   {
-      Con::errorf("Cannot name menu %s to %s.  First character of a menu's text cannot be a digit.", menuTarget, newMenuText);
-      return;
-   }
-   GuiMenuBar::Menu *menu = object->findMenu(menuTarget);
-   if(!menu)
-   {
-      Con::errorf("Cannot find menu %s for setMenuText.", menuTarget);
-      return;
-   }
-   dFree(menu->text);
-   menu->text = dStrdup(newMenuText);
-   object->menuBarDirty = true;
-}
-
-DefineEngineMethod(GuiMenuBar, setMenuBitmapIndex, void, (const char* menuTarget, S32 bitmapindex, bool bitmaponly, bool drawborder),,
-   "@brief Sets the bitmap index for the menu and toggles rendering only the bitmap.\n\n"
-   "@param menuTarget Menu to affect\n"
-   "@param bitmapindex Bitmap index to set for the menu\n"
-   "@param bitmaponly If true, only the bitmap will be rendered\n"
-   "@param drawborder If true, a border will be drawn around the menu.\n"
-   "@tsexample\n"
-   "// Define the menuTarget to affect\n"
-   "%menuTarget = \"New Menu\";  or %menuTarget = \"3\";\n\n"
-   "// Set the bitmap index\n"
-   "%bitmapIndex = \"5\";\n\n"
-   "// Set if we are only to render the bitmap or not\n"
-   "%bitmaponly = \"true\";\n\n"
-   "// Set if we are rendering a border or not\n"
-   "%drawborder = \"true\";\n\n"
-   "// Inform the GuiMenuBar of the bitmap and rendering changes\n"
-   "%thisGuiMenuBar.setMenuBitmapIndex(%menuTarget,%bitmapIndex,%bitmapOnly,%drawBorder);\n"
-   "@endtsexample\n\n"
-   "@see GuiTickCtrl")
-{
-   GuiMenuBar::Menu *menu = object->findMenu(menuTarget);
-   if(!menu)
-   {
-      Con::errorf("Cannot find menu %s for setMenuBitmapIndex.", menuTarget);
-      return;
-   }
-
-   menu->bitmapIndex = bitmapindex;
-   menu->drawBitmapOnly = bitmaponly;
-   menu->drawBorder = drawborder;
-
-   object->menuBarDirty = true;
-}
-
-DefineEngineMethod(GuiMenuBar, setMenuVisible, void, (const char* menuTarget, bool visible),,
-   "@brief Sets the whether or not to display the specified menu.\n\n"
-   "@param menuTarget Menu item to affect\n"
-   "@param visible Whether the menu item will be visible or not\n"
-   "@tsexample\n"
-   "// Define the menu to work with\n"
-   "%menuTarget = \"New Menu\";  or  %menuTarget = \"4\";\n\n"
-   "// Define if the menu should be visible or not\n"
-   "%visible = \"true\";\n\n"
-   "// Inform the GuiMenuBar control of the new visibility state for the defined menu\n"
-   "%thisGuiMenuBar.setMenuVisible(%menuTarget,%visible);\n"
-   "@endtsexample\n\n"
-   "@see GuiTickCtrl")
-{
-   GuiMenuBar::Menu *menu = object->findMenu(menuTarget);
-   if(!menu)
-   {
-      Con::errorf("Cannot find menu %s for setMenuVisible.", menuTarget);
-      return;
-   }
-   menu->visible = visible;
-   object->menuBarDirty = true;
-   object->setUpdate();
-}
-
-DefineEngineMethod(GuiMenuBar, setMenuItemText, void, (const char* menuTarget, const char* menuItemTarget, const char* newMenuItemText),,
-   "@brief Sets the text of the specified menu item to the new string.\n\n"
-   "@param menuTarget Menu to affect\n"
-   "@param menuItem Menu item in the menu to change the text at\n"
-   "@param newMenuItemText New menu text\n"
-   "@tsexample\n"
-   "// Define the menuTarget\n"
-   "%menuTarget = \"New Menu\";  or  %menuTarget = \"4\";\n\n"
-   "// Define the menuItem\n"
-   "%menuItem = \"New Menu Item\";  or  %menuItem = \"2\";\n\n"
-   "// Define the new text for the menu item\n"
-   "%newMenuItemText = \"Very New Menu Item\";\n\n"
-   "// Inform the GuiMenuBar control to change the defined menu item with the new text\n"
-   "%thisGuiMenuBar.setMenuItemText(%menuTarget,%menuItem,%newMenuItemText);\n"
-   "@endtsexample\n\n"
-   "@see GuiTickCtrl")
-{
-   if(dIsdigit(newMenuItemText[0]))
-   {
-      Con::errorf("Cannot name menu item %s to %s.  First character of a menu item's text cannot be a digit.", menuItemTarget, newMenuItemText);
-      return;
-   }
-   GuiMenuBar::Menu *menu = object->findMenu(menuTarget);
-   if(!menu)
-   {
-      Con::errorf("Cannot find menu %s for setMenuItemText.", menuTarget);
-      return;
-   }
-   GuiMenuBar::MenuItem *menuItem = object->findMenuItem(menu, menuItemTarget);
-   if(!menuItem)
-   {
-      Con::errorf("Cannot find menu item %s for setMenuItemText.", menuItemTarget);
-      return;
-   }
-   dFree(menuItem->text);
-   menuItem->text = dStrdup(newMenuItemText);
-}
-
-DefineEngineMethod(GuiMenuBar, setMenuItemVisible, void, (const char* menuTarget, const char* menuItemTarget, bool isVisible),,
-   "@brief Brief Description.\n\n"
-   "Detailed description\n\n"
-   "@param menuTarget Menu to affect the menu item in\n"
-   "@param menuItem Menu item to affect\n"
-   "@param isVisible Visible state to set the menu item to.\n"
-   "@tsexample\n"
-   "// Define the menuTarget\n"
-   "%menuTarget = \"New Menu\";  or  %menuTarget = \"3\";\n\n"
-   "// Define the menuItem\n"
-   "%menuItem = \"New Menu Item\";  or  %menuItem = \"2\";\n\n"
-   "// Define the visibility state\n"
-   "%isVisible = \"true\";\n\n"
-   "// Inform the GuiMenuBarControl of the visibility state of the defined menu item\n"
-   "%thisGuiMenuBar.setMenuItemVisible(%menuTarget,%menuItem,%isVisible);\n"
-   "@endtsexample\n\n"
-   "@see GuiTickCtrl")
-{
-   GuiMenuBar::Menu *menu = object->findMenu(menuTarget);
-   if(!menu)
-   {
-      Con::errorf("Cannot find menu %s for setMenuItemVisible.", menuTarget);
-      return;
-   }
-   GuiMenuBar::MenuItem *menuItem = object->findMenuItem(menu, menuItemTarget);
-   if(!menuItem)
-   {
-      Con::errorf("Cannot find menu item %s for setMenuItemVisible.", menuItemTarget);
-      return;
-   }
-   menuItem->visible = isVisible;
-}
-
-DefineEngineMethod(GuiMenuBar, setMenuItemBitmap, void, (const char* menuTarget, const char* menuItemTarget, S32 bitmapIndex),,
-   "@brief Sets the specified menu item bitmap index in the bitmap array.  Setting the item's index to -1 will remove any bitmap.\n\n"
-   "@param menuTarget Menu to affect the menuItem in\n"
-   "@param menuItem Menu item to affect\n"
-   "@param bitmapIndex Bitmap index to set the menu item to\n"
-   "@tsexample\n"
-   "// Define the menuTarget\n"
-   "%menuTarget = \"New Menu\";  or  %menuTarget = \"3\";\n\n"
-   "// Define the menuItem\"\n"
-   "%menuItem = \"New Menu Item\";  or %menuItem = \"2\";\n\n"
-   "// Define the bitmapIndex\n"
-   "%bitmapIndex = \"6\";\n\n"
-   "// Inform the GuiMenuBar control to set the menu item to the defined bitmap\n"
-   "%thisGuiMenuBar.setMenuItemBitmap(%menuTarget,%menuItem,%bitmapIndex);\n"
-   "@endtsexample\n\n"
-   "@see GuiTickCtrl")
-{
-   GuiMenuBar::Menu *menu = object->findMenu(menuTarget);
-   if(!menu)
-   {
-      Con::errorf("Cannot find menu %s for setMenuItemBitmap.", menuTarget);
-      return;
-   }
-   GuiMenuBar::MenuItem *menuItem = object->findMenuItem(menu, menuItemTarget);
-   if(!menuItem)
-   {
-      Con::errorf("Cannot find menu item %s for setMenuItemBitmap.", menuItemTarget);
-      return;
-   }
-   menuItem->bitmapIndex = bitmapIndex;
-}
-
-DefineEngineMethod(GuiMenuBar, removeMenuItem, void, (const char* menuTarget, const char* menuItemTarget),,
-   "@brief Removes the specified menu item from the menu.\n\n"
-   "@param menuTarget Menu to affect the menu item in\n"
-   "@param menuItem Menu item to affect\n"
-   "@tsexample\n"
-   "// Define the menuTarget\n"
-   "%menuTarget = \"New Menu\";  or %menuTarget = \"3\";\n\n"
-   "// Define the menuItem\n"
-   "%menuItem = \"New Menu Item\";  or  %menuItem = \"5\";\n\n"
-   "// Request the GuiMenuBar control to remove the define menu item\n"
-   "%thisGuiMenuBar.removeMenuItem(%menuTarget,%menuItem);\n\n"
-   "@endtsexample\n\n"
-   "@see GuiTickCtrl")
-{
-   GuiMenuBar::Menu *menu = object->findMenu(menuTarget);
-   if(!menu)
-   {
-      Con::errorf("Cannot find menu %s for removeMenuItem.", menuTarget);
-      return;
-   }
-   GuiMenuBar::MenuItem *menuItem = object->findMenuItem(menu, menuItemTarget);
-   if(!menuItem)
-   {
-      Con::errorf("Cannot find menu item %s for removeMenuItem.", menuItemTarget);
-      return;
-   }
-   object->removeMenuItem(menu, menuItem);
-}
-
-DefineEngineMethod(GuiMenuBar, clearMenuItems, void, (const char* menuTarget),,
-   "@brief Removes all the menu items from the specified menu.\n\n"
-   "@param menuTarget Menu to remove all items from\n"  
-   "@tsexample\n"
-   "// Define the menuTarget\n"
-   "%menuTarget = \"New Menu\";  or %menuTarget = \"3\";\n\n"
-   "// Inform the GuiMenuBar control to clear all menu items from the defined menu\n"
-   "%thisGuiMenuBar.clearMenuItems(%menuTarget);\n"
-   "@endtsexample\n\n"
-   "@see GuiTickCtrl")
-{
-   GuiMenuBar::Menu *menu = object->findMenu(menuTarget);
-   if(!menu)
-   {
-      //Con::errorf("Cannot find menu %s for clearMenuItems.", menuTarget);
-      return;
-   }
-   object->clearMenuItems(menu);
-}
-
-DefineEngineMethod( GuiMenuBar, removeMenu, void, (const char* menuTarget),,
-   "@brief Removes the specified menu from the menu bar.\n\n"
-   "@param menuTarget Menu to remove from the menu bar\n"  
-   "@tsexample\n"
-   "// Define the menuTarget\n"
-   "%menuTarget = \"New Menu\";  or %menuTarget = \"3\";\n\n"
-   "// Inform the GuiMenuBar to remove the defined menu from the menu bar\n"
-   "%thisGuiMenuBar.removeMenu(%menuTarget);\n"
-   "@endtsexample\n\n"
-   "@see GuiTickCtrl")
-{
-   GuiMenuBar::Menu *menu = object->findMenu(menuTarget);
-   if(!menu)
-   {
-      //Con::errorf("Cannot find menu %s for removeMenu.", menuTarget);
-      return;
-   }
-   object->clearMenuItems(menu);
-   object->menuBarDirty = true;
-}
-
-//------------------------------------------------------------------------------
-//  Submenu console methods
-//------------------------------------------------------------------------------
-
-DefineEngineMethod(GuiMenuBar, setMenuItemSubmenuState, void, (const char* menuTarget, const char* menuItem, bool isSubmenu),,
-   "@brief Sets the given menu item to be a submenu.\n\n"
-   "@param menuTarget Menu to affect a submenu in\n"
-   "@param menuItem Menu item to affect\n"
-   "@param isSubmenu Whether or not the menuItem will become a subMenu or not\n"
-   "@tsexample\n"
-   "// Define the menuTarget\n"
-   "%menuTarget = \"New Menu\";  or %menuTarget = \"3\";\n\n"
-   "// Define the menuItem\n"
-   "%menuItem = \"New Menu Item\";  or  %menuItem = \"5\";\n\n"
-   "// Define whether or not the Menu Item is a sub menu or not\n"
-   "%isSubmenu = \"true\";\n\n"
-   "// Inform the GuiMenuBar control to set the defined menu item to be a submenu or not.\n"
-   "%thisGuiMenuBar.setMenuItemSubmenuState(%menuTarget,%menuItem,%isSubmenu);\n"
-   "@endtsexample\n\n"
-   "@see GuiTickCtrl")
-{
-   GuiMenuBar::Menu *menu = object->findMenu(menuTarget);
-   if(!menu)
-   {
-      Con::errorf("Cannot find menu %s for setMenuItemSubmenuState.", menuTarget);
-      return;
-   }
-
-   GuiMenuBar::MenuItem *menuitem = object->findMenuItem(menu, menuItem);
-   if(!menuitem)
-   {
-      Con::errorf("Cannot find menuitem %s for setMenuItemSubmenuState.", menuItem);
-      return;
-   }
-
-   menuitem->isSubmenu = isSubmenu;
-}
-
-DefineEngineMethod(GuiMenuBar, addSubmenuItem, void, (const char* menuTarget, const char* menuItem, const char* submenuItemText, 
-                                         int submenuItemId, const char* accelerator, int checkGroup),,
-   "@brief Adds a menu item to the specified menu.  The menu argument can be either the text of a menu or its id.\n\n"
-   "@param menuTarget Menu to affect a submenu in\n"
-   "@param menuItem Menu item to affect\n"
-   "@param submenuItemText Text to show for the new submenu\n"
-   "@param submenuItemId Id for the new submenu\n"
-   "@param accelerator Accelerator key for the new submenu\n"
-   "@param checkGroup Which check group the new submenu should be in, or -1 for none.\n"
-   "@tsexample\n"
-   "// Define the menuTarget\n"
-   "%menuTarget = \"New Menu\";  or  %menuTarget = \"3\";\n\n"
-   "// Define the menuItem\n"
-   "%menuItem = \"New Menu Item\";  or  %menuItem = \"5\";\n\n"
-   "// Define the text for the new submenu\n"
-   "%submenuItemText = \"New Submenu Item\";\n\n"
-   "// Define the id for the new submenu\n"
-   "%submenuItemId = \"4\";\n\n"
-   "// Define the accelerator key for the new submenu\n"
-   "%accelerator = \"n\";\n\n"
-   "// Define the checkgroup for the new submenu\n"
-   "%checkgroup = \"7\";\n\n"
-   "// Request the GuiMenuBar control to add the new submenu with the defined information\n"
-   "%thisGuiMenuBar.addSubmenuItem(%menuTarget,%menuItem,%submenuItemText,%submenuItemId,%accelerator,%checkgroup);\n"
-   "@endtsexample\n\n"
-   "@see GuiTickCtrl\n")
-{
-   if(dIsdigit(submenuItemText[0]))
-   {
-      Con::errorf("Cannot add submenu item %s (id = %s).  First character of a menu item's text cannot be a digit.", submenuItemText, submenuItemId);
-      return;
-   }
-
-   GuiMenuBar::Menu *menu = object->findMenu(menuTarget);
-   if(!menu)
-   {
-      Con::errorf("Cannot find menu %s for addMenuItem.", menuTarget);
-      return;
-   }
-
-   GuiMenuBar::MenuItem *menuitem = object->findMenuItem(menu, menuItem);
-   if(!menuitem)
-   {
-      Con::errorf("Cannot find menuitem %s for addSubmenuItem.", menuItem);
-      return;
-   }
-
-   object->addSubmenuItem(menu, menuitem, submenuItemText, submenuItemId, !accelerator ? "" : accelerator, checkGroup == -1 ? -1 : checkGroup);
-}
-
-DefineEngineMethod(GuiMenuBar, clearSubmenuItems, void, (const char* menuTarget, const char* menuItem),,
-   "@brief Removes all the menu items from the specified submenu.\n\n"
-   "@param menuTarget Menu to affect a submenu in\n"
-   "@param menuItem Menu item to affect\n"
-   "@tsexample\n"
-   "// Define the menuTarget\n"
-   "%menuTarget = \"New Menu\";  or %menuTarget = \"3\";\n\n"
-   "// Define the menuItem\n"
-   "%menuItem = \"New Menu Item\";  or  %menuItem = \"5\";\n\n"
-   "// Inform the GuiMenuBar to remove all submenu items from the defined menu item\n"
-   "%thisGuiMenuBar.clearSubmenuItems(%menuTarget,%menuItem);\n\n"
-   "@endtsexample\n\n"
-   "@see GuiControl")
-{
-   GuiMenuBar::Menu *menu = object->findMenu(menuTarget);
-   if(!menu)
-   {
-      Con::errorf("Cannot find menu %s for clearSubmenuItems.", menuTarget);
-      return;
-   }
-
-   GuiMenuBar::MenuItem *menuitem = object->findMenuItem(menu, menuItem);
-   if(!menuitem)
-   {
-      Con::errorf("Cannot find menuitem %s for clearSubmenuItems.", menuItem);
-      return;
-   }
-
-   object->clearSubmenuItems(menuitem);
-}
-
-DefineEngineMethod(GuiMenuBar, setSubmenuItemChecked, void, (const char* menuTarget, const char* menuItemTarget, const char* submenuItemText, bool checked),,
-   "@brief Sets the menu item bitmap to a check mark, which by default is the first element in the\n"
-   "bitmap array (although this may be changed with setCheckmarkBitmapIndex()).\n"
-   "Any other menu items in the menu with the same check group become unchecked if they are checked.\n\n"
-   "@param menuTarget Menu to affect a submenu in\n"
-   "@param menuItem Menu item to affect\n"
-   "@param submenuItemText Text to show for submenu\n"
-   "@param checked Whether or not this submenu item will be checked.\n"
-   "@tsexample\n"
-   "// Define the menuTarget\n"
-   "%menuTarget = \"New Menu\";  or %menuTarget = \"3\";\n\n"
-   "// Define the menuItem\n"
-   "%menuItem = \"New Menu Item\";  or  %menuItem = \"5\";\n\n"
-   "// Define the text for the new submenu\n"
-   "%submenuItemText = \"Submenu Item\";\n\n"
-   "// Define if this submenu item should be checked or not\n"
-   "%checked = \"true\";\n\n"
-   "// Inform the GuiMenuBar control to set the checked state of the defined submenu item\n"
-   "%thisGuiMenuBar.setSubmenuItemChecked(%menuTarget,%menuItem,%submenuItemText,%checked);\n"
-   "@endtsexample\n\n"
-   "@return If not void, return value and description\n\n"
-   "@see References")
-{
-   // Find the parent menu
-   GuiMenuBar::Menu *menu = object->findMenu(menuTarget);
-   if(!menu)
-   {
-      Con::errorf("Cannot find menu %s for setSubmenuItemChecked.", menuTarget);
-      return;
-   }
-
-   // Find the parent menu item
-   GuiMenuBar::MenuItem *menuItem = object->findMenuItem(menu, menuItemTarget);
-   if(!menuItem)
-   {
-      Con::errorf("Cannot find menu item %s for setSubmenuItemChecked.", menuItemTarget);
-      return;
-   }
-
-   // Find the submenu item
-   GuiMenuBar::MenuItem *submenuItem = object->findSubmenuItem(menu, menuItemTarget, submenuItemText);
-   if(!submenuItem)
-   {
-      Con::errorf("Cannot find submenu item %s for setSubmenuItemChecked.", submenuItemText);
-      return;
-   }
-
-   if(checked && submenuItem->checkGroup != -1)
-   {
-      // first, uncheck everything in the group:
-      for(GuiMenuBar::MenuItem *itemWalk = menuItem->submenu->firstMenuItem; itemWalk; itemWalk = itemWalk->nextMenuItem)
-         if(itemWalk->checkGroup == submenuItem->checkGroup && itemWalk->bitmapIndex == object->mCheckmarkBitmapIndex)
-            itemWalk->bitmapIndex = -1;
-   }
-   submenuItem->bitmapIndex = checked ? object->mCheckmarkBitmapIndex : -1;
-}
-
-//------------------------------------------------------------------------------
-// menu management methods
-//------------------------------------------------------------------------------
-GuiMenuBar::Menu* GuiMenuBar::sCreateMenu(const char *menuText, U32 menuId)
-{
-   // allocate the menu
-   Menu *newMenu = new Menu;
-   newMenu->text = dStrdup(menuText);
-   newMenu->id = menuId;
-   newMenu->nextMenu = NULL;
-   newMenu->firstMenuItem = NULL;
-   newMenu->visible = true;
-
-   // Menu bitmap variables
-   newMenu->bitmapIndex = -1;
-   newMenu->drawBitmapOnly = false;
-   newMenu->drawBorder = true;
-
-   return newMenu;
-}
-
-void GuiMenuBar::addMenu(GuiMenuBar::Menu *newMenu, S32 pos)
-{
-   // add it to the menu list
-   menuBarDirty = true;
-   if (pos == -1)
-      mMenuList.push_back(newMenu);
-   else
-      mMenuList.insert(pos, newMenu);
-}
-
-void GuiMenuBar::addMenu(const char *menuText, U32 menuId)
-{
-   Menu *newMenu = sCreateMenu(menuText, menuId);
-   
-   addMenu(newMenu);
-}
-
-GuiMenuBar::Menu *GuiMenuBar::findMenu(const char *menu)
-{
-   if(dIsdigit(menu[0]))
-   {
-      U32 id = dAtoi(menu);
-      for (U32 i = 0; i < mMenuList.size(); ++i)
-         if (id == mMenuList[i].id)
-            return mMenuList[i];
-      return NULL;
-   }
-   else
-   {
-      for (U32 i = 0; i < mMenuList.size(); ++i)
-         if (!dStricmp(menu, mMenuList[i].text))
-            return mMenuList[i];
-      return NULL;
-   }
-}
-
-GuiMenuBar::MenuItem *GuiMenuBar::findMenuItem(Menu *menu, const char *menuItem)
-{
-   if(dIsdigit(menuItem[0]))
-   {
-      U32 id = dAtoi(menuItem);
-      for(MenuItem *walk = menu->firstMenuItem; walk; walk = walk->nextMenuItem)
-         if(id == walk->id)
-            return walk;
-      return NULL;
-   }
-   else
-   {
-      for(MenuItem *walk = menu->firstMenuItem; walk; walk = walk->nextMenuItem)
-         if(!dStricmp(menuItem, walk->text))
-            return walk;
-      return NULL;
-   }
-}
-
-void GuiMenuBar::removeMenu(Menu *menu)
-{
-   menuBarDirty = true;
-   clearMenuItems(menu);
-
-   for (U32 i = 0; i < mMenuList.size(); ++i)
-   {
-      if (mMenuList[i] == menu)
-      {
-         mMenuList.erase(i);
-         break;
-      }
-   }
-}
-
-void GuiMenuBar::removeMenuItem(Menu *menu, MenuItem *menuItem)
-{
-   for(MenuItem **walk = &menu->firstMenuItem; *walk; walk = &(*walk)->nextMenuItem)
-   {
-      if(*walk == menuItem)
-      {
-         *walk = menuItem->nextMenuItem;
-         break;
-      }
-   }
-
-   //  If this is a submenu, then be sure to clear the submenu's items
-   if(menuItem->isSubmenu)
-   {
-      clearSubmenuItems(menuItem);
-   }
-
-   dFree(menuItem->text);
-   dFree(menuItem->accelerator);
-   delete menuItem;
-}
-
-GuiMenuBar::MenuItem* GuiMenuBar::addMenuItem(Menu *menu, const char *text, U32 id, const char *accelerator, S32 checkGroup, const char *cmd )
-{
-   // allocate the new menu item
-   MenuItem *newMenuItem = new MenuItem;
-   newMenuItem->text = dStrdup(text);
-   if(accelerator[0])
-      newMenuItem->accelerator = dStrdup(accelerator);
-   else
-      newMenuItem->accelerator = NULL;
-   newMenuItem->cmd = cmd;
-   newMenuItem->id = id;
-   newMenuItem->checkGroup = checkGroup;
-   newMenuItem->nextMenuItem = NULL;
-   newMenuItem->acceleratorIndex = 0;
-   newMenuItem->enabled = text[0] != '-';
-   newMenuItem->visible = true;
-   newMenuItem->bitmapIndex = -1;
-
-   //  Default to not having a submenu
-   newMenuItem->isSubmenu = false;
-   newMenuItem->submenu = NULL;
-   newMenuItem->submenuParentMenu = NULL;
-
-   // link it into the menu's menu item list
-   if(menu)
-   {
-      MenuItem **walk = &menu->firstMenuItem;
-      while(*walk)
-         walk = &(*walk)->nextMenuItem;
-      *walk = newMenuItem;
-   }
-
-   return newMenuItem;
-}
-
-GuiMenuBar::MenuItem* GuiMenuBar::addMenuItem(Menu *menu, MenuItem* newMenuItem)
-{
-   // link it into the menu's menu item list
-   if(menu)
-   {
-      MenuItem **walk = &menu->firstMenuItem;
-      while(*walk)
-         walk = &(*walk)->nextMenuItem;
-      *walk = newMenuItem;
-   }
-
-   return newMenuItem;
-}
-
-void GuiMenuBar::clearMenuItems(Menu *menu)
-{
-   while(menu->firstMenuItem)
-      removeMenuItem(menu, menu->firstMenuItem);
-}
-
-void GuiMenuBar::clearMenus()
-{
-   mMenuList.clear();
-}
-
-void GuiMenuBar::attachToMenuBar(Menu* menu, S32 pos)
-{
-   addMenu(menu, pos);
-}
-
-void GuiMenuBar::removeFromMenuBar(Menu* menu)
-{
-   menuBarDirty = true;
-
-   for (U32 i = 0; i < mMenuList.size(); ++i)
-   {
-      if (mMenuList[i] == menu)
-      {
-         mMenuList.erase(i);
-         break;
-      }
-   }
-}
-
-//------------------------------------------------------------------------------
-//  Submenu methods
-//------------------------------------------------------------------------------
-
-//  This method will return the MenuItem class of of a submenu's menu item given
-// its parent menu and parent menuitem.  If the menuitem ID is used, then the submenu
-// ID must also be used.
-GuiMenuBar::MenuItem *GuiMenuBar::findSubmenuItem(Menu *menu, const char *menuItem, const char *submenuItem)
-{
-   if(dIsdigit(menuItem[0]))
-   {
-      //  Search by ID
-      U32 id = dAtoi(menuItem);
-      for(MenuItem *walk = menu->firstMenuItem; walk; walk = walk->nextMenuItem)
-         if(id == walk->id)
-       {
-          if(walk->isSubmenu && walk->submenu)
-         {
-            return GuiMenuBar::findMenuItem(walk->submenu, submenuItem);
-         }
-         return NULL;
-       }
-      return NULL;
-   }
-   else
-   {
-      //  Search by name
-      for(MenuItem *walk = menu->firstMenuItem; walk; walk = walk->nextMenuItem)
-         if(!dStricmp(menuItem, walk->text))
-       {
-          if(walk->isSubmenu && walk->submenu)
-         {
-            return GuiMenuBar::findMenuItem(walk->submenu, submenuItem);
-         }
-         return NULL;
-       }
-      return NULL;
-   }
-}
-
-GuiMenuBar::MenuItem* GuiMenuBar::findSubmenuItem(MenuItem *menuItem, const char *submenuItem)
-{
-   if( !menuItem->isSubmenu )
-      return NULL;
-
-   return GuiMenuBar::findMenuItem( menuItem->submenu, submenuItem );
-}
-
-//  Add a menuitem to the given submenu
-void GuiMenuBar::addSubmenuItem(Menu *menu, MenuItem *submenu, const char *text, U32 id, const char *accelerator, S32 checkGroup)
-{
-   // Check that the given menu item supports a submenu
-   if(submenu && !submenu->isSubmenu)
-   {
-      Con::errorf("GuiMenuBar::addSubmenuItem: Attempting to add menuitem '%s' to an invalid submenu",text);
-     return;
-   }
-
-   // allocate the new menu item
-   MenuItem *newMenuItem = new MenuItem;
-   newMenuItem->text = dStrdup(text);
-   if(accelerator[0])
-      newMenuItem->accelerator = dStrdup(accelerator);
-   else
-      newMenuItem->accelerator = NULL;
-   newMenuItem->id = id;
-   newMenuItem->checkGroup = checkGroup;
-   newMenuItem->nextMenuItem = NULL;
-   newMenuItem->acceleratorIndex = 0;
-   newMenuItem->enabled = (dStrlen(text) > 1 || text[0] != '-');
-   newMenuItem->visible = true;
-   newMenuItem->bitmapIndex = -1;
-
-   //  Default to not having a submenu
-   newMenuItem->isSubmenu = false;
-   newMenuItem->submenu = NULL;
-
-   //  Point back to the submenu's menu
-   newMenuItem->submenuParentMenu = menu;
-
-   // link it into the menu's menu item list
-   MenuItem **walk = &submenu->submenu->firstMenuItem;
-   while(*walk)
-      walk = &(*walk)->nextMenuItem;
-   *walk = newMenuItem;
-}
-
-void GuiMenuBar::addSubmenuItem(Menu *menu, MenuItem *submenu, MenuItem *newMenuItem )
-{
-   AssertFatal( submenu && newMenuItem, "");
-
-   //  Point back to the submenu's menu
-   newMenuItem->submenuParentMenu = menu;
-
-   // link it into the menu's menu item list
-   MenuItem **walk = &submenu->submenu->firstMenuItem;
-   while(*walk)
-      walk = &(*walk)->nextMenuItem;
-   *walk = newMenuItem;
-}
-
-//  Remove a submenu item
-void GuiMenuBar::removeSubmenuItem(MenuItem *menuItem, MenuItem *submenuItem)
-{
-   // Check that the given menu item supports a submenu
-   if(menuItem && !menuItem->isSubmenu)
-   {
-      Con::errorf("GuiMenuBar::removeSubmenuItem: Attempting to remove submenuitem '%s' from an invalid submenu",submenuItem->text);
-     return;
-   }
-
-   GuiMenuBar::removeMenuItem(menuItem->submenu, submenuItem);
-}
-
-//  Clear all menuitems from a submenu
-void GuiMenuBar::clearSubmenuItems(MenuItem *menuitem)
-{
-   // Check that the given menu item supports a submenu
-   if(menuitem && !menuitem->isSubmenu)
-   {
-      Con::errorf("GuiMenuBar::clearSubmenuItems: Attempting to clear an invalid submenu");
-     return;
-   }
-
-   while(menuitem->submenu->firstMenuItem)
-      removeSubmenuItem(menuitem, menuitem->submenu->firstMenuItem);
-}
-*/
 //------------------------------------------------------------------------------
 // initialization, input and render methods
 //------------------------------------------------------------------------------
@@ -1456,7 +517,10 @@ void GuiMenuBar::insert(SimObject* pObject, S32 pos)
 {
    PopupMenu* menu = dynamic_cast<PopupMenu*>(pObject);
    if (menu == nullptr)
+   {
+      Con::errorf("GuiMenuBar::insert() - attempted to insert non-popupMenu object: %d", pObject->getId());
       return;
+   }
 
    MenuEntry newMenu;
    newMenu.pos = pos >= mMenuList.size() || pos == -1 ? pos = mMenuList.size() : pos;
@@ -1471,6 +535,28 @@ void GuiMenuBar::insert(SimObject* pObject, S32 pos)
       mMenuList.push_back(newMenu);
    else
       mMenuList.insert(pos, newMenu);
+
+   menuBarDirty = true; //ensure we refresh
+}
+
+void GuiMenuBar::remove(SimObject* pObject)
+{
+   PopupMenu* menu = dynamic_cast<PopupMenu*>(pObject);
+   if (menu == nullptr)
+   {
+      Con::errorf("GuiMenuBar::remove() - attempted to remove non-popupMenu object: %d", pObject->getId());
+      return;
+   }
+
+   for(U32 i=0; i < mMenuList.size(); i++)
+   {
+      if(mMenuList[i].popupMenu == menu)
+      {
+                 mMenuList.erase(i);
+         menuBarDirty = true; //ensure we refresh
+         return;
+      }
+   }
 }
 
 PopupMenu* GuiMenuBar::getMenu(U32 index)
@@ -1525,9 +611,25 @@ DefineEngineMethod(GuiMenuBar, getMenu, S32, (S32 index), (0), "(Index)")
 //-----------------------------------------------------------------------------
 DefineEngineMethod(GuiMenuBar, insert, void, (SimObject* pObject, S32 pos), (nullAsType<SimObject*>(), -1), "(object, pos) insert object at position")
 {
+   if(pObject == nullptr)
+   {
+      Con::errorf("GuiMenuBar::insert() - null object");
+      return;
+   }
    object->insert(pObject, pos);
 }
 
+DefineEngineMethod(GuiMenuBar, remove, void, (SimObject* pObject), (nullAsType<SimObject*>()), "(object, pos) remove object")
+{
+   if (pObject == nullptr)
+   {
+      Con::errorf("GuiMenuBar::remove() - null object");
+      return;
+   }
+   object->remove(pObject);
+}
+
+
 DefineEngineMethod(GuiMenuBar, findMenu, S32, (const char* barTitle), (""), "(barTitle)")
 {
    PopupMenu* menu = object->findMenu(barTitle);

+ 1 - 0
Engine/source/gui/editor/guiMenuBar.h

@@ -110,6 +110,7 @@ public:
    void processTick();
 
    void insert(SimObject* pObject, S32 pos);
+   void remove(SimObject* pObject);
 
    static void initPersistFields();
 

+ 20 - 0
Engine/source/gui/editor/guiPopupMenuCtrl.cpp

@@ -210,11 +210,31 @@ bool GuiPopupMenuTextListCtrl::onKeyDown(const GuiEvent &event)
 
 void GuiPopupMenuTextListCtrl::onMouseDown(const GuiEvent &event)
 {
+   if(mLastHighlightedMenuIdx != -1)
+   {
+      //See if we're trying to click on a submenu
+      if(mList[mLastHighlightedMenuIdx].text[1] != 1)
+      {
+         //yep, so abort
+         return;
+      }
+   }
+
    Parent::onMouseDown(event);
 }
 
 void GuiPopupMenuTextListCtrl::onMouseUp(const GuiEvent &event)
 {
+   if (mLastHighlightedMenuIdx != -1)
+   {
+      //See if we're trying to click on a submenu
+      if (mList[mLastHighlightedMenuIdx].text[1] != 1)
+      {
+         //yep, so abort
+         return;
+      }
+   }
+
    Parent::onMouseUp(event);
 
    S32 selectionIndex = getSelectedCell().y;

+ 0 - 485
Templates/BaseGame/game/tools/MainEditor/guis/MainEditorWindow.gui

@@ -1,485 +0,0 @@
-//--- OBJECT WRITE BEGIN ---
-$guiContent = new GuiContainer(NewEditorGui) {
-   margin = "0 0 0 0";
-   padding = "0 0 0 0";
-   anchorTop = "1";
-   anchorBottom = "0";
-   anchorLeft = "1";
-   anchorRight = "0";
-   position = "0 0";
-   extent = "1920 1080";
-   minExtent = "8 8";
-   horizSizing = "right";
-   vertSizing = "bottom";
-   profile = "ToolsGuiDefaultProfile";
-   visible = "1";
-   active = "1";
-   tooltipProfile = "GuiToolTipProfile";
-   hovertime = "1000";
-   isContainer = "1";
-   canSave = "1";
-   canSaveDynamicFields = "1";
-      enabled = "1";
-
-   new GuiSplitContainer(NewEditorGuiLayout) {
-      orientation = "Vertical";
-      splitterSize = "2";
-      splitPoint = "1661 100";
-      fixedPanel = "None";
-      useMinExtent="0";
-      fixedSize = "260";
-      docking = "None";
-      margin = "0 0 0 0";
-      padding = "0 0 0 0";
-      anchorTop = "1";
-      anchorBottom = "0";
-      anchorLeft = "1";
-      anchorRight = "0";
-      position = "0 0";
-      extent = "1921 1081";
-      minExtent = "64 64";
-      horizSizing = "width";
-      vertSizing = "height";
-      profile = "GuiDefaultProfile";
-      visible = "1";
-      active = "1";
-      tooltipProfile = "GuiToolTipProfile";
-      hovertime = "1000";
-      isContainer = "1";
-      canSave = "1";
-      canSaveDynamicFields = "0";
-
-      new GuiPanel() {
-         docking = "Client";
-         margin = "0 0 0 0";
-         padding = "0 0 0 0";
-         anchorTop = "1";
-         anchorBottom = "0";
-         anchorLeft = "1";
-         anchorRight = "0";
-         position = "0 0";
-         extent = "1659 1081";
-         minExtent = "0 0";
-         horizSizing = "right";
-         vertSizing = "bottom";
-         profile = "GuiDefaultProfile";
-         visible = "1";
-         active = "1";
-         tooltipProfile = "GuiToolTipProfile";
-         hovertime = "1000";
-         isContainer = "1";
-         internalName = "Panel1";
-         canSave = "1";
-         canSaveDynamicFields = "0";
-
-         new GuiSplitContainer(Editor_ToolsMainSplit) {
-            orientation = "Vertical";
-            splitterSize = "2";
-            splitPoint = "230 100";
-            fixedPanel = "None";
-            useMinExtent="0";
-            fixedSize = "1429";
-            docking = "None";
-            margin = "0 0 0 0";
-            padding = "0 0 0 0";
-            anchorTop = "1";
-            anchorBottom = "0";
-            anchorLeft = "1";
-            anchorRight = "0";
-            position = "0 0";
-            extent = "1659 1081";
-            minExtent = "64 64";
-            horizSizing = "width";
-            vertSizing = "height";
-            profile = "GuiDefaultProfile";
-            visible = "1";
-            active = "1";
-            tooltipProfile = "GuiToolTipProfile";
-            hovertime = "1000";
-            isContainer = "1";
-            canSave = "1";
-            canSaveDynamicFields = "0";
-
-            new GuiPanel(Editor_ToolSidebarPanel) {
-               docking = "Client";
-               margin = "0 0 0 0";
-               padding = "0 0 0 0";
-               anchorTop = "1";
-               anchorBottom = "0";
-               anchorLeft = "1";
-               anchorRight = "0";
-               position = "0 0";
-               extent = "228 1081";
-               minExtent = "0 0";
-               horizSizing = "right";
-               vertSizing = "bottom";
-               profile = "GuiDefaultProfile";
-               visible = "1";
-               active = "1";
-               tooltipProfile = "GuiToolTipProfile";
-               hovertime = "1000";
-               isContainer = "1";
-               internalName = "Panel1";
-               canSave = "1";
-               canSaveDynamicFields = "0";
-
-               new GuiWindowCtrl(Editor_ToolsSidebarWindow) {
-                  text = "Tool Settings";
-                  resizeWidth = "0";
-                  resizeHeight = "0";
-                  canMove = "0";
-                  canClose = "0";
-                  canMinimize = "0";
-                  canMaximize = "0";
-                  canCollapse = "0";
-                  edgeSnap = "1";
-                  margin = "0 0 0 0";
-                  padding = "0 0 0 0";
-                  anchorTop = "1";
-                  anchorBottom = "0";
-                  anchorLeft = "1";
-                  anchorRight = "0";
-                  position = "0 0";
-                  extent = "228 1081";
-                  minExtent = "8 2";
-                  horizSizing = "width";
-                  vertSizing = "height";
-                  profile = "GuiWindowProfile";
-                  visible = "1";
-                  active = "1";
-                  tooltipProfile = "GuiToolTipProfile";
-                  hovertime = "1000";
-                  isContainer = "1";
-                  canSave = "1";
-                  canSaveDynamicFields = "0";
-               };
-            };
-            new GuiPanel(Editor_MainWindowPanel) {
-               docking = "Client";
-               margin = "0 0 0 0";
-               padding = "0 0 0 0";
-               anchorTop = "1";
-               anchorBottom = "0";
-               anchorLeft = "1";
-               anchorRight = "0";
-               position = "232 0";
-               extent = "1427 1081";
-               minExtent = "0 0";
-               horizSizing = "right";
-               vertSizing = "bottom";
-               profile = "GuiDefaultProfile";
-               visible = "1";
-               active = "1";
-               tooltipProfile = "GuiToolTipProfile";
-               hovertime = "1000";
-               isContainer = "1";
-               internalName = "panel2";
-               canSave = "1";
-               canSaveDynamicFields = "0";
-
-               new GuiSplitContainer(Editor_MainViewSplit) {
-                  orientation = "Horizontal";
-                  splitterSize = "2";
-                  splitPoint = "182 745";
-                  fixedPanel = "None";
-                  useMinExtent="0";
-                  fixedSize = "273";
-                  docking = "None";
-                  margin = "0 0 0 0";
-                  padding = "0 0 0 0";
-                  anchorTop = "1";
-                  anchorBottom = "0";
-                  anchorLeft = "1";
-                  anchorRight = "0";
-                  position = "0 0";
-                  extent = "1427 1081";
-                  minExtent = "64 64";
-                  horizSizing = "width";
-                  vertSizing = "height";
-                  profile = "GuiDefaultProfile";
-                  visible = "1";
-                  active = "1";
-                  tooltipProfile = "GuiToolTipProfile";
-                  hovertime = "1000";
-                  isContainer = "1";
-                  canSave = "1";
-                  canSaveDynamicFields = "0";
-
-                  new GuiPanel(Editor_MainViewPanel) {
-                     docking = "Client";
-                     margin = "0 0 0 0";
-                     padding = "0 0 0 0";
-                     anchorTop = "1";
-                     anchorBottom = "0";
-                     anchorLeft = "1";
-                     anchorRight = "0";
-                     position = "0 0";
-                     extent = "1427 743";
-                     minExtent = "0 0";
-                     horizSizing = "right";
-                     vertSizing = "bottom";
-                     profile = "GuiDefaultProfile";
-                     visible = "1";
-                     active = "1";
-                     tooltipProfile = "GuiToolTipProfile";
-                     hovertime = "1000";
-                     isContainer = "1";
-                     internalName = "Panel1";
-                     canSave = "1";
-                     canSaveDynamicFields = "0";
-
-                     new GuiTabBookCtrl(Editor_MainViewTabBook) {
-                        tabPosition = "Top";
-                        tabMargin = "7";
-                        minTabWidth = "64";
-                        tabHeight = "20";
-                        allowReorder = "0";
-                        defaultPage = "-1";
-                        selectedPage = "-1";
-                        frontTabPadding = "0";
-                        margin = "0 0 0 0";
-                        padding = "0 0 0 0";
-                        anchorTop = "1";
-                        anchorBottom = "0";
-                        anchorLeft = "1";
-                        anchorRight = "0";
-                        position = "0 0";
-                        extent = "1427 743";
-                        minExtent = "8 2";
-                        horizSizing = "width";
-                        vertSizing = "height";
-                        profile = "ToolsGuiTabBookProfile";
-                        visible = "1";
-                        active = "1";
-                        tooltipProfile = "GuiToolTipProfile";
-                        hovertime = "1000";
-                        isContainer = "1";
-                        canSave = "1";
-                        canSaveDynamicFields = "0";
-                     };
-                     new GuiBitmapButtonCtrl(Editor_InspectorSidebarButton) {
-                        bitmap = "tools/gui/images/iconAdd.png";
-                        bitmapMode = "Stretched";
-                        autoFitExtents = "0";
-                        useModifiers = "0";
-                        useStates = "1";
-                        masked = "0";
-                        groupNum = "-1";
-                        buttonType = "PushButton";
-                        useMouseEvents = "0";
-                        position = "1411 61";
-                        extent = "15 15";
-                        minExtent = "8 2";
-                        horizSizing = "left";
-                        vertSizing = "bottom";
-                        profile = "GuiDefaultProfile";
-                        visible = "1";
-                        active = "1";
-                        tooltipProfile = "GuiToolTipProfile";
-                        hovertime = "1000";
-                        isContainer = "0";
-                        canSave = "1";
-                        canSaveDynamicFields = "0";
-                     };
-                     new GuiBitmapButtonCtrl(Editor_ToolsSidebarButton) {
-                        bitmap = "tools/gui/images/iconAdd.png";
-                        bitmapMode = "Stretched";
-                        autoFitExtents = "0";
-                        useModifiers = "0";
-                        useStates = "1";
-                        masked = "0";
-                        groupNum = "-1";
-                        buttonType = "PushButton";
-                        useMouseEvents = "0";
-                        position = "0 61";
-                        extent = "15 15";
-                        minExtent = "8 2";
-                        horizSizing = "right";
-                        vertSizing = "bottom";
-                        profile = "GuiDefaultProfile";
-                        visible = "1";
-                        active = "1";
-                        tooltipProfile = "GuiToolTipProfile";
-                        hovertime = "1000";
-                        isContainer = "0";
-                        canSave = "1";
-                        canSaveDynamicFields = "0";
-                     };
-                     new GuiBitmapButtonCtrl(Editor_AssetBrowserButton) {
-                        bitmap = "tools/gui/images/iconAdd.png";
-                        bitmapMode = "Stretched";
-                        autoFitExtents = "0";
-                        useModifiers = "0";
-                        useStates = "1";
-                        masked = "0";
-                        groupNum = "-1";
-                        buttonType = "PushButton";
-                        useMouseEvents = "0";
-                        position = "1411 725";
-                        extent = "15 15";
-                        minExtent = "8 2";
-                        horizSizing = "left";
-                        vertSizing = "top";
-                        profile = "GuiDefaultProfile";
-                        visible = "1";
-                        active = "1";
-                        tooltipProfile = "GuiToolTipProfile";
-                        hovertime = "1000";
-                        isContainer = "0";
-                        canSave = "1";
-                        canSaveDynamicFields = "0";
-                     };
-                     new GuiBitmapButtonCtrl(Editor_VisibilityOptionsButton) {
-                        bitmap = "tools/gui/images/visible";
-                        bitmapMode = "Stretched";
-                        autoFitExtents = "0";
-                        useModifiers = "0";
-                        useStates = "1";
-                        masked = "0";
-                        groupNum = "-1";
-                        buttonType = "PushButton";
-                        useMouseEvents = "0";
-                        position = "16 30";
-                        extent = "18 18";
-                        minExtent = "8 2";
-                        horizSizing = "right";
-                        vertSizing = "bottom";
-                        profile = "GuiDefaultProfile";
-                        visible = "1";
-                        active = "1";
-                        tooltipProfile = "GuiToolTipProfile";
-                        hovertime = "1000";
-                        isContainer = "0";
-                        canSave = "1";
-                        canSaveDynamicFields = "0";
-                     };
-                  };
-                  new GuiPanel(Editor_AssetBrowserPanel) {
-                     docking = "Client";
-                     margin = "0 0 0 0";
-                     padding = "0 0 0 0";
-                     anchorTop = "1";
-                     anchorBottom = "0";
-                     anchorLeft = "1";
-                     anchorRight = "0";
-                     position = "0 747";
-                     extent = "1427 334";
-                     minExtent = "16 2";
-                     horizSizing = "right";
-                     vertSizing = "bottom";
-                     profile = "GuiDefaultProfile";
-                     visible = "1";
-                     active = "1";
-                     tooltipProfile = "GuiToolTipProfile";
-                     hovertime = "1000";
-                     isContainer = "1";
-                     internalName = "panel2";
-                     canSave = "1";
-                     canSaveDynamicFields = "0";
-                  };
-               };
-            };
-         };
-      };
-      new GuiPanel(Editor_InspectorPanel) {
-         docking = "Client";
-         margin = "0 0 0 0";
-         padding = "0 0 0 0";
-         anchorTop = "1";
-         anchorBottom = "0";
-         anchorLeft = "1";
-         anchorRight = "0";
-         position = "1663 0";
-         extent = "258 1081";
-         minExtent = "0 0";
-         horizSizing = "right";
-         vertSizing = "bottom";
-         profile = "GuiDefaultProfile";
-         visible = "1";
-         active = "1";
-         tooltipProfile = "GuiToolTipProfile";
-         hovertime = "1000";
-         isContainer = "1";
-         internalName = "panel2";
-         canSave = "1";
-         canSaveDynamicFields = "0";
-
-         new GuiSplitContainer() {
-            orientation = "Horizontal";
-            splitterSize = "2";
-            splitPoint = "182 556";
-            fixedPanel = "None";
-            useMinExtent="0";
-            fixedSize = "100";
-            docking = "None";
-            margin = "0 0 0 0";
-            padding = "0 0 0 0";
-            anchorTop = "1";
-            anchorBottom = "0";
-            anchorLeft = "1";
-            anchorRight = "0";
-            position = "0 0";
-            extent = "258 1081";
-            minExtent = "64 64";
-            horizSizing = "right";
-            vertSizing = "bottom";
-            profile = "GuiDefaultProfile";
-            visible = "1";
-            active = "1";
-            tooltipProfile = "GuiToolTipProfile";
-            hovertime = "1000";
-            isContainer = "1";
-            canSave = "1";
-            canSaveDynamicFields = "0";
-
-            new GuiPanel(Editor_SceneTreePanel) {
-               docking = "Client";
-               margin = "0 0 0 0";
-               padding = "0 0 0 0";
-               anchorTop = "1";
-               anchorBottom = "0";
-               anchorLeft = "1";
-               anchorRight = "0";
-               position = "0 0";
-               extent = "258 554";
-               minExtent = "0 0";
-               horizSizing = "right";
-               vertSizing = "bottom";
-               profile = "GuiDefaultProfile";
-               visible = "1";
-               active = "1";
-               tooltipProfile = "GuiToolTipProfile";
-               hovertime = "1000";
-               isContainer = "1";
-               internalName = "Panel1";
-               canSave = "1";
-               canSaveDynamicFields = "0";
-            };
-            new GuiPanel(Editor_PropertiesPanel) {
-               docking = "Client";
-               margin = "0 0 0 0";
-               padding = "0 0 0 0";
-               anchorTop = "1";
-               anchorBottom = "0";
-               anchorLeft = "1";
-               anchorRight = "0";
-               position = "0 558";
-               extent = "258 523";
-               minExtent = "0 0";
-               horizSizing = "right";
-               vertSizing = "bottom";
-               profile = "GuiDefaultProfile";
-               visible = "1";
-               active = "1";
-               tooltipProfile = "GuiToolTipProfile";
-               hovertime = "1000";
-               isContainer = "1";
-               internalName = "panel2";
-               canSave = "1";
-               canSaveDynamicFields = "0";
-            };
-         };
-      };
-   };
-};
-//--- OBJECT WRITE END ---

+ 14 - 0
Templates/BaseGame/game/tools/editorCore/editorCore.module

@@ -0,0 +1,14 @@
+<ModuleDefinition
+	ModuleId="EditorCore"
+	VersionId="1"
+	Description="Core module that acts as the backbone of the editor suite"
+	ScriptFile="editorCore"
+	CreateFunction="onCreate"
+	DestroyFunction="onDestroy"
+	Group="Tools">
+	<DeclaredAssets
+        canSave="true"
+        canSaveDynamicFields="true"
+        Extension="asset.taml"
+        Recurse="true" />
+</ModuleDefinition>

+ 12 - 0
Templates/BaseGame/game/tools/editorCore/editorCore.tscript

@@ -0,0 +1,12 @@
+
+function EditorCore::onCreate(%this)
+{
+   exec("./scripts/menuBar/menuBuilder.ed.tscript");
+   
+   MenuBuilder::init();
+}
+
+function EditorCore::onDestroy(%this)
+{
+   MenuBuilder::clearMenus();
+}

+ 443 - 0
Templates/BaseGame/game/tools/editorCore/scripts/menuBar/menuBuilder.ed.tscript

@@ -0,0 +1,443 @@
+//-----------------------------------------------------------------------------
+// Copyright (c) 2012 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// Menu Builder Helper Class
+//-----------------------------------------------------------------------------
+/// @class MenuBuilder 
+/// @brief Create Dynamic Context and MenuBar Menus
+///
+///
+/// Summary : The MenuBuilder script class exists merely as a helper for creating
+///           popup menu's for use in torque editors.  It is setup as a single 
+///           object with dynamic fields starting with item[0]..[n] that describe
+///           how to create the menu in question.  An example is below.
+///
+/// isPopup : isPopup is a persistent field on PopupMenu console class which
+///           when specified to true will allow you to perform .showPopup(x,y) 
+///           commands which allow popupmenu's to be used/reused as menubar menus
+///           as well as context menus.
+///
+/// barPosition : barPosition indicates which index on the menu bar (0 = leftmost)
+///           to place this menu if it is attached.  Use the attachToMenuBar() command
+///           to attach a menu.
+///
+/// barName : barName specifies the visible name of a menu item that is attached
+///           to the global menubar.
+///
+/// canvas  : The GuiCanvas object the menu should be attached to. This defaults to
+///           the global Canvas object if unspecified.
+///
+/// Remarks : If you wish to use a menu as a context popup menu, isPopup must be 
+///           specified as true at the creation time of the menu.
+///
+/// 
+/// @li @b item[n] (String) TAB (String) TAB (String) : <c>A Menu Item Definition.</c>
+/// @code item[0] = "Open File..." TAB "Ctrl O" TAB "Something::OpenFile"; @endcode
+///
+/// @li @b isPopup (bool) : <c>If Specified the menu will be considered a popup menu and should be used via .showPopup()</c>
+/// @code isPopup = true; @endcode
+///
+///
+/// Example : Creating a @b MenuBar Menu
+/// @code
+/// %%editMenu = new PopupMenu()
+/// {
+///    barPosition = 3;
+///    barName     = "View";
+///    superClass = "MenuBuilder";
+///    item[0] = "Undo" TAB "Ctrl Z" TAB "levelBuilderUndo(1);";
+///    item[1] = "Redo" TAB "Ctrl Y" TAB "levelBuilderRedo(1);";
+///    item[2] = "-";
+/// };
+///
+/// %%editMenu.attachToMenuBar( 1, "Edit" );
+///
+/// @endcode
+///
+///
+/// Example : Creating a @b Context (Popup) Menu
+/// @code
+/// %%contextMenu = new PopupMenu()
+/// {
+///    superClass = MenuBuilder;
+///    isPopup    = true;
+///    item[0] = "My Super Cool Item" TAB "Ctrl 2" TAB "echo(\"Clicked Super Cool Item\");";
+///    item[1] = "-";
+/// };
+///
+/// %%contextMenu.showPopup();
+/// @endcode
+///
+///
+/// Example : Modifying a Menu
+/// @code
+/// %%editMenu = new PopupMenu()
+/// {
+///    item[0] = "Foo" TAB "Ctrl F" TAB "echo(\"clicked Foo\")";
+///    item[1] = "-";
+/// };
+/// %%editMenu.addItem( 2, "Bar" TAB "Ctrl B" TAB "echo(\"clicked Bar\")" );
+/// %%editMenu.removeItem( 0 );
+/// %%editMenu.addItem( 0, "Modified Foo" TAB "Ctrl F" TAB "echo(\"clicked modified Foo\")" );
+/// @endcode
+///
+///
+/// @see PopupMenu
+///
+//------------------------------------------------------------------------------
+
+//==============================================================================
+// Static functions for managing the menus
+
+// Static function
+function MenuBuilder::init()
+{
+   new ArrayObject(MenuBuilderMenuList){};
+}
+
+// Static function
+function MenuBuilder::clearMenus()
+{
+   MenuBuilderMenuList.empty();  
+}
+
+// Static function
+function MenuBuilder::addMenuToMenubar(%menuBar, %menu, %pos)
+{
+   if(%pos $= "")
+      %pos = -1; //if we don't specify, throw it on the end
+      
+   %menuBar.insert(%menu, %pos);
+}
+
+// Static function
+function MenuBuilder::newMenu(%title, %className)
+{
+   if(%title $= "")
+   {
+      error("MenuBuilder::newMenu() - menu requires title!");
+      return 0;  
+   }
+   
+   if(%className $= "")
+      %className = "EditorWorldMenu";
+      
+   %newMenu = new PopupMenu() {
+      superClass = "MenuBuilder";
+      class = %className;
+      barTitle = %title;
+      
+      numItems = 0;
+      isSubmenu = false;
+   };
+   
+   MenuBuilderMenuList.add(%newMenu);
+   
+   return %newMenu;
+}
+
+function MenuBuilder::newItem(%this, %itemLabel, %command, %accelerator, %pos, %icon)
+{
+   if(%pos < 0)
+   {
+      error("MenuBuilder::addItem() - position must be greater than 0!");  
+      return;
+   }
+   
+   if(%pos $= "")
+   {
+      %pos = %this.numItems;
+   }
+   else
+   {
+      //ok, we need to nudge all indexed items up from the insert position and up
+      for(%i = %this.numItems; %i > %pos; %i--)
+      {
+         %this.item[%i+1] = %this.item[%i]; 
+      }
+   }
+   
+   if(isObject(%command))
+      %this.item[%pos] = %itemLabel TAB %command;
+   else      
+      %this.item[%pos] = %itemLabel TAB %accelerator TAB %command TAB %icon;
+   
+   %this.numItems++;
+   
+   %this.reloadItems();
+}
+
+function MenuBuilder::newSubmenu(%this, %title, %className, %pos)
+{
+   if(%title $= "")
+   {
+      error("MenuBuilder::addSubmenu() - menu requires title!");
+      return 0;  
+   }
+   
+   if(%pos < 0)
+   {
+      error("MenuBuilder::addSubmenu() - position must be greater than 0!");  
+      return;
+   }
+   
+   if(%className $= "")
+      %className = "EditorWorldMenu";
+      
+   %newMenu = new PopupMenu() {
+      superClass = "MenuBuilder";
+      class = %className;
+      barTitle = %title;
+      
+      numItems = 0;
+      isSubmenu = true;
+   };
+   
+   %this.newItem(%pos, %title TAB %newMenu);
+   
+   return %newMenu;
+}
+
+function MenuBuilder::newSeparator(%this, %pos)
+{
+   if(%pos < 0)
+   {
+      error("MenuBuilder::addItem() - position must be greater than 0!");  
+      return;
+   }
+   
+   if(%pos $= "")
+   {
+      %pos = %this.numItems;
+   }
+   else
+   {
+      //ok, we need to nudge all indexed items up from the insert position and up
+      for(%i = %this.numItems; %i > %pos; %i--)
+      {
+         %this.item[%i+1] = %this.item[%i]; 
+      }
+   }
+   
+   %this.item[%pos] = "-";
+   %this.numItems++;
+   
+   %this.reloadItems();
+}
+
+// Static function
+function MenuBuilder::findMenu(%title)
+{
+   for(%i=0; %i < MenuBuilderMenuList.count(); %i++)
+   {
+      %menu = MenuBuilderMenuList.getObject(%i);
+      if(%menu.barTitle $= %title)
+      {
+         return %menu;  
+      }
+   }
+   
+   return 0;
+}
+
+function MenuBuilder::findMenu(%this, %title)
+{
+   for(%i=0; %i < %this.numItems; %i++)
+   {
+      %item = %this.item[%i];
+      %menu = getField(%item, 1);
+      if(isObject(%menu))
+      {
+         if(%menu.barTitle $= %title)
+            return %menu;
+      }
+   }
+   
+   return 0;
+}
+
+function MenuBuilder::findItem(%this, %itemLabel)
+{
+   for(%i=0; %i < %this.numItems; %i++)
+   {
+      %item = %this.item[%i];
+      if(getField(%item, 0) $= %itemLabel)
+         return %i;  
+   }
+   
+   return -1;
+}
+//==============================================================================
+//==============================================================================
+// Adds one item to the menu.
+// if %item is skipped or "", we will use %item[#], which was set when the menu was created.
+// if %item is provided, then we update %item[#].
+function MenuBuilder::addItem(%this, %pos, %item)
+{
+   if(%item $= "")
+      %item = %this.item[%pos];
+   
+   if(%item !$= %this.item[%pos])
+      %this.item[%pos] = %item;
+   
+   %name = getField(%item, 0);
+   %accel = getField(%item, 1);
+   %cmd = getField(%item, 2);
+   %bitmapIdx = getField(%item, 3);
+   
+   // We replace the [this] token with our object ID
+   %cmd = strreplace( %cmd, "[this]", %this );
+   %this.item[%pos] = setField( %item, 2, %cmd );
+   
+   if(isObject(%accel))
+   {
+      // If %accel is an object, we want to add a sub menu
+      %this.insertSubmenu(%pos, %name, %accel);
+   }
+   else
+   {
+      %this.insertItem(%pos, %name !$= "-" ? %name : "", %accel, %cmd, %bitmapIdx $= "" ? -1 : %bitmapIdx);
+   }
+}
+
+function MenuBuilder::appendItem(%this, %item)
+{
+   %this.addItem(%this.getItemCount(), %item);
+}
+
+function MenuBuilder::onAdd(%this)
+{
+   if(! isObject(%this.canvas))
+      %this.canvas = Canvas;
+      
+   for(%i = 0;%this.item[%i] !$= "";%i++)
+   {
+      %this.addItem(%i);
+   }
+}
+
+function MenuBuilder::reloadItems(%this)
+{
+   %this.clearItems();
+   
+   for(%i = 0;%this.item[%i] !$= "";%i++)
+   {
+      %this.addItem(%i);
+   }
+}
+
+function MenuBuilder::onRemove(%this)
+{
+   if(%this.isMethod("removeFromMenuBar"))
+      %this.removeFromMenuBar();
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+function MenuBuilder::onSelectItem(%this, %id, %text)
+{
+   %cmd = getField(%this.item[%id], 2);
+   if(%cmd !$= "")
+   {
+      eval( %cmd );
+      return true;
+   }
+   return false;
+}
+
+/// Sets a new name on an existing menu item.
+function MenuBuilder::setItemName( %this, %id, %name )
+{
+   %item = %this.item[%id];
+   %accel = getField(%item, 1);
+   %this.setItem( %id, %name, %accel );
+}
+
+/// Sets a new command on an existing menu item.
+function MenuBuilder::setItemCommand( %this, %id, %command )
+{
+   %this.item[%id] = setField( %this.item[%id], 2, %command );
+}
+
+/// (SimID this)
+/// Wraps the attachToMenuBar call so that it does not require knowledge of
+/// barName or barIndex to be removed/attached.  This makes the individual 
+/// MenuBuilder items very easy to add and remove dynamically from a bar.
+///
+function MenuBuilder::attachToMenuBar( %this )
+{
+   if( %this.barName $= "" )
+   {
+      error("MenuBuilder::attachToMenuBar - Menu property 'barName' not specified.");
+      return false;
+   }
+   
+   if( %this.barPosition < 0 )
+   {
+      error("MenuBuilder::attachToMenuBar - Menu " SPC %this.barName SPC "property 'barPosition' is invalid, must be zero or greater.");
+      return false;
+   }
+   
+   Parent::attachToMenuBar( %this, %this.canvas, %this.barPosition, %this.barName );
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+// Callbacks from PopupMenu. These callbacks are now passed on to submenus
+// in C++, which was previously not the case. Thus, no longer anything to
+// do in these. I am keeping the callbacks in case they are needed later.
+
+function MenuBuilder::onAttachToMenuBar(%this, %canvas, %pos, %title)
+{
+}
+
+function MenuBuilder::onRemoveFromMenuBar(%this, %canvas)
+{
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+/// Method called to setup default state for the menu. Expected to be overriden
+/// on an individual menu basis. See the mission editor for an example.
+function MenuBuilder::setupDefaultState(%this)
+{
+   for(%i = 0;%this.item[%i] !$= "";%i++)
+   {
+      %name = getField(%this.item[%i], 0);
+      %accel = getField(%this.item[%i], 1);
+      %cmd = getField(%this.item[%i], 2);
+      
+      // Pass on to sub menus
+      if(isObject(%accel))
+         %accel.setupDefaultState();
+   }
+}
+
+/// Method called to easily enable or disable all items in a menu.
+function MenuBuilder::enableAllItems(%this, %enable)
+{
+   for(%i = 0; %this.item[%i] !$= ""; %i++)
+   {
+      %this.enableItem(%i, %enable);
+   }
+}

+ 3 - 3
Templates/BaseGame/game/tools/settings.xml

@@ -123,7 +123,7 @@
             <Setting
                 name="documentationReference">../../../Documentation/Torque 3D - Script Manual.chm</Setting>
             <Setting
-                name="documentationURL">http://www.garagegames.com/products/torque-3d/documentation/user</Setting>
+                name="documentationURL">https://docs.torque3d.org</Setting>
         </Group>
         <Group
             name="Library">
@@ -410,9 +410,9 @@
             <Setting
                 name="documentationReference">../../../Documentation/Torque 3D - Script Manual.chm</Setting>
             <Setting
-                name="documentationURL">http://www.garagegames.com/products/torque-3d/documentation/user</Setting>
+                name="documentationURL">https://docs.torque3d.org</Setting>
             <Setting
-                name="forumURL">http://www.garagegames.com/products/torque-3d/forums</Setting>
+                name="forumURL">https://torque3d.org/</Setting>
         </Group>
         <Group
             name="Grid">

+ 1 - 1
Templates/BaseGame/game/tools/tools.tscript

@@ -16,7 +16,7 @@ function ToolsModule::onCreate(%this)
    // to find exactly which subsystems should be readied before kicking things off. 
    // ----------------------------------------------------------------------------
    
-   //ModuleDatabase.LoadExplicit( "MainEditor" );
+   ModuleDatabase.LoadExplicit( "EditorCore" );
    //ModuleDatabase.LoadExplicit( "Tools_ObjectViewer" );
 }
 

+ 12 - 13
Templates/BaseGame/game/tools/worldEditor/scripts/menus.ed.tscript

@@ -364,19 +364,18 @@ function EditorGui::buildMenus(%this)
    %this.menuBar.insert(%toolsMenu);
       
    // Help Menu
-   %helpMenu = new PopupMenu()
-   {
-      superClass = "MenuBuilder";
-      class = "EditorHelpMenu";
-
-      barTitle = "Help";
-
-      item[0] = "Online Documentation..." TAB "Alt F1" TAB "gotoWebPage(EWorldEditor.documentationURL);";
-      item[1] = "Offline User Guide..." TAB "" TAB "gotoWebPage(EWorldEditor.documentationLocal);";
-      item[2] = "Offline Reference Guide..." TAB "" TAB "shellexecute(EWorldEditor.documentationReference);";
-      item[3] = "Torque 3D Forums..." TAB "" TAB "gotoWebPage(EWorldEditor.forumURL);";
-   };
-   %this.menuBar.insert(%helpMenu);
+   %helpMenu = MenuBuilder::newMenu("Help", "EditorHelpMenu");
+   %helpMenu.newItem("Online Documentation...", "gotoWebPage(EWorldEditor.documentationURL);", "Alt F1");
+   %helpMenu.newItem("Offline User Guide...", "gotoWebPage(EWorldEditor.documentationLocal);");
+   %helpMenu.newItem("Offline Reference Guide...", "shellexecute(EWorldEditor.documentationReference);");
+   %helpMenu.newItem("Torque 3D Forums...", "gotoWebPage(EWorldEditor.forumURL);");
+   
+   //These files don't currently exist, so we're going to disable them until such a time
+   //as they exist again
+   %helpMenu.enableItem(1, false);
+   %helpMenu.enableItem(2, false);
+   
+   MenuBuilder::addMenuToMenubar(%this.menubar, %helpMenu);
    
    // Menus that are added/removed dynamically (temporary)