Explorar o código

Implements the right-mouse popup menus in the editor in SDL to make it match to Windows.

Areloch %!s(int64=9) %!d(string=hai) anos
pai
achega
818b617972

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

@@ -0,0 +1,184 @@
+//-----------------------------------------------------------------------------
+// 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/guiPopupMenuCtrl.h"
+#include "gfx/gfxDrawUtil.h"
+#include "gfx/primBuilder.h"
+#include "gui/core/guiCanvas.h"
+
+GuiPopupMenuBackgroundCtrl::GuiPopupMenuBackgroundCtrl(GuiPopupMenuTextListCtrl *textList)
+{
+   mTextList = textList;
+   mTextList->mBackground = this;
+}
+
+void GuiPopupMenuBackgroundCtrl::onMouseDown(const GuiEvent &event)
+{
+   mTextList->setSelectedCell(Point2I(-1, -1));
+   close();
+}
+
+void GuiPopupMenuBackgroundCtrl::onMouseMove(const GuiEvent &event)
+{
+}
+
+void GuiPopupMenuBackgroundCtrl::onMouseDragged(const GuiEvent &event)
+{
+}
+
+void GuiPopupMenuBackgroundCtrl::close()
+{
+   getRoot()->removeObject(this);
+}
+
+GuiPopupMenuTextListCtrl::GuiPopupMenuTextListCtrl()
+{
+   isSubMenu = false; //  Added
+   mMenu = NULL;
+   mMenuBar = NULL;
+   mPopup = NULL;
+}
+
+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
+   {
+      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++;
+
+      if (mProfile->mBitmapArrayRects.size() > index)
+      {
+         RectI rect = mProfile->mBitmapArrayRects[index];
+         Point2I off = 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 GuiPopupMenuTextListCtrl::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)
+      {
+         mBackground->close();
+         return true;
+      }
+      else if (event.keyCode == KEY_ESCAPE)
+      {
+         mSelectedCell.set(-1, -1);
+         mBackground->close();
+         return true;
+      }
+   }
+
+   //otherwise, pass the event to it's parent
+   return Parent::onKeyDown(event);
+}
+
+void GuiPopupMenuTextListCtrl::onMouseDown(const GuiEvent &event)
+{
+   Parent::onMouseDown(event);
+}
+
+void GuiPopupMenuTextListCtrl::onMouseUp(const GuiEvent &event)
+{
+   Parent::onMouseUp(event);
+
+   S32 selectionIndex = getSelectedCell().y;
+
+   if (selectionIndex != -1)
+   {
+      GuiMenuBar::MenuItem *list = mMenu->firstMenuItem;
+
+      while (selectionIndex && list)
+      {
+         list = list->nextMenuItem;
+         selectionIndex--;
+      }
+      if (list)
+      {
+         if (list->enabled)
+            dAtob(Con::executef(mPopup, "onSelectItem", Con::getIntArg(getSelectedCell().y), list->text ? list->text : ""));
+      }
+   }
+
+   mSelectedCell.set(-1, -1);
+   mBackground->close();
+}
+
+void GuiPopupMenuTextListCtrl::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;
+   }
+}

+ 85 - 0
Engine/source/gui/editor/guiPopupMenuCtrl.h

