소스 검색

Merge pull request #2118 from Areloch/MenuAndPopups

Refactors the Popup menus and GuiMenuBars
Areloch 7 년 전
부모
커밋
c23c99dbea
30개의 변경된 파일977개의 추가작업 그리고 3098개의 파일을 삭제
  1. 39 24
      Engine/source/gui/core/guiCanvas.cpp
  2. 1 0
      Engine/source/gui/core/guiCanvas.h
  3. 194 678
      Engine/source/gui/editor/guiMenuBar.cpp
  4. 35 141
      Engine/source/gui/editor/guiMenuBar.h
  5. 85 21
      Engine/source/gui/editor/guiPopupMenuCtrl.cpp
  6. 13 5
      Engine/source/gui/editor/guiPopupMenuCtrl.h
  7. 506 0
      Engine/source/gui/editor/popupMenu.cpp
  8. 56 61
      Engine/source/gui/editor/popupMenu.h
  9. 0 127
      Engine/source/platform/menus/menuBar.cpp
  10. 0 71
      Engine/source/platform/menus/menuBar.h
  11. 0 269
      Engine/source/platform/menus/popupMenu.cpp
  12. 0 35
      Engine/source/platformSDL/menus/PlatformSDLPopupMenuData.h
  13. 0 51
      Engine/source/platformSDL/menus/guiPlatformGenericMenuBar.h
  14. 0 200
      Engine/source/platformSDL/menus/menuBarSDL.cpp
  15. 0 393
      Engine/source/platformSDL/menus/popupMenuSDL.cpp
  16. 0 177
      Engine/source/platformWin32/menus/menuBarWin32.cpp
  17. 0 746
      Engine/source/platformWin32/menus/popupMenuWin32.cpp
  18. 0 1
      Engine/source/windowManager/sdl/sdlWindow.cpp
  19. 0 1
      Templates/BaseGame/game/tools/gui/guiDialogs.ed.cs
  20. 0 19
      Templates/BaseGame/game/tools/gui/guiPlatformGenericMenubar.ed.cs
  21. 0 14
      Templates/BaseGame/game/tools/gui/guiPlatformGenericMenubar.ed.gui
  22. 5 1
      Templates/BaseGame/game/tools/guiEditor/scripts/guiEditorCanvas.ed.cs
  23. 1 1
      Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.cs
  24. 18 13
      Templates/BaseGame/game/tools/worldEditor/scripts/menus.ed.cs
  25. 0 1
      Templates/Full/game/tools/gui/guiDialogs.ed.cs
  26. 0 19
      Templates/Full/game/tools/gui/guiPlatformGenericMenubar.ed.cs
  27. 0 14
      Templates/Full/game/tools/gui/guiPlatformGenericMenubar.ed.gui
  28. 5 1
      Templates/Full/game/tools/guiEditor/scripts/guiEditorCanvas.ed.cs
  29. 1 1
      Templates/Full/game/tools/worldEditor/scripts/EditorGui.ed.cs
  30. 18 13
      Templates/Full/game/tools/worldEditor/scripts/menus.ed.cs

+ 39 - 24
Engine/source/gui/core/guiCanvas.cpp

@@ -276,8 +276,6 @@ bool GuiCanvas::onAdd()
    // Define the menu bar for this canvas (if any)
    Con::executef(this, "onCreateMenu");
 
-   Sim::findObject("PlatformGenericMenubar", mMenuBarCtrl);
-
    return parentRet;
 }
 
@@ -302,21 +300,39 @@ void GuiCanvas::setMenuBar(SimObject *obj)
         Parent::removeObject( oldMenuBar );
 
     // set new menubar    
-    if( mMenuBarCtrl )
-        Parent::addObject(mMenuBarCtrl);
+    if (mMenuBarCtrl)
+    {
+       //Add a wrapper control so that the menubar sizes correctly
+       GuiControlProfile* profile;
+       Sim::findObject("GuiModelessDialogProfile", profile);
+
+       if (!profile)
+       {
+          Con::errorf("GuiCanvas::setMenuBar: Unable to find the GuiModelessDialogProfile profile!");
+          return;
+       }
+
+       GuiControl* menuBackground = new GuiControl();
+       menuBackground->registerObject();
+
+       menuBackground->setControlProfile(profile);
+
+       menuBackground->addObject(mMenuBarCtrl);
+
+       Parent::addObject(menuBackground);
+    }
 
     // update window accelerator keys
     if( oldMenuBar != mMenuBarCtrl )
     {
-        StringTableEntry ste = StringTable->insert("menubar");
-        GuiMenuBar* menu = NULL;
-        menu = !oldMenuBar ? NULL : dynamic_cast<GuiMenuBar*>(oldMenuBar->findObjectByInternalName( ste, true));
-        if( menu )
-            menu->removeWindowAcceleratorMap( *getPlatformWindow()->getInputGenerator() );
-
-        menu = !mMenuBarCtrl ? NULL : dynamic_cast<GuiMenuBar*>(mMenuBarCtrl->findObjectByInternalName( ste, true));
-        if( menu )
-                menu->buildWindowAcceleratorMap( *getPlatformWindow()->getInputGenerator() );
+        GuiMenuBar* oldMenu = dynamic_cast<GuiMenuBar*>(oldMenuBar);
+        GuiMenuBar* newMenu = dynamic_cast<GuiMenuBar*>(mMenuBarCtrl);
+
+        if(oldMenu)
+           oldMenu->removeWindowAcceleratorMap(*getPlatformWindow()->getInputGenerator());
+
+        if(newMenu)
+           newMenu->buildWindowAcceleratorMap(*getPlatformWindow()->getInputGenerator());
     }
 }
 
@@ -1633,27 +1649,26 @@ void GuiCanvas::maintainSizing()
       Point2I newPos = screenRect.point;
 
       // if menubar is active displace content gui control
-      if( mMenuBarCtrl && (ctrl == getContentControl()) )
-      {          
-          const SimObject *menu = mMenuBarCtrl->findObjectByInternalName( StringTable->insert("menubar"), true);
+      if (mMenuBarCtrl && (ctrl == getContentControl()))
+      {
+         /*const SimObject *menu = mMenuBarCtrl->findObjectByInternalName( StringTable->insert("menubar"), true);
 
-          if( !menu )
-              continue;
+         if( !menu )
+             continue;
 
-          AssertFatal( dynamic_cast<const GuiControl*>(menu), "");
+         AssertFatal( dynamic_cast<const GuiControl*>(menu), "");*/
 
-          const U32 yOffset = static_cast<const GuiControl*>(menu)->getExtent().y;
-          newPos.y += yOffset;
-          newExt.y -= yOffset;
+         const U32 yOffset = static_cast<const GuiMenuBar*>(mMenuBarCtrl)->mMenubarHeight;
+         newPos.y += yOffset;
+         newExt.y -= yOffset;
       }
 
-      if(pos != newPos || ext != newExt)
+      if (pos != newPos || ext != newExt)
       {
          ctrl->resize(newPos, newExt);
          resetUpdateRegions();
       }
    }
-
 }
 
 void GuiCanvas::setupFences()

+ 1 - 0
Engine/source/gui/core/guiCanvas.h

@@ -210,6 +210,7 @@ public:
    virtual void onRemove();
 
    void setMenuBar(SimObject *obj);
+   SimObject* getMenuBar() { return mMenuBarCtrl; }
 
    static void initPersistFields();
 

+ 194 - 678
Engine/source/gui/editor/guiMenuBar.cpp

