Browse Source

Fixes design oversight where the general game menu keybind was being overridden due to order of operations issues with an offscreen canvas demoing the options menu
Fixed via several solutions to prevent issue from cropping up again.
Firstly, Adjusted behavior script-side so game menu keybind is pushed with the PlayGUI since almost every single game will use the game menu
Secondly, added logic so that the guiInputCtrl, when going to push an ActionMap(if it has one) will check if it's root canvas is active.
Thirdly, to allow guiInputCtrls to respond to a canvas becoming active, such as a GUi-on-Material surface displaying a menu and it's activated, an offscreen canvas becoming active now trips a signal that guiInputCtrl listens for.

JeffR 1 month ago
parent
commit
970aba9766

+ 4 - 0
Engine/source/T3D/fps/guiCrossHairHud.cpp

@@ -161,6 +161,9 @@ void GuiCrossHairHud::onRender(Point2I offset, const RectI &updateRect)
       {
       {
          if (mFrameTime->getElapsedMs() > 32)
          if (mFrameTime->getElapsedMs() > 32)
          {
          {
+            if (GuiOffscreenCanvas::sActiveOffscreenCanvas)
+               GuiOffscreenCanvas::sActiveOffscreenCanvas->setActive(false);
+
             GuiOffscreenCanvas::sActiveOffscreenCanvas = NULL;
             GuiOffscreenCanvas::sActiveOffscreenCanvas = NULL;
             mFrameTime->reset();
             mFrameTime->reset();
 
 
@@ -197,6 +200,7 @@ void GuiCrossHairHud::onRender(Point2I offset, const RectI &updateRect)
                            canvas->setCursorPos(newCursorPos);
                            canvas->setCursorPos(newCursorPos);
                            canvas->markDirty();
                            canvas->markDirty();
                            GuiOffscreenCanvas::sActiveOffscreenCanvas = canvas;
                            GuiOffscreenCanvas::sActiveOffscreenCanvas = canvas;
+                           GuiOffscreenCanvas::sActiveOffscreenCanvas->setActive(true);
                            break;
                            break;
                         }
                         }
                      }
                      }

+ 16 - 0
Engine/source/gui/core/guiCanvas.cpp

@@ -393,6 +393,7 @@ void GuiCanvas::setWindowTitle(const char *newTitle)
 }
 }
 
 
 CanvasSizeChangeSignal GuiCanvas::smCanvasSizeChangeSignal;
 CanvasSizeChangeSignal GuiCanvas::smCanvasSizeChangeSignal;
+CanvasSetActiveSignal GuiCanvas::smCanvasSetActiveSignal;
 
 
 void GuiCanvas::handleResize( WindowId did, S32 width, S32 height )
 void GuiCanvas::handleResize( WindowId did, S32 width, S32 height )
 {
 {
@@ -2202,6 +2203,13 @@ StringTableEntry GuiCanvas::getLastInputDeviceType()
    return StringTable->EmptyString();
    return StringTable->EmptyString();
 }
 }
 
 
