Browse Source

Expands functionality of MenuBuilder to act as primary API for building out menus
Shifts "Help" menubar entry in world editor to use new API structure as example/test
Removes extraneous 'MainEditor'
Adds EditorCore module
Moved Menubuilder to EditorCore module
Fixes Help Menu editor settings so they properly point at modern documentation and forum URLs
Fixes handling of MenuBar so when inserting new items, ensures the menubar refreshes as would be expected
Adds remove function to menubar to remove a menu
Removes old commented console methods from menubar file
Adds checks for onMouseDown and onMouseUp for PopupMenu so items that are submenus aren't clickable like normal items

Areloch 1 năm trước cách đây
mục cha
commit
c2d1e9d654

+ 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)