2
0
LuisAntonRebollo 10 жил өмнө
parent
commit
475f218bcd
33 өөрчлөгдсөн 436 нэмэгдсэн , 136 устгасан
  1. 1 1
      Engine/source/cinterface/cinterface.cpp
  2. 2 8
      Engine/source/gfx/D3D9/pc/gfxPCD3D9Device.cpp
  3. 2 4
      Engine/source/gfx/D3D9/pc/gfxPCD3D9Target.cpp
  4. 63 4
      Engine/source/gui/core/guiCanvas.cpp
  5. 4 0
      Engine/source/gui/core/guiCanvas.h
  6. 87 54
      Engine/source/gui/editor/guiMenuBar.cpp
  7. 19 12
      Engine/source/gui/editor/guiMenuBar.h
  8. 4 4
      Engine/source/platform/menus/popupMenu.cpp
  9. 2 2
      Engine/source/platform/menus/popupMenu.h
  10. 1 0
      Engine/source/platform/nativeDialogs/msgBox.h
  11. 10 0
      Engine/source/platform/platform.h
  12. 60 41
      Engine/source/platform/platformAssert.cpp
  13. 1 0
      Engine/source/platform/platformAssert.h
  14. 4 0
      Engine/source/platformWin32/menus/menuBarWin32.cpp
  15. 5 2
      Engine/source/platformWin32/menus/popupMenuWin32.cpp
  16. 2 1
      Engine/source/platformWin32/nativeDialogs/win32MsgBox.cpp
  17. 4 0
      Engine/source/platformWin32/winExec.cpp
  18. 2 0
      Engine/source/platformWin32/winInput.cpp
  19. 38 0
      Engine/source/platformWin32/winWindow.cpp
  20. 1 0
      Engine/source/platformX86UNIX/x86UNIXStub.dedicated.cpp
  21. 1 1
      Engine/source/windowManager/platformInterface.cpp
  22. 11 0
      Engine/source/windowManager/platformWindow.h
  23. 3 1
      Engine/source/windowManager/win32/win32SplashScreen.cpp
  24. 12 0
      Engine/source/windowManager/win32/win32Window.cpp
  25. 2 0
      Engine/source/windowManager/win32/win32Window.h
  26. 5 1
      Engine/source/windowManager/win32/win32WindowMgr.cpp
  27. 5 0
      Engine/source/windowManager/win32/winDispatch.cpp
  28. 13 0
      Engine/source/windowManager/windowInputGenerator.cpp
  29. 46 0
      Engine/source/windowManager/windowInputGenerator.h
  30. 1 0
      Templates/Empty/game/tools/gui/guiDialogs.ed.cs
  31. 12 0
      Templates/Empty/game/tools/gui/profiles.ed.cs
  32. 1 0
      Templates/Full/game/tools/gui/guiDialogs.ed.cs
  33. 12 0
      Templates/Full/game/tools/gui/profiles.ed.cs

+ 1 - 1
Engine/source/cinterface/cinterface.cpp

@@ -427,7 +427,7 @@ extern "C" {
 			PlatformWindowManager::get()->getFirstWindow()->setSize(Point2I(width,height));
 	}
 