@@ -0,0 +1,85 @@
+//-----------------------------------------------------------------------------
+// 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
+
+#ifndef GUI_POPUP_MENU_CTRL_H
+#define GUI_POPUP_MENU_CTRL_H
+
+#ifndef _GUITEXTLISTCTRL_H_
+#include "gui/controls/guiTextListCtrl.h"
+#endif
+
+#ifndef _GUIMENUBAR_H_
+#include "gui/editor/guiMenuBar.h"
+#endif
+
+#ifndef _POPUPMENU_H_
+#include "platform/menus/popupMenu.h"
+#endif
+
+class GuiPopupMenuBackgroundCtrl;
+
+class GuiPopupMenuTextListCtrl : public GuiTextListCtrl
+{
+   friend class GuiPopupMenuBackgroundCtrl;
+
+private:
+   typedef GuiTextListCtrl Parent;
+
+   GuiPopupMenuBackgroundCtrl* mBackground;
+
+public:
+   bool isSubMenu; //  Indicates that this text list is in a submenu
+   Point2I maxBitmapSize;
+   GuiMenuBar::Menu* mMenu;
+   GuiMenuBar* mMenuBar;
+   PopupMenu* mPopup;
+
+   GuiPopupMenuTextListCtrl();
+
+   // 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 GuiPopupMenuBackgroundCtrl : public GuiControl
+{
+   typedef GuiControl Parent;
+
+protected:
+   GuiPopupMenuTextListCtrl *mTextList;
+
+public:
+   GuiPopupMenuBackgroundCtrl(GuiPopupMenuTextListCtrl* textList);
+   void onMouseDown(const GuiEvent &event);
+   void onMouseMove(const GuiEvent &event);
+   void onMouseDragged(const GuiEvent &event);
+
+   void close();
+};
+
+#endif

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

@@ -0,0 +1,29 @@
+#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;
+
+};

+ 2 - 24
Engine/source/platformSDL/menus/menuBarSDL.cpp

@@ -31,6 +31,8 @@
 
 
 #include "platformSDL/menus/PlatformSDLPopupMenuData.h"
 #include "platformSDL/menus/PlatformSDLPopupMenuData.h"
 
 
+#include "platformSDL/menus/guiPlatformGenericMenuBar.h"
+
 #ifdef TORQUE_SDL
 #ifdef TORQUE_SDL
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -44,30 +46,6 @@
 
 
 Map<GuiMenuBar::Menu*, PopupMenu*> PlatformPopupMenuData::mMenuMap;
 Map<GuiMenuBar::Menu*, PopupMenu*> PlatformPopupMenuData::mMenuMap;
 
 
-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;
-
-};
-
 IMPLEMENT_CONOBJECT(GuiPlatformGenericMenuBar);
 IMPLEMENT_CONOBJECT(GuiPlatformGenericMenuBar);
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------

+ 143 - 3
Engine/source/platformSDL/menus/popupMenuSDL.cpp

@@ -23,7 +23,7 @@
 #ifdef TORQUE_SDL
 #ifdef TORQUE_SDL
 
 
 #include "platform/menus/popupMenu.h"
 #include "platform/menus/popupMenu.h"
-#include "platform/menus//menuBar.h"
+#include "platform/menus/menuBar.h"
 #include "console/consoleTypes.h"
 #include "console/consoleTypes.h"
 #include "gui/core/guiCanvas.h"
 #include "gui/core/guiCanvas.h"
 #include "core/util/safeDelete.h"
 #include "core/util/safeDelete.h"
@@ -37,10 +37,25 @@
 #include "platformSDL/menus/PlatformSDLPopupMenuData.h"
 #include "platformSDL/menus/PlatformSDLPopupMenuData.h"
 #include "console/engineAPI.h"
 #include "console/engineAPI.h"
 
 
+#include "platformSDL/menus/guiPlatformGenericMenuBar.h"
+#include "gui/editor/guiPopupMenuCtrl.h"
+
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////
 // Platform Menu Data
 // 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;
+}
 
 
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////
 
 
@@ -215,8 +230,133 @@ bool PopupMenu::handleSelect(U32 command, const char *text /* = NULL */)
 
 
 void PopupMenu::showPopup(GuiCanvas *owner, S32 x /* = -1 */, S32 y /* = -1 */)
 void PopupMenu::showPopup(GuiCanvas *owner, S32 x /* = -1 */, S32 y /* = -1 */)
 {
 {
-    if(owner == NULL || isAttachedToMenuBar())
+    if(owner == NULL)
       return;
       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);
+       }
+    }
 }
 }
 
 
 //////////////////////////////////////////////////////////////////////////
 //////////////////////////////////////////////////////////////////////////