@@ -142,24 +142,11 @@ IMPLEMENT_CALLBACK( GuiMenuBar, onMenuItemSelect, void, ( S32 menuId, const char
    "@see GuiTickCtrl\n\n"
 );
 
-IMPLEMENT_CALLBACK( GuiMenuBar, onSubmenuSelect, void, ( S32 submenuId, const char* submenuText ),( submenuId, submenuText ),
-   "@brief Called whenever a submenu is selected.\n\n"
-   "@param submenuId Id of the selected submenu\n"
-   "@param submenuText Text of the selected submenu\n\n"
-   "@tsexample\n"
-   "GuiMenuBar::onSubmenuSelect(%this,%submenuId,%submenuText)\n"
-   "{\n"
-   "  // Code to run when the callback occurs\n"
-   "}\n"
-   "@endtsexample\n\n"
-   "@see GuiTickCtrl\n\n"
-);
-
 //------------------------------------------------------------------------------
 // console methods
 //------------------------------------------------------------------------------
 
-DefineEngineMethod( GuiMenuBar, clearMenus, void, (),,
+/*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"
@@ -818,14 +805,14 @@ GuiMenuBar::Menu *GuiMenuBar::findMenu(const char *menu)
    {
       U32 id = dAtoi(menu);
       for (U32 i = 0; i < mMenuList.size(); ++i)
-         if (id == mMenuList[i]->id)
+         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))
+         if (!dStricmp(menu, mMenuList[i].text))
             return mMenuList[i];
       return NULL;
    }
@@ -1093,19 +1080,18 @@ void GuiMenuBar::clearSubmenuItems(MenuItem *menuitem)
    while(menuitem->submenu->firstMenuItem)
       removeSubmenuItem(menuitem, menuitem->submenu->firstMenuItem);
 }
-
+*/
 //------------------------------------------------------------------------------
 // initialization, input and render methods
 //------------------------------------------------------------------------------
 
 GuiMenuBar::GuiMenuBar()
 {
-   mMenuList.clear();
+   //mMenuList.clear();
    menuBarDirty = true;
    mouseDownMenu = NULL;
    mouseOverMenu = NULL;
    mCurAcceleratorIndex = 0;
-   mBackground = NULL;
    mPadding = 0;
 
    mCheckmarkBitmapIndex = 0; // Default to the first image in the bitmap array for the check mark
@@ -1114,21 +1100,28 @@ GuiMenuBar::GuiMenuBar()
    mVerticalMargin = 1;   // Default number of pixels on the top and bottom of a menu's text
    mBitmapMargin = 2;     // Default number of pixels between a menu's bitmap and text
 
+   mMenubarHeight = 20;
+
    //  Added:
    mouseDownSubmenu = NULL;
    mouseOverSubmenu = NULL;
-   mSubmenuBackground = NULL;
-   mSubmenuTextList = NULL;
-   mMouseOverCounter = 0;
-   mCountMouseOver = false;
-   mMouseHoverAmount = 30;
+
+   mMouseInMenu = false;
+
    setProcessTicks(false);
 }
 
+void GuiMenuBar::onRemove()
+{
+   Parent::onRemove();
+}
+
 void GuiMenuBar::initPersistFields()
 {
    addField("padding", TypeS32, Offset( mPadding, GuiMenuBar ),"Extra padding to add to the bounds of the control.\n");
 
+   addField("menubarHeight", TypeS32, Offset(mMenubarHeight, GuiMenuBar), "Sets the height of the menubar when attached to the canvas.\n");
+
    Parent::initPersistFields();
 }
 
@@ -1153,52 +1146,75 @@ bool GuiMenuBar::onWake()
    return true;
 }
 
-GuiMenuBar::Menu *GuiMenuBar::findHitMenu(Point2I mousePoint)
+void GuiMenuBar::addObject(SimObject* object)
+{
+   PopupMenu* popup = dynamic_cast<PopupMenu*>(object);
+
+   if (!popup)
+   {
+      //if it's not a popup, handle it normally
+      Parent::addObject(object);
+   }
+   else
+   {
+      //otherwise, if it IS a popup, don't add it as a child object, but instead just insert it as a menu entry
+      insert(object, -1);
+   }
+}
+
+GuiMenuBar::MenuEntry *GuiMenuBar::findHitMenu(Point2I mousePoint)
 {
    Point2I pos = globalToLocalCoord(mousePoint);
 
    for (U32 i = 0; i < mMenuList.size(); ++i)
-      if (mMenuList[i]->visible && mMenuList[i]->bounds.pointInRect(pos))
-         return mMenuList[i];
+   {
+      if (mMenuList[i].visible && mMenuList[i].bounds.pointInRect(pos))
+         return &mMenuList[i];
+   }
+
    return NULL;
 }
 
 void GuiMenuBar::onPreRender()
 {
+   setHeight(mMenubarHeight);
+
    Parent::onPreRender();
-   if(menuBarDirty)
+   if (menuBarDirty)
    {
       menuBarDirty = false;
       U32 curX = mPadding;
       for (U32 i = 0; i < mMenuList.size(); ++i)
       {
-         if (!mMenuList[i]->visible)
+         if (!mMenuList[i].visible)
             continue;
 
-       // Bounds depends on if there is a bitmap to be drawn or not
-         if (mMenuList[i]->bitmapIndex == -1)
-       {
+         // Bounds depends on if there is a bitmap to be drawn or not
+         if (mMenuList[i].bitmapIndex == -1)
+         {
             // Text only
-            mMenuList[i]->bounds.set(curX, 0, mProfile->mFont->getStrWidth(mMenuList[i]->text) + (mHorizontalMargin * 2), getHeight() - (mVerticalMargin * 2));
+            mMenuList[i].bounds.set(curX, 0, mProfile->mFont->getStrWidth(mMenuList[i].text) + (mHorizontalMargin * 2), getHeight() - (mVerticalMargin * 2));
 
-         } else
-       {
-            // Will the bitmap and text be draw?
-          if (!mMenuList[i]->drawBitmapOnly)
+         }
+         else
          {
+            // Will the bitmap and text be draw?
+            if (!mMenuList[i].drawBitmapOnly)
+            {
                // Draw the bitmap and the text
                RectI *bitmapBounds = mProfile->mBitmapArrayRects.address();
-               mMenuList[i]->bounds.set(curX, 0, bitmapBounds[mMenuList[i]->bitmapIndex].extent.x + mProfile->mFont->getStrWidth(mMenuList[i]->text) + (mHorizontalMargin * 2), getHeight() + (mVerticalMargin * 2));
+               mMenuList[i].bounds.set(curX, 0, bitmapBounds[mMenuList[i].bitmapIndex].extent.x + mProfile->mFont->getStrWidth(mMenuList[i].text) + (mHorizontalMargin * 2), getHeight() + (mVerticalMargin * 2));
 
-         } else
-         {
+            }
+            else
+            {
                // Only the bitmap will be drawn
                RectI *bitmapBounds = mProfile->mBitmapArrayRects.address();
-               mMenuList[i]->bounds.set(curX, 0, bitmapBounds[mMenuList[i]->bitmapIndex].extent.x + mBitmapMargin + (mHorizontalMargin * 2), getHeight() + (mVerticalMargin * 2));
+               mMenuList[i].bounds.set(curX, 0, bitmapBounds[mMenuList[i].bitmapIndex].extent.x + mBitmapMargin + (mHorizontalMargin * 2), getHeight() + (mVerticalMargin * 2));
+            }
          }
-       }
 
-         curX += mMenuList[i]->bounds.extent.x;
+         curX += mMenuList[i].bounds.extent.x;
       }
       mouseOverMenu = NULL;
       mouseDownMenu = NULL;
@@ -1207,12 +1223,12 @@ void GuiMenuBar::onPreRender()
 
 void GuiMenuBar::checkMenuMouseMove(const GuiEvent &event)
 {
-   Menu *hit = findHitMenu(event.mousePoint);
+   MenuEntry *hit = findHitMenu(event.mousePoint);
    if(hit && hit != mouseDownMenu)
    {
       // gotta close out the current menu...
-      mTextList->setSelectedCell(Point2I(-1, -1));
-      closeMenu();
+      mouseDownMenu->popupMenu->hidePopup();
+      
       mouseOverMenu = mouseDownMenu = hit;
       setUpdate();
       onAction();
@@ -1221,87 +1237,63 @@ void GuiMenuBar::checkMenuMouseMove(const GuiEvent &event)
 
 void GuiMenuBar::onMouseMove(const GuiEvent &event)
 {
-   Menu *hit = findHitMenu(event.mousePoint);
-   if(hit != mouseOverMenu)
-   {
-      //  If we need to, reset the mouse over menu counter and indicate
-      // that we should track it.
-      if(hit)
-           mMouseOverCounter = 0;
-      if(!mCountMouseOver)
-      {
-           //  We've never started the counter, so start it.
-           if(hit)
-              mCountMouseOver = true;
-      }
+   MenuEntry *hit = findHitMenu(event.mousePoint);
 
-      mouseOverMenu = hit;
+   if (mouseDownMenu != nullptr && hit != nullptr)
+   {
+      //we have a standing click, so just update and go
+      mouseDownMenu = mouseOverMenu = hit;
       setUpdate();
+      onAction();
+
+      return;
    }
+
+   mouseOverMenu = hit;
+   setUpdate();
+}
+
+void GuiMenuBar::onMouseEnter(const GuiEvent &event)
+{
+   onMouseInMenu_callback(true);
+   mMouseInMenu = true;
 }
 
 void GuiMenuBar::onMouseLeave(const GuiEvent &event)
 {
    if(mouseOverMenu)
       setUpdate();
-   mouseOverMenu = NULL;
 
-   //  As we've left the control, don't track how long the mouse has been
-   // within it.
-   if(mCountMouseOver && mMouseOverCounter >= mMouseHoverAmount)
-   {
-     onMouseInMenu_callback(false); // Last parameter indicates if we've entered or left the menu
-   }
-   mCountMouseOver = false;
-   mMouseOverCounter = 0;
+   mouseOverMenu = NULL;
+   mMouseInMenu = false;
 }
 
 void GuiMenuBar::onMouseDragged(const GuiEvent &event)
 {
-   Menu *hit = findHitMenu(event.mousePoint);
-   
-   if(hit != mouseOverMenu)
-   {
-      //  If we need to, reset the mouse over menu counter and indicate
-      // that we should track it.
-      if(hit)
-           mMouseOverCounter = 0;
-      if(!mCountMouseOver)
-      {
-           //  We've never started the counter, so start it.
-           if(hit)
-              mCountMouseOver = true;
-      }
-
-      mouseOverMenu = hit;
-      mouseDownMenu = hit;
-      setUpdate();
-      onAction();
-   }
 }
 
 void GuiMenuBar::onMouseDown(const GuiEvent &event)
 {
-   mouseDownMenu = mouseOverMenu = findHitMenu(event.mousePoint);
-   setUpdate();
-   onAction();
 }
 
 void GuiMenuBar::onMouseUp(const GuiEvent &event)
 {
-   mouseDownMenu = NULL;
+   mouseDownMenu = mouseOverMenu = findHitMenu(event.mousePoint);
    setUpdate();
+   onAction();
 }
 
 void GuiMenuBar::onRender(Point2I offset, const RectI &updateRect)
 {
-   RectI ctrlRect(offset, getExtent());
+   Point2I extent = getExtent();
+
+   RectI ctrlRect(offset, extent);
 
    GFXDrawUtil* drawUtil = GFX->getDrawUtil();
 
    //if opaque, fill the update rect with the fill color
    if (mProfile->mOpaque)
-      drawUtil->drawRectFill(RectI(offset, getExtent()), mProfile->mFillColor);
+      drawUtil->drawRectFill(RectI(offset, extent), mProfile->mFillColor);
 
    //if there's a border, draw the border
    if (mProfile->mBorder)
@@ -1309,63 +1301,65 @@ void GuiMenuBar::onRender(Point2I offset, const RectI &updateRect)
 
    for (U32 i = 0; i < mMenuList.size(); ++i)
    {
-      if (!mMenuList[i]->visible)
+      if (!mMenuList[i].visible)
          continue;
+
       ColorI fontColor = mProfile->mFontColor;
-      RectI bounds = mMenuList[i]->bounds;
+      RectI bounds = mMenuList[i].bounds;
       bounds.point += offset;
-      
+
       Point2I start;
 
-      start.x = mMenuList[i]->bounds.point.x + mHorizontalMargin;
-      start.y = mMenuList[i]->bounds.point.y + (mMenuList[i]->bounds.extent.y - mProfile->mFont->getHeight()) / 2;
-
-     // Draw the border
-      if (mMenuList[i]->drawBorder)
-     {
-        RectI highlightBounds = bounds;
-        highlightBounds.inset(1,1);
-        if (mMenuList[i] == mouseDownMenu)
-            renderFilledBorder(highlightBounds, mProfile->mBorderColorHL, mProfile->mFillColorHL );
-        else if (mMenuList[i] == mouseOverMenu && mouseDownMenu == NULL)
-           renderFilledBorder(highlightBounds, mProfile->mBorderColorHL, mProfile->mFillColorHL);
-     }
-
-     // Do we draw a bitmap?
-      if (mMenuList[i]->bitmapIndex != -1)
-     {
-        S32 index = mMenuList[i]->bitmapIndex * 3;
-        if (mMenuList[i] == mouseDownMenu)
+      start.x = mMenuList[i].bounds.point.x + mHorizontalMargin;
+      start.y = mMenuList[i].bounds.point.y + (mMenuList[i].bounds.extent.y - mProfile->mFont->getHeight()) / 2;
+
+      // Draw the border
+      if (mMenuList[i].drawBorder)
+      {
+         RectI highlightBounds = bounds;
+         highlightBounds.inset(1, 1);
+         if (&mMenuList[i] == mouseDownMenu)
+            renderFilledBorder(highlightBounds, mProfile->mBorderColorHL, mProfile->mFillColorHL);
+         else if (&mMenuList[i] == mouseOverMenu && mouseDownMenu == NULL)
+            renderFilledBorder(highlightBounds, mProfile->mBorderColorHL, mProfile->mFillColorHL);
+      }
+
+      // Do we draw a bitmap?
+      if (mMenuList[i].bitmapIndex != -1)
+      {
+         S32 index = mMenuList[i].bitmapIndex * 3;
+         if (&mMenuList[i] == mouseDownMenu)
             ++index;
-        else if (mMenuList[i] == mouseOverMenu && mouseDownMenu == NULL)
+         else if (&mMenuList[i] == mouseOverMenu && mouseDownMenu == NULL)
             index += 2;
 
          RectI rect = mProfile->mBitmapArrayRects[index];
 
-       Point2I bitmapstart(start);
-       bitmapstart.y = mMenuList[i]->bounds.point.y + (mMenuList[i]->bounds.extent.y - rect.extent.y) / 2;
+         Point2I bitmapstart(start);
+         bitmapstart.y = mMenuList[i].bounds.point.y + (mMenuList[i].bounds.extent.y - rect.extent.y) / 2;
 
          drawUtil->clearBitmapModulation();
-         drawUtil->drawBitmapSR( mProfile->mTextureObject, offset + bitmapstart, rect);
+         drawUtil->drawBitmapSR(mProfile->mTextureObject, offset + bitmapstart, rect);
 
-       // Should we also draw the text?
-         if (!mMenuList[i]->drawBitmapOnly)
-       {
+         // Should we also draw the text?
+         if (!mMenuList[i].drawBitmapOnly)
+         {
             start.x += mBitmapMargin;
-      drawUtil->setBitmapModulation( fontColor );
-      drawUtil->drawText(mProfile->mFont, start + offset, mMenuList[i]->text, mProfile->mFontColors);
-       }
-     } else
-     {
-      drawUtil->setBitmapModulation( fontColor );
-      drawUtil->drawText(mProfile->mFont, start + offset, mMenuList[i]->text, mProfile->mFontColors);
-     }
+            drawUtil->setBitmapModulation(fontColor);
+            drawUtil->drawText(mProfile->mFont, start + offset, mMenuList[i].text, mProfile->mFontColors);
+         }
+      }
+      else
+      {
+         drawUtil->setBitmapModulation(fontColor);
+         drawUtil->drawText(mProfile->mFont, start + offset, mMenuList[i].text, mProfile->mFontColors);
+      }
    }
 
-   renderChildControls( offset, updateRect );
+   renderChildControls(offset, updateRect);
 }
 
-void GuiMenuBar::buildWindowAcceleratorMap( WindowInputGenerator &inputGenerator )
+void GuiMenuBar::buildWindowAcceleratorMap(WindowInputGenerator &inputGenerator)
 {
    // ok, accelerator map is cleared...
    // add all our keys:
@@ -1373,20 +1367,21 @@ void GuiMenuBar::buildWindowAcceleratorMap( WindowInputGenerator &inputGenerator
 
    for (U32 i = 0; i < mMenuList.size(); ++i)
    {
-      for (MenuItem *item = mMenuList[i]->firstMenuItem; item; item = item->nextMenuItem)
+      for (U32 item = 0; item < mMenuList[i].popupMenu->mMenuItems.size(); item++)
       {
-         if(!item->accelerator)
+         if (!mMenuList[i].popupMenu->mMenuItems[item].accelerator)
          {
-            item->accelerator = 0;
+            mMenuList[i].popupMenu->mMenuItems[item].accelerator = 0;
             continue;
          }
+
          EventDescriptor accelEvent;
-       ActionMap::createEventDescriptor(item->accelerator, &accelEvent);
-   
+         ActionMap::createEventDescriptor(mMenuList[i].popupMenu->mMenuItems[item].accelerator, &accelEvent);
+
          //now we have a modifier, and a key, add them to the canvas
-         inputGenerator.addAcceleratorKey( this, item->cmd, accelEvent.eventCode, accelEvent.flags);
+         inputGenerator.addAcceleratorKey(this, mMenuList[i].popupMenu->mMenuItems[item].cmd, accelEvent.eventCode, accelEvent.flags);
 
-         item->acceleratorIndex = mCurAcceleratorIndex;
+         mMenuList[i].popupMenu->mMenuItems[item].acceleratorIndex = mCurAcceleratorIndex;
          mCurAcceleratorIndex++;
       }
    }
@@ -1403,591 +1398,112 @@ void GuiMenuBar::acceleratorKeyPress(U32 index)
    // and find the item that corresponds to the accelerator index
    for (U32 i = 0; i < mMenuList.size(); ++i)
    {
-      if (!mMenuList[i]->visible)
+      if (!mMenuList[i].visible)
          continue;
 
-      for (MenuItem *item = mMenuList[i]->firstMenuItem; item; item = item->nextMenuItem)
+      for(U32 item = 0; item < mMenuList[i].popupMenu->mMenuItems.size(); item++)
       {
-         if(item->acceleratorIndex == index)
+         if(mMenuList[i].popupMenu->mMenuItems[item].acceleratorIndex == index)
          {
             // first, call the script callback for menu selection:
-            onMenuSelect_callback(mMenuList[i]->id, mMenuList[i]->text);
-         
-            if(item->visible)
-               menuItemSelected(mMenuList[i], item);
+            onMenuSelect_callback(mMenuList[i].popupMenu->getId(), mMenuList[i].text);
             return;
          }
       }
    }
 }
 
-//------------------------------------------------------------------------------
-// Menu display class methods
-//------------------------------------------------------------------------------
-
-GuiMenuBackgroundCtrl::GuiMenuBackgroundCtrl(GuiMenuBar *ctrl, GuiMenuTextListCtrl *textList)
-{
-   mMenuBarCtrl = ctrl;
-   mTextList = textList;
-}
-
-void GuiMenuBackgroundCtrl::onMouseDown(const GuiEvent &event)
-{
-   mTextList->setSelectedCell(Point2I(-1,-1));
-   mMenuBarCtrl->closeMenu();
-}
-
-void GuiMenuBackgroundCtrl::onMouseMove(const GuiEvent &event)
-{
-   GuiCanvas *root = getRoot();
-   GuiControl *ctrlHit = root->findHitControl(event.mousePoint, mLayer - 1);
-   if(ctrlHit == mMenuBarCtrl)  // see if the current mouse over menu is right...
-      mMenuBarCtrl->checkMenuMouseMove(event);
-}
-
-void GuiMenuBackgroundCtrl::onMouseDragged(const GuiEvent &event)
-{
-   GuiCanvas *root = getRoot();
-   GuiControl *ctrlHit = root->findHitControl(event.mousePoint, mLayer - 1);
-   if(ctrlHit == mMenuBarCtrl)  // see if the current mouse over menu is right...
-      mMenuBarCtrl->checkMenuMouseMove(event);
-}
-
-GuiMenuTextListCtrl::GuiMenuTextListCtrl(GuiMenuBar *ctrl)
-{
-   mMenuBarCtrl = ctrl;
-   isSubMenu = false; //  Added
-}
-
-void GuiMenuTextListCtrl::onRenderCell(Point2I offset, Point2I cell, bool selected, bool mouseOver)
-{
-   if(dStrcmp(mList[cell.y].text + 3, "-\t")) //  Was: dStrcmp(mList[cell.y].text + 2, "-\t")) but has been changed to take into account the submenu flag
-      Parent::onRenderCell(offset, cell, selected, mouseOver);
-   else
-   {
-      S32 yp = offset.y + mCellSize.y / 2;
-      GFX->getDrawUtil()->drawLine(offset.x, yp, offset.x + mCellSize.x, yp, ColorI(128,128,128));
-      GFX->getDrawUtil()->drawLine(offset.x, yp+1, offset.x + mCellSize.x, yp+1, ColorI(255,255,255));
-   }
-   // now see if there's a bitmap...
-   U8 idx = mList[cell.y].text[0];
-   if(idx != 1)
-   {
-      // there's a bitmap...
-      U32 index = U32(idx - 2) * 3;
-      if(!mList[cell.y].active)
-         index += 2;
-      else if(selected || mouseOver)
-         index ++;
-
-      RectI rect = mProfile->mBitmapArrayRects[index];
-      Point2I off = mMenuBarCtrl->maxBitmapSize - rect.extent;
-      off /= 2;
-
-      GFX->getDrawUtil()->clearBitmapModulation();
-      GFX->getDrawUtil()->drawBitmapSR(mProfile->mTextureObject, offset + off, rect);
-   } 
-
-   //  Check if this is a submenu
-   idx = mList[cell.y].text[1];
-   if(idx != 1)
-   {
-      // This is a submenu, so draw an arrow
-      S32 left = offset.x + mCellSize.x - 12;
-      S32 right = left + 8;
-      S32 top = mCellSize.y / 2 + offset.y - 4;
-      S32 bottom = top + 8;
-      S32 middle = top + 4;
-
-      PrimBuild::begin( GFXTriangleList, 3 );
-         if( selected || mouseOver )
-            PrimBuild::color( mProfile->mFontColorHL );
-         else
-            PrimBuild::color( mProfile->mFontColor );
-
-         PrimBuild::vertex2i( left,  top );
-         PrimBuild::vertex2i( right, middle );
-         PrimBuild::vertex2i( left, bottom );
-      PrimBuild::end();
-   }
-}
-
-bool GuiMenuTextListCtrl::onKeyDown(const GuiEvent &event)
-{
-   //if the control is a dead end, don't process the input:
-   if ( !mVisible || !mActive || !mAwake )
-      return false;
-   
-   //see if the key down is a <return> or not
-   if ( event.modifier == 0 )
-   {
-      if ( event.keyCode == KEY_RETURN )
-      {
-         mMenuBarCtrl->closeMenu();
-         return true;
-      }
-      else if ( event.keyCode == KEY_ESCAPE )
-      {
-         mSelectedCell.set( -1, -1 );
-         mMenuBarCtrl->closeMenu();
-         return true;
-      }
-   }
-   
-   //otherwise, pass the event to it's parent
-   return Parent::onKeyDown(event);
-}
-
-void GuiMenuTextListCtrl::onMouseDown(const GuiEvent &event)
-{
-   Parent::onMouseDown(event);
-}
-
-void GuiMenuTextListCtrl::onMouseUp(const GuiEvent &event)
-{
-   Parent::onMouseUp(event);
-   mMenuBarCtrl->closeMenu();
-}
-
-void GuiMenuTextListCtrl::onCellHighlighted(Point2I cell)
-{
-   // If this text list control is part of a submenu, then don't worry about
-   // passing this along
-   if(!isSubMenu)
-   {
-      RectI globalbounds(getBounds());
-      Point2I globalpoint = localToGlobalCoord(globalbounds.point);
-      globalbounds.point = globalpoint;
-      mMenuBarCtrl->highlightedMenuItem(cell.y, globalbounds, mCellSize);
-   }
-}
-
-//------------------------------------------------------------------------------
-// Submenu display class methods
-//------------------------------------------------------------------------------
-
-GuiSubmenuBackgroundCtrl::GuiSubmenuBackgroundCtrl(GuiMenuBar *ctrl, GuiMenuTextListCtrl *textList) : GuiMenuBackgroundCtrl(ctrl, textList)
-{
-}
-
-void GuiSubmenuBackgroundCtrl::onMouseDown(const GuiEvent &event)
-{
-   mTextList->setSelectedCell(Point2I(-1,-1));
-   mMenuBarCtrl->closeMenu();
-}
-
-bool GuiSubmenuBackgroundCtrl::pointInControl(const Point2I& parentCoordPoint)
-{
-   S32 xt = parentCoordPoint.x - getLeft();
-   S32 yt = parentCoordPoint.y - getTop();
-
-   if(findHitControl(Point2I(xt,yt)) == this)
-      return false;
-   else
-      return true;
-//   return xt >= 0 && yt >= 0 && xt < getWidth() && yt < getHeight();
-}
-
-//------------------------------------------------------------------------------
-
-void GuiMenuBar::menuItemSelected(GuiMenuBar::Menu *menu, GuiMenuBar::MenuItem *item)
-{
-   if(item->enabled)
-      onMenuItemSelect_callback(menu->id, menu->text, item->id, item->text);
-}
-
 void GuiMenuBar::onSleep()
 {
-   if(mBackground) // a menu is up?
-   {
-      mTextList->setSelectedCell(Point2I(-1, -1));
-      closeMenu();
-   }
    Parent::onSleep();
 }
 
-void GuiMenuBar::closeMenu()
-{
-   //  First close any open submenu
-   closeSubmenu();
-
-   // Get the selection from the text list:
-   S32 selectionIndex = mTextList->getSelectedCell().y;
-
-   // Pop the background:
-   if( getRoot() )
-      getRoot()->popDialogControl(mBackground);
-   else
-      return;
-   
-   // Kill the popup:
-   mBackground->deleteObject();
-   mBackground = NULL;
-   
-   // Now perform the popup action:
-   if ( selectionIndex != -1 )
-   {
-      MenuItem *list = mouseDownMenu->firstMenuItem;
-
-      while(selectionIndex && list)
-      {
-         list = list->nextMenuItem;
-         selectionIndex--;
-      }
-      if(list)
-         menuItemSelected(mouseDownMenu, list);
-   }
-   mouseDownMenu = NULL;
-}
-
-//  Called when a menu item is highlighted by the mouse
-void GuiMenuBar::highlightedMenuItem(S32 selectionIndex, const RectI& bounds, Point2I cellSize)
-{
-   S32 selstore = selectionIndex;
-
-   // Now perform the popup action:
-   if ( selectionIndex != -1 )
-   {
-      MenuItem *list = mouseDownMenu->firstMenuItem;
-
-      while(selectionIndex && list)
-      {
-         list = list->nextMenuItem;
-         selectionIndex--;
-      }
-
-      if(list)
-     {
-         // If the highlighted item has changed...
-         if(mouseOverSubmenu != list)
-       {
-            closeSubmenu();
-            mouseOverSubmenu = NULL;
-
-            // Check if this is a submenu.  If so, open the submenu.
-            if(list->isSubmenu)
-          {
-            // If there are submenu items, then open the submenu
-             if(list->submenu->firstMenuItem)
-            {
-               mouseOverSubmenu = list;
-               onSubmenuAction(selstore, bounds, cellSize);
-            }
-         }
-       }
-     }
-   }
-}
-
 //------------------------------------------------------------------------------
 void GuiMenuBar::onAction()
 {
    if(!mouseDownMenu)
       return;
 
-   // first, call the script callback for menu selection:
-   onMenuSelect_callback(mouseDownMenu->id, mouseDownMenu->text);
+   mouseDownMenu->popupMenu->hidePopup();
 
-   MenuItem *visWalk = mouseDownMenu->firstMenuItem;
-   while(visWalk)
-   {
-      if(visWalk->visible)
-         break;
-      visWalk = visWalk->nextMenuItem;
-   }
-   if(!visWalk)
-   {
-      mouseDownMenu = NULL;
-      return;
-   }
-
-   mTextList = new GuiMenuTextListCtrl(this);
-   mTextList->setControlProfile(mProfile);
+   // first, call the script callback for menu selection:
+   onMenuSelect_callback(mouseDownMenu->popupMenu->getId(), mouseDownMenu->text);
 
-   mBackground = new GuiMenuBackgroundCtrl(this, mTextList);
+   mouseDownMenu->popupMenu->mMenuBarCtrl = this;
 
    GuiCanvas *root = getRoot();
-   Point2I windowExt = root->getExtent();
-
-   mBackground->resize( Point2I(0,0), root->getExtent());
-   S32 textWidth = 0, width = 0;
-   S32 acceleratorWidth = 0;
-
-   GFont *font = mProfile->mFont;
-
-   for(MenuItem *walk = mouseDownMenu->firstMenuItem; walk; walk = walk->nextMenuItem)
-   {
-      if(!walk->visible)
-         continue;
-
-      S32 iTextWidth = font->getStrWidth(walk->text);
-      S32 iAcceleratorWidth = walk->accelerator ? font->getStrWidth(walk->accelerator) : 0;
-
-      if(iTextWidth > textWidth)
-         textWidth = iTextWidth;
-      if(iAcceleratorWidth > acceleratorWidth)
-         acceleratorWidth = iAcceleratorWidth;
-   }
-   width = textWidth + acceleratorWidth + maxBitmapSize.x * 2 + 2 + 4;
-
-   mTextList->setCellSize(Point2I(width, font->getHeight()+2));
-   mTextList->clearColumnOffsets();
-   mTextList->addColumnOffset(-1); // add an empty column in for the bitmap index.
-   mTextList->addColumnOffset(maxBitmapSize.x + 1);
-   mTextList->addColumnOffset(maxBitmapSize.x + 1 + textWidth + 4);
-
-   U32 entryCount = 0;
-
-   for(MenuItem *walk = mouseDownMenu->firstMenuItem; walk; walk = walk->nextMenuItem)
-   {
-      if(!walk->visible)
-         continue;
-
-      char buf[512];
-
-     //  If this menu item is a submenu, then set the isSubmenu to 2 to indicate
-     // an arrow should be drawn.  Otherwise set the isSubmenu normally.
-     char isSubmenu = 1;
-     if(walk->isSubmenu)
-        isSubmenu = 2;
-
-      char bitmapIndex = 1;
-      if(walk->bitmapIndex >= 0 && (walk->bitmapIndex * 3 <= mProfile->mBitmapArrayRects.size()))
-         bitmapIndex = walk->bitmapIndex + 2;
-      dSprintf(buf, sizeof(buf), "%c%c\t%s\t%s", bitmapIndex, isSubmenu, walk->text, walk->accelerator ? walk->accelerator : "");
-      mTextList->addEntry(entryCount, buf);
-
-      if(!walk->enabled)
-         mTextList->setEntryActive(entryCount, false);
-
-      entryCount++;
-   }
-   Point2I menuPoint = localToGlobalCoord(mouseDownMenu->bounds.point);
-   menuPoint.y += mouseDownMenu->bounds.extent.y; //  Used to have this at the end: + 2;
-
-   GuiControl *ctrl = new GuiControl;
-   RectI ctrlBounds(  menuPoint, mTextList->getExtent() + Point2I(6, 6));
-   
-   ctrl->setControlProfile(mProfile);
-   mTextList->setPosition( mTextList->getPosition() + Point2I(3,3) );
-   
-   //  Make sure the menu doesn't go beyond the Canvas' bottom edge.
-   if((ctrlBounds.point.y + ctrlBounds.extent.y) > windowExt.y)
-   {
-      //  Pop the menu above the menu bar
-      Point2I menuBar = localToGlobalCoord(mouseDownMenu->bounds.point);
-      ctrlBounds.point.y = menuBar.y - ctrl->getHeight();
-   }
-
-   ctrl->resize(ctrlBounds.point, ctrlBounds.extent);
-   //mTextList->setPosition(Point2I(3,3));
-
-   mTextList->registerObject();
-   mBackground->registerObject();
-   ctrl->registerObject();
-
-   mBackground->addObject( ctrl );
-   ctrl->addObject( mTextList );
-
-   root->pushDialogControl(mBackground, mLayer + 1);
-   mTextList->setFirstResponder();
+   Point2I pos = Point2I(mouseDownMenu->bounds.point.x, mouseDownMenu->bounds.point.y + mouseDownMenu->bounds.extent.y);
+   mouseDownMenu->popupMenu->showPopup(root, pos.x, pos.y);
 }
 
-//------------------------------------------------------------------------------
-//  Performs an action when a menu item that is a submenu is selected/highlighted
-void GuiMenuBar::onSubmenuAction(S32 selectionIndex, const RectI& bounds, Point2I cellSize)
+//  Process a tick
+void GuiMenuBar::processTick()
 {
-   if(!mouseOverSubmenu)
-      return;
-
-   // first, call the script callback for menu selection:
-   onSubmenuSelect_callback(mouseOverSubmenu->id, mouseOverSubmenu->text);
+   if(mMouseInMenu)
+      onMouseInMenu_callback(true);
+}
 
-   MenuItem *visWalk = mouseOverSubmenu->submenu->firstMenuItem;
-   while(visWalk)
-   {
-      if(visWalk->visible)
-         break;
-      visWalk = visWalk->nextMenuItem;
-   }
-   if(!visWalk)
-   {
-      mouseOverSubmenu = NULL;
+void GuiMenuBar::insert(SimObject* pObject, S32 pos)
+{
+   PopupMenu* menu = dynamic_cast<PopupMenu*>(pObject);
+   if (menu == nullptr)
       return;
-   }
-
-   mSubmenuTextList = new GuiMenuTextListCtrl(this);
-   mSubmenuTextList->setControlProfile(mProfile);
-   mSubmenuTextList->isSubMenu = true; // Indicate that this text list is part of a submenu
-
-   mSubmenuBackground = new GuiSubmenuBackgroundCtrl(this, mSubmenuTextList);
-
-   GuiCanvas *root = getRoot();
-   Point2I windowExt = root->getExtent();
-
-   mSubmenuBackground->resize( Point2I(0,0), root->getExtent());
-   S32 textWidth = 0, width = 0;
-   S32 acceleratorWidth = 0;
-
-   GFont *font = mProfile->mFont;
-
-   for(MenuItem *walk = mouseOverSubmenu->submenu->firstMenuItem; walk; walk = walk->nextMenuItem)
-   {
-      if(!walk->visible)
-         continue;
-
-      S32 iTextWidth = font->getStrWidth(walk->text);
-      S32 iAcceleratorWidth = walk->accelerator ? font->getStrWidth(walk->accelerator) : 0;
-
-      if(iTextWidth > textWidth)
-         textWidth = iTextWidth;
-      if(iAcceleratorWidth > acceleratorWidth)
-         acceleratorWidth = iAcceleratorWidth;
-   }
-   width = textWidth + acceleratorWidth + maxBitmapSize.x * 2 + 2 + 4;
-
-   mSubmenuTextList->setCellSize(Point2I(width, font->getHeight()+3));
-   mSubmenuTextList->clearColumnOffsets();
-   mSubmenuTextList->addColumnOffset(-1); // add an empty column in for the bitmap index.
-   mSubmenuTextList->addColumnOffset(maxBitmapSize.x + 1);
-   mSubmenuTextList->addColumnOffset(maxBitmapSize.x + 1 + textWidth + 4);
-
-   U32 entryCount = 0;
-
-   for(MenuItem *walk = mouseOverSubmenu->submenu->firstMenuItem; walk; walk = walk->nextMenuItem)
-   {
-      if(!walk->visible)
-         continue;
-
-      char buf[512];
-
-     //  Can't have submenus within submenus.
-     char isSubmenu = 1;
-
-      char bitmapIndex = 1;
-      if(walk->bitmapIndex >= 0 && (walk->bitmapIndex * 3 <= mProfile->mBitmapArrayRects.size()))
-         bitmapIndex = walk->bitmapIndex + 2;
-      dSprintf(buf, sizeof(buf), "%c%c\t%s\t%s", bitmapIndex, isSubmenu, walk->text, walk->accelerator ? walk->accelerator : "");
-      mSubmenuTextList->addEntry(entryCount, buf);
 
-      if(!walk->enabled)
-         mSubmenuTextList->setEntryActive(entryCount, false);
+   MenuEntry newMenu;
+   newMenu.pos = pos >= mMenuList.size() || pos == -1 ? pos = mMenuList.size() : pos;
+   newMenu.drawBitmapOnly = false;
+   newMenu.drawBorder = true;
+   newMenu.bitmapIndex = -1;
+   newMenu.text = menu->barTitle;
+   newMenu.visible = true;
+   newMenu.popupMenu = menu;
 
-      entryCount++;
-   }
-   Point2I menuPoint = bounds.point; //localToGlobalCoord(bounds.point);
-   menuPoint.x += bounds.extent.x;
-   menuPoint.y += cellSize.y * selectionIndex - 6;
-
-   GuiControl *ctrl = new GuiControl;
-   RectI ctrlBounds(menuPoint, mSubmenuTextList->getExtent() + Point2I(6, 6));
-   ctrl->setControlProfile(mProfile);
-   mSubmenuTextList->setPosition( getPosition() + Point2I(3,3));
-
-   //  Make sure the menu doesn't go beyond the Canvas' bottom edge.
-   if((ctrlBounds.point.y + ctrlBounds.extent.y ) > windowExt.y)
-   {
-      //  Pop the menu above the menu bar
-      ctrlBounds.point.y -= mSubmenuTextList->getHeight() - cellSize.y - 6 - 3;
-   }
-
-   //  And the same for the right edge
-   if((ctrlBounds.point.x + ctrlBounds.extent.x) > windowExt.x)
-   {
-      //  Pop the submenu to the left of the menu
-      ctrlBounds.point.x -= mSubmenuTextList->getWidth() + cellSize.x + 6;
-   }
-   ctrl->resize(ctrlBounds.point, ctrlBounds.extent);
-
-   //mSubmenuTextList->setPosition(Point2I(3,3));
-
-   mSubmenuTextList->registerObject();
-   mSubmenuBackground->registerObject();
-   ctrl->registerObject();
-
-   mSubmenuBackground->addObject( ctrl );
-   ctrl->addObject( mSubmenuTextList );
-
-   root->pushDialogControl(mSubmenuBackground, mLayer + 1);
-   mSubmenuTextList->setFirstResponder();
+   if (pos >= mMenuList.size() || pos == -1)
+      mMenuList.push_back(newMenu);
+   else
+      mMenuList.insert(pos, newMenu);
 }
 
-//  Close down the submenu controls
-void GuiMenuBar::closeSubmenu()
+PopupMenu* GuiMenuBar::getMenu(U32 index)
 {
-   if(!mSubmenuBackground || !mSubmenuTextList)
-      return;
+   if (index >= mMenuList.size())
+      return nullptr;
 
-   // Get the selection from the text list:
-   S32 selectionIndex = mSubmenuTextList->getSelectedCell().y;
+   return mMenuList[index].popupMenu;
+}
 
-   // Pop the background:
-   if( getRoot() )
-      getRoot()->popDialogControl(mSubmenuBackground);
-   
-   // Kill the popup:
-   mSubmenuBackground->deleteObject();
-   mSubmenuBackground = NULL;
-   mSubmenuTextList = NULL;
-   
-   // Now perform the popup action:
-   if ( selectionIndex != -1 )
+//-----------------------------------------------------------------------------
+// Console Methods
+//-----------------------------------------------------------------------------
+DefineConsoleMethod(GuiMenuBar, attachToCanvas, void, (const char *canvas, S32 pos), , "(GuiCanvas, pos)")
+{
+   GuiCanvas* canv = dynamic_cast<GuiCanvas*>(Sim::findObject(canvas));
+   if (canv)
    {
-      MenuItem *list = NULL;
-     if(mouseOverSubmenu)
-     {
-         list = mouseOverSubmenu->submenu->firstMenuItem;
-
-         while(selectionIndex && list)
-         {
-            list = list->nextMenuItem;
-            selectionIndex--;
-         }
-     }
-      if(list)
-         menuItemSelected(list->submenuParentMenu, list);
+      canv->setMenuBar(object);
    }
-   mouseOverSubmenu = NULL;
 }
 
-//  Find if the mouse pointer is within a menu item
-GuiMenuBar::MenuItem *GuiMenuBar::findHitMenuItem(Point2I mousePoint)
+DefineConsoleMethod(GuiMenuBar, removeFromCanvas, void, (), , "()")
 {
+   GuiCanvas* canvas = object->getRoot();
 
-//   for(Menu *walk = menuList; walk; walk = walk->nextMenu)
-//      if(walk->visible && walk->bounds.pointInRect(pos))
-//         return walk;
-   return NULL;
+   if(canvas)
+      canvas->setMenuBar(nullptr);
 }
 
-//  Checks if the mouse has been moved to a new menu item
-void GuiMenuBar::checkSubmenuMouseMove(const GuiEvent &event)
+DefineConsoleMethod(GuiMenuBar, getMenuCount, S32, (), , "()")
 {
-   MenuItem *hit = findHitMenuItem(event.mousePoint);
-   if(hit && hit != mouseOverSubmenu)
-   {
-      // gotta close out the current menu...
-      mSubmenuTextList->setSelectedCell(Point2I(-1, -1));
-//      closeSubmenu();
-      setUpdate();
-   }
+   return object->getMenuListCount();
 }
 
-//  Process a tick
-void GuiMenuBar::processTick()
+DefineConsoleMethod(GuiMenuBar, getMenu, S32, (S32 index), (0), "(Index)")
 {
-   // If we are to track a tick, then do so.
-   if(mCountMouseOver)
-   {
-      //  If we're at a particular number of ticks, notify the script function
-      if(mMouseOverCounter < mMouseHoverAmount)
-     {
-         ++mMouseOverCounter;
-
-     } else if(mMouseOverCounter == mMouseHoverAmount)
-     {
-         ++mMouseOverCounter;
-       onMouseInMenu_callback(true); // Last parameter indicates if we've entered or left the menu
-     }
-   }
+   return object->getMenu(index)->getId();
 }
+
+//-----------------------------------------------------------------------------
+DefineConsoleMethod(GuiMenuBar, insert, void, (SimObject* pObject, S32 pos), (nullAsType<SimObject*>(), -1), "(object, pos) insert object at position")
+{
+   object->insert(pObject, pos);
+}

+ 35 - 141
Engine/source/gui/editor/guiMenuBar.h

@@ -23,119 +23,43 @@
 #ifndef _GUIMENUBAR_H_
 #define _GUIMENUBAR_H_
 
-#ifndef _GUITEXTLISTCTRL_H_
-#include "gui/controls/guiTextListCtrl.h"
-#endif
 #ifndef _GUITICKCTRL_H_
 #include "gui/shiny/guiTickCtrl.h"
 #endif
 
+#ifndef _POPUPMENU_H_
+#include "gui/editor/popupMenu.h"
+#endif
+
 class GuiMenuBar;
-class GuiMenuTextListCtrl;
 class WindowInputGenerator;
 
-class GuiMenuBackgroundCtrl : public GuiControl
-{
-   typedef GuiControl Parent;
-
-protected:
-   GuiMenuBar *mMenuBarCtrl;
-   GuiMenuTextListCtrl *mTextList; 
-public:
-   GuiMenuBackgroundCtrl(GuiMenuBar *ctrl, GuiMenuTextListCtrl* textList);
-   void onMouseDown(const GuiEvent &event);
-   void onMouseMove(const GuiEvent &event);
-   void onMouseDragged(const GuiEvent &event);
-};
-
-class GuiSubmenuBackgroundCtrl : public GuiMenuBackgroundCtrl
-{
-   typedef GuiMenuBackgroundCtrl Parent;
-
-public:
-   GuiSubmenuBackgroundCtrl(GuiMenuBar *ctrl, GuiMenuTextListCtrl* textList);
-   bool pointInControl(const Point2I & parentCoordPoint);
-   void onMouseDown(const GuiEvent &event);
-};
-
-//------------------------------------------------------------------------------
-
-class GuiMenuTextListCtrl : public GuiTextListCtrl
-{
-   private:
-      typedef GuiTextListCtrl Parent;
-
-   protected:
-      GuiMenuBar *mMenuBarCtrl;
-
-   public:
-	  bool isSubMenu; //  Indicates that this text list is in a submenu
-
-      GuiMenuTextListCtrl(); // for inheritance
-      GuiMenuTextListCtrl(GuiMenuBar *ctrl);
-
-      // GuiControl overloads:
-      bool onKeyDown(const GuiEvent &event);
-		void onMouseDown(const GuiEvent &event);
-      void onMouseUp(const GuiEvent &event);
-      void onRenderCell(Point2I offset, Point2I cell, bool selected, bool mouseOver);
-
-      virtual void onCellHighlighted(Point2I cell); //  Added
-};
-
 //------------------------------------------------------------------------------
-
 class GuiMenuBar : public GuiTickCtrl //  Was: GuiControl
 {
    typedef GuiTickCtrl Parent; //  Was: GuiControl Parent;
 public:
 
-	struct Menu;
-
-	struct MenuItem   // an individual item in a pull-down menu
-	{
-		char *text;    // the text of the menu item
-		U32 id;        // a script-assigned identifier
-		char *accelerator; // the keyboard accelerator shortcut for the menu item
-      U32 acceleratorIndex; // index of this accelerator
-		bool enabled;        // true if the menu item is selectable
-      bool visible;        // true if the menu item is visible
-      S32 bitmapIndex;     // index of the bitmap in the bitmap array
-      S32 checkGroup;      // the group index of the item visa vi check marks - 
-                           // only one item in the group can be checked.
-		MenuItem *nextMenuItem; // next menu item in the linked list
-
-		bool isSubmenu;				//  This menu item has a submenu that will be displayed
-
-		Menu* submenuParentMenu; //  For a submenu, this is the parent menu
-      Menu* submenu;
-      String cmd;
-	};
-
-	struct Menu
-	{
-		char *text;
-		U32 id;
-		RectI bounds;
+   struct MenuEntry
+   {
+      U32 pos;
+      RectI bounds;
+
       bool visible;
 
-		S32 bitmapIndex;		// Index of the bitmap in the bitmap array (-1 = no bitmap)
-		bool drawBitmapOnly;	// Draw only the bitmap and not the text
-		bool drawBorder;		// Should a border be drawn around this menu (usually if we only have a bitmap, we don't want a border)
+      S32 bitmapIndex;
+      bool drawBitmapOnly;
 
-		Menu *nextMenu;
-		MenuItem *firstMenuItem;
-	};
-	
-	GuiMenuBackgroundCtrl *mBackground;
-	GuiMenuTextListCtrl *mTextList;
-	
-	GuiSubmenuBackgroundCtrl *mSubmenuBackground; //  Background for a submenu
-	GuiMenuTextListCtrl *mSubmenuTextList;     //  Text list for a submenu
+      bool drawBorder;
+
+      StringTableEntry text;
+      PopupMenu* popupMenu;
+   };
+
+   Vector<MenuEntry> mMenuList;
 
-   Vector<Menu*> mMenuList;
-   Menu *mouseDownMenu;
-   Menu *mouseOverMenu;
+   MenuEntry *mouseDownMenu;
+   MenuEntry *mouseOverMenu;
 
    MenuItem* mouseDownSubmenu; //  Stores the menu item that is a submenu that has been selected
    MenuItem* mouseOverSubmenu; //  Stores the menu item that is a submenu that has been highlighted
@@ -151,59 +75,26 @@ public:
    S32 mVerticalMargin;   // Top and bottom margin around the text of each menu
    S32 mBitmapMargin;     // Margin between a menu's bitmap and text
 
-   //  Used to keep track of the amount of ticks that the mouse is hovering
-   // over a menu.
-   S32 mMouseOverCounter;
-   bool mCountMouseOver;
-   S32 mMouseHoverAmount;
+   U32 mMenubarHeight;
+
+   bool mMouseInMenu;
 	
 	GuiMenuBar();
+
+   void onRemove();
    bool onWake();
    void onSleep();
 
-	// internal menu handling functions
-	// these are used by the script manipulation functions to add/remove/change menu items
-   static Menu* sCreateMenu(const char *menuText, U32 menuId);
-   void addMenu(Menu *menu, S32 pos = -1);
-   void addMenu(const char *menuText, U32 menuId);
-	Menu *findMenu(const char *menu);  // takes either a menu text or a string id
-	static MenuItem *findMenuItem(Menu *menu, const char *menuItem); // takes either a menu text or a string id
-	void removeMenu(Menu *menu);
-	static void removeMenuItem(Menu *menu, MenuItem *menuItem);
-	static MenuItem* addMenuItem(Menu *menu, const char *text, U32 id, const char *accelerator, S32 checkGroup, const char *cmd);
-   static MenuItem* addMenuItem(Menu *menu, MenuItem *menuItem);
-	static void clearMenuItems(Menu *menu);
-   void clearMenus();
-
-   void attachToMenuBar(Menu* menu, S32 pos = -1);
-   void removeFromMenuBar(Menu* menu);
-
-   //  Methods to deal with submenus
-   static MenuItem* findSubmenuItem(Menu *menu, const char *menuItem, const char *submenuItem);
-   static MenuItem* findSubmenuItem(MenuItem *menuItem, const char *submenuItem);
-   static void addSubmenuItem(Menu *menu, MenuItem *submenu, const char *text, U32 id, const char *accelerator, S32 checkGroup);
-   static void addSubmenuItem(Menu *menu, MenuItem *submenu, MenuItem *newMenuItem );
-   static void removeSubmenuItem(MenuItem *menuItem, MenuItem *submenuItem);
-   static void clearSubmenuItems(MenuItem *menuitem);
-   void onSubmenuAction(S32 selectionIndex, const RectI& bounds, Point2I cellSize);
-   void closeSubmenu();
-   void checkSubmenuMouseMove(const GuiEvent &event);
-   MenuItem *findHitMenuItem(Point2I mousePoint);
-
-   void highlightedMenuItem(S32 selectionIndex, const RectI& bounds, Point2I cellSize); //  Called whenever a menu item is highlighted by the mouse
-
-	// display/mouse functions
-
-	Menu *findHitMenu(Point2I mousePoint);
-
-   //  Called when the GUI theme changes and a bitmap arrary may need updating
-  // void onThemeChange();
+   virtual void addObject(SimObject* object);
+
+	MenuEntry *findHitMenu(Point2I mousePoint);
 
    void onPreRender();
 	void onRender(Point2I offset, const RectI &updateRect);
 
    void checkMenuMouseMove(const GuiEvent &event);
    void onMouseMove(const GuiEvent &event);
+   void onMouseEnter(const GuiEvent &event);
    void onMouseLeave(const GuiEvent &event);
    void onMouseDown(const GuiEvent &event);
    void onMouseDragged(const GuiEvent &event);
@@ -215,18 +106,21 @@ public:
    void removeWindowAcceleratorMap( WindowInputGenerator &inputGenerator );
    void acceleratorKeyPress(U32 index);
 
-   virtual void menuItemSelected(Menu *menu, MenuItem *item);
-
    //  Added to support 'ticks'
    void processTick();
 
+   void insert(SimObject* pObject, S32 pos);
+
    static void initPersistFields();
 
+   U32 getMenuListCount() { return mMenuList.size(); }
+
+   PopupMenu* getMenu(U32 index);
+
    DECLARE_CONOBJECT(GuiMenuBar);
    DECLARE_CALLBACK( void, onMouseInMenu, ( bool hasLeftMenu ));
    DECLARE_CALLBACK( void, onMenuSelect, ( S32 menuId, const char* menuText ));
    DECLARE_CALLBACK( void, onMenuItemSelect, ( S32 menuId, const char* menuText, S32 menuItemId, const char* menuItemText  ));
-   DECLARE_CALLBACK( void, onSubmenuSelect, ( S32 submenuId, const char* submenuText ));
 };
 
 #endif

+ 85 - 21
Engine/source/gui/editor/guiPopupMenuCtrl.cpp

@@ -25,20 +25,32 @@
 #include "gfx/primBuilder.h"
 #include "gui/core/guiCanvas.h"
 
-GuiPopupMenuBackgroundCtrl::GuiPopupMenuBackgroundCtrl(GuiPopupMenuTextListCtrl *textList)
+GuiPopupMenuBackgroundCtrl::GuiPopupMenuBackgroundCtrl()
 {
-   mTextList = textList;
-   mTextList->mBackground = this;
+   mMenuBarCtrl = nullptr;
 }
 
 void GuiPopupMenuBackgroundCtrl::onMouseDown(const GuiEvent &event)
 {
-   mTextList->setSelectedCell(Point2I(-1, -1));
+   
+}
+
+void GuiPopupMenuBackgroundCtrl::onMouseUp(const GuiEvent &event)
+{
+   clearPopups();
+
+   //Pass along the event just in case we clicked over a menu item. We don't want to eat the input for it.
+   if (mMenuBarCtrl)
+      mMenuBarCtrl->onMouseUp(event);
+
    close();
 }
 
 void GuiPopupMenuBackgroundCtrl::onMouseMove(const GuiEvent &event)
 {
+   //It's possible we're trying to pan through a menubar while a popup is displayed. Pass along our event to the menubar for good measure
+   if (mMenuBarCtrl)
+      mMenuBarCtrl->onMouseMove(event);
 }
 
 void GuiPopupMenuBackgroundCtrl::onMouseDragged(const GuiEvent &event)
@@ -48,26 +60,64 @@ void GuiPopupMenuBackgroundCtrl::onMouseDragged(const GuiEvent &event)
 void GuiPopupMenuBackgroundCtrl::close()
 {
    getRoot()->removeObject(this);
+
+   mMenuBarCtrl = nullptr;
+}
+
+S32 GuiPopupMenuBackgroundCtrl::findPopupMenu(PopupMenu* menu)
+{
+   S32 menuId = -1;
+
+   for (U32 i = 0; i < mPopups.size(); i++)
+   {
+      if (mPopups[i]->getId() == menu->getId())
+         return i;
+   }
+
+   return menuId;
+}
+
+void GuiPopupMenuBackgroundCtrl::clearPopups()
+{
+   for (U32 i = 0; i < mPopups.size(); i++)
+   {
+      mPopups[i]->mTextList->setSelectedCell(Point2I(-1, -1));
+      mPopups[i]->mTextList->mPopup->hidePopup();
+   }
 }
 
 GuiPopupMenuTextListCtrl::GuiPopupMenuTextListCtrl()
 {
    isSubMenu = false; //  Added
-   mMenu = NULL;
-   mMenuBar = NULL;
-   mPopup = NULL;
+
+   mMenuBar = nullptr;
+   mPopup = nullptr;
+
+   mLastHighlightedMenuIdx = -1;
 }
 
 void GuiPopupMenuTextListCtrl::onRenderCell(Point2I offset, Point2I cell, bool selected, bool mouseOver)
 {
-   if (dStrcmp(mList[cell.y].text + 3, "-\t")) //  Was: dStrcmp(mList[cell.y].text + 2, "-\t")) but has been changed to take into account the submenu flag
-      Parent::onRenderCell(offset, cell, selected, mouseOver);
-   else
+   //check if we're a real entry, or if it's a divider
+   if (mPopup->mMenuItems[cell.y].isSpacer)
    {
       S32 yp = offset.y + mCellSize.y / 2;
-      GFX->getDrawUtil()->drawLine(offset.x, yp, offset.x + mCellSize.x, yp, ColorI(128, 128, 128));
-      GFX->getDrawUtil()->drawLine(offset.x, yp + 1, offset.x + mCellSize.x, yp + 1, ColorI(255, 255, 255));
+      GFX->getDrawUtil()->drawLine(offset.x + 5, yp, offset.x + mCellSize.x - 5, yp, ColorI(128, 128, 128));
+   }
+   else
+   {
+      if (dStrcmp(mList[cell.y].text + 3, "-\t")) //  Was: dStrcmp(mList[cell.y].text + 2, "-\t")) but has been changed to take into account the submenu flag
+      {
+         Parent::onRenderCell(offset, cell, selected, mouseOver);
+      }
+      else
+      {
+         S32 yp = offset.y + mCellSize.y / 2;
+         GFX->getDrawUtil()->drawLine(offset.x, yp, offset.x + mCellSize.x, yp, ColorI(128, 128, 128));
+         GFX->getDrawUtil()->drawLine(offset.x, yp + 1, offset.x + mCellSize.x, yp + 1, ColorI(255, 255, 255));
+      }
    }
+
    // now see if there's a bitmap...
    U8 idx = mList[cell.y].text[0];
    if (idx != 1)
@@ -153,17 +203,12 @@ void GuiPopupMenuTextListCtrl::onMouseUp(const GuiEvent &event)
 
    if (selectionIndex != -1)
    {
-      GuiMenuBar::MenuItem *list = mMenu->firstMenuItem;
+      MenuItem *item = &mPopup->mMenuItems[selectionIndex];
 
-      while (selectionIndex && list)
+      if (item)
       {
-         list = list->nextMenuItem;
-         selectionIndex--;
-      }
-      if (list)
-      {
-         if (list->enabled)
-            dAtob(Con::executef(mPopup, "onSelectItem", Con::getIntArg(getSelectedCell().y), list->text ? list->text : ""));
+         if (item->enabled)
+            dAtob(Con::executef(mPopup, "onSelectItem", Con::getIntArg(getSelectedCell().y), item->text.isNotEmpty() ? item->text : ""));
       }
    }
 
@@ -181,4 +226,23 @@ void GuiPopupMenuTextListCtrl::onCellHighlighted(Point2I cell)
       Point2I globalpoint = localToGlobalCoord(globalbounds.point);
       globalbounds.point = globalpoint;
    }
+
+   S32 selectionIndex = cell.y;
+
+   if (selectionIndex != -1 && mLastHighlightedMenuIdx != selectionIndex)
+   {
+      mLastHighlightedMenuIdx = selectionIndex;
+
+      mPopup->hidePopupSubmenus();
+   }
+
+   if (selectionIndex != -1)
+   {
+      MenuItem *list = &mPopup->mMenuItems[selectionIndex];
+
+      if (list->isSubmenu && list->subMenu != nullptr)
+      {
+         list->subMenu->showPopup(getRoot(), getPosition().x + mCellSize.x, getPosition().y + (selectionIndex * mCellSize.y));
+      }
+   }
 }

+ 13 - 5
Engine/source/gui/editor/guiPopupMenuCtrl.h

@@ -42,6 +42,7 @@ class GuiPopupMenuBackgroundCtrl;
 class GuiPopupMenuTextListCtrl : public GuiTextListCtrl
 {
    friend class GuiPopupMenuBackgroundCtrl;
+   friend class PopupMenu;
 
 private:
    typedef GuiTextListCtrl Parent;
@@ -51,10 +52,12 @@ private:
 public:
    bool isSubMenu; //  Indicates that this text list is in a submenu
    Point2I maxBitmapSize;
-   GuiMenuBar::Menu* mMenu;
+
    GuiMenuBar* mMenuBar;
    PopupMenu* mPopup;
 
+   S32 mLastHighlightedMenuIdx;
+
    GuiPopupMenuTextListCtrl();
 
    // GuiControl overloads:
@@ -70,16 +73,21 @@ class GuiPopupMenuBackgroundCtrl : public GuiControl
 {
    typedef GuiControl Parent;
 
-protected:
-   GuiPopupMenuTextListCtrl *mTextList;
-
 public:
-   GuiPopupMenuBackgroundCtrl(GuiPopupMenuTextListCtrl* textList);
+   GuiPopupMenuBackgroundCtrl();
    void onMouseDown(const GuiEvent &event);
+   void onMouseUp(const GuiEvent &event);
    void onMouseMove(const GuiEvent &event);
    void onMouseDragged(const GuiEvent &event);
 
    void close();
+
+   void clearPopups();
+
+   S32 findPopupMenu(PopupMenu* menu);
+
+   Vector<PopupMenu*> mPopups;
+   GuiMenuBar* mMenuBarCtrl;
 };
 
 #endif

+ 506 - 0
Engine/source/gui/editor/popupMenu.cpp

@@ -0,0 +1,506 @@
+//-----------------------------------------------------------------------------
+// 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.
+//-----------------------------------------------------------------------------
+#include "gui/editor/popupMenu.h"
+#include "console/consoleTypes.h"
+#include "console/engineAPI.h"
+#include "gui/core/guiCanvas.h"
+#include "core/util/safeDelete.h"
+#include "gui/editor/guiPopupMenuCtrl.h"
+#include "gui/editor/guiMenuBar.h"
+
+static U32 sMaxPopupGUID = 0;
+PopupMenuEvent PopupMenu::smPopupMenuEvent;
+bool PopupMenu::smSelectionEventHandled = false;
+
+/// Event class used to remove popup menus from the event notification in a safe way
+class PopUpNotifyRemoveEvent : public SimEvent
+{   
+public:
+   void process(SimObject *object)
+   {
+      PopupMenu::smPopupMenuEvent.remove((PopupMenu *)object, &PopupMenu::handleSelectEvent);
+   }
+};
+
+//-----------------------------------------------------------------------------
+// Constructor/Destructor
+//-----------------------------------------------------------------------------
+PopupMenu::PopupMenu()
+{
+   bitmapIndex = -1;
+
+   barTitle = StringTable->EmptyString();
+
+   mMenuBarCtrl = nullptr;
+   mTextList = nullptr;
+
+   isSubmenu = false;
+}
+
+PopupMenu::~PopupMenu()
+{
+   PopupMenu::smPopupMenuEvent.remove(this, &PopupMenu::handleSelectEvent);
+}
+
+IMPLEMENT_CONOBJECT(PopupMenu);
+
+ConsoleDocClass( PopupMenu,
+   "@brief PopupMenu represents a system menu.\n\n"
+   "You can add menu items to the menu, but there is no torque object associated "
+   "with these menu items, they exist only in a  platform specific manner.\n\n"
+   "@note Internal use only\n\n"
+   "@internal"
+);
+
+//-----------------------------------------------------------------------------
+void PopupMenu::initPersistFields()
+{
+   Parent::initPersistFields();
+
+   addField("barTitle", TypeCaseString, Offset(barTitle, PopupMenu), "");
+}
+
+//-----------------------------------------------------------------------------
+bool PopupMenu::onAdd()
+{
+   if(! Parent::onAdd())
+      return false;
+
+   Con::executef(this, "onAdd");
+   return true;
+}
+
+void PopupMenu::onRemove()
+{
+   Con::executef(this, "onRemove");
+
+   Parent::onRemove();
+}
+
+//-----------------------------------------------------------------------------
+void PopupMenu::onMenuSelect()
+{
+   Con::executef(this, "onMenuSelect");
+}
+
+//-----------------------------------------------------------------------------
+void PopupMenu::handleSelectEvent(U32 popID, U32 command)
+{  
+}
+
+//-----------------------------------------------------------------------------
+bool PopupMenu::onMessageReceived(StringTableEntry queue, const char* event, const char* data)
+{
+   return Con::executef(this, "onMessageReceived", queue, event, data);
+}
+
+bool PopupMenu::onMessageObjectReceived(StringTableEntry queue, Message *msg )
+{
+   return Con::executef(this, "onMessageReceived", queue, Con::getIntArg(msg->getId()));
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Platform Menu Data
+//////////////////////////////////////////////////////////////////////////
+GuiMenuBar* PopupMenu::getMenuBarCtrl()
+{
+   return mMenuBarCtrl;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Public Methods
+//////////////////////////////////////////////////////////////////////////
+S32 PopupMenu::insertItem(S32 pos, const char *title, const char* accelerator, const char* cmd)
+{
+   String titleString = title;
+
+   MenuItem newItem;
+   newItem.id = pos;
+   newItem.text = titleString;
+   newItem.cmd = cmd;
+
+   if (titleString.isEmpty() || titleString == String("-"))
+      newItem.isSpacer = true;
+   else
+      newItem.isSpacer = false;
+
+   if (accelerator[0])
+      newItem.accelerator = dStrdup(accelerator);
+   else
+      newItem.accelerator = NULL;
+
+   newItem.visible = true;
+   newItem.isChecked = false;
+   newItem.acceleratorIndex = 0;
+   newItem.enabled = !newItem.isSpacer;
+
+   newItem.isSubmenu = false;
+   newItem.subMenu = nullptr;
+   newItem.subMenuParentMenu = nullptr;
+
+   mMenuItems.push_back(newItem);
+
+   return pos;
+}
+
+S32 PopupMenu::insertSubMenu(S32 pos, const char *title, PopupMenu *submenu)
+{
+   S32 itemPos = insertItem(pos, title, "", "");
+
+   mMenuItems[itemPos].isSubmenu = true;
+   mMenuItems[itemPos].subMenu = submenu;
+   mMenuItems[itemPos].subMenuParentMenu = this;
+
+   submenu->isSubmenu = true;
+
+   return itemPos;
+}
+
+bool PopupMenu::setItem(S32 pos, const char *title, const char* accelerator, const char* cmd)
+{
+   String titleString = title;
+
+   for (U32 i = 0; i < mMenuItems.size(); i++)
+   {
+      if (mMenuItems[i].text == titleString)
+      {
+         mMenuItems[i].id = pos;
+         mMenuItems[i].cmd = cmd;
+         
+         if (accelerator && accelerator[0])
+            mMenuItems[i].accelerator = dStrdup(accelerator);
+         else
+            mMenuItems[i].accelerator = NULL;
+         return true;
+      }
+   }
+   
+   return false;
+}
+
+void PopupMenu::removeItem(S32 itemPos)
+{
+   if (mMenuItems.size() < itemPos || itemPos < 0)
+      return;
+
+   mMenuItems.erase(itemPos);
+}
+
+//////////////////////////////////////////////////////////////////////////
+void PopupMenu::enableItem(S32 pos, bool enable)
+{
+   if (mMenuItems.size() < pos || pos < 0)
+      return;
+
+   mMenuItems[pos].enabled = enable;
+}
+
+void PopupMenu::checkItem(S32 pos, bool checked)
+{
+   if (mMenuItems.size() < pos || pos < 0)
+      return;
+
+   if (checked && mMenuItems[pos].checkGroup != -1)
+   {
+      // first, uncheck everything in the group:
+      for (U32 i = 0; i < mMenuItems.size(); i++)
+         if (mMenuItems[i].checkGroup == mMenuItems[pos].checkGroup && mMenuItems[i].isChecked)
+            mMenuItems[i].isChecked = false;
+   }
+
+   mMenuItems[pos].isChecked;
+}
+
+void PopupMenu::checkRadioItem(S32 firstPos, S32 lastPos, S32 checkPos)
+{
+   for (U32 i = 0; i < mMenuItems.size(); i++)
+   {
+      if (mMenuItems[i].id >= firstPos && mMenuItems[i].id <= lastPos)
+      {
+         mMenuItems[i].isChecked = false;
+      }
+   }
+}
+
+bool PopupMenu::isItemChecked(S32 pos)
+{
+   if (mMenuItems.size() < pos || pos < 0)
+      return false;
+
+   return mMenuItems[pos].isChecked;
+}
+
+U32 PopupMenu::getItemCount()
+{
+   return mMenuItems.size();
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool PopupMenu::canHandleID(U32 id)
+{
+   return true;
+}
+
+bool PopupMenu::handleSelect(U32 command, const char *text /* = NULL */)
+{
+   return dAtob(Con::executef(this, "onSelectItem", Con::getIntArg(command), text ? text : ""));
+}
+
+//////////////////////////////////////////////////////////////////////////
+void PopupMenu::showPopup(GuiCanvas *owner, S32 x /* = -1 */, S32 y /* = -1 */)
+{
+   if (owner == NULL)
+      return;
+
+   GuiControl* editorGui;
+   Sim::findObject("EditorGui", editorGui);
+
+   if (editorGui)
+   {
+      GuiPopupMenuBackgroundCtrl* backgroundCtrl;
+      Sim::findObject("PopUpMenuControl", backgroundCtrl);
+
+      GuiControlProfile* profile;
+      Sim::findObject("GuiMenubarProfile", profile);
+
+      if (!profile)
+         return;
+
+      if (mTextList == nullptr)
+      {
+         mTextList = new GuiPopupMenuTextListCtrl();
+         mTextList->registerObject();
+         mTextList->setControlProfile(profile);
+
+         mTextList->mPopup = this;
+         mTextList->mMenuBar = getMenuBarCtrl();
+      }
+
+      if (!backgroundCtrl)
+      {
+         backgroundCtrl = new GuiPopupMenuBackgroundCtrl();
+
+         backgroundCtrl->registerObject("PopUpMenuControl");
+      }
+
+      if (!backgroundCtrl || !mTextList)
+         return;
+
+      if (!isSubmenu)
+      {
+         //if we're a 'parent' menu, then tell the background to clear out all existing other popups
+
+         backgroundCtrl->clearPopups();
+      }
+
+      //find out if we're doing a first-time add
+      S32 popupIndex = backgroundCtrl->findPopupMenu(this);
+
+      if (popupIndex == -1)
+      {
+         backgroundCtrl->addObject(mTextList);
+         backgroundCtrl->mPopups.push_back(this);
+      }
+
+      mTextList->mBackground = backgroundCtrl;
+
+      owner->pushDialogControl(backgroundCtrl, 10);
+
+      //Set the background control's menubar, if any, and if it's not already set
+      if(backgroundCtrl->mMenuBarCtrl == nullptr)
+         backgroundCtrl->mMenuBarCtrl = getMenuBarCtrl();
+
+      backgroundCtrl->setExtent(editorGui->getExtent());
+
+      mTextList->clear();
+
+      S32 textWidth = 0, width = 0;
+      S32 acceleratorWidth = 0;
+      GFont *font = profile->mFont;
+
+      Point2I maxBitmapSize = Point2I(0, 0);
+
+      S32 numBitmaps = profile->mBitmapArrayRects.size();
+      if (numBitmaps)
+      {
+         RectI *bitmapBounds = profile->mBitmapArrayRects.address();
+         for (S32 i = 0; i < numBitmaps; i++)
+         {
+            if (bitmapBounds[i].extent.x > maxBitmapSize.x)
+               maxBitmapSize.x = bitmapBounds[i].extent.x;
+            if (bitmapBounds[i].extent.y > maxBitmapSize.y)
+               maxBitmapSize.y = bitmapBounds[i].extent.y;
+         }
+      }
+
+      for (U32 i = 0; i < mMenuItems.size(); i++)
+      {
+         if (!mMenuItems[i].visible)
+            continue;
+
+         S32 iTextWidth = font->getStrWidth(mMenuItems[i].text.c_str());
+         S32 iAcceleratorWidth = mMenuItems[i].accelerator ? font->getStrWidth(mMenuItems[i].accelerator) : 0;
+
+         if (iTextWidth > textWidth)
+            textWidth = iTextWidth;
+         if (iAcceleratorWidth > acceleratorWidth)
+            acceleratorWidth = iAcceleratorWidth;
+      }
+
+      width = textWidth + acceleratorWidth + maxBitmapSize.x * 2 + 2 + 4;
+
+      mTextList->setCellSize(Point2I(width, font->getHeight() + 2));
+      mTextList->clearColumnOffsets();
+      mTextList->addColumnOffset(-1); // add an empty column in for the bitmap index.
+      mTextList->addColumnOffset(maxBitmapSize.x + 1);
+      mTextList->addColumnOffset(maxBitmapSize.x + 1 + textWidth + 4);
+
+      U32 entryCount = 0;
+
+      for (U32 i = 0; i < mMenuItems.size(); i++)
+      {
+         if (!mMenuItems[i].visible)
+            continue;
+
+         char buf[512];
+
+         //  If this menu item is a submenu, then set the isSubmenu to 2 to indicate
+         // an arrow should be drawn.  Otherwise set the isSubmenu normally.
+         char isSubmenu = 1;
+         if (mMenuItems[i].isSubmenu)
+            isSubmenu = 2;
+
+         char bitmapIndex = 1;
+         if (mMenuItems[i].bitmapIndex >= 0 && (mMenuItems[i].bitmapIndex * 3 <= profile->mBitmapArrayRects.size()))
+            bitmapIndex = mMenuItems[i].bitmapIndex + 2;
+
+         dSprintf(buf, sizeof(buf), "%c%c\t%s\t%s", bitmapIndex, isSubmenu, mMenuItems[i].text.c_str(), mMenuItems[i].accelerator ? mMenuItems[i].accelerator : "");
+         mTextList->addEntry(entryCount, buf);
+
+         if (!mMenuItems[i].enabled)
+            mTextList->setEntryActive(entryCount, false);
+
+         entryCount++;
+      }
+
+      Point2I pos = Point2I::Zero;
+
+      if (x == -1 && y == -1)
+         pos = owner->getCursorPos();
+      else
+         pos = Point2I(x, y);
+
+      mTextList->setPosition(pos);
+
+      //nudge in if we'd overshoot the screen
+      S32 widthDiff = (mTextList->getPosition().x + mTextList->getExtent().x) - backgroundCtrl->getWidth();
+      if (widthDiff > 0)
+      {
+         Point2I popupPos = mTextList->getPosition();
+         mTextList->setPosition(popupPos.x - widthDiff, popupPos.y);
+      }
+
+      mTextList->setHidden(false);
+   }
+}
+
+void PopupMenu::hidePopup()
+{
+   if (mTextList)
+   {
+      mTextList->setHidden(true);
+   }
+
+   hidePopupSubmenus();
+}
+
+void PopupMenu::hidePopupSubmenus()
+{
+   for (U32 i = 0; i < mMenuItems.size(); i++)
+   {
+      if (mMenuItems[i].subMenu != nullptr)
+         mMenuItems[i].subMenu->hidePopup();
+   }
+}
+
+//-----------------------------------------------------------------------------
+// Console Methods
+//-----------------------------------------------------------------------------
+DefineConsoleMethod(PopupMenu, insertItem, S32, (S32 pos, const char * title, const char * accelerator, const char* cmd), ("", "", ""), "(pos[, title][, accelerator][, cmd])")
+{
+   return object->insertItem(pos, title, accelerator, cmd);
+}
+
+DefineConsoleMethod(PopupMenu, removeItem, void, (S32 pos), , "(pos)")
+{
+   object->removeItem(pos);
+}
+
+DefineConsoleMethod(PopupMenu, insertSubMenu, S32, (S32 pos, String title, String subMenu), , "(pos, title, subMenu)")
+{
+   PopupMenu *mnu = dynamic_cast<PopupMenu *>(Sim::findObject(subMenu));
+   if(mnu == NULL)
+   {
+      Con::errorf("PopupMenu::insertSubMenu - Invalid PopupMenu object specified for submenu");
+      return -1;
+   }
+   return object->insertSubMenu(pos, title, mnu);
+}
+
+DefineConsoleMethod(PopupMenu, setItem, bool, (S32 pos, const char * title, const char * accelerator, const char *cmd), (""), "(pos, title[, accelerator][, cmd])")
+{
+   return object->setItem(pos, title, accelerator, cmd);
+}
+
+//-----------------------------------------------------------------------------
+
+DefineConsoleMethod(PopupMenu, enableItem, void, (S32 pos, bool enabled), , "(pos, enabled)")
+{
+   object->enableItem(pos, enabled);
+}
+
+DefineConsoleMethod(PopupMenu, checkItem, void, (S32 pos, bool checked), , "(pos, checked)")
+{
+   object->checkItem(pos, checked);
+}
+
+DefineConsoleMethod(PopupMenu, checkRadioItem, void, (S32 firstPos, S32 lastPos, S32 checkPos), , "(firstPos, lastPos, checkPos)")
+{
+   object->checkRadioItem(firstPos, lastPos, checkPos);
+}
+
+DefineConsoleMethod(PopupMenu, isItemChecked, bool, (S32 pos), , "(pos)")
+{
+   return object->isItemChecked(pos);
+}
+
+DefineConsoleMethod(PopupMenu, getItemCount, S32, (), , "()")
+{
+   return object->getItemCount();
+}
+
+//-----------------------------------------------------------------------------
+DefineConsoleMethod(PopupMenu, showPopup, void, (const char * canvasName, S32 x, S32 y), ( -1, -1), "(Canvas,[x, y])")
+{
+   GuiCanvas *pCanvas = dynamic_cast<GuiCanvas*>(Sim::findObject(canvasName));
+   object->showPopup(pCanvas, x, y);
+}

+ 56 - 61
Engine/source/platform/menus/popupMenu.h → Engine/source/gui/editor/popupMenu.h

@@ -19,17 +19,43 @@
 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 // IN THE SOFTWARE.
 //-----------------------------------------------------------------------------
+#ifndef _POPUPMENU_H_
+#define _POPUPMENU_H_
+
 #include "console/simBase.h"
 #include "core/util/tVector.h"
 #include "util/messaging/dispatcher.h"
 #include "gui/core/guiCanvas.h"
 
-#ifndef _POPUPMENU_H_
-#define _POPUPMENU_H_
+class PopupMenu;
+class GuiMenuBar;
+class GuiPopupMenuTextListCtrl;
+class GuiPopupMenuBackgroundCtrl;
+
+struct MenuItem   // an individual item in a pull-down menu
+{
+   String text;    // the text of the menu item
+   U32 id;        // a script-assigned identifier
+   char *accelerator; // the keyboard accelerator shortcut for the menu item
+   U32 acceleratorIndex; // index of this accelerator
+   bool enabled;        // true if the menu item is selectable
+   bool visible;        // true if the menu item is visible
+   S32 bitmapIndex;     // index of the bitmap in the bitmap array
+   S32 checkGroup;      // the group index of the item visa vi check marks - 
+                        // only one item in the group can be checked.
+
+   bool isSubmenu;				//  This menu item has a submenu that will be displayed
+
+   bool isChecked;
 
-// Forward ref used by the platform code
-struct PlatformPopupMenuData;
-class MenuBar;
+   bool isSpacer;
+
+   bool isMenubarEntry;
+
+   PopupMenu* subMenuParentMenu; //  For a submenu, this is the parent menu
+   PopupMenu* subMenu;
+   String cmd;
+};
 
 // PopupMenu represents a menu.
 // You can add menu items to the menu, but there is no torque object associated
@@ -37,30 +63,32 @@ class MenuBar;
 class PopupMenu : public SimObject, public virtual Dispatcher::IMessageListener
 {
    typedef SimObject Parent;
+   friend class GuiMenuBar;
+   friend class GuiPopupMenuTextListCtrl;
+   friend class GuiPopupMenuBackgroundCtrl;
 
-   friend class MenuBar;
+protected:
+   Vector<MenuItem> mMenuItems;
 
-private:
-   /// Used by MenuBar to attach the menu to the menu bar. Do not use anywhere else.
-   void attachToMenuBar(GuiCanvas *owner, S32 pos);
+   GuiMenuBar* mMenuBarCtrl;
 
-protected:
-   PlatformPopupMenuData *mData;
-   
-   SimSet *mSubmenus;
-   SimObjectPtr<GuiCanvas> mCanvas;
+   StringTableEntry barTitle;
 
-   StringTableEntry mBarTitle;
+   RectI bounds;
+   bool visible;
 
-	U32 mPopupGUID;
-   
-   bool mIsPopup;
+   S32 bitmapIndex;		// Index of the bitmap in the bitmap array (-1 = no bitmap)
+   bool drawBitmapOnly;	// Draw only the bitmap and not the text
+   bool drawBorder;		// Should a border be drawn around this menu (usually if we only have a bitmap, we don't want a border)
+
+   bool isSubmenu;
+
+   //This is the gui control that renders our popup
+   GuiPopupMenuTextListCtrl *mTextList;
 
 public:
    PopupMenu();
    virtual ~PopupMenu();
-   void createPlatformPopupMenuData();
-   void deletePlatformPopupMenuData();
    
    DECLARE_CONOBJECT(PopupMenu);
 
@@ -72,15 +100,6 @@ public:
 	static PopupMenuEvent smPopupMenuEvent;
 	static bool smSelectionEventHandled; /// Set to true if any menu or submenu handles a selection event
    
-   /// Creates the platform specific menu object, a peer to this object.
-   /// The platform menu *must* exist before calling any method that manipulates
-   /// menu items or displays the menu.
-   /// implementd on a per-platform basis.
-   void createPlatformMenu();
-
-   void setBarTitle(const char * val) { mBarTitle = StringTable->insert(val, true); }	
-   StringTableEntry getBarTitle() const { return mBarTitle; }
-   
    /// pass NULL for @p title to insert a separator
    /// returns the menu item's ID, or -1 on failure.
    /// implementd on a per-platform basis.
@@ -118,39 +137,7 @@ public:
    /// Returns the number of items in the menu.
    U32 getItemCount();
 
-	/// Returns the popup GUID
-	U32 getPopupGUID() { return mPopupGUID; }
-
-   //-----------------------------------------------------------------------------
-   // New code should not use these methods directly, use the menu bar instead.
-   //
-   // They remain for compatibility with old code and will be changing/going away
-   // once the existing code is moved over to the menu bar.
-   //-----------------------------------------------------------------------------
-
-   /// Places this menu in the menu bar of the application's main window.
-   /// @param owner The GuiCanvas that owns the PlatformWindow that this call is associated with
-   /// @param pos The relative position at which to place the menu.
-   /// @param title The name of the menu
-   void attachToMenuBar(GuiCanvas *owner, S32 pos, const char *title);
-   
-   /// Removes this menu from the menu bar.
-   void removeFromMenuBar();
-
    //-----------------------------------------------------------------------------
-
-   /// Called when the menu has been attached to the menu bar
-   void onAttachToMenuBar(GuiCanvas *canvas, S32 pos, const char *title);
-   
-   /// Called when the menu has been removed from the menu bar
-   void onRemoveFromMenuBar(GuiCanvas *canvas);
-
-   /// Returns the position index of this menu on the bar.
-   S32 getPosOnMenuBar();
-
-   /// Returns true if this menu is attached to the menu bar
-   bool isAttachedToMenuBar()       { return mCanvas != NULL; }
-
    /// Displays this menu as a popup menu and blocks until the user has selected
    /// an item.
    /// @param canvas the owner to show this popup associated with
@@ -159,6 +146,9 @@ public:
    /// implemented on a per-platform basis.
    void showPopup(GuiCanvas *owner, S32 x = -1, S32 y = -1);
 
+   void hidePopup();
+   void hidePopupSubmenus();
+
    /// Returns true iff this menu contains an item that matches @p iD.
    /// implemented on a per-platform basis.
    /// TODO: factor out common code
@@ -184,6 +174,11 @@ public:
 
    virtual bool onMessageReceived(StringTableEntry queue, const char* event, const char* data );
    virtual bool onMessageObjectReceived(StringTableEntry queue, Message *msg );
+
+   bool isVisible() { return visible; }
+   void setVisible(bool isVis) { visible = isVis; }
+
+   GuiMenuBar* getMenuBarCtrl();
 };
 
 #endif // _POPUPMENU_H_

+ 0 - 127
Engine/source/platform/menus/menuBar.cpp

@@ -1,127 +0,0 @@
-//-----------------------------------------------------------------------------
-// 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.
-//-----------------------------------------------------------------------------
-
-#include "platform/platform.h"
-#include "platform/menus/menuBar.h"
-#include "platform/menus/popupMenu.h"
-#include "gui/core/guiCanvas.h"
-#include "console/engineAPI.h"
-
-//-----------------------------------------------------------------------------
-// Constructor/Destructor
-//-----------------------------------------------------------------------------
-
-MenuBar::MenuBar()
-{
-   createPlatformPopupMenuData();
-
-   mCanvas = NULL;
-}
-
-MenuBar::~MenuBar()
-{
-   removeFromCanvas();
-
-   deletePlatformPopupMenuData();
-}
-
-IMPLEMENT_CONOBJECT(MenuBar);
-
-ConsoleDocClass( MenuBar,
-   "@brief Used for rendering platform menu bars\n\n"
-   "Internal use only\n\n"
-   "@internal"
-);
-
-//-----------------------------------------------------------------------------
-// Public Methods
-//-----------------------------------------------------------------------------
-
-void MenuBar::addObject(SimObject *obj)
-{
-   Parent::addObject(obj);
-   updateMenuBar(dynamic_cast<PopupMenu *>(obj));
-}
-
-void MenuBar::removeObject(SimObject *obj)
-{
-   Parent::removeObject(obj);
-   updateMenuBar(dynamic_cast<PopupMenu *>(obj));
-}
-
-void MenuBar::insertObject(SimObject *obj, S32 pos)
-{
-   Parent::addObject(obj);
-   
-   if(pos >= size())
-      pos = size() - 1;
-
-   if(pos < size())
-   {
-      if(pos < 0) pos = 0;
-      Parent::reOrder(obj, at(pos));
-   }
-   updateMenuBar(dynamic_cast<PopupMenu *>(obj));
-}
-
-void MenuBar::pushObject(SimObject *obj)
-{
-   Parent::pushObject(obj);
-   updateMenuBar(dynamic_cast<PopupMenu *>(obj));
-}
-
-void MenuBar::popObject()
-{
-   Parent::popObject();
-   updateMenuBar();
-}
-
-bool MenuBar::reOrder(SimObject *obj, SimObject *target /*= 0*/)
-{
-   bool ret = Parent::reOrder(obj, target);
-   if(ret)
-      updateMenuBar(dynamic_cast<PopupMenu *>(obj));
-   return ret;
-}
-
-//-----------------------------------------------------------------------------
-// Console Methods
-//-----------------------------------------------------------------------------
-
-DefineConsoleMethod(MenuBar, attachToCanvas, void, (const char *canvas, S32 pos), , "(GuiCanvas, pos)")
-{
-   object->attachToCanvas(dynamic_cast<GuiCanvas*>(Sim::findObject(canvas)), pos);
-}
-
-DefineConsoleMethod(MenuBar, removeFromCanvas, void, (), , "()")
-{
-   object->removeFromCanvas();
-}
-
-//-----------------------------------------------------------------------------
-
-DefineConsoleMethod(MenuBar, insert, void, (SimObject* pObject, S32 pos), ,"(object, pos) insert object at position")
-{
-
-   if(pObject)
-      object->insertObject(pObject, pos);
-}

+ 0 - 71
Engine/source/platform/menus/menuBar.h

@@ -1,71 +0,0 @@
-//-----------------------------------------------------------------------------
-// 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.
-//-----------------------------------------------------------------------------
-
-#include "console/simBase.h"
-
-#ifndef _MENUBAR_H_
-#define _MENUBAR_H_
-
-// Forward Refs
-class PlatformMenuBarData;
-class PopupMenu;
-class GuiCanvas;
-
-class MenuBar : public SimSet
-{
-   typedef SimSet Parent;
-
-protected:
-   PlatformMenuBarData *mData;
-   GuiCanvas *mCanvas;
-
-   /// Update the native menu bar to ensure consistency with the set
-   void updateMenuBar(PopupMenu *menu = NULL);
-   
-   void createPlatformPopupMenuData();
-   void deletePlatformPopupMenuData();
-   
-public:
-   MenuBar();
-   virtual ~MenuBar();
-   DECLARE_CONOBJECT(MenuBar);
-
-   /// Attach this menu bar to the native menu bar
-   void attachToCanvas(GuiCanvas *owner, S32 pos);
-   /// Remove this menu bar from the native menu bar
-   void removeFromCanvas();
-
-   /// Returns true if this menu is attached to the menu bar
-   bool isAttachedToCanvas()                      { return mCanvas != NULL; }
-
-   virtual void insertObject(SimObject *obj, S32 pos);
-
-   // Overridden SimSet methods to ensure menu bar consistency when attached
-   virtual void addObject(SimObject *obj);
-   virtual void removeObject(SimObject *obj);
-   virtual void pushObject(SimObject *obj);
-   virtual void popObject();
-
-   virtual bool reOrder(SimObject *obj, SimObject *target = 0);
-};
-
-#endif // _MENUBAR_H_

+ 0 - 269
Engine/source/platform/menus/popupMenu.cpp

@@ -1,269 +0,0 @@
-//-----------------------------------------------------------------------------
-// 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.
-//-----------------------------------------------------------------------------
-
-#include "platform/menus/popupMenu.h"
-#include "console/consoleTypes.h"
-#include "console/engineAPI.h"
-#include "gui/core/guiCanvas.h"
-#include "core/util/safeDelete.h"
-
-static U32 sMaxPopupGUID = 0;
-PopupMenuEvent PopupMenu::smPopupMenuEvent;
-bool PopupMenu::smSelectionEventHandled = false;
-
-/// Event class used to remove popup menus from the event notification in a safe way
-class PopUpNotifyRemoveEvent : public SimEvent
-{   
-public:
-   void process(SimObject *object)
-   {
-      PopupMenu::smPopupMenuEvent.remove((PopupMenu *)object, &PopupMenu::handleSelectEvent);
-   }
-};
-
-//-----------------------------------------------------------------------------
-// Constructor/Destructor
-//-----------------------------------------------------------------------------
-
-PopupMenu::PopupMenu() : mCanvas(NULL)
-{
-   createPlatformPopupMenuData();
-
-   mSubmenus = new SimSet;
-   mSubmenus->registerObject();
-
-   mBarTitle = StringTable->EmptyString();
-   mIsPopup = false;
-
-   mPopupGUID = sMaxPopupGUID++;
-}
-
-PopupMenu::~PopupMenu()
-{
-   // This searches the menu bar so is safe to call for menus
-   // that aren't on it, since nothing will happen.
-   removeFromMenuBar();
-
-   SimSet::iterator i;
-   while((i = mSubmenus->begin()) != mSubmenus->end())
-   {
-      (*i)->deleteObject();
-   }
-
-   mSubmenus->deleteObject();
-   deletePlatformPopupMenuData();
-
-   PopupMenu::smPopupMenuEvent.remove(this, &PopupMenu::handleSelectEvent);
-}
-
-IMPLEMENT_CONOBJECT(PopupMenu);
-
-ConsoleDocClass( PopupMenu,
-   "@brief PopupMenu represents a system menu.\n\n"
-   "You can add menu items to the menu, but there is no torque object associated "
-   "with these menu items, they exist only in a  platform specific manner.\n\n"
-   "@note Internal use only\n\n"
-   "@internal"
-);
-
-
-//-----------------------------------------------------------------------------
-
-void PopupMenu::initPersistFields()
-{
-   addField("isPopup",     TypeBool,         Offset(mIsPopup, PopupMenu),  "true if this is a pop-up/context menu. defaults to false.");
-   addField("barTitle",    TypeCaseString,   Offset(mBarTitle, PopupMenu), "the title of this menu when attached to a menu bar");
-
-   Parent::initPersistFields();
-}
-
-//-----------------------------------------------------------------------------
-
-bool PopupMenu::onAdd()
-{
-   if(! Parent::onAdd())
-      return false;
-
-   createPlatformMenu();
-
-   Con::executef(this, "onAdd");
-   return true;
-}
-
-void PopupMenu::onRemove()
-{
-   Con::executef(this, "onRemove");
-
-   Parent::onRemove();
-}
-
-//-----------------------------------------------------------------------------
-
-void PopupMenu::onMenuSelect()
-{
-   Con::executef(this, "onMenuSelect");
-}
-
-//-----------------------------------------------------------------------------
-
-void PopupMenu::handleSelectEvent(U32 popID, U32 command)
-{  
-   if (popID == mPopupGUID && canHandleID(command))   
-      if (handleSelect(command))
-         smSelectionEventHandled = true;
-}
-
-//-----------------------------------------------------------------------------
-
-void PopupMenu::onAttachToMenuBar(GuiCanvas *canvas, S32 pos, const char *title)
-{
-   mCanvas = canvas;
-
-   // Attached menus must be notified of menu events
-   smPopupMenuEvent.notify(this, &PopupMenu::handleSelectEvent);
-   
-   // Pass on to sub menus
-   for(SimSet::iterator i = mSubmenus->begin();i != mSubmenus->end();++i)
-   {
-      PopupMenu *mnu = dynamic_cast<PopupMenu *>(*i);
-      if(mnu == NULL)
-         continue;
-
-      mnu->onAttachToMenuBar(canvas, pos, title);
-   }
-
-   // Call script
-   if(isProperlyAdded())
-      Con::executef(this, "onAttachToMenuBar", Con::getIntArg(canvas ? canvas->getId() : 0), Con::getIntArg(pos), title);
-}
-
-void PopupMenu::onRemoveFromMenuBar(GuiCanvas *canvas)
-{
-   mCanvas = NULL;
-
-   // We are no longer interested in select events, remove ourselves from the notification list in a safe way
-   Sim::postCurrentEvent(this, new PopUpNotifyRemoveEvent());
-      
-   // Pass on to sub menus
-   for(SimSet::iterator i = mSubmenus->begin();i != mSubmenus->end();++i)
-   {
-      PopupMenu *mnu = dynamic_cast<PopupMenu *>(*i);
-      if(mnu == NULL)
-         continue;
-
-      mnu->onRemoveFromMenuBar(canvas);
-   }
-
-   // Call script
-   if(isProperlyAdded())
-      Con::executef(this, "onRemoveFromMenuBar", Con::getIntArg(canvas ? canvas->getId() : 0));
-}
-
-//-----------------------------------------------------------------------------
-
-bool PopupMenu::onMessageReceived(StringTableEntry queue, const char* event, const char* data)
-{
-   return Con::executef(this, "onMessageReceived", queue, event, data);
-}
-
-
-bool PopupMenu::onMessageObjectReceived(StringTableEntry queue, Message *msg )
-{
-   return Con::executef(this, "onMessageReceived", queue, Con::getIntArg(msg->getId()));
-}
-
-//-----------------------------------------------------------------------------
-// Console Methods
-//-----------------------------------------------------------------------------
-
-DefineConsoleMethod(PopupMenu, insertItem, S32, (S32 pos, const char * title, const char * accelerator, const char* cmd), ("", "", ""), "(pos[, title][, accelerator][, cmd])")
-{
-   return object->insertItem(pos, title, accelerator, cmd);
-}
-
-DefineConsoleMethod(PopupMenu, removeItem, void, (S32 pos), , "(pos)")
-{
-   object->removeItem(pos);
-}
-
-DefineConsoleMethod(PopupMenu, insertSubMenu, S32, (S32 pos, String title, String subMenu), , "(pos, title, subMenu)")
-{
-   PopupMenu *mnu = dynamic_cast<PopupMenu *>(Sim::findObject(subMenu));
-   if(mnu == NULL)
-   {
-      Con::errorf("PopupMenu::insertSubMenu - Invalid PopupMenu object specified for submenu");
-      return -1;
-   }
-   return object->insertSubMenu(pos, title, mnu);
-}
-
-DefineConsoleMethod(PopupMenu, setItem, bool, (S32 pos, const char * title, const char * accelerator, const char *cmd), (""), "(pos, title[, accelerator][, cmd])")
-{
-   return object->setItem(pos, title, accelerator, cmd);
-}
-
-//-----------------------------------------------------------------------------
-
-DefineConsoleMethod(PopupMenu, enableItem, void, (S32 pos, bool enabled), , "(pos, enabled)")
-{
-   object->enableItem(pos, enabled);
-}
-
-DefineConsoleMethod(PopupMenu, checkItem, void, (S32 pos, bool checked), , "(pos, checked)")
-{
-   object->checkItem(pos, checked);
-}
-
-DefineConsoleMethod(PopupMenu, checkRadioItem, void, (S32 firstPos, S32 lastPos, S32 checkPos), , "(firstPos, lastPos, checkPos)")
-{
-   object->checkRadioItem(firstPos, lastPos, checkPos);
-}
-
-DefineConsoleMethod(PopupMenu, isItemChecked, bool, (S32 pos), , "(pos)")
-{
-   return object->isItemChecked(pos);
-}
-
-DefineConsoleMethod(PopupMenu, getItemCount, S32, (), , "()")
-{
-   return object->getItemCount();
-}
-
-//-----------------------------------------------------------------------------
-
-DefineConsoleMethod(PopupMenu, attachToMenuBar, void, (const char * canvasName, S32 pos, const char * title), , "(GuiCanvas, pos, title)")
-{
-   object->attachToMenuBar(dynamic_cast<GuiCanvas*>(Sim::findObject(canvasName)), pos, title);
-}
-
-DefineConsoleMethod(PopupMenu, removeFromMenuBar, void, (), , "()")
-{
-   object->removeFromMenuBar();
-}
-
-//-----------------------------------------------------------------------------
-
-DefineConsoleMethod(PopupMenu, showPopup, void, (const char * canvasName, S32 x, S32 y), ( -1, -1), "(Canvas,[x, y])")
-{
-   GuiCanvas *pCanvas = dynamic_cast<GuiCanvas*>(Sim::findObject(canvasName));
-   object->showPopup(pCanvas, x, y);
-}

+ 0 - 35
Engine/source/platformSDL/menus/PlatformSDLPopupMenuData.h

@@ -1,35 +0,0 @@
-#ifndef PLATFORM_SDL_POPUPMENU_DATA_H
-#define PLATFORM_SDL_POPUPMENU_DATA_H
-
-#include "core/util/tDictionary.h"
-
-class GuiMenuBar;
-struct EventDescriptor;
-class PopupMenu;
-class MenuBar;
-
-struct PlatformPopupMenuData
-{
-   MenuBar *mMenuBar;
-   GuiMenuBar::Menu *mMenuGui;
-
-   static const U8 mCheckedBitmapIdx = 0;
-   static Map<GuiMenuBar::Menu*, PopupMenu*> mMenuMap;
-
-   PlatformPopupMenuData()
-   {
-      mMenuBar = NULL;
-      mMenuGui = NULL;
-   }
-
-   ~PlatformPopupMenuData()
-   {
-      
-   }
-
-   void insertAccelerator(EventDescriptor &desc, U32 id);
-   void removeAccelerator(U32 id);
-   void setAccelleratorEnabled(U32 id, bool enabled);
-};
-
-#endif //PLATFORM_SDL_POPUPMENU_DATA_H

+ 0 - 51
Engine/source/platformSDL/menus/guiPlatformGenericMenuBar.h

@@ -1,51 +0,0 @@
-//-----------------------------------------------------------------------------
-// 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.
-//-----------------------------------------------------------------------------
-
-#pragma once
-
-#include "gui/editor/guiMenuBar.h"
-#include "platformSDL/menus/PlatformSDLPopupMenuData.h"
-#include "platform/menus/popupMenu.h"
-
-class GuiPlatformGenericMenuBar : public GuiMenuBar
-{
-   typedef GuiMenuBar Parent;
-public:
-   DECLARE_CONOBJECT(GuiPlatformGenericMenuBar);
-
-   virtual void menuItemSelected(Menu *menu, MenuItem *item)
-   {
-      AssertFatal(menu && item, "");
-
-      PopupMenu *popupMenu = PlatformPopupMenuData::mMenuMap[menu];
-      AssertFatal(popupMenu, "");
-
-      popupMenu->handleSelect(item->id);
-
-      Parent::menuItemSelected(menu, item);
-   }
-
-protected:
-   /// menu id / item id
-   Map<CompoundKey<U32, U32>, String> mCmds;
-
-};

+ 0 - 200
Engine/source/platformSDL/menus/menuBarSDL.cpp

@@ -1,200 +0,0 @@
-//-----------------------------------------------------------------------------
-// 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.
-//-----------------------------------------------------------------------------
-
-#include "platform/menus/menuBar.h"
-#include "platform/menus/popupMenu.h"
-#include "gui/core/guiCanvas.h"
-#include "windowManager/platformWindowMgr.h"
-#include "core/util/safeDelete.h"
-
-#include "windowManager/sdl/sdlWindow.h"
-#include "gui/editor/guiMenuBar.h"
-
-#include "platformSDL/menus/PlatformSDLPopupMenuData.h"
-
-#include "platformSDL/menus/guiPlatformGenericMenuBar.h"
-
-#ifdef TORQUE_SDL
-
-//-----------------------------------------------------------------------------
-// Platform Data
-//-----------------------------------------------------------------------------
-
-// class PlatformMenuBarData
-// {
-// 
-// };
-
-Map<GuiMenuBar::Menu*, PopupMenu*> PlatformPopupMenuData::mMenuMap;
-
-IMPLEMENT_CONOBJECT(GuiPlatformGenericMenuBar);
-
-//-----------------------------------------------------------------------------
-// MenuBar Methods
-//-----------------------------------------------------------------------------
-
-void MenuBar::createPlatformPopupMenuData()
-{
-   mData = NULL;
-}
-
-void MenuBar::deletePlatformPopupMenuData()
-{
-//    SAFE_DELETE(mData);
-}
-
-//-----------------------------------------------------------------------------
-
-GuiPlatformGenericMenuBar* _FindMenuBarCtrl()
-{
-   GuiControl* control;
-   Sim::findObject("PlatformGenericMenubar", control);
-   AssertFatal(control, "");
-   if( !control )      
-      return NULL;   
-
-   GuiPlatformGenericMenuBar* menuBar;
-   menuBar = dynamic_cast<GuiPlatformGenericMenuBar*>( control->findObjectByInternalName(  StringTable->insert("menubar"), true) );
-   AssertFatal(menuBar, "");
-   return menuBar;
-}
-
-
-void MenuBar::updateMenuBar(PopupMenu *popupMenu /* = NULL */)
-{
-   //if(! isAttachedToCanvas())
-   //   return;   
-
-   if(!popupMenu)
-      return;
-
-   GuiPlatformGenericMenuBar* menuBarGui = _FindMenuBarCtrl();
-   popupMenu->mData->mMenuBar = this;
-
-   String menuTitle = popupMenu->getBarTitle();
-
-   //Next, find out if we're still in the list of entries
-   SimSet::iterator itr = find(begin(), end(), popupMenu);
-
-   GuiMenuBar::Menu* menuGui = menuBarGui->findMenu(menuTitle);
-   if (!menuGui)
-   {
-      //This is our first time setting this particular menu up, so we'll OK it.
-      if (itr == end())
-         menuBarGui->attachToMenuBar(popupMenu->mData->mMenuGui);
-      else
-         menuBarGui->attachToMenuBar(popupMenu->mData->mMenuGui, itr - begin());
-   }
-   else
-   {
-      //Not our first time through, so we're really updating it.
-
-      //So, first, remove it from the menubar
-      menuBarGui->removeFromMenuBar(menuGui);
-
-      //Next, find out if we're still in the list of entries
-      SimSet::iterator itr = find(begin(), end(), popupMenu);
-
-      //if we're no longer in the list, we're pretty much done here
-      if (itr == end())
-         return;
-
-      //We're still here, so this is a valid menu for our current bar configuration, so add us back in.
-      menuBarGui->attachToMenuBar(menuGui, itr - begin());
-   }
-}
-
-//-----------------------------------------------------------------------------
-
-void MenuBar::attachToCanvas(GuiCanvas *owner, S32 pos)
-{
-   if(owner == NULL || isAttachedToCanvas())
-      return;
-
-   // This is set for popup menus in the onAttachToMenuBar() callback
-   mCanvas = owner;
-
-   PlatformWindowSDL *pWindow = dynamic_cast<PlatformWindowSDL*>(owner->getPlatformWindow());
-   if(pWindow == NULL) 
-      return;
-
-   // Setup the native menu bar
-   GuiMenuBar *hWindowMenu = static_cast<GuiMenuBar*>( pWindow->getMenuHandle() );
-	if( hWindowMenu == NULL && !Journal::IsPlaying() )
-      hWindowMenu = _FindMenuBarCtrl();
-
-   if(hWindowMenu)
-   {
-      pWindow->setMenuHandle( hWindowMenu );
-      GuiControl *base = hWindowMenu->getParent();
-         
-      while( base->getParent() )
-      {
-         base = base->getParent();
-      }         
-
-      mCanvas->setMenuBar( base );
-   }
-
-   for (S32 i = 0; i < size(); ++i)
-   {
-      PopupMenu *mnu = dynamic_cast<PopupMenu *>(at(i));
-      if (mnu == NULL)
-      {
-         Con::warnf("MenuBar::attachToMenuBar - Non-PopupMenu object in set");
-         continue;
-      }
-
-      if (mnu->isAttachedToMenuBar())
-         mnu->removeFromMenuBar();
-
-      mnu->attachToMenuBar(owner, pos + i);
-   }
-   
-}
-
-void MenuBar::removeFromCanvas()
-{
-   if (mCanvas == NULL || !isAttachedToCanvas())
-      return;
-
-   //_FindMenuBarCtrl()->clearMenus();
-
-   // Add the items
-   for (S32 i = 0; i < size(); ++i)
-   {
-      PopupMenu *mnu = dynamic_cast<PopupMenu *>(at(i));
-      if (mnu == NULL)
-      {
-         Con::warnf("MenuBar::removeFromMenuBar - Non-PopupMenu object in set");
-         continue;
-      }
-
-      mnu->removeFromMenuBar();
-   }
-
-   mCanvas->setMenuBar(NULL);
-
-   mCanvas = NULL;
-}
-
-#endif

+ 0 - 393
Engine/source/platformSDL/menus/popupMenuSDL.cpp

@@ -1,393 +0,0 @@
-//-----------------------------------------------------------------------------
-// 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.
-//-----------------------------------------------------------------------------
-
-#ifdef TORQUE_SDL
-
-#include "platform/menus/popupMenu.h"
-#include "platform/menus/menuBar.h"
-#include "console/consoleTypes.h"
-#include "gui/core/guiCanvas.h"
-#include "core/util/safeDelete.h"
-
-#include "sim/actionMap.h"
-#include "platform/platformInput.h"
-
-#include "windowManager/sdl/sdlWindow.h"
-#include "gui/editor/guiMenuBar.h"
-
-#include "platformSDL/menus/PlatformSDLPopupMenuData.h"
-#include "console/engineAPI.h"
-
-#include "platformSDL/menus/guiPlatformGenericMenuBar.h"
-#include "gui/editor/guiPopupMenuCtrl.h"
-
-//////////////////////////////////////////////////////////////////////////
-// Platform Menu Data
-//////////////////////////////////////////////////////////////////////////
-GuiPlatformGenericMenuBar* findMenuBarCtrl()
-{
-   GuiControl* control;
-   Sim::findObject("PlatformGenericMenubar", control);
-   AssertFatal(control, "");
-   if (!control)
-      return NULL;
-
-   GuiPlatformGenericMenuBar* menuBar;
-   menuBar = dynamic_cast<GuiPlatformGenericMenuBar*>(control->findObjectByInternalName(StringTable->insert("menubar"), true));
-   AssertFatal(menuBar, "");
-   return menuBar;
-}
-
-//////////////////////////////////////////////////////////////////////////
-
-void PlatformPopupMenuData::insertAccelerator(EventDescriptor &desc, U32 id)
-{
-   AssertFatal(0, "");
-}
-
-void PlatformPopupMenuData::removeAccelerator(U32 id)
-{
-   AssertFatal(0, "");
-}
-
-void PlatformPopupMenuData::setAccelleratorEnabled( U32 id, bool enabled )
-{   
-  AssertFatal(0, "");
-}
-
-//////////////////////////////////////////////////////////////////////////
-
-void PopupMenu::createPlatformPopupMenuData()
-{
-   mData = new PlatformPopupMenuData;
-}
-
-void PopupMenu::deletePlatformPopupMenuData()
-{
-   SAFE_DELETE(mData);
-}
-void PopupMenu::createPlatformMenu()
-{
-   mData->mMenuGui = GuiMenuBar::sCreateMenu( getBarTitle(), getId() );
-   PlatformPopupMenuData::mMenuMap[ mData->mMenuGui ] = this;
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-// Public Methods
-//////////////////////////////////////////////////////////////////////////
-
-S32 PopupMenu::insertItem(S32 pos, const char *title, const char* accelerator, const char* cmd)
-{   
-   GuiMenuBar::MenuItem *item = GuiMenuBar::findMenuItem( mData->mMenuGui, title );
-   
-   //We'll make a special exception for the spacer items
-   if(item && dStrcmp(title, ""))
-   {
-      setItem( pos, title, accelerator, cmd);
-      return pos;
-   }
-
-   item = GuiMenuBar::addMenuItem( mData->mMenuGui, title, pos, accelerator, -1, cmd );
-   item->submenuParentMenu = this->mData->mMenuGui;
-   
-   return pos;
-}
-
-S32 PopupMenu::insertSubMenu(S32 pos, const char *title, PopupMenu *submenu)
-{  
-   GuiMenuBar::MenuItem *item = GuiMenuBar::addMenuItem( mData->mMenuGui, title, pos, "", -1, "" );
-   item->isSubmenu = true;
-   item->submenu = submenu->mData->mMenuGui;
-   item->submenuParentMenu = this->mData->mMenuGui;
-
-   return pos;
-}
-
-bool PopupMenu::setItem(S32 pos, const char *title, const char* accelerator, const char* cmd)
-{
-   GuiMenuBar::MenuItem *item = NULL;
-
-   item = GuiMenuBar::findMenuItem( mData->mMenuGui, title );
-   
-   if(item)
-   {
-      item->id = pos;
-      item->cmd = cmd;
-      if( accelerator && accelerator[0] )
-         item->accelerator = dStrdup( accelerator );
-      else
-         item->accelerator = NULL;
-      return true;
-   }
-
-   return false;
-}
-
-void PopupMenu::removeItem(S32 itemPos)
-{
-   GuiMenuBar::MenuItem *item = GuiMenuBar::findMenuItem( mData->mMenuGui, String::ToString(itemPos) );
-   if(item)
-   {
-      GuiMenuBar::removeMenuItem( mData->mMenuGui, item);
-   }
-}
-
-//////////////////////////////////////////////////////////////////////////
-
-void PopupMenu::enableItem( S32 pos, bool enable )
-{
-   GuiMenuBar::MenuItem *item = NULL;
-   for( item = mData->mMenuGui->firstMenuItem; item; item = item->nextMenuItem )
-   {
-      if( item->id == pos)
-         item->enabled = enable;
-   }
-}
-
-void PopupMenu::checkItem(S32 pos, bool checked)
-{
-   GuiMenuBar::MenuItem *item = NULL;
-   for( item = mData->mMenuGui->firstMenuItem; item; item = item->nextMenuItem )   
-      if(item->id == pos)
-         break;   
-
-   if( !item )
-      return;
-
-   if(checked && item->checkGroup != -1)
-   {
-      // first, uncheck everything in the group:
-      for( GuiMenuBar::MenuItem *itemWalk = mData->mMenuGui->firstMenuItem; itemWalk; itemWalk = itemWalk->nextMenuItem )
-         if( itemWalk->checkGroup == item->checkGroup && itemWalk->bitmapIndex == mData->mCheckedBitmapIdx )
-            itemWalk->bitmapIndex = -1;
-   }
-
-   item->bitmapIndex = checked ? mData->mCheckedBitmapIdx : -1;   
-}
-
-void PopupMenu::checkRadioItem(S32 firstPos, S32 lastPos, S32 checkPos)
-{
-   GuiMenuBar::MenuItem *item = NULL;
-   for( item = mData->mMenuGui->firstMenuItem; item; item = item->nextMenuItem )
-   {
-      if(item->id >= firstPos && item->id <= lastPos)
-      {
-         item->bitmapIndex = (item->id  == checkPos) ? mData->mCheckedBitmapIdx : -1;  
-      }
-   }
-}
-
-bool PopupMenu::isItemChecked(S32 pos)
-{
-   GuiMenuBar::MenuItem *item = NULL;
-   for( item = mData->mMenuGui->firstMenuItem; item; item = item->nextMenuItem )   
-      if(item->id == pos)      
-         return item->bitmapIndex == mData->mCheckedBitmapIdx;   
-
-   return false;
-}
-
-U32 PopupMenu::getItemCount()
-{
-   int count = 0;
-   for( GuiMenuBar::MenuItem *item = mData->mMenuGui->firstMenuItem; item; item = item->nextMenuItem )
-      ++count;
-
-   return count;
-}
-
-//////////////////////////////////////////////////////////////////////////
-
-bool PopupMenu::canHandleID(U32 id)
-{
-   return true;
-}
-
-bool PopupMenu::handleSelect(U32 command, const char *text /* = NULL */)
-{
-   return dAtob(Con::executef(this, "onSelectItem", Con::getIntArg(command), text ? text : ""));
-}
-
-//////////////////////////////////////////////////////////////////////////
-
-void PopupMenu::showPopup(GuiCanvas *owner, S32 x /* = -1 */, S32 y /* = -1 */)
-{
-    if(owner == NULL)
-      return;
-
-    GuiControl* editorGui;
-    Sim::findObject("EditorGui", editorGui);
-
-    if (editorGui)
-    {
-       GuiPopupMenuTextListCtrl* textList;
-       GuiPopupMenuBackgroundCtrl* backgroundCtrl;
-       Sim::findObject("PopUpMenuControl", backgroundCtrl);
-
-       GuiControlProfile* profile;
-       Sim::findObject("GuiMenubarProfile", profile);
-
-       if (!profile)
-          return;
-
-       if (!backgroundCtrl)
-       {
-          textList = new GuiPopupMenuTextListCtrl();
-
-          textList->registerObject();
-
-          backgroundCtrl = new GuiPopupMenuBackgroundCtrl(textList);
-
-          backgroundCtrl->registerObject("PopUpMenuControl");
-
-          textList->setControlProfile(profile);
-
-          backgroundCtrl->addObject(textList);
-       }
-       else
-       {
-          textList = dynamic_cast<GuiPopupMenuTextListCtrl*>(backgroundCtrl->first());
-       }
-
-       if (!backgroundCtrl || !textList)
-          return;
-
-       owner->pushDialogControl(backgroundCtrl, 10);
-
-       backgroundCtrl->setExtent(editorGui->getExtent());
-
-       textList->clear();
-       textList->mMenu = mData->mMenuGui;
-       textList->mMenuBar = findMenuBarCtrl();
-       textList->mPopup = this;
-
-       S32 textWidth = 0, width = 0;
-       S32 acceleratorWidth = 0;
-       GFont *font = profile->mFont;
-
-       Point2I maxBitmapSize = Point2I(0, 0);
-
-       S32 numBitmaps = profile->mBitmapArrayRects.size();
-       if (numBitmaps)
-       {
-          RectI *bitmapBounds = profile->mBitmapArrayRects.address();
-          for (S32 i = 0; i < numBitmaps; i++)
-          {
-             if (bitmapBounds[i].extent.x > maxBitmapSize.x)
-                maxBitmapSize.x = bitmapBounds[i].extent.x;
-             if (bitmapBounds[i].extent.y > maxBitmapSize.y)
-                maxBitmapSize.y = bitmapBounds[i].extent.y;
-          }
-       }
-
-       for (GuiMenuBar::MenuItem *walk = mData->mMenuGui->firstMenuItem; walk; walk = walk->nextMenuItem)
-       {
-          if (!walk->visible)
-             continue;
-
-          S32 iTextWidth = font->getStrWidth(walk->text);
-          S32 iAcceleratorWidth = walk->accelerator ? font->getStrWidth(walk->accelerator) : 0;
-
-          if (iTextWidth > textWidth)
-             textWidth = iTextWidth;
-          if (iAcceleratorWidth > acceleratorWidth)
-             acceleratorWidth = iAcceleratorWidth;
-       }
-       width = textWidth + acceleratorWidth + maxBitmapSize.x * 2 + 2 + 4;
-
-       textList->setCellSize(Point2I(width, font->getHeight() + 2));
-       textList->clearColumnOffsets();
-       textList->addColumnOffset(-1); // add an empty column in for the bitmap index.
-       textList->addColumnOffset(maxBitmapSize.x + 1);
-       textList->addColumnOffset(maxBitmapSize.x + 1 + textWidth + 4);
-
-       U32 entryCount = 0;
-
-       for (GuiMenuBar::MenuItem *walk = mData->mMenuGui->firstMenuItem; walk; walk = walk->nextMenuItem)
-       {
-          if (!walk->visible)
-             continue;
-
-          char buf[512];
-
-          //  If this menu item is a submenu, then set the isSubmenu to 2 to indicate
-          // an arrow should be drawn.  Otherwise set the isSubmenu normally.
-          char isSubmenu = 1;
-          if (walk->isSubmenu)
-             isSubmenu = 2;
-
-          char bitmapIndex = 1;
-          if (walk->bitmapIndex >= 0 && (walk->bitmapIndex * 3 <= profile->mBitmapArrayRects.size()))
-             bitmapIndex = walk->bitmapIndex + 2;
-          dSprintf(buf, sizeof(buf), "%c%c\t%s\t%s", bitmapIndex, isSubmenu, walk->text, walk->accelerator ? walk->accelerator : "");
-          textList->addEntry(entryCount, buf);
-
-          if (!walk->enabled)
-             textList->setEntryActive(entryCount, false);
-
-          entryCount++;
-       }
-
-       Point2I pos = owner->getCursorPos();
-       textList->setPosition(pos);
-
-       //nudge in if we'd overshoot the screen
-       S32 widthDiff = (textList->getPosition().x + textList->getExtent().x) - backgroundCtrl->getWidth();
-       if (widthDiff > 0)
-       {
-          Point2I popupPos = textList->getPosition();
-          textList->setPosition(popupPos.x - widthDiff, popupPos.y);
-       }
-    }
-}
-
-//////////////////////////////////////////////////////////////////////////
-
-void PopupMenu::attachToMenuBar(GuiCanvas *owner, S32 pos, const char *title)
-{
-   if(owner == NULL || isAttachedToMenuBar())
-      return;   
-}
-
-// New version of above for use by MenuBar class. Do not use yet.
-void PopupMenu::attachToMenuBar(GuiCanvas *owner, S32 pos)
-{
-   if(owner == NULL || isAttachedToMenuBar())
-      return;
-
-   //mData->mMenuBar = owner->setMenuBar();
-}
-
-void PopupMenu::removeFromMenuBar()
-{
-   if(isAttachedToMenuBar())
-      return;
-}
-
-S32 PopupMenu::getPosOnMenuBar()
-{
-   
-   return 0;
-}
-
-#endif

+ 0 - 177
Engine/source/platformWin32/menus/menuBarWin32.cpp

@@ -1,177 +0,0 @@
-//-----------------------------------------------------------------------------
-// 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.
-//-----------------------------------------------------------------------------
-
-#include "platformWin32/platformWin32.h"
-#include "platform/menus/menuBar.h"
-#include "platform/menus/popupMenu.h"
-#include "gui/core/guiCanvas.h"
-#include "windowManager/platformWindowMgr.h"
-#include "windowManager/win32/win32Window.h"
-#include "core/util/safeDelete.h"
-
-//-----------------------------------------------------------------------------
-// Platform Data
-//-----------------------------------------------------------------------------
-
-// class PlatformMenuBarData
-// {
-// 
-// };
-
-//-----------------------------------------------------------------------------
-// MenuBar Methods
-//-----------------------------------------------------------------------------
-
-#ifndef TORQUE_SDL
-
-void MenuBar::createPlatformPopupMenuData()
-{
-//    mData = new PlatformMenuBarData;
-
-   // [tom, 6/4/2007] Nothing currently needed for win32
-   mData = NULL;
-}
-
-void MenuBar::deletePlatformPopupMenuData()
-{
-//    SAFE_DELETE(mData);
-}
-
-//-----------------------------------------------------------------------------
-
-void MenuBar::updateMenuBar(PopupMenu *menu /* = NULL */)
-{
-   if(! isAttachedToCanvas())
-      return;
-
-   if(menu == NULL)
-   {
-      // [tom, 6/4/2007] Kludgetastic
-      GuiCanvas *oldCanvas = mCanvas;
-      S32 pos = -1;
-      PopupMenu *mnu = dynamic_cast<PopupMenu *>(at(0));
-      if(mnu)
-         pos = mnu->getPosOnMenuBar();
-
-      removeFromCanvas();
-      attachToCanvas(oldCanvas, pos);
-
-      return;
-   }
-
-   menu->removeFromMenuBar();
-   SimSet::iterator itr = find(begin(), end(), menu);
-   if(itr == end())
-      return;
-
-   menu->attachToMenuBar(mCanvas, itr - begin());
-
-   Win32Window *pWindow = dynamic_cast<Win32Window*>(mCanvas->getPlatformWindow());
-   if(pWindow == NULL) 
-      return;
-
-   HWND hWindow = pWindow->getHWND();
-   DrawMenuBar(hWindow);
-}
-
-//-----------------------------------------------------------------------------
-
-void MenuBar::attachToCanvas(GuiCanvas *owner, S32 pos)
-{
-   if(owner == NULL || isAttachedToCanvas())
-      return;
-
-   // This is set for popup menus in the onAttachToMenuBar() callback
-   mCanvas = owner;
-
-   Win32Window *pWindow = dynamic_cast<Win32Window*>(owner->getPlatformWindow());
-   if(pWindow == NULL) 
-      return;
-
-   // Setup the native menu bar
-   HMENU hWindowMenu = pWindow->getMenuHandle();
-	if(hWindowMenu == NULL && !Journal::IsPlaying())
-   {
-      hWindowMenu = CreateMenu();
-      if(hWindowMenu)
-      {
-         pWindow->setMenuHandle( hWindowMenu);
-      }
-   }
-
-   // Add the items
-   for(S32 i = 0;i < size();++i)
-   {
-      PopupMenu *mnu = dynamic_cast<PopupMenu *>(at(i));
-      if(mnu == NULL)
-      {
-         Con::warnf("MenuBar::attachToMenuBar - Non-PopupMenu object in set");
-         continue;
-      }
-
-      if(mnu->isAttachedToMenuBar())
-         mnu->removeFromMenuBar();
-
-      mnu->attachToMenuBar(owner, pos + i);
-   }
-
-   HWND hWindow = pWindow->getHWND();
-   SetMenu(hWindow, hWindowMenu);
-   DrawMenuBar(hWindow);
-
-}
-
-void MenuBar::removeFromCanvas()
-{
-   if(mCanvas == NULL || ! isAttachedToCanvas())
-      return;
-
-   Win32Window *pWindow = dynamic_cast<Win32Window*>(mCanvas->getPlatformWindow());
-   if(pWindow == NULL) 
-      return;
-
-   // Setup the native menu bar
-   HMENU hWindowMenu = pWindow->getMenuHandle();
-   if(hWindowMenu == NULL)
-      return;
-
-   // Add the items
-   for(S32 i = 0;i < size();++i)
-   {
-      PopupMenu *mnu = dynamic_cast<PopupMenu *>(at(i));
-      if(mnu == NULL)
-      {
-         Con::warnf("MenuBar::removeFromMenuBar - Non-PopupMenu object in set");
-         continue;
-      }
-
-      mnu->removeFromMenuBar();
-   }
-
-   HWND hWindow = pWindow->getHWND();
-   SetMenu(hWindow, NULL);
-   DrawMenuBar(hWindow);
-
-   mCanvas = NULL;
-}
-
-#endif

+ 0 - 746
Engine/source/platformWin32/menus/popupMenuWin32.cpp

@@ -1,746 +0,0 @@
-//-----------------------------------------------------------------------------
-// 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.
-//-----------------------------------------------------------------------------
-
-#ifndef TORQUE_SDL
-
-#include "platform/menus/popupMenu.h"
-#include "platformWin32/platformWin32.h"
-#include "console/engineAPI.h"
-#include "console/consoleTypes.h"
-#include "gui/core/guiCanvas.h"
-#include "windowManager/platformWindowMgr.h"
-#include "windowManager/win32/win32Window.h"
-#include "core/util/safeDelete.h"
-
-#include "sim/actionMap.h"
-#include "platform/platformInput.h"
-
-//////////////////////////////////////////////////////////////////////////
-// Platform Menu Data
-//////////////////////////////////////////////////////////////////////////
-
-struct PlatformPopupMenuData
-{
-   static U32 mLastPopupMenuID;
-   static const U32 PopupMenuIDRange;
-
-   HMENU mMenu;
-   U32 mMenuID;
-   U32 mLastID;
-
-   Win32Window::AcceleratorList mAccelerators;
-   Win32Window::AcceleratorList mDisabledAccelerators;
-
-   PlatformPopupMenuData()
-   {
-      mMenu = NULL;
-      mMenuID = mLastPopupMenuID++;
-      mLastID = 0;
-   }
-
-   ~PlatformPopupMenuData()
-   {
-      if(mMenu)
-         DestroyMenu(mMenu);
-   }
-
-   void insertAccelerator(EventDescriptor &desc, U32 id);
-   void removeAccelerator(U32 id);
-   void setAccelleratorEnabled(U32 id, bool enabled);
-};
-
-U32 PlatformPopupMenuData::mLastPopupMenuID = 0;
-const U32 PlatformPopupMenuData::PopupMenuIDRange = 100;
-
-//////////////////////////////////////////////////////////////////////////
-
-void PlatformPopupMenuData::insertAccelerator(EventDescriptor &desc, U32 id)
-{
-   if(desc.eventType != SI_KEY)
-      return;
-
-   Win32Window::AcceleratorList::iterator i;
-   for(i = mAccelerators.begin();i != mAccelerators.end();++i)
-   {
-      if(i->mID == id)
-      {
-         // Update existing entry
-         i->mDescriptor.eventType = desc.eventType;
-         i->mDescriptor.eventCode = desc.eventCode;
-         i->mDescriptor.flags = desc.flags;
-         return;
-      }
-
-      if(i->mDescriptor.eventType == desc.eventType && i->mDescriptor.eventCode == desc.eventCode && i->mDescriptor.flags == desc.flags)
-      {
-         // Already have a matching accelerator, don't add another one
-         return;
-      }
-   }
-
-   Win32Window::Accelerator accel;
-   accel.mDescriptor = desc;
-   accel.mID = id;
-   mAccelerators.push_back(accel);
-}
-
-void PlatformPopupMenuData::removeAccelerator(U32 id)
-{
-   Win32Window::AcceleratorList::iterator i;
-   for(i = mAccelerators.begin();i != mAccelerators.end();++i)
-   {
-      if(i->mID == id)
-      {
-         mAccelerators.erase(i);
-         return;
-      }
-   }
-}
-
-void PlatformPopupMenuData::setAccelleratorEnabled( U32 id, bool enabled )
-{   
-   Win32Window::AcceleratorList *src = NULL;
-   Win32Window::AcceleratorList *dst = NULL;
-   
-   if ( enabled )
-   {
-      src = &mDisabledAccelerators;
-      dst = &mAccelerators;
-   }
-   else
-   {
-      src = &mAccelerators;
-      dst = &mDisabledAccelerators;
-   }
-
-   Win32Window::AcceleratorList::iterator i;
-   for ( i = src->begin(); i != src->end(); ++i )
-   {
-      if ( i->mID == id )
-      {
-         Win32Window::Accelerator tmp = *i;
-         src->erase( i );
-         dst->push_back( tmp );
-         return;
-      }
-   }
-}
-
-//////////////////////////////////////////////////////////////////////////
-
-void PopupMenu::createPlatformPopupMenuData()
-{
-   mData = new PlatformPopupMenuData;
-}
-
-void PopupMenu::deletePlatformPopupMenuData()
-{
-   SAFE_DELETE(mData);
-}
-void PopupMenu::createPlatformMenu()
-{
-   mData->mMenu = mIsPopup ? CreatePopupMenu() : CreateMenu();
-   AssertFatal(mData->mMenu, "Unable to create menu");
-
-   MENUINFO mi = { 0 };
-   mi.cbSize = sizeof(mi);
-   mi.fMask = MIM_MENUDATA;
-   mi.dwMenuData = (ULONG_PTR)this;
-   SetMenuInfo(mData->mMenu, &mi);
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Public Methods
-//////////////////////////////////////////////////////////////////////////
-
-S32 PopupMenu::insertItem(S32 pos, const char *title, const char* accelerator, const char *)
-{
-   Win32Window *pWindow = mCanvas ? dynamic_cast<Win32Window*>(mCanvas->getPlatformWindow()) : NULL;
-   bool isAttached = isAttachedToMenuBar();
-   if(isAttached && pWindow == NULL)
-      return -1;
-
-   MENUITEMINFOA mi = { 0 };
-   mi.cbSize = sizeof(mi);
-   mi.fMask = MIIM_ID|MIIM_TYPE;
-   mi.wID = (mData->mMenuID * PlatformPopupMenuData::PopupMenuIDRange) + mData->mLastID + 1;
-   mData->mLastID++;
-   if(title && *title)
-      mi.fType = MFT_STRING;
-   else
-      mi.fType = MFT_SEPARATOR;
-   
-   char buf[1024];
-   if(accelerator && *accelerator)
-   {
-      dSprintf(buf, sizeof(buf), "%s\t%s", title, accelerator);
-
-      if(isAttached)
-         pWindow->removeAccelerators(mData->mAccelerators);
-
-      // Build entry for accelerator table
-      EventDescriptor accelDesc;
-      if(ActionMap::createEventDescriptor(accelerator, &accelDesc))
-         mData->insertAccelerator(accelDesc, mi.wID);
-      else
-         Con::errorf("PopupMenu::insertItem - Could not create event descriptor for accelerator \"%s\"", accelerator);
-
-      if(isAttached)
-         pWindow->addAccelerators(mData->mAccelerators);
-   }
-   else
-      dSprintf(buf, sizeof(buf), "%s", title);
-
-   mi.dwTypeData = (LPSTR)buf;
-
-   if(InsertMenuItemA(mData->mMenu, pos, TRUE, &mi))
-   {
-      if(isAttached)
-      {
-         HWND hWindow = pWindow->getHWND();
-         DrawMenuBar(hWindow);
-      }
-      return mi.wID;
-   }
-
-   return -1;
-}
-
-S32 PopupMenu::insertSubMenu(S32 pos, const char *title, PopupMenu *submenu)
-{
-   Win32Window *pWindow = mCanvas ? dynamic_cast<Win32Window*>(mCanvas->getPlatformWindow()) : NULL;
-   bool isAttached = isAttachedToMenuBar();
-   if(isAttached && pWindow == NULL)
-      return -1;
-
-   for(S32 i = 0;i < mSubmenus->size();i++)
-   {
-      if(submenu == (*mSubmenus)[i])
-      {
-         Con::errorf("PopupMenu::insertSubMenu - Attempting to add submenu twice");
-         return -1;
-      }
-   }
-
-   MENUITEMINFOA mi;
-   mi.cbSize = sizeof(mi);
-   mi.fMask = MIIM_ID|MIIM_TYPE|MIIM_SUBMENU|MIIM_DATA;
-   mi.wID = (mData->mMenuID * PlatformPopupMenuData::PopupMenuIDRange) + mData->mLastID + 1;
-   if(title && *title)
-      mi.fType = MFT_STRING;
-   else
-      mi.fType = MFT_SEPARATOR;
-   mi.dwTypeData = (LPSTR)title;
-   mi.hSubMenu = submenu->mData->mMenu;
-   mi.dwItemData = (ULONG_PTR)submenu;
-   if(InsertMenuItemA(mData->mMenu, pos, TRUE, &mi))
-   {
-      mSubmenus->addObject(submenu);
-
-      if(isAttached)
-      {
-         pWindow->addAccelerators(submenu->mData->mAccelerators);
-
-         HWND hWindow = pWindow->getHWND();
-         DrawMenuBar(hWindow);
-      }
-      return mi.wID;
-   }
-
-   return -1;
-}
-
-bool PopupMenu::setItem(S32 pos, const char *title, const char* accelerator, const char *)
-{
-   Win32Window *pWindow = mCanvas ? dynamic_cast<Win32Window*>(mCanvas->getPlatformWindow()) : NULL;
-   bool isAttached = isAttachedToMenuBar();
-   if(isAttached && pWindow == NULL)
-      return false;
-
-   // Are we out of range?
-   if ( pos >= getItemCount() )
-      return false;
-
-   MENUITEMINFOA mi;
-   mi.cbSize = sizeof(mi);
-   mi.fMask = MIIM_TYPE;
-
-   if(title && *title)
-      mi.fType = MFT_STRING;
-   else
-      mi.fType = MFT_SEPARATOR;
-
-   char buf[1024];
-   if(accelerator && *accelerator)
-   {
-      dSprintf(buf, sizeof(buf), "%s\t%s", title, accelerator);
-
-      if(isAttached)
-         pWindow->removeAccelerators(mData->mAccelerators);
-
-      // Build entry for accelerator table
-      EventDescriptor accelDesc;
-      if(ActionMap::createEventDescriptor(accelerator, &accelDesc))
-         mData->insertAccelerator(accelDesc, pos);
-      else
-         Con::errorf("PopupMenu::setItem - Could not create event descriptor for accelerator \"%s\"", accelerator);
-
-      if(isAttached)
-         pWindow->addAccelerators(mData->mAccelerators);
-   }
-   else
-      dSprintf(buf, sizeof(buf), "%s", title);
-
-   mi.dwTypeData = (LPSTR)buf;
-
-   if(SetMenuItemInfoA(mData->mMenu, pos, TRUE, &mi))
-   {
-      if(isAttached)
-      {
-         HWND hWindow = pWindow->getHWND();
-         DrawMenuBar(hWindow);
-      }
-
-      return true;
-   }
-
-   return false;
-}
-
-void PopupMenu::removeItem(S32 itemPos)
-{
-   Win32Window *pWindow = mCanvas ? dynamic_cast<Win32Window*>(mCanvas->getPlatformWindow()) : NULL;
-   bool isAttached = isAttachedToMenuBar();
-   if(isAttached && pWindow == NULL)
-      return;
-   
-   MENUITEMINFOA mi;
-   mi.cbSize = sizeof(mi);
-   mi.fMask = MIIM_DATA|MIIM_ID;
-   if(GetMenuItemInfoA(mData->mMenu, itemPos, TRUE, &mi))
-   {
-      bool submenu = false;
-
-      // Update list of submenus if this is a submenu
-      if(mi.fMask & MIIM_DATA)
-      {
-         PopupMenu *mnu = (PopupMenu *)mi.dwItemData;
-         if( mnu != NULL )
-         {
-            if(isAttached)
-               pWindow->removeAccelerators(mnu->mData->mAccelerators);
-            mSubmenus->removeObject(mnu);
-
-            submenu = true;
-         }
-      }
-
-      if(! submenu)
-      {
-         // Update accelerators if this has an accelerator and wasn't a sub menu
-         for(S32 i = 0;i < mData->mAccelerators.size();++i)
-         {
-            if(mData->mAccelerators[i].mID == mi.wID)
-            {
-               if(isAttached)
-                  pWindow->removeAccelerators(mData->mAccelerators);
-
-               mData->mAccelerators.erase(i);
-
-               if(isAttached)
-                  pWindow->addAccelerators(mData->mAccelerators);
-
-               break;
-            }
-         }
-      }
-   }
-   else
-      return;
-
-   RemoveMenu(mData->mMenu, itemPos, MF_BYPOSITION);
-
-   if(isAttached)
-   {
-      HWND hWindow = pWindow->getHWND();
-      DrawMenuBar(hWindow);
-   }
-}
-
-//////////////////////////////////////////////////////////////////////////
-
-void PopupMenu::enableItem( S32 pos, bool enable )
-{
-   U32 flags = enable ? MF_ENABLED : MF_GRAYED;
-   EnableMenuItem( mData->mMenu, pos, MF_BYPOSITION|flags );
-
-   // Update accelerators.
-
-   // NOTE: This really DOES need to happen. A disabled menu item
-   // should not still have an accelerator mapped to it. 
-   //
-   // Unfortunately, the editors currently only set menu items 
-   // enabled/disabled when the menu itself is selected which means our 
-   // accelerators would be out of synch.
-
-   /*
-   Win32Window *pWindow = mCanvas ? dynamic_cast<Win32Window*>( mCanvas->getPlatformWindow() ) : NULL;
-   bool isAttached = isAttachedToMenuBar();
-   if ( isAttached && pWindow == NULL )
-      return;
-
-   MENUITEMINFOA mi;
-   mi.cbSize = sizeof(mi);
-   mi.fMask = MIIM_DATA|MIIM_ID;
-   if ( !GetMenuItemInfoA( mData->mMenu, pos, TRUE, &mi) )
-      return;
-
-   if ( isAttached )
-      pWindow->removeAccelerators( mData->mAccelerators );
-
-   mData->setAccelleratorEnabled( mi.wID, enable );
-
-   if ( isAttached )
-      pWindow->addAccelerators( mData->mAccelerators );
-   */
-}
-
-void PopupMenu::checkItem(S32 pos, bool checked)
-{
-//    U32 flags = checked ? MF_CHECKED : MF_UNCHECKED;
-//    CheckMenuItem(mData->mMenu, pos, MF_BYPOSITION|flags);
-
-   MENUITEMINFOA mi;
-   mi.cbSize = sizeof(mi);
-   mi.fMask = MIIM_STATE;
-   mi.fState = checked ? MFS_CHECKED : MFS_UNCHECKED;
-   SetMenuItemInfoA(mData->mMenu, pos, TRUE, &mi);
-}
-
-void PopupMenu::checkRadioItem(S32 firstPos, S32 lastPos, S32 checkPos)
-{
-   CheckMenuRadioItem(mData->mMenu, firstPos, lastPos, checkPos, MF_BYPOSITION);
-}
-
-bool PopupMenu::isItemChecked(S32 pos)
-{
-   MENUITEMINFOA mi;
-   mi.cbSize = sizeof(mi);
-   mi.fMask = MIIM_STATE;
-   if(GetMenuItemInfoA(mData->mMenu, pos, TRUE, &mi) && (mi.fState & MFS_CHECKED))
-      return true;
-   return false;
-}
-
-U32 PopupMenu::getItemCount()
-{
-   return GetMenuItemCount( mData->mMenu );
-}
-
-//////////////////////////////////////////////////////////////////////////
-
-bool PopupMenu::canHandleID(U32 id)
-{
-   for(S32 i = 0;i < mSubmenus->size();i++)
-   {
-      PopupMenu *subM = dynamic_cast<PopupMenu *>((*mSubmenus)[i]);
-      if(subM == NULL)
-         continue;
-
-      if(subM->canHandleID(id))
-         return true;
-   }
-
-   if(id >= mData->mMenuID * PlatformPopupMenuData::PopupMenuIDRange &&
-      id < (mData->mMenuID+1) * PlatformPopupMenuData::PopupMenuIDRange)
-   {
-      return true;
-   }
-
-   return false;
-}
-
-bool PopupMenu::handleSelect(U32 command, const char *text /* = NULL */)
-{
-   // [tom, 8/20/2006] Pass off to a sub menu if it's for them
-   for(S32 i = 0;i < mSubmenus->size();i++)
-   {
-      PopupMenu *subM = dynamic_cast<PopupMenu *>((*mSubmenus)[i]);
-      if(subM == NULL)
-         continue;
-
-      if(subM->canHandleID(command))
-      {
-         return subM->handleSelect(command, text);
-      }
-   }
-
-   // [tom, 8/21/2006] Cheesey hack to find the position based on ID
-   char buf[512];
-   MENUITEMINFOA mi;
-   mi.cbSize = sizeof(mi);
-   mi.dwTypeData = NULL;
-
-   S32 numItems = GetMenuItemCount(mData->mMenu);
-   S32 pos = -1;
-   for(S32 i = 0;i < numItems;i++)
-   {
-      mi.fMask = MIIM_ID|MIIM_STRING|MIIM_STATE;
-      if(GetMenuItemInfoA(mData->mMenu, i, TRUE, &mi))
-      {
-         if(mi.wID == command)
-         {
-            if(text == NULL)
-            {
-               mi.dwTypeData = buf;
-               mi.cch++;
-               GetMenuItemInfoA(mData->mMenu, i, TRUE, &mi);
-               
-               // [tom, 5/11/2007] Don't do anything if the menu item is disabled
-               if(mi.fState & MFS_DISABLED)
-                  return false;
-
-               text = StringTable->insert(mi.dwTypeData);
-            }
-            pos = i;
-            break;
-         }
-      }
-   }
-
-   if(pos == -1)
-   {
-      Con::errorf("PopupMenu::handleSelect - Could not find menu item position for ID %d ... this shouldn't happen!", command);
-      return false;
-   }
-
-   // [tom, 8/20/2006] Wasn't handled by a submenu, pass off to script
-   return dAtob(Con::executef(this, "onSelectItem", Con::getIntArg(pos), text ? text : ""));
-}
-
-//////////////////////////////////////////////////////////////////////////
-
-void PopupMenu::showPopup(GuiCanvas *owner, S32 x /* = -1 */, S32 y /* = -1 */)
-{
-   if( owner == NULL )
-   {
-      Con::warnf("PopupMenu::showPopup - Invalid canvas supplied!");
-      return;
-   }
-
-   // [tom, 6/4/2007] showPopup() blocks until the menu is closed by the user, 
-   // so the canvas pointer is not needed beyond the scope of this function
-   // when working with context menus. Setting mCanvas here will cause undesired
-   // behavior in relation to the menu bar.
-
-   Win32Window *pWindow = dynamic_cast<Win32Window*>(owner->getPlatformWindow());
-   if(pWindow == NULL)
-      return;
-   HWND hWindow = pWindow->getHWND();
-   POINT p;
-   if(x == -1 && y == -1)
-      GetCursorPos(&p);
-   else
-   {
-      p.x = x;
-      p.y = y;
-      ClientToScreen(hWindow, &p);
-   }
-
-   winState.renderThreadBlocked = true;
-   U32 opt = (int)TrackPopupMenu(mData->mMenu, TPM_NONOTIFY|TPM_RETURNCMD, p.x, p.y, 0, hWindow, NULL);
-   if(opt > 0)
-      handleSelect(opt, NULL);
-   winState.renderThreadBlocked = false;
-}
-
-//////////////////////////////////////////////////////////////////////////
-
-void PopupMenu::attachToMenuBar(GuiCanvas *owner, S32 pos, const char *title)
-{
-   if(owner == NULL || isAttachedToMenuBar())
-      return;
-
-   // This is set for sub-menus in the onAttachToMenuBar() callback
-   mCanvas = owner;
-
-   Win32Window *pWindow = dynamic_cast<Win32Window*>(owner->getPlatformWindow());
-   if(pWindow == NULL) 
-      return;
-
-   HMENU hWindowMenu = pWindow->getMenuHandle();
-   if(hWindowMenu == NULL)
-   {
-      hWindowMenu = CreateMenu();
-      if(hWindowMenu)
-      {
-         pWindow->setMenuHandle( hWindowMenu);
-      }
-   }
-
-   MENUITEMINFOA mii;
-
-   mii.cbSize = sizeof(MENUITEMINFOA);
-
-   mii.fMask = MIIM_STRING|MIIM_DATA;
-   mii.dwTypeData = (LPSTR)title;
-   mii.fMask |= MIIM_ID;
-   mii.wID = mData->mMenuID;
-   mii.fMask |= MIIM_SUBMENU;
-   mii.hSubMenu = mData->mMenu;
-   mii.dwItemData = (ULONG_PTR)this;
-
-   InsertMenuItemA(hWindowMenu, pos, TRUE, &mii);
-
-   HWND hWindow = pWindow->getHWND();
-   DrawMenuBar(hWindow);
-
-   pWindow->addAccelerators(mData->mAccelerators);
-
-   // Add accelerators for sub menus
-   for(SimSet::iterator i = mSubmenus->begin();i != mSubmenus->end();++i)
-   {
-      PopupMenu *submenu = dynamic_cast<PopupMenu *>(*i);
-      if(submenu == NULL)
-         continue;
-
-      pWindow->addAccelerators(submenu->mData->mAccelerators);
-   }
-
-   onAttachToMenuBar(owner, pos, title);
-}
-
-// New version of above for use by MenuBar class. Do not use yet.
-void PopupMenu::attachToMenuBar(GuiCanvas *owner, S32 pos)
-{
-   Win32Window *pWindow = dynamic_cast<Win32Window*>(owner->getPlatformWindow());
-   if(pWindow == NULL) 
-      return;
-
-	//When playing a journal, the system menu is not actually shown
-	if (Journal::IsPlaying())
-	{
-		onAttachToMenuBar(owner, pos, mBarTitle);
-		return;
-	}
-
-   HMENU hWindowMenu = pWindow->getMenuHandle();
-
-   MENUITEMINFOA mii;
-
-   mii.cbSize = sizeof(MENUITEMINFOA);
-
-   mii.fMask = MIIM_STRING|MIIM_DATA;
-   mii.dwTypeData = (LPSTR)mBarTitle;
-   mii.fMask |= MIIM_ID;
-   mii.wID = mData->mMenuID;
-   mii.fMask |= MIIM_SUBMENU;
-   mii.hSubMenu = mData->mMenu;
-   mii.dwItemData = (ULONG_PTR)this;
-
-   InsertMenuItemA(hWindowMenu, pos, TRUE, &mii);
-
-   pWindow->addAccelerators(mData->mAccelerators);
-
-   // Add accelerators for sub menus (have to do this here as it's platform specific)
-   for(SimSet::iterator i = mSubmenus->begin();i != mSubmenus->end();++i)
-   {
-      PopupMenu *submenu = dynamic_cast<PopupMenu *>(*i);
-      if(submenu == NULL)
-         continue;
-
-      pWindow->addAccelerators(submenu->mData->mAccelerators);
-   }
-
-   onAttachToMenuBar(owner, pos, mBarTitle);
-}
-
-void PopupMenu::removeFromMenuBar()
-{
-   S32 pos = getPosOnMenuBar();
-   if(pos == -1)
-      return;
-
-   Win32Window *pWindow = mCanvas ? dynamic_cast<Win32Window*>(mCanvas->getPlatformWindow()) : NULL;
-   if(pWindow == NULL)
-      return;
-
-   HMENU hMenuHandle = pWindow->getMenuHandle();
-   if(!hMenuHandle)
-      return;
-
-   RemoveMenu(hMenuHandle, pos, MF_BYPOSITION);
-
-   HWND hWindow = pWindow->getHWND();
-
-   DrawMenuBar(hWindow);
-
-   pWindow->removeAccelerators(mData->mAccelerators);
-
-   // Remove accelerators for sub menus
-   for(SimSet::iterator i = mSubmenus->begin();i != mSubmenus->end();++i)
-   {
-      PopupMenu *submenu = dynamic_cast<PopupMenu *>(*i);
-      if(submenu == NULL)
-         continue;
-
-      pWindow->removeAccelerators(submenu->mData->mAccelerators);
-   }
-
-   onRemoveFromMenuBar(mCanvas);
-}
-
-S32 PopupMenu::getPosOnMenuBar()
-{
-   if(mCanvas == NULL)
-      return -1;
-
-   Win32Window *pWindow = mCanvas ? dynamic_cast<Win32Window*>(mCanvas->getPlatformWindow()) : NULL;
-   if(pWindow == NULL) 
-      return -1;
-
-   HMENU hMenuHandle = pWindow->getMenuHandle();
-   S32 numItems = GetMenuItemCount(hMenuHandle);
-   S32 pos = -1;
-   for(S32 i = 0;i < numItems;i++)
-   {
-      MENUITEMINFOA mi;
-      mi.cbSize = sizeof(mi);
-      mi.fMask = MIIM_DATA;
-      if(GetMenuItemInfoA(hMenuHandle, i, TRUE, &mi))
-      {
-         if(mi.fMask & MIIM_DATA)
-         {
-            PopupMenu *mnu = (PopupMenu *)mi.dwItemData;
-            if(mnu == this)
-            {
-               pos = i;
-               break;
-            }
-         }
-      }
-   }
-
-   return pos;
-}
-
-#endif

+ 0 - 1
Engine/source/windowManager/sdl/sdlWindow.cpp

@@ -27,7 +27,6 @@
 #include "windowManager/sdl/sdlWindowMgr.h"
 #include "windowManager/sdl/sdlCursorController.h"
 #include "platformSDL/sdlInput.h"
-#include "platform/menus/popupMenu.h"
 #include "platform/platformInput.h"
 
 #include "gfx/gfxDevice.h"

+ 0 - 1
Templates/BaseGame/game/tools/gui/guiDialogs.ed.cs

@@ -35,5 +35,4 @@ exec("./GuiEaseEditDlg.ed.cs");
 exec("./guiObjectInspector.ed.cs");
 exec("./uvEditor.ed.gui");
 exec("./objectSelection.ed.cs");
-exec("./guiPlatformGenericMenubar.ed.cs");
 exec("./postFxManager.gui");

+ 0 - 19
Templates/BaseGame/game/tools/gui/guiPlatformGenericMenubar.ed.cs

@@ -1,19 +0,0 @@
-if(isClass(GuiPlatformGenericMenuBar))
-{
-   exec("./guiPlatformGenericMenubar.ed.gui");
-}
-else
-{
-   %guiContent = new GuiControl(PlatformGenericMenubar) {
-      profile = "GuiModelessDialogProfile";
-      
-      new GuiControl()
-      {
-         internalName = "menubar";
-         extent = "1024 20";
-         minExtent = "320 20";
-         horizSizing = "width";
-         profile = "GuiMenuBarProfile";
-      };
-   };
-}

+ 0 - 14
Templates/BaseGame/game/tools/gui/guiPlatformGenericMenubar.ed.gui

@@ -1,14 +0,0 @@
-//--- OBJECT WRITE BEGIN ---
-%guiContent = new GuiControl(PlatformGenericMenubar) {
-   profile = "GuiModelessDialogProfile";
-      
-   new GuiPlatformGenericMenuBar()
-   {
-      internalName = "menubar";
-      extent = "1024 20";
-      minExtent = "320 20";
-      horizSizing = "width";
-      profile = "GuiMenuBarProfile";
-   };
-};
-//--- OBJECT WRITE END ---

+ 5 - 1
Templates/BaseGame/game/tools/guiEditor/scripts/guiEditorCanvas.ed.cs

@@ -66,9 +66,13 @@ function GuiEditCanvas::onCreateMenu(%this)
    }
    
    // Menu bar
-   %this.menuBar = new MenuBar()
+   %this.menuBar = new GuiMenuBar(GuiEditorMenubar)
    {
       dynamicItemInsertPos = 3;
+      extent = "1024 20";
+      minExtent = "320 20";
+      horizSizing = "width";
+      profile = "GuiMenuBarProfile";
       
       new PopupMenu()
       {

+ 1 - 1
Templates/BaseGame/game/tools/worldEditor/scripts/EditorGui.ed.cs

@@ -2043,7 +2043,7 @@ function EWorldEditor::syncGui( %this )
    %this.syncToolPalette();
    
    EditorTree.update();
-   Editor.getUndoManager().updateUndoMenu( EditorGui.menuBar-->EditMenu );
+   Editor.getUndoManager().updateUndoMenu( EditorGui.findMenu("Edit") );
    EditorGuiStatusBar.setSelectionObjectsByCount( %this.getSelectionSize() );
    
    EWTreeWindow-->LockSelection.setStateOn( %this.getSelectionLockCount() > 0 );

+ 18 - 13
Templates/BaseGame/game/tools/worldEditor/scripts/menus.ed.cs

@@ -110,9 +110,13 @@ function EditorGui::buildMenus(%this)
    };
       
    // Menu bar
-   %this.menuBar = new MenuBar(WorldEditorMenubar)
+   %this.menuBar = new GuiMenuBar(WorldEditorMenubar)
    {
       dynamicItemInsertPos = 3;
+      extent = "1024 20";
+      minExtent = "320 20";
+      horizSizing = "width";
+      profile = "GuiMenuBarProfile";
    };
    
    // File Menu
@@ -158,7 +162,7 @@ function EditorGui::buildMenus(%this)
    %fileMenu.appendItem("Exit Level" TAB "" TAB "EditorExitMission();");
    %fileMenu.appendItem("Quit" TAB %quitShortcut TAB "EditorQuitGame();");
 
-   %this.menuBar.insert(%fileMenu, %this.menuBar.getCount());
+   %this.menuBar.insert(%fileMenu);
    
    // Edit Menu
    %editMenu = new PopupMenu()
@@ -187,7 +191,7 @@ function EditorGui::buildMenus(%this)
       item[15] = "Game Options..." TAB "" TAB "Canvas.pushDialog(optionsDlg);";
       item[16] = "PostEffect Manager" TAB "" TAB "Canvas.pushDialog(PostFXManager);";
    };
-   %this.menuBar.insert(%editMenu, %this.menuBar.getCount());
+   %this.menuBar.insert(%editMenu);
       
    // View Menu
    %viewMenu = new PopupMenu()
@@ -201,7 +205,7 @@ function EditorGui::buildMenus(%this)
       item[ 0 ] = "Visibility Layers" TAB "Alt V" TAB "VisibilityDropdownToggle();";
       item[ 1 ] = "Show Grid in Ortho Views" TAB %cmdCtrl @ "-Shift-Alt G" TAB "EditorGui.toggleOrthoGrid();";
    };
-   %this.menuBar.insert(%viewMenu, %this.menuBar.getCount());
+   %this.menuBar.insert(%viewMenu);
       
    // Camera Menu
    %cameraMenu = new PopupMenu()
@@ -229,7 +233,7 @@ function EditorGui::buildMenus(%this)
       Item[15] = "Manage Bookmarks..." TAB "Ctrl-Shift B" TAB "EditorGui.toggleCameraBookmarkWindow();";
       item[16] = "Jump to Bookmark" TAB %this.cameraBookmarksMenu;
    };
-   %this.menuBar.insert(%cameraMenu, %this.menuBar.getCount());
+   %this.menuBar.insert(%cameraMenu);
       
    // Editors Menu
    %editorsMenu = new PopupMenu()
@@ -246,7 +250,7 @@ function EditorGui::buildMenus(%this)
          //item[4] = "Terrain Painter" TAB "F4" TAB TerrainPainterPlugin;
          //item[5] = "-";
    };
-   %this.menuBar.insert(%editorsMenu, %this.menuBar.getCount());
+   %this.menuBar.insert(%editorsMenu);
       
    // Lighting Menu
    %lightingMenu = new PopupMenu()
@@ -263,7 +267,7 @@ function EditorGui::buildMenus(%this)
          // NOTE: The light managers will be inserted as the
          // last menu items in EditorLightingMenu::onAdd().
    };
-   %this.menuBar.insert(%lightingMenu, %this.menuBar.getCount());
+   %this.menuBar.insert(%lightingMenu);
    
    // Tools Menu
    %toolsMenu = new PopupMenu()
@@ -278,7 +282,7 @@ function EditorGui::buildMenus(%this)
 	  item[2] = "Torque SimView" TAB "" TAB "tree();";
       item[3] = "Make Selected a Mesh" TAB "" TAB "makeSelectedAMesh();";
    };
-   %this.menuBar.insert(%toolsMenu, %this.menuBar.getCount());
+   %this.menuBar.insert(%toolsMenu);
       
    // Help Menu
    %helpMenu = new PopupMenu()
@@ -293,7 +297,7 @@ function EditorGui::buildMenus(%this)
       item[2] = "Offline Reference Guide..." TAB "" TAB "shellexecute(EWorldEditor.documentationReference);";
       item[3] = "Torque 3D Forums..." TAB "" TAB "gotoWebPage(EWorldEditor.forumURL);";
    };
-   %this.menuBar.insert(%helpMenu, %this.menuBar.getCount());
+   %this.menuBar.insert(%helpMenu);
    
    // Menus that are added/removed dynamically (temporary)
    
@@ -398,9 +402,9 @@ function EditorGui::setMenuDefaultState(%this)
    if(! isObject(%this.menuBar))
       return 0;
       
-   for(%i = 0;%i < %this.menuBar.getCount();%i++)
+   for(%i = 0;%i < %this.menuBar.getMenuCount();%i++)
    {
-      %menu = %this.menuBar.getObject(%i);
+      %menu = %this.menuBar.getMenu(%i);
       %menu.setupDefaultState();
    }
    
@@ -414,9 +418,10 @@ function EditorGui::findMenu(%this, %name)
    if(! isObject(%this.menuBar))
       return 0;
       
-   for(%i = 0;%i < %this.menuBar.getCount();%i++)
+   
+   for(%i = 0; %i < %this.menuBar.getMenuCount(); %i++)
    {
-      %menu = %this.menuBar.getObject(%i);
+      %menu = %this.menuBar.getMenu(%i);
       
       if(%name $= %menu.barTitle)
          return %menu;

+ 0 - 1
Templates/Full/game/tools/gui/guiDialogs.ed.cs

@@ -35,4 +35,3 @@ exec("./GuiEaseEditDlg.ed.cs");
 exec("./guiObjectInspector.ed.cs");
 exec("./uvEditor.ed.gui");
 exec("./objectSelection.ed.cs");
-exec("./guiPlatformGenericMenubar.ed.cs");

+ 0 - 19
Templates/Full/game/tools/gui/guiPlatformGenericMenubar.ed.cs

@@ -1,19 +0,0 @@
-if(isClass(GuiPlatformGenericMenuBar))
-{
-   exec("./guiPlatformGenericMenubar.ed.gui");
-}
-else
-{
-   %guiContent = new GuiControl(PlatformGenericMenubar) {
-      profile = "GuiModelessDialogProfile";
-      
-      new GuiControl()
-      {
-         internalName = "menubar";
-         extent = "1024 20";
-         minExtent = "320 20";
-         horizSizing = "width";
-         profile = "GuiMenuBarProfile";
-      };
-   };
-}

+ 0 - 14
Templates/Full/game/tools/gui/guiPlatformGenericMenubar.ed.gui

@@ -1,14 +0,0 @@
-//--- OBJECT WRITE BEGIN ---
-%guiContent = new GuiControl(PlatformGenericMenubar) {
-   profile = "GuiModelessDialogProfile";
-      
-   new GuiPlatformGenericMenuBar()
-   {
-      internalName = "menubar";
-      extent = "1024 20";
-      minExtent = "320 20";
-      horizSizing = "width";
-      profile = "GuiMenuBarProfile";
-   };
-};
-//--- OBJECT WRITE END ---

+ 5 - 1
Templates/Full/game/tools/guiEditor/scripts/guiEditorCanvas.ed.cs

@@ -66,9 +66,13 @@ function GuiEditCanvas::onCreateMenu(%this)
    }
    
    // Menu bar
-   %this.menuBar = new MenuBar()
+   %this.menuBar = new GuiMenuBar(GuiEditorMenubar)
    {
       dynamicItemInsertPos = 3;
+      extent = "1024 20";
+      minExtent = "320 20";
+      horizSizing = "width";
+      profile = "GuiMenuBarProfile";
       
       new PopupMenu()
       {

+ 1 - 1
Templates/Full/game/tools/worldEditor/scripts/EditorGui.ed.cs

@@ -2017,7 +2017,7 @@ function EWorldEditor::syncGui( %this )
    %this.syncToolPalette();
    
    EditorTree.update();
-   Editor.getUndoManager().updateUndoMenu( EditorGui.menuBar-->EditMenu );
+   Editor.getUndoManager().updateUndoMenu( EditorGui.findMenu("Edit") );
    EditorGuiStatusBar.setSelectionObjectsByCount( %this.getSelectionSize() );
    
    EWTreeWindow-->LockSelection.setStateOn( %this.getSelectionLockCount() > 0 );

+ 18 - 13
Templates/Full/game/tools/worldEditor/scripts/menus.ed.cs

@@ -110,9 +110,13 @@ function EditorGui::buildMenus(%this)
    };
       
    // Menu bar
-   %this.menuBar = new MenuBar(WorldEditorMenubar)
+   %this.menuBar = new GuiMenuBar(WorldEditorMenubar)
    {
       dynamicItemInsertPos = 3;
+      extent = "1024 20";
+      minExtent = "320 20";
+      horizSizing = "width";
+      profile = "GuiMenuBarProfile";
    };
    
    // File Menu
@@ -158,7 +162,7 @@ function EditorGui::buildMenus(%this)
    %fileMenu.appendItem("Exit Level" TAB "" TAB "EditorExitMission();");
    %fileMenu.appendItem("Quit" TAB %quitShortcut TAB "EditorQuitGame();");
 
-   %this.menuBar.insert(%fileMenu, %this.menuBar.getCount());
+   %this.menuBar.insert(%fileMenu);
    
    // Edit Menu
    %editMenu = new PopupMenu()
@@ -187,7 +191,7 @@ function EditorGui::buildMenus(%this)
       item[15] = "Game Options..." TAB "" TAB "Canvas.pushDialog(optionsDlg);";
       item[16] = "PostEffect Manager" TAB "" TAB "Canvas.pushDialog(PostFXManager);";
    };
-   %this.menuBar.insert(%editMenu, %this.menuBar.getCount());
+   %this.menuBar.insert(%editMenu);
       
    // View Menu
    %viewMenu = new PopupMenu()
@@ -201,7 +205,7 @@ function EditorGui::buildMenus(%this)
       item[ 0 ] = "Visibility Layers" TAB "Alt V" TAB "VisibilityDropdownToggle();";
       item[ 1 ] = "Show Grid in Ortho Views" TAB %cmdCtrl @ "-Shift-Alt G" TAB "EditorGui.toggleOrthoGrid();";
    };
-   %this.menuBar.insert(%viewMenu, %this.menuBar.getCount());
+   %this.menuBar.insert(%viewMenu);
       
    // Camera Menu
    %cameraMenu = new PopupMenu()
@@ -229,7 +233,7 @@ function EditorGui::buildMenus(%this)
       Item[15] = "Manage Bookmarks..." TAB "Ctrl-Shift B" TAB "EditorGui.toggleCameraBookmarkWindow();";
       item[16] = "Jump to Bookmark" TAB %this.cameraBookmarksMenu;
    };
-   %this.menuBar.insert(%cameraMenu, %this.menuBar.getCount());
+   %this.menuBar.insert(%cameraMenu);
       
    // Editors Menu
    %editorsMenu = new PopupMenu()
@@ -246,7 +250,7 @@ function EditorGui::buildMenus(%this)
          //item[4] = "Terrain Painter" TAB "F4" TAB TerrainPainterPlugin;
          //item[5] = "-";
    };
-   %this.menuBar.insert(%editorsMenu, %this.menuBar.getCount());
+   %this.menuBar.insert(%editorsMenu);
       
    // Lighting Menu
    %lightingMenu = new PopupMenu()
@@ -263,7 +267,7 @@ function EditorGui::buildMenus(%this)
          // NOTE: The light managers will be inserted as the
          // last menu items in EditorLightingMenu::onAdd().
    };
-   %this.menuBar.insert(%lightingMenu, %this.menuBar.getCount());
+   %this.menuBar.insert(%lightingMenu);
    
    // Tools Menu
    %toolsMenu = new PopupMenu()
@@ -278,7 +282,7 @@ function EditorGui::buildMenus(%this)
 	  item[2] = "Torque SimView" TAB "" TAB "tree();";
       item[3] = "Make Selected a Mesh" TAB "" TAB "makeSelectedAMesh();";
    };