+void GuiCanvas::setActive(bool value)
+{
+   Parent::setActive(value);
+
+   GuiCanvas::getCanvasSetActiveSignal().trigger(this, value);
+}
+
 DefineEngineMethod( GuiCanvas, getContent, S32, (),,
 DefineEngineMethod( GuiCanvas, getContent, S32, (),,
                "@brief Get the GuiControl which is being used as the content.\n\n"
                "@brief Get the GuiControl which is being used as the content.\n\n"
 
 
@@ -3027,3 +3035,11 @@ DefineEngineMethod(GuiCanvas, getLastInputDevice, const char*, (), , "Returns th
 {
 {
    return object->getLastInputDeviceType();
    return object->getLastInputDeviceType();
 }
 }
+
+DefineEngineMethod(GuiCanvas, getActiveOffscreenCanvas, S32, (), , "Returns the SimID of the active offscreen canvas, if one exists. If not, returns 0")
+{
+   if (GuiOffscreenCanvas::sActiveOffscreenCanvas && GuiOffscreenCanvas::sActiveOffscreenCanvas->isActive())
+      return GuiOffscreenCanvas::sActiveOffscreenCanvas->getId();
+
+   return 0;
+}

+ 10 - 2
Engine/source/gui/core/guiCanvas.h

@@ -86,6 +86,8 @@
 class guiCanvas;
 class guiCanvas;
 class Point2I;
 class Point2I;
 typedef Signal<void(GuiCanvas* canvas)> CanvasSizeChangeSignal;
 typedef Signal<void(GuiCanvas* canvas)> CanvasSizeChangeSignal;
+typedef Signal<void(GuiCanvas* canvas, bool isActive)> CanvasSetActiveSignal;
+
 class GuiCanvas : public GuiControl, public IProcessInput
 class GuiCanvas : public GuiControl, public IProcessInput
 {
 {
 
 
@@ -210,10 +212,13 @@ protected:
    void checkLockMouseMove( const GuiEvent& event );
    void checkLockMouseMove( const GuiEvent& event );
    //Signal used to let others know this canvas has changed size.
    //Signal used to let others know this canvas has changed size.
 	static CanvasSizeChangeSignal smCanvasSizeChangeSignal;
 	static CanvasSizeChangeSignal smCanvasSizeChangeSignal;
+   static CanvasSetActiveSignal smCanvasSetActiveSignal;
 
 
    GuiControl *mMenuBarCtrl;
    GuiControl *mMenuBarCtrl;
    GuiControl* mMenuBackground;
    GuiControl* mMenuBackground;
    bool mConstrainMouse;
    bool mConstrainMouse;
+
+   typedef Signal< void(SetModification modification, SimSet* set, SimObject* object) > SetModificationSignal;
 public:
 public:
    DECLARE_CONOBJECT(GuiCanvas);
    DECLARE_CONOBJECT(GuiCanvas);
    DECLARE_CATEGORY( "Gui Core" );
    DECLARE_CATEGORY( "Gui Core" );
@@ -230,6 +235,7 @@ public:
    static void initPersistFields();
    static void initPersistFields();
 
 
    static CanvasSizeChangeSignal& getCanvasSizeChangeSignal() { return smCanvasSizeChangeSignal; }
    static CanvasSizeChangeSignal& getCanvasSizeChangeSignal() { return smCanvasSizeChangeSignal; }
+   static CanvasSetActiveSignal& getCanvasSetActiveSignal() { return smCanvasSetActiveSignal; }
 
 
    /// @name Rendering methods
    /// @name Rendering methods
    ///
    ///
@@ -477,16 +483,18 @@ public:
 
 
 private:
 private:
    static const U32 MAX_GAMEPADS = 4; ///< The maximum number of supported gamepads
    static const U32 MAX_GAMEPADS = 4; ///< The maximum number of supported gamepads
-  protected:
+protected:
      bool   mConsumeLastInputEvent;
      bool   mConsumeLastInputEvent;
      S32    mLastInputDeviceType;
      S32    mLastInputDeviceType;
-  public:
+public:
      void clearMouseRightButtonDown(void) { mMouseRightButtonDown = false; }
      void clearMouseRightButtonDown(void) { mMouseRightButtonDown = false; }
      void clearMouseButtonDown(void) { mMouseButtonDown = false; }
      void clearMouseButtonDown(void) { mMouseButtonDown = false; }
      void setConsumeLastInputEvent(bool flag) { mConsumeLastInputEvent = flag; }
      void setConsumeLastInputEvent(bool flag) { mConsumeLastInputEvent = flag; }
      bool getLastCursorPoint(Point2I& pt) const { pt = mLastCursorPt; return mLastCursorEnabled; }
      bool getLastCursorPoint(Point2I& pt) const { pt = mLastCursorPt; return mLastCursorEnabled; }
 
 
      StringTableEntry getLastInputDeviceType();
      StringTableEntry getLastInputDeviceType();
+
+   void setActive(bool value) override;
 };
 };
 typedef GuiCanvas::KeyTranslationMode KeyboardTranslationMode;
 typedef GuiCanvas::KeyTranslationMode KeyboardTranslationMode;
 DefineEnumType(KeyboardTranslationMode);
 DefineEnumType(KeyboardTranslationMode);

+ 32 - 2
Engine/source/gui/utility/guiInputCtrl.cpp

@@ -23,6 +23,7 @@
 #include "gui/utility/guiInputCtrl.h"
 #include "gui/utility/guiInputCtrl.h"
 #include "sim/actionMap.h"
 #include "sim/actionMap.h"
 #include "console/engineAPI.h"
 #include "console/engineAPI.h"
+#include "gui/core/guiCanvas.h"
 
 
 IMPLEMENT_CONOBJECT(GuiInputCtrl);
 IMPLEMENT_CONOBJECT(GuiInputCtrl);
 
 
@@ -88,6 +89,13 @@ void GuiInputCtrl::initPersistFields()
 }
 }
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
+bool GuiInputCtrl::onAdd()
+{
+   if (!Parent::onAdd())
+      return false;
+
+   GuiCanvas::getCanvasSetActiveSignal().notify(this, &GuiInputCtrl::handleCanvasSetActive);
+}
 
 
 bool GuiInputCtrl::onWake()
 bool GuiInputCtrl::onWake()
 {
 {
@@ -108,8 +116,11 @@ bool GuiInputCtrl::onWake()
 
 
    if(mActionmap != nullptr)
    if(mActionmap != nullptr)
    {
    {
-      SimSet* actionMapSet = Sim::getActiveActionMapSet();
-      actionMapSet->pushObject(mActionmap);
+      if (getRoot()->isActive())
+      {
+         SimSet* actionMapSet = Sim::getActiveActionMapSet();
+         actionMapSet->pushObject(mActionmap);
+      }
    }
    }
       
       
    setFirstResponder();
    setFirstResponder();
@@ -152,6 +163,25 @@ void GuiInputCtrl::setActive(bool value)
 
 
 }
 }
 
 
+void GuiInputCtrl::handleCanvasSetActive(GuiCanvas* canvas, bool isActive)
+{
+   if (mActionmap == nullptr)
+      return;
+
+   if (getRoot() == canvas)
+   {
+      if (isActive)
+      {
+         SimSet* actionMapSet = Sim::getActiveActionMapSet();
+         actionMapSet->pushObject(mActionmap);
+      }
+      else
+      {
+         SimSet* actionMapSet = Sim::getActiveActionMapSet();
+         actionMapSet->removeObject(mActionmap);
+      }
+   }
+}
 
 
 //------------------------------------------------------------------------------
 //------------------------------------------------------------------------------
 static bool isModifierKey( U16 keyCode )
 static bool isModifierKey( U16 keyCode )

+ 4 - 0
Engine/source/gui/utility/guiInputCtrl.h

@@ -47,6 +47,8 @@ public:
 
 
    GuiInputCtrl();
    GuiInputCtrl();
 
 
+   bool onAdd() override;
+
    // GuiControl.
    // GuiControl.
    bool onWake() override;
    bool onWake() override;
    void onSleep() override;
    void onSleep() override;
@@ -57,6 +59,8 @@ public:
 
 
    static void initPersistFields();
    static void initPersistFields();
 
 
+   void handleCanvasSetActive(GuiCanvas* canvas, bool isActive);
+
    DECLARE_CONOBJECT(GuiInputCtrl);
    DECLARE_CONOBJECT(GuiInputCtrl);
    DECLARE_CATEGORY( "Gui Other Script" );
    DECLARE_CATEGORY( "Gui Other Script" );
    DECLARE_DESCRIPTION( "A control that locks the mouse and reports all input events to script." );
    DECLARE_DESCRIPTION( "A control that locks the mouse and reports all input events to script." );

+ 1 - 0
Templates/BaseGame/game/data/Prototyping/Prototyping.tscript

@@ -50,6 +50,7 @@ function Prototyping::onCreateClientConnection(%this)
          dynamicTarget = false;
          dynamicTarget = false;
          canInteract = true;
          canInteract = true;
          maxInteractDistance = "3";
          maxInteractDistance = "3";
+         active = false;
       };
       };
    }
    }