-#ifdef TORQUE_OS_WIN
+#if defined(TORQUE_OS_WIN) && !defined(TORQUE_SDL)
    // retrieve the hwnd of our render window
    void* torque_gethwnd()
    {

+ 2 - 8
Engine/source/gfx/D3D9/pc/gfxPCD3D9Device.cpp

@@ -332,10 +332,8 @@ void GFXPCD3D9Device::init( const GFXVideoMode &mode, PlatformWindow *window /*
 
    initD3DXFnTable();
 
-   Win32Window *win = dynamic_cast<Win32Window*>( window );
-   AssertISV( win, "GFXD3D9Device::init - got a non Win32Window window passed in! Did DX go crossplatform?" );
-
-   HWND winHwnd = win->getHWND();
+   HWND winHwnd = (HWND)window->getSystemWindow( PlatformWindow::WindowSystem_Windows );
+   AssertISV(winHwnd, "GFXPCD3D9WindowTarget::initPresentationParams() - no HWND");
 
    // Create D3D Presentation params
    D3DPRESENT_PARAMETERS d3dpp = setupPresentParams( mode, winHwnd );
@@ -1021,10 +1019,6 @@ bool GFXPCD3D9Device::beginSceneInternal()
 GFXWindowTarget * GFXPCD3D9Device::allocWindowTarget( PlatformWindow *window )
 {
    AssertFatal(window,"GFXD3D9Device::allocWindowTarget - no window provided!");
-#ifndef TORQUE_OS_XENON
-   AssertFatal(dynamic_cast<Win32Window*>(window), 
-      "GFXD3D9Device::allocWindowTarget - only works with Win32Windows!");
-#endif
 
    // Set up a new window target...
    GFXPCD3D9WindowTarget *gdwt = new GFXPCD3D9WindowTarget();

+ 2 - 4
Engine/source/gfx/D3D9/pc/gfxPCD3D9Target.cpp

@@ -372,10 +372,8 @@ void GFXPCD3D9WindowTarget::initPresentationParams()
          "GFXPCD3D9WindowTarget::initPresentationParams - Cannot go fullscreen with secondary window!");
    }
 
-   Win32Window *win = dynamic_cast<Win32Window*>(mWindow);
-   AssertISV(win, "GFXPCD3D9WindowTarget::initPresentationParams() - got a non Win32Window window passed in! Did DX go crossplatform?");
-
-   HWND hwnd = win->getHWND();
+   HWND hwnd = (HWND)mWindow->getSystemWindow( PlatformWindow::WindowSystem_Windows );
+   AssertISV(hwnd, "GFXPCD3D9WindowTarget::initPresentationParams() - no HWND");
 
    // At some point, this will become GFXPCD3D9WindowTarget like trunk has,
    // so this cast isn't as bad as it looks. ;) BTR

+ 63 - 4
Engine/source/gui/core/guiCanvas.cpp

@@ -30,6 +30,7 @@
 #include "gfx/gfxDrawUtil.h"
 #include "gui/core/guiTypes.h"
 #include "gui/core/guiControl.h"
+#include "gui/editor/guiMenuBar.h"
 #include "console/consoleTypes.h"
 #include "gfx/screenshot.h"
 #include "gfx/video/videoCapture.h"
@@ -283,6 +284,8 @@ bool GuiCanvas::onAdd()
    mLastPurchaseHideTime = 0;
 #endif
 
+   Sim::findObject("PlatformGenericMenubar", mMenuBarCtrl);
+
    return parentRet;
 }
 
@@ -302,6 +305,34 @@ void GuiCanvas::onRemove()
    Parent::onRemove();
 }
 
+void GuiCanvas::setMenuBar(SimObject *obj)
+{
+    GuiControl *oldMenuBar = mMenuBarCtrl;
+    mMenuBarCtrl = dynamic_cast<GuiControl*>(obj);
+
+    //remove old menubar
+    if( oldMenuBar )
+        Parent::removeObject( oldMenuBar );
+
+    // set new menubar    
+    if( mMenuBarCtrl )
+        Parent::addObject(mMenuBarCtrl);
+
+    // 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() );
+    }
+}
+
 void GuiCanvas::setWindowTitle(const char *newTitle)
 {
    if (mPlatformWindow)
@@ -1023,7 +1054,7 @@ void GuiCanvas::rootMouseDown(const GuiEvent &event)
       {
          i--;
          GuiControl *ctrl = static_cast<GuiControl *>(*i);
-         GuiControl *controlHit = ctrl->findHitControl(event.mousePoint);
+         GuiControl *controlHit = ctrl->findHitControl( event.mousePoint - ctrl->getPosition() );
 
          //see if the controlHit is a modeless dialog...
          if( !controlHit->getControlProfile()->mModal )
@@ -1293,6 +1324,9 @@ void GuiCanvas::setContentControl(GuiControl *gui)
       Sim::getGuiGroup()->addObject( ctrl );
    }
 
+   // set current menu bar
+   setMenuBar( mMenuBarCtrl );
+
    // lose the first responder from the old GUI
    GuiControl* responder = gui->findFirstTabable();
    if(responder)
@@ -1556,10 +1590,27 @@ void GuiCanvas::maintainSizing()
       GuiControl *ctrl = static_cast<GuiControl*>(*i);
       Point2I ext = ctrl->getExtent();
       Point2I pos = ctrl->getPosition();
+      Point2I newExt = screenRect.extent;
+      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(pos != screenRect.point || ext != screenRect.extent)
+          if( !menu )
+              continue;
+
+          AssertFatal( dynamic_cast<const GuiControl*>(menu), "");
+
+          const U32 yOffset = static_cast<const GuiControl*>(menu)->getExtent().y;
+          newPos.y += yOffset;
+          newExt.y -= yOffset;
+      }
+
+      if(pos != newPos || ext != newExt)
       {
-         ctrl->resize(screenRect.point, screenRect.extent);
+         ctrl->resize(newPos, newExt);
          resetUpdateRegions();
       }
    }
@@ -2273,7 +2324,7 @@ DefineEngineFunction(excludeOtherInstance, bool, (const char* appIdentifer),,
 					 "@ingroup GuiCore")
 {
 	   // mac/360 can only run one instance in general.
-#if !defined(TORQUE_OS_MAC) && !defined(TORQUE_OS_XENON) && !defined(TORQUE_DEBUG)
+#if !defined(TORQUE_OS_MAC) && !defined(TORQUE_OS_XENON) && !defined(TORQUE_DEBUG) && !defined(TORQUE_OS_LINUX)
    return Platform::excludeOtherInstances(appIdentifer);
 #else
    // We can just return true if we get here.
@@ -2580,6 +2631,14 @@ DefineConsoleMethod( GuiCanvas, setFocus, void, (), , "() - Claim OS input focus
       window->setFocus();
 }
 
+DefineEngineMethod( GuiCanvas, setMenuBar, void, ( GuiControl* menu ),,
+   "Translate a coordinate from canvas window-space to screen-space.\n"
+   "@param coordinate The coordinate in window-space.\n"
+   "@return The given coordinate translated to screen-space." )
+{
+   return object->setMenuBar( menu );
+}
+
 DefineConsoleMethod( GuiCanvas, setVideoMode, void, 
                (U32 width, U32 height, bool fullscreen, U32 bitDepth, U32 refreshRate, U32 antialiasLevel), 
                ( false, 0, 0, 0),

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

@@ -190,6 +190,8 @@ protected:
    
    void checkLockMouseMove( const GuiEvent& event );
 
+   GuiControl *mMenuBarCtrl;
+
 public:
    DECLARE_CONOBJECT(GuiCanvas);
    DECLARE_CATEGORY( "Gui Core" );
@@ -200,6 +202,8 @@ public:
    virtual bool onAdd();
    virtual void onRemove();
 
+   void setMenuBar(SimObject *obj);
+
    static void initPersistFields();
 
    /// @name Rendering methods

+ 87 - 54
Engine/source/gui/editor/guiMenuBar.cpp

@@ -215,8 +215,8 @@ DefineEngineMethod(GuiMenuBar, addMenu, void, (const char* menuText, S32 menuId)
    object->addMenu(menuText, menuId);
 }
 
-DefineEngineMethod(GuiMenuBar, addMenuItem, void, (const char* targetMenu, const char* menuItemText, S32 menuItemId, const char* accelerator, int checkGroup),
-												 ("","",0,"",-1),
+DefineEngineMethod(GuiMenuBar, addMenuItem, void, (const char* targetMenu, const char* menuItemText, S32 menuItemId, const char* accelerator, int checkGroup, const char *cmd),
+												 ("","",0,NULL,-1,""),
    "@brief Adds a menu item to the specified menu.  The menu argument can be either the text of a menu or its id.\n\n"
    "@param menu Menu name or menu Id to add the new item to.\n"
    "@param menuItemText Text for the new menu item.\n"
@@ -250,7 +250,7 @@ DefineEngineMethod(GuiMenuBar, addMenuItem, void, (const char* targetMenu, const
       Con::errorf("Cannot find menu %s for addMenuItem.", targetMenu);
       return;
    }
-   object->addMenuItem(menu, menuItemText, menuItemId, accelerator != NULL ? accelerator : "", checkGroup == -1 ? -1 : checkGroup);
+   object->addMenuItem(menu, menuItemText, menuItemId, accelerator != NULL ? accelerator : "", checkGroup == -1 ? -1 : checkGroup, cmd);
 }
 
 DefineEngineMethod(GuiMenuBar, setMenuItemEnable, void, (const char* menuTarget, const char* menuItemTarget, bool enabled),,
@@ -767,7 +767,7 @@ DefineEngineMethod(GuiMenuBar, setSubmenuItemChecked, void, (const char* menuTar
    if(checked && submenuItem->checkGroup != -1)
    {
       // first, uncheck everything in the group:
-      for(GuiMenuBar::MenuItem *itemWalk = menuItem->firstSubmenuItem; itemWalk; itemWalk = itemWalk->nextMenuItem)
+      for(GuiMenuBar::MenuItem *itemWalk = menuItem->submenu->firstMenuItem; itemWalk; itemWalk = itemWalk->nextMenuItem)
          if(itemWalk->checkGroup == submenuItem->checkGroup && itemWalk->bitmapIndex == object->mCheckmarkBitmapIndex)
             itemWalk->bitmapIndex = -1;
    }
@@ -777,8 +777,7 @@ DefineEngineMethod(GuiMenuBar, setSubmenuItemChecked, void, (const char* menuTar
 //------------------------------------------------------------------------------
 // menu management methods
 //------------------------------------------------------------------------------
-
-void GuiMenuBar::addMenu(const char *menuText, U32 menuId)
+GuiMenuBar::Menu* GuiMenuBar::sCreateMenu(const char *menuText, U32 menuId)
 {
    // allocate the menu
    Menu *newMenu = new Menu;
@@ -792,7 +791,12 @@ void GuiMenuBar::addMenu(const char *menuText, U32 menuId)
    newMenu->bitmapIndex = -1;
    newMenu->drawBitmapOnly = false;
    newMenu->drawBorder = true;
-   
+
+   return newMenu;
+}
+
+void GuiMenuBar::addMenu(GuiMenuBar::Menu *newMenu)
+{
    // add it to the menu list
    menuBarDirty = true;
    Menu **walk;
@@ -801,6 +805,13 @@ void GuiMenuBar::addMenu(const char *menuText, U32 menuId)
    *walk = newMenu;
 }
 
+void GuiMenuBar::addMenu(const char *menuText, U32 menuId)
+{
+   Menu *newMenu = sCreateMenu(menuText, menuId);
+   
+   addMenu(newMenu);
+}
+
 GuiMenuBar::Menu *GuiMenuBar::findMenu(const char *menu)
 {
 	if(dIsdigit(menu[0]))
@@ -877,7 +888,7 @@ void GuiMenuBar::removeMenuItem(Menu *menu, MenuItem *menuItem)
    delete menuItem;
 }
 
-void GuiMenuBar::addMenuItem(Menu *menu, const char *text, U32 id, const char *accelerator, S32 checkGroup)
+GuiMenuBar::MenuItem* GuiMenuBar::addMenuItem(Menu *menu, const char *text, U32 id, const char *accelerator, S32 checkGroup, const char *cmd )
 {
    // allocate the new menu item
    MenuItem *newMenuItem = new MenuItem;
@@ -886,6 +897,7 @@ void GuiMenuBar::addMenuItem(Menu *menu, const char *text, U32 id, const char *a
       newMenuItem->accelerator = dStrdup(accelerator);
    else
       newMenuItem->accelerator = NULL;
+   newMenuItem->cmd = cmd;
    newMenuItem->id = id;
    newMenuItem->checkGroup = checkGroup;
    newMenuItem->nextMenuItem = NULL;
@@ -896,15 +908,33 @@ void GuiMenuBar::addMenuItem(Menu *menu, const char *text, U32 id, const char *a
 
    //  Default to not having a submenu
    newMenuItem->isSubmenu = false;
-   newMenuItem->firstSubmenuItem = NULL;
+   newMenuItem->submenu = NULL;
    newMenuItem->submenuParentMenu = NULL;
 
    // link it into the menu's menu item list
-   MenuItem **walk = &menu->firstMenuItem;
-   while(*walk)
-      walk = &(*walk)->nextMenuItem;
-   *walk = newMenuItem;
+   if(menu)
+   {
+      MenuItem **walk = &menu->firstMenuItem;
+      while(*walk)
+         walk = &(*walk)->nextMenuItem;
+      *walk = newMenuItem;
+   }
 
+   return newMenuItem;
+}
+
+GuiMenuBar::MenuItem* GuiMenuBar::addMenuItem(Menu *menu, MenuItem* newMenuItem)
+{
+   // link it into the menu's menu item list
+   if(menu)
+   {
+      MenuItem **walk = &menu->firstMenuItem;
+      while(*walk)
+         walk = &(*walk)->nextMenuItem;
+      *walk = newMenuItem;
+   }
+
+   return newMenuItem;
 }
 
 void GuiMenuBar::clearMenuItems(Menu *menu)
@@ -935,16 +965,9 @@ GuiMenuBar::MenuItem *GuiMenuBar::findSubmenuItem(Menu *menu, const char *menuIt
       for(MenuItem *walk = menu->firstMenuItem; walk; walk = walk->nextMenuItem)
          if(id == walk->id)
 		 {
-		    if(walk->isSubmenu)
+		    if(walk->isSubmenu && walk->submenu)
 			{
-               U32 subid = dAtoi(submenuItem);
-	           for(MenuItem *subwalk = walk->firstSubmenuItem; subwalk; subwalk = subwalk->nextMenuItem)
-			   {
-				  if(subid == walk->id)
-				  {
-                     return subwalk;
-				  }
-			   }
+            return GuiMenuBar::findMenuItem(walk->submenu, submenuItem);
 			}
 			return NULL;
 		 }
@@ -956,13 +979,9 @@ GuiMenuBar::MenuItem *GuiMenuBar::findSubmenuItem(Menu *menu, const char *menuIt
       for(MenuItem *walk = menu->firstMenuItem; walk; walk = walk->nextMenuItem)
          if(!dStricmp(menuItem, walk->text))
 		 {
-		    if(walk->isSubmenu)
+		    if(walk->isSubmenu && walk->submenu)
 			{
-			   for(MenuItem *subwalk = walk->firstSubmenuItem; subwalk; subwalk = subwalk->nextMenuItem)
-			   {
-			      if(!dStricmp(submenuItem, subwalk->text))
-                      return subwalk;
-			   }
+            return GuiMenuBar::findMenuItem(walk->submenu, submenuItem);
 			}
 			return NULL;
 		 }
@@ -970,6 +989,14 @@ GuiMenuBar::MenuItem *GuiMenuBar::findSubmenuItem(Menu *menu, const char *menuIt
    }
 }
 
+GuiMenuBar::MenuItem* GuiMenuBar::findSubmenuItem(MenuItem *menuItem, const char *submenuItem)
+{
+   if( !menuItem->isSubmenu )
+      return NULL;
+
+   return GuiMenuBar::findMenuItem( menuItem->submenu, submenuItem );
+}
+
 //  Add a menuitem to the given submenu
 void GuiMenuBar::addSubmenuItem(Menu *menu, MenuItem *submenu, const char *text, U32 id, const char *accelerator, S32 checkGroup)
 {
@@ -997,17 +1024,30 @@ void GuiMenuBar::addSubmenuItem(Menu *menu, MenuItem *submenu, const char *text,
 
    //  Default to not having a submenu
    newMenuItem->isSubmenu = false;
-   newMenuItem->firstSubmenuItem = NULL;
+   newMenuItem->submenu = NULL;
 
    //  Point back to the submenu's menu
    newMenuItem->submenuParentMenu = menu;
 
    // link it into the menu's menu item list
-   MenuItem **walk = &submenu->firstSubmenuItem;
+   MenuItem **walk = &submenu->submenu->firstMenuItem;
    while(*walk)
       walk = &(*walk)->nextMenuItem;
    *walk = newMenuItem;
+}
+
+void GuiMenuBar::addSubmenuItem(Menu *menu, MenuItem *submenu, MenuItem *newMenuItem )
+{
+   AssertFatal( submenu && newMenuItem, "");
+
+   //  Point back to the submenu's menu
+   newMenuItem->submenuParentMenu = menu;
 
+   // link it into the menu's menu item list
+   MenuItem **walk = &submenu->submenu->firstMenuItem;
+   while(*walk)
+      walk = &(*walk)->nextMenuItem;
+   *walk = newMenuItem;
 }
 
 //  Remove a submenu item
@@ -1020,17 +1060,7 @@ void GuiMenuBar::removeSubmenuItem(MenuItem *menuItem, MenuItem *submenuItem)
 	  return;
    }
 
-   for(MenuItem **subwalk = &menuItem->firstSubmenuItem; *subwalk; subwalk = &(*subwalk)->nextMenuItem)
-   {
-      if(*subwalk == submenuItem)
-      {
-         *subwalk = submenuItem->nextMenuItem;
-         break;
-      }
-   }
-   dFree(submenuItem->text);
-   dFree(submenuItem->accelerator);
-   delete submenuItem;
+   GuiMenuBar::removeMenuItem(menuItem->submenu, submenuItem);
 }
 
 //  Clear all menuitems from a submenu
@@ -1043,8 +1073,8 @@ void GuiMenuBar::clearSubmenuItems(MenuItem *menuitem)
 	  return;
    }
 
-   while(menuitem->firstSubmenuItem)
-      removeSubmenuItem(menuitem, menuitem->firstSubmenuItem);
+   while(menuitem->submenu->firstMenuItem)
+      removeSubmenuItem(menuitem, menuitem->submenu->firstMenuItem);
 }
 
 //------------------------------------------------------------------------------
@@ -1317,9 +1347,8 @@ void GuiMenuBar::onRender(Point2I offset, const RectI &updateRect)
    renderChildControls( offset, updateRect );
 }
 
-void GuiMenuBar::buildAcceleratorMap()
+void GuiMenuBar::buildWindowAcceleratorMap( WindowInputGenerator &inputGenerator )
 {
-   Parent::buildAcceleratorMap();
    // ok, accelerator map is cleared...
    // add all our keys:
    mCurAcceleratorIndex = 1;
@@ -1334,18 +1363,22 @@ void GuiMenuBar::buildAcceleratorMap()
             continue;
          }
          EventDescriptor accelEvent;
-			ActionMap::createEventDescriptor(item->accelerator, &accelEvent);
+		 ActionMap::createEventDescriptor(item->accelerator, &accelEvent);
    
          //now we have a modifier, and a key, add them to the canvas
-         GuiCanvas *root = getRoot();
-         if (root)
-            root->addAcceleratorKey(this, mCurAcceleratorIndex, accelEvent.eventCode, accelEvent.flags);
+         inputGenerator.addAcceleratorKey( this, item->cmd, accelEvent.eventCode, accelEvent.flags);
+
          item->acceleratorIndex = mCurAcceleratorIndex;
          mCurAcceleratorIndex++;
       }
    }
 }
 
+void GuiMenuBar::removeWindowAcceleratorMap( WindowInputGenerator &inputGenerator )
+{
+    inputGenerator.removeAcceleratorKeys( this );
+}
+
 void GuiMenuBar::acceleratorKeyPress(U32 index)
 {
    // loop through all the menus
@@ -1617,7 +1650,7 @@ void GuiMenuBar::highlightedMenuItem(S32 selectionIndex, RectI bounds, Point2I c
             if(list->isSubmenu)
 		    {
 			   // If there are submenu items, then open the submenu
-			   if(list->firstSubmenuItem)
+             if(list->submenu->firstMenuItem)
 			   {
 				   mouseOverSubmenu = list;
 				   onSubmenuAction(selstore, bounds, cellSize);
@@ -1752,7 +1785,7 @@ void GuiMenuBar::onSubmenuAction(S32 selectionIndex, RectI bounds, Point2I cellS
    // first, call the script callback for menu selection:
    onSubmenuSelect_callback(Con::getIntArg(mouseOverSubmenu->id), mouseOverSubmenu->text);
 
-   MenuItem *visWalk = mouseOverSubmenu->firstSubmenuItem;
+   MenuItem *visWalk = mouseOverSubmenu->submenu->firstMenuItem;
    while(visWalk)
    {
       if(visWalk->visible)
@@ -1780,7 +1813,7 @@ void GuiMenuBar::onSubmenuAction(S32 selectionIndex, RectI bounds, Point2I cellS
 
    GFont *font = mProfile->mFont;
 
-   for(MenuItem *walk = mouseOverSubmenu->firstSubmenuItem; walk; walk = walk->nextMenuItem)
+   for(MenuItem *walk = mouseOverSubmenu->submenu->firstMenuItem; walk; walk = walk->nextMenuItem)
    {
       if(!walk->visible)
          continue;
@@ -1803,7 +1836,7 @@ void GuiMenuBar::onSubmenuAction(S32 selectionIndex, RectI bounds, Point2I cellS
 
    U32 entryCount = 0;
 
-   for(MenuItem *walk = mouseOverSubmenu->firstSubmenuItem; walk; walk = walk->nextMenuItem)
+   for(MenuItem *walk = mouseOverSubmenu->submenu->firstMenuItem; walk; walk = walk->nextMenuItem)
    {
       if(!walk->visible)
          continue;
@@ -1885,7 +1918,7 @@ void GuiMenuBar::closeSubmenu()
       MenuItem *list = NULL;
 	  if(mouseOverSubmenu)
 	  {
-         list = mouseOverSubmenu->firstSubmenuItem;
+         list = mouseOverSubmenu->submenu->firstMenuItem;
 
          while(selectionIndex && list)
          {

+ 19 - 12
Engine/source/gui/editor/guiMenuBar.h

@@ -32,6 +32,7 @@
 
 class GuiMenuBar;
 class GuiMenuTextListCtrl;
+class WindowInputGenerator;
 
 class GuiMenuBackgroundCtrl : public GuiControl
 {
@@ -105,9 +106,10 @@ public:
 		MenuItem *nextMenuItem; // next menu item in the linked list
 
 		bool isSubmenu;				//  This menu item has a submenu that will be displayed
-		MenuItem *firstSubmenuItem;	//  The first menu item in the submenu
 
 		Menu* submenuParentMenu; //  For a submenu, this is the parent menu
+      Menu* submenu;
+      String cmd;
 	};
 
 	struct Menu
@@ -161,21 +163,25 @@ public:
 
 	// 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);
    void addMenu(const char *menuText, U32 menuId);
 	Menu *findMenu(const char *menu);  // takes either a menu text or a string id
-	MenuItem *findMenuItem(Menu *menu, const char *menuItem); // 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);
-	void removeMenuItem(Menu *menu, MenuItem *menuItem);
-	void addMenuItem(Menu *menu, const char *text, U32 id, const char *accelerator, S32 checkGroup);
-	void clearMenuItems(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();
 
    //  Methods to deal with submenus
-   MenuItem* findSubmenuItem(Menu *menu, const char *menuItem, const char *submenuItem);
-   void addSubmenuItem(Menu *menu, MenuItem *submenu, const char *text, U32 id, const char *accelerator, S32 checkGroup);
-   void removeSubmenuItem(MenuItem *menuItem, MenuItem *submenuItem);
-   void clearSubmenuItems(MenuItem *menuitem);
+   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, RectI bounds, Point2I cellSize);
    void closeSubmenu();
    void checkSubmenuMouseMove(const GuiEvent &event);
@@ -202,10 +208,11 @@ public:
    
    void onAction();
    void closeMenu();
-   void buildAcceleratorMap();
+   void buildWindowAcceleratorMap( WindowInputGenerator &inputGenerator );
+   void removeWindowAcceleratorMap( WindowInputGenerator &inputGenerator );
    void acceleratorKeyPress(U32 index);
 
-   void menuItemSelected(Menu *menu, MenuItem *item);
+   virtual void menuItemSelected(Menu *menu, MenuItem *item);
 
    //  Added to support 'ticks'
    void processTick();

+ 4 - 4
Engine/source/platform/menus/popupMenu.cpp

@@ -195,9 +195,9 @@ bool PopupMenu::onMessageObjectReceived(StringTableEntry queue, Message *msg )
 // Console Methods
 //-----------------------------------------------------------------------------
 
-DefineConsoleMethod(PopupMenu, insertItem, S32, (S32 pos, const char * title, const char * accelerator), ("", ""), "(pos[, title][, accelerator])")
+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);
+   return object->insertItem(pos, title, accelerator, cmd);
 }
 
 DefineConsoleMethod(PopupMenu, removeItem, void, (S32 pos), , "(pos)")
@@ -216,9 +216,9 @@ DefineConsoleMethod(PopupMenu, insertSubMenu, S32, (S32 pos, String title, Strin
    return object->insertSubMenu(pos, title, mnu);
 }
 
-DefineConsoleMethod(PopupMenu, setItem, bool, (S32 pos, const char * title, const char * accelerator), (""), "(pos, title[, accelerator])")
+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);
+   return object->setItem(pos, title, accelerator, cmd);
 }
 
 //-----------------------------------------------------------------------------

+ 2 - 2
Engine/source/platform/menus/popupMenu.h

@@ -85,11 +85,11 @@ public:
    /// returns the menu item's ID, or -1 on failure.
    /// implementd on a per-platform basis.
    /// TODO: factor out common code
-   S32 insertItem(S32 pos, const char *title, const char* accelerator);
+   S32 insertItem(S32 pos, const char *title, const char* accelerator, const char* cmd);
 
    /// Sets the name title and accelerator for 
    /// an existing item.
-   bool setItem(S32 pos, const char *title, const char* accelerator);
+   bool setItem(S32 pos, const char *title, const char* accelerator, const char* cmd);
 
    /// pass NULL for @p title to insert a separator
    /// returns the menu item's ID, or -1 on failure.

+ 1 - 0
Engine/source/platform/nativeDialogs/msgBox.h

@@ -37,6 +37,7 @@ enum MBButtons
    MBRetryCancel,
    MBSaveDontSave,
    MBSaveDontSaveCancel,
+   MBAlertAssert
 };
 
 enum MBIcons

+ 10 - 0
Engine/source/platform/platform.h

@@ -174,6 +174,15 @@ namespace Platform
       bool isdst;     ///< True if daylight savings time is active
    };
 
+	enum ALERT_ASSERT_RESULT
+	{
+		ALERT_ASSERT_DEBUG,
+		ALERT_ASSERT_IGNORE,
+		ALERT_ASSERT_IGNORE_ALL,
+		ALERT_ASSERT_EXIT
+	};
+
+
    void getLocalTime(LocalTime &);
    
    /// Converts the local time to a formatted string appropriate
@@ -300,6 +309,7 @@ namespace Platform
    void AlertOK(const char *windowTitle, const char *message);
    bool AlertOKCancel(const char *windowTitle, const char *message);
    bool AlertRetry(const char *windowTitle, const char *message);
+   ALERT_ASSERT_RESULT AlertAssert(const char *windowTitle, const char *message);
 
    // Volumes
    struct VolumeInformation

+ 60 - 41
Engine/source/platform/platformAssert.cpp

@@ -33,6 +33,7 @@ PlatformAssert *PlatformAssert::platformAssert = NULL;
 PlatformAssert::PlatformAssert()
 {
    processing = false;
+   ignoreAll = false;
 }
 
 //--------------------------------------
@@ -94,47 +95,57 @@ bool PlatformAssert::process(Type         assertType,
                              U32          lineNumber,
                              const char  *message)
 {
-   // If we're somehow recursing, just die.
-   if(processing)
-      Platform::debugBreak();
-
-   processing = true;
-   bool ret = true;
-
-   // always dump to the Assert to the Console
-   if (Con::isActive())
-   {
-      if (assertType == Warning)
-         Con::warnf(ConsoleLogEntry::Assert, "%s(%ld) : %s - %s", filename, lineNumber, typeName[assertType], message);
-      else
-	      Con::errorf(ConsoleLogEntry::Assert, "%s(%ld) : %s - %s", filename, lineNumber, typeName[assertType], message);
-   }
-
-   // if not a WARNING pop-up a dialog box
-   if (assertType != Warning)
-   {
-      // used for processing navGraphs (an assert won't botch the whole build)
-      if(Con::getBoolVariable("$FP::DisableAsserts", false) == true)
-         Platform::forceShutdown(1);
-
-      char buffer[2048];
-      dSprintf(buffer, 2048, "%s(%ld) : %s", filename, lineNumber, typeName[assertType] );
-
-#ifdef TORQUE_DEBUG
-      // In debug versions, allow a retry even for ISVs...
-      bool retry = displayMessageBox(buffer, message, true);
-#else
-      bool retry = displayMessageBox(buffer, message, ((assertType == Fatal) ? true : false) );
-#endif
-      if(!retry)
-         Platform::forceShutdown(1);
-      
-      ret = askToEnterDebugger(message);
-   }
-
-   processing = false;
-
-   return ret;
+    // If we're somehow recursing, just die.
+    if(processing)
+        Platform::debugBreak();
+    
+    processing = true;
+    bool ret = false;
+    
+    // always dump to the Assert to the Console
+    if (Con::isActive())
+    {
+        if (assertType == Warning)
+            Con::warnf(ConsoleLogEntry::Assert, "%s(%ld,0): {%s} - %s", filename, lineNumber, typeName[assertType], message);
+        else
+            Con::errorf(ConsoleLogEntry::Assert, "%s(%ld,0): {%s} - %s", filename, lineNumber, typeName[assertType], message);
+    }
+    
+    // if not a WARNING pop-up a dialog box
+    if (assertType != Warning)
+    {
+        // used for processing navGraphs (an assert won't botch the whole build)
+        if(Con::getBoolVariable("$FP::DisableAsserts", false) == true)
+            Platform::forceShutdown(1);
+        
+        char buffer[2048];
+        dSprintf(buffer, 2048, "%s: (%s @ %ld)", typeName[assertType], filename, lineNumber);
+        if( !ignoreAll )
+        {
+            // Display message box with Debug, Ignore, Ignore All, and Exit options
+            switch( Platform::AlertAssert(buffer, message) )
+            {
+                case Platform::ALERT_ASSERT_DEBUG:				
+                    ret = true;
+                    break;
+                case Platform::ALERT_ASSERT_IGNORE:
+                    ret = false;
+                    break;
+                case Platform::ALERT_ASSERT_IGNORE_ALL:
+                    ignoreAll = true;
+                    ret = false;
+                    break;
+                default:
+                case Platform::ALERT_ASSERT_EXIT:
+                    Platform::forceShutdown(1);
+                    break;
+            }
+        }
+    }
+    
+    processing = false;
+    
+    return ret;
 }
 
 bool PlatformAssert::processingAssert()
@@ -170,3 +181,11 @@ const char* avar(const char *message, ...)
    dVsprintf(buffer, sizeof(buffer), message, args);
    return( buffer );
 }
+
+//-----------------------------------------------------------------------------
+
+ConsoleFunction( Assert, void, 3, 3, "(condition, message) - Fatal Script Assertion" )
+{
+    // Process Assertion.
+    AssertISV( dAtob(argv[1]), argv[2] );
+}

+ 1 - 0
Engine/source/platform/platformAssert.h

@@ -40,6 +40,7 @@ public:
 private:
    static PlatformAssert *platformAssert;
    bool processing;
+   bool ignoreAll;
 
    virtual bool displayMessageBox(const char *title, const char *message, bool retry);
    virtual bool process(Type         assertType,

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

@@ -41,6 +41,8 @@
 // MenuBar Methods
 //-----------------------------------------------------------------------------
 
+#ifndef TORQUE_SDL
+
 void MenuBar::createPlatformPopupMenuData()
 {
 //    mData = new PlatformMenuBarData;
@@ -171,3 +173,5 @@ void MenuBar::removeFromCanvas()
 
    mCanvas = NULL;
 }
+
+#endif

+ 5 - 2
Engine/source/platformWin32/menus/popupMenuWin32.cpp

@@ -20,6 +20,8 @@
 // IN THE SOFTWARE.
 //-----------------------------------------------------------------------------
 
+#ifndef TORQUE_SDL
+
 #include "platform/menus/popupMenu.h"
 #include "platformWin32/platformWin32.h"
 #include "console/consoleTypes.h"
@@ -169,7 +171,7 @@ void PopupMenu::createPlatformMenu()
 // Public Methods
 //////////////////////////////////////////////////////////////////////////
 
-S32 PopupMenu::insertItem(S32 pos, const char *title, const char* accelerator)
+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();
@@ -266,7 +268,7 @@ S32 PopupMenu::insertSubMenu(S32 pos, const char *title, PopupMenu *submenu)
    return -1;
 }
 
-bool PopupMenu::setItem(S32 pos, const char *title, const char* accelerator)
+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();
@@ -740,3 +742,4 @@ S32 PopupMenu::getPosOnMenuBar()
    return pos;
 }
 
+#endif

+ 2 - 1
Engine/source/platformWin32/nativeDialogs/win32MsgBox.cpp

@@ -80,7 +80,7 @@ static U32 getMaskFromID(_FlagMap *map, S32 id)
 }
 
 //-----------------------------------------------------------------------------
-
+#ifndef TORQUE_SDL
 S32 Platform::messageBox(const UTF8 *title, const UTF8 *message, MBButtons buttons, MBIcons icon)
 {
    PlatformWindow *pWindow = WindowManager->getFirstWindow();
@@ -127,3 +127,4 @@ S32 Platform::messageBox(const UTF8 *title, const UTF8 *message, MBButtons butto
 
    return getMaskFromID(sgMsgBoxRetMap, ret);
 }
+#endif

+ 4 - 0
Engine/source/platformWin32/winExec.cpp

@@ -153,6 +153,8 @@ DefineConsoleFunction( shellExecute, bool, (const char * executable, const char
    return true;
 }
 
+#ifndef TORQUE_SDL
+
 void Platform::openFolder(const char* path )
 {
    char filePath[1024];
@@ -187,3 +189,5 @@ void Platform::openFile(const char* path )
    ::ShellExecute( NULL,TEXT("open"),p, NULL, NULL, SW_SHOWNORMAL);
 }
 
+#endif // !TORQUE_SDL
+

+ 2 - 0
Engine/source/platformWin32/winInput.cpp

@@ -20,6 +20,7 @@
 // IN THE SOFTWARE.
 //-----------------------------------------------------------------------------
 
+#if !defined( TORQUE_SDL )
 #include "platformWin32/platformWin32.h"
 
 #include "platform/platformInput.h"
@@ -863,3 +864,4 @@ bool Platform::setClipboard(const char *text)
 	return true;
 }
 
+#endif

+ 38 - 0
Engine/source/platformWin32/winWindow.cpp

@@ -190,6 +190,7 @@ bool Platform::checkOtherInstances(const char *mutexName)
    return false;
 }
 
+#ifndef TORQUE_SDL
 //--------------------------------------
 void Platform::AlertOK(const char *windowTitle, const char *message)
 {
@@ -232,6 +233,43 @@ bool Platform::AlertRetry(const char *windowTitle, const char *message)
 #endif
 }
 
+Platform::ALERT_ASSERT_RESULT Platform::AlertAssert(const char *windowTitle, const char *message)
+{
+#ifndef TORQUE_TOOLS
+   ShowCursor(true);
+#endif // TORQUE_TOOLS
+
+#ifdef UNICODE
+   UTF16 messageUTF[1024], title[512];
+   convertUTF8toUTF16((UTF8 *)windowTitle, title, sizeof(title));
+   convertUTF8toUTF16((UTF8 *)message, messageUTF, sizeof(messageUTF));
+#else
+   const char* messageUTF = message;
+   const char* title = windowTitle;
+#endif
+
+   // TODO: Change this to a custom dialog that has Exit, Ignore, Ignore All, and Debug buttons
+   ALERT_ASSERT_RESULT alertResult = ALERT_ASSERT_DEBUG;
+   int result = MessageBox(winState.appWindow, messageUTF, title, MB_ABORTRETRYIGNORE | MB_ICONSTOP | MB_DEFBUTTON2 | MB_TASKMODAL | MB_SETFOREGROUND);
+   switch( result )
+   {
+		case IDABORT:
+			alertResult = ALERT_ASSERT_EXIT;
+			break;
+		case IDIGNORE:
+			alertResult = ALERT_ASSERT_IGNORE;
+			break;
+		default:
+		case IDRETRY:
+			alertResult = ALERT_ASSERT_DEBUG;
+			break;
+   }
+
+   return alertResult;
+}
+
+#endif
+
 //--------------------------------------
 HIMC gIMEContext;
 

+ 1 - 0
Engine/source/platformX86UNIX/x86UNIXStub.dedicated.cpp

@@ -107,6 +107,7 @@ void Platform::AlertOK(const char *, const char *) {}
 bool Platform::AlertOKCancel(const char *, const char *) { return false; }
 S32  Platform::messageBox(char const*, char const*, MBButtons, MBIcons) { return 0; }
 bool Platform::AlertRetry(char const*, char const*) { return false ; }
+Platform::ALERT_ASSERT_RESULT Platform::AlertAssert(const char *windowTitle, const char *message) { return ALERT_ASSERT_EXIT; }
 
 // file dialog
 IMPLEMENT_CONOBJECT(FileDialog);

+ 1 - 1
Engine/source/windowManager/platformInterface.cpp

@@ -136,7 +136,7 @@ HWND getWin32WindowHandle()
          return NULL;
    }
 
-   return ( ( Win32Window* ) window )->getHWND();
+   return (HWND)window->getSystemWindow( PlatformWindow::WindowSystem_Windows );
 }
 
 #endif

+ 11 - 0
Engine/source/windowManager/platformWindow.h

@@ -124,10 +124,21 @@ public:
    /// Get the WindowController associated with this window
    virtual void setInputController( IProcessInput *controller ) { if( mWindowInputGenerator ) mWindowInputGenerator->setInputController( controller ); };
 
+   WindowInputGenerator* getInputGenerator() const { return mWindowInputGenerator; }
+
    /// Get the ID that uniquely identifies this window in the context of its
    /// window manager.
    virtual WindowId getWindowId() { return 0; };
 
+   enum WindowSystem
+   {
+      WindowSystem_Unknown = 0,
+      WindowSystem_Windows,
+      WindowSystem_X11,
+   };
+
+   virtual void* getSystemWindow(const WindowSystem system) { return NULL; }
+
    /// Set the flag that determines whether to suppress a GFXDevice reset
    inline void setSuppressReset(bool suppress) { mSuppressReset = suppress; };
 

+ 3 - 1
Engine/source/windowManager/win32/win32SplashScreen.cpp

@@ -121,6 +121,8 @@ void CloseSplashWindow(HINSTANCE hinst)
 	
 }
 
+#ifndef TORQUE_SDL
+
 bool Platform::closeSplashWindow()
 {
    CloseSplashWindow(GetModuleHandle(NULL));
@@ -155,4 +157,4 @@ bool Platform::displaySplashWindow( String path )
 	return true;
 }
 
-
+#endif

+ 12 - 0
Engine/source/windowManager/win32/win32Window.cpp

@@ -20,6 +20,8 @@
 // IN THE SOFTWARE.
 //-----------------------------------------------------------------------------
 
+#if !defined(TORQUE_SDL)
+
 #include <windows.h>
 #include <tchar.h>
 #include <winuser.h>
@@ -121,6 +123,14 @@ Win32Window::~Win32Window()
 	_unregisterWindowClass();
 }
 
+void* Win32Window::getSystemWindow(const WindowSystem system)
+{
+   if( system == WindowSystem_Windows)
+      return getHWND();
+
+     return NULL;
+}
+
 GFXDevice * Win32Window::getGFXDevice()
 {
 	return mDevice;
@@ -1209,3 +1219,5 @@ const UTF16 *Win32Window::getCurtainWindowClassName()
 {
 	return _CurtainWindowClassName;
 }
+
+#endif

+ 2 - 0
Engine/source/windowManager/win32/win32Window.h

@@ -139,6 +139,8 @@ public:
       return mWindowHandle;
    }
 
+   virtual void* getSystemWindow(const WindowSystem system);
+
    HMENU &getMenuHandle()
    {
       return mMenuHandle;

+ 5 - 1
Engine/source/windowManager/win32/win32WindowMgr.cpp

@@ -27,6 +27,8 @@
 #include "core/util/journal/process.h"
 #include "core/strings/unicode.h"
 
+#if !defined( TORQUE_SDL )
+
 // ------------------------------------------------------------------------
 
 void CloseSplashWindow(HINSTANCE hinst);
@@ -522,4 +524,6 @@ void Win32WindowManager::raiseCurtain()
 
    DestroyWindow(mCurtainWindow);
    mCurtainWindow = NULL;
-}
+}
+
+#endif

+ 5 - 0
Engine/source/windowManager/win32/winDispatch.cpp

@@ -39,6 +39,8 @@
 #include "core/util/journal/process.h"
 #include "core/util/journal/journaledSignal.h"
 
+#if !defined( TORQUE_SDL )
+
 static U32 _ModifierKeys=0;
 static BYTE keyboardState[256];
 static bool initKBState = false;
@@ -591,3 +593,6 @@ void DispatchRemove(HWND hWnd)
 {
 	_MessageQueue.remove(hWnd);
 }
+
+
+#endif

+ 13 - 0
Engine/source/windowManager/windowInputGenerator.cpp

@@ -85,6 +85,19 @@ void WindowInputGenerator::generateInputEvent( InputEventInfo &inputEvent )
    if( !mInputController || !mFocused )
       return;
 
+    if (inputEvent.action == SI_MAKE && inputEvent.deviceType == KeyboardDeviceType)
+    {
+        for( int i = 0; i < mAcceleratorMap.size(); ++i )
+        {
+            const AccKeyMap &acc = mAcceleratorMap[i];
+            if( acc.modifier & inputEvent.modifier && acc.keyCode == inputEvent.objInst )
+            {
+                Con::evaluatef(acc.cmd);
+                return;
+            }
+        }
+    }
+
    // Give the ActionMap first shot.
    if (ActionMap::handleEventGlobal(&inputEvent))
       return;

+ 46 - 0
Engine/source/windowManager/windowInputGenerator.h

@@ -61,6 +61,16 @@ class WindowInputGenerator
       void handleInputEvent (U32 deviceInst, F32 fValue, F32 fValue2, F32 fValue3, F32 fValue4, S32 iValue, U16 deviceType, U16 objType, U16 ascii, U16 objInst, U8 action, U8 modifier);
 
       void generateInputEvent( InputEventInfo &inputEvent );
+
+      /// Accelerator key map
+       struct AccKeyMap
+       {
+          void *hnd;
+          String cmd;
+          U32 keyCode;
+          U32 modifier;
+       };
+       Vector <AccKeyMap> mAcceleratorMap;
       
    public:
    
@@ -72,6 +82,42 @@ class WindowInputGenerator
       /// Returns true if the given keypress event should be send as a raw keyboard
       /// event even if it maps to a character input event.
       bool wantAsKeyboardEvent( U32 modifiers, U32 key );
+
+    void addAcceleratorKey( void *hnd, const String &cmd, U32 keycode, U32 modifier)
+    {
+        AccKeyMap acc;
+        acc.hnd = hnd;
+        acc.cmd = cmd;
+        acc.keyCode = keycode;
+        acc.modifier = modifier;
+        mAcceleratorMap.push_back(acc);
+    }
+
+    void removeAcceleratorKeys( void *hnd )
+    {
+         for( int i = 0; i < mAcceleratorMap.size(); )
+         {
+            if( mAcceleratorMap[i].hnd == hnd )
+            {
+                mAcceleratorMap.erase( i, 1 );
+                continue;
+            }
+
+             ++i;
+         }
+    }
+
+    void removeAcceleratorKey( void *hnd, U32 keycode, U32 modifier )
+    {
+         for( int i = 0; i < mAcceleratorMap.size(); ++i )
+         {
+            if( mAcceleratorMap[i].hnd == hnd && mAcceleratorMap[i].keyCode == keycode && mAcceleratorMap[i].modifier == modifier )
+            {
+                mAcceleratorMap.erase( i, 1 );
+                return;
+            }
+         }
+    }
 };
 
 #endif // _WINDOW_INPUTGENERATOR_H_

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

@@ -35,6 +35,7 @@ exec("./GuiEaseEditDlg.ed.cs");
 exec("./guiObjectInspector.ed.cs");
 exec("./uvEditor.ed.gui");
 exec("./objectSelection.ed.cs");
+exec("./guiPlatformGenericMenubar.ed.cs");
 
 if (isDemo())
    exec("./messageBoxOKBuy.ed.gui");

+ 12 - 0
Templates/Empty/game/tools/gui/profiles.ed.cs

@@ -1063,3 +1063,15 @@ singleton GuiControlProfile( GuiCreatorIconButtonProfile )
    //bevelColorLL = "0 0 0";
    category = "Editor";
 };
+
+singleton GuiControlProfile( GuiMenuBarProfile )
+{
+   fillcolor = "255 255 255";
+   borderColor = "0 0 0";
+   border = 1;
+   borderThickness = 1;
+   opaque = true;
+   mouseOverSelected = true;
+   category = "Editor";
+   bitmap = "tools/gui/images/checkbox-menubar";
+};

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

@@ -35,6 +35,7 @@ exec("./GuiEaseEditDlg.ed.cs");
 exec("./guiObjectInspector.ed.cs");
 exec("./uvEditor.ed.gui");
 exec("./objectSelection.ed.cs");
+exec("./guiPlatformGenericMenubar.ed.cs");
 
 if (isDemo())
    exec("./messageBoxOKBuy.ed.gui");

+ 12 - 0
Templates/Full/game/tools/gui/profiles.ed.cs

@@ -1063,3 +1063,15 @@ singleton GuiControlProfile( GuiCreatorIconButtonProfile )
    //bevelColorLL = "0 0 0";
    category = "Editor";
 };
+
+singleton GuiControlProfile( GuiMenuBarProfile )
+{
+   fillcolor = "255 255 255";
+   borderColor = "0 0 0";
+   border = 1;
+   borderThickness = 1;
+   opaque = true;
+   mouseOverSelected = true;
+   category = "Editor";
+   bitmap = "tools/gui/images/checkbox-menubar";
+};