-   %this.menuBar.insert(%toolsMenu, %this.menuBar.getCount());
+   %this.menuBar.insert(%toolsMenu);
       
    // Help Menu
    %helpMenu = new PopupMenu()
@@ -293,7 +297,7 @@ function EditorGui::buildMenus(%this)
       item[2] = "Offline Reference Guide..." TAB "" TAB "shellexecute(EWorldEditor.documentationReference);";
       item[3] = "Torque 3D Forums..." TAB "" TAB "gotoWebPage(EWorldEditor.forumURL);";
    };
-   %this.menuBar.insert(%helpMenu, %this.menuBar.getCount());
+   %this.menuBar.insert(%helpMenu);
    
    // Menus that are added/removed dynamically (temporary)
    
@@ -398,9 +402,9 @@ function EditorGui::setMenuDefaultState(%this)
    if(! isObject(%this.menuBar))
       return 0;
       
-   for(%i = 0;%i < %this.menuBar.getCount();%i++)
+   for(%i = 0;%i < %this.menuBar.getMenuCount();%i++)
    {
-      %menu = %this.menuBar.getObject(%i);
+      %menu = %this.menuBar.getMenu(%i);
       %menu.setupDefaultState();
    }
    
@@ -414,9 +418,10 @@ function EditorGui::findMenu(%this, %name)
    if(! isObject(%this.menuBar))
       return 0;
       
-   for(%i = 0;%i < %this.menuBar.getCount();%i++)
+   
+   for(%i = 0; %i < %this.menuBar.getMenuCount(); %i++)
    {
-      %menu = %this.menuBar.getObject(%i);
+      %menu = %this.menuBar.getMenu(%i);
       
       if(%name $= %menu.barTitle)
          return %menu;