From f281a97a9d21a58275c47ca4eeb7d93d4690dd8c Mon Sep 17 00:00:00 2001 From: xezon <4720891+xezon@users.noreply.github.com> Date: Thu, 4 Sep 2025 22:27:11 +0200 Subject: [PATCH 1/5] feat(options): Implement user options to control the screen edge scrolling behavior --- .../Include/Common/UserPreferences.h | 4 ++ .../Include/GameClient/LookAtXlat.h | 23 +++++++++-- .../GUI/GUICallbacks/Menus/OptionsMenu.cpp | 41 +++++++++++++++++++ .../GameClient/MessageStream/LookAtXlat.cpp | 34 ++++++++++++--- 4 files changed, 93 insertions(+), 9 deletions(-) diff --git a/GeneralsMD/Code/GameEngine/Include/Common/UserPreferences.h b/GeneralsMD/Code/GameEngine/Include/Common/UserPreferences.h index ac2c7e8cbaf..08946b593b3 100644 --- a/GeneralsMD/Code/GameEngine/Include/Common/UserPreferences.h +++ b/GeneralsMD/Code/GameEngine/Include/Common/UserPreferences.h @@ -40,6 +40,7 @@ class Money; enum CursorCaptureMode CPP_11(: Int); +typedef UnsignedInt ScreenEdgeScrollMode; //----------------------------------------------------------------------------- // PUBLIC TYPES /////////////////////////////////////////////////////////////// @@ -98,6 +99,9 @@ class OptionPreferences : public UserPreferences Bool getDrawScrollAnchor(void); Bool getMoveScrollAnchor(void); CursorCaptureMode getCursorCaptureMode() const; + Bool getScreenEdgeScrollEnabled() const; + Bool getScreenEdgeScrollFullscreenOnly() const; + ScreenEdgeScrollMode getScreenEdgeScrollMode() const; Bool getSendDelay(void); // convenience function Int getFirewallBehavior(void); // convenience function Short getFirewallPortAllocationDelta(void); // convenience function diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/LookAtXlat.h b/GeneralsMD/Code/GameEngine/Include/GameClient/LookAtXlat.h index d23c58aa8e3..89e8767d279 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameClient/LookAtXlat.h +++ b/GeneralsMD/Code/GameEngine/Include/GameClient/LookAtXlat.h @@ -32,16 +32,28 @@ #include "GameClient/InGameUI.h" +//----------------------------------------------------------------------------- +typedef UnsignedInt ScreenEdgeScrollMode; +enum ScreenEdgeScrollMode_ CPP_11(: ScreenEdgeScrollMode) +{ + ScreenEdgeScrollMode_Enabled = 1<<0, // Can scroll when touching the edge + ScreenEdgeScrollMode_FullscreenOnly = 1<<1, // Can scroll in fullscreen only + + ScreenEdgeScrollMode_Default = ScreenEdgeScrollMode_Enabled | ScreenEdgeScrollMode_FullscreenOnly, +}; + //----------------------------------------------------------------------------- class LookAtTranslator : public GameMessageTranslator { public: LookAtTranslator(); ~LookAtTranslator(); + virtual GameMessageDisposition translateGameMessage(const GameMessage *msg); virtual const ICoord2D* getRMBScrollAnchor(void); // get m_anchor ICoord2D if we're RMB scrolling Bool hasMouseMovedRecently( void ); void setCurrentPos( const ICoord2D& pos ); + void setScreenEdgeScrollMode(ScreenEdgeScrollMode mode); void resetModes(); //Used when disabling input, so when we reenable it we aren't stuck in a mode. @@ -50,7 +62,7 @@ class LookAtTranslator : public GameMessageTranslator { MAX_VIEW_LOCS = 8 }; - enum + enum ScrollType { SCROLL_NONE = 0, SCROLL_RMB, @@ -67,10 +79,13 @@ class LookAtTranslator : public GameMessageTranslator UnsignedInt m_timestamp; // set when button goes down DrawableID m_lastPlaneID; ViewLocation m_viewLocation[ MAX_VIEW_LOCS ]; - Int m_scrollType; - void setScrolling( Int ); - void stopScrolling( void ); + ScrollType m_scrollType; + ScreenEdgeScrollMode m_screenEdgeScrollMode; UnsignedInt m_lastMouseMoveFrame; + + void setScrolling( ScrollType scrollType ); + void stopScrolling( void ); + Bool canScrollAtScreenEdge() const; }; extern LookAtTranslator *TheLookAtTranslator; diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp index b671e5c5fea..7ae3c4b71dc 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp @@ -44,6 +44,7 @@ #include "GameClient/ClientInstance.h" #include "GameClient/GameClient.h" #include "GameClient/InGameUI.h" +#include "GameClient/LookAtXlat.h" #include "GameClient/WindowLayout.h" #include "GameClient/Gadget.h" #include "GameClient/GadgetCheckBox.h" @@ -422,6 +423,38 @@ CursorCaptureMode OptionPreferences::getCursorCaptureMode() const return mode; } +Bool OptionPreferences::getScreenEdgeScrollEnabled() const +{ + OptionPreferences::const_iterator it = find("ScreenEdgeScrollEnabled"); + if (it == end()) + return (ScreenEdgeScrollMode_Default & ScreenEdgeScrollMode_Enabled); + + if (stricmp(it->second.str(), "yes") == 0) { + return TRUE; + } + return FALSE; +} + +Bool OptionPreferences::getScreenEdgeScrollFullscreenOnly() const +{ + OptionPreferences::const_iterator it = find("ScreenEdgeScrollFullscreenOnly"); + if (it == end()) + return (ScreenEdgeScrollMode_Default & ScreenEdgeScrollMode_FullscreenOnly); + + if (stricmp(it->second.str(), "yes") == 0) { + return TRUE; + } + return FALSE; +} + +ScreenEdgeScrollMode OptionPreferences::getScreenEdgeScrollMode() const +{ + ScreenEdgeScrollMode mode = 0; + mode |= getScreenEdgeScrollEnabled() ? ScreenEdgeScrollMode_Enabled : 0; + mode |= getScreenEdgeScrollFullscreenOnly() ? ScreenEdgeScrollMode_FullscreenOnly : 0; + return mode; +} + Bool OptionPreferences::usesSystemMapDir(void) { OptionPreferences::const_iterator it = find("UseSystemMapDir"); @@ -1251,6 +1284,14 @@ static void saveOptions( void ) TheMouse->setCursorCaptureMode(mode); } + // TheSuperHackers @todo Add combo box ? + { + ScreenEdgeScrollMode mode = pref->getScreenEdgeScrollMode(); + (*pref)["ScreenEdgeScrollEnabled"] = (mode & ScreenEdgeScrollMode_Enabled) ? "yes" : "no"; + (*pref)["ScreenEdgeScrollFullscreenOnly"] = (mode & ScreenEdgeScrollMode_FullscreenOnly) ? "yes" : "no"; + TheLookAtTranslator->setScreenEdgeScrollMode(mode); + } + //------------------------------------------------------------------------------------------------- // scroll speed val val = GadgetSliderGetPosition(sliderScrollSpeed); diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp index 762d617e914..1516188dfa7 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp @@ -35,6 +35,7 @@ #include "Common/PlayerList.h" #include "Common/Recorder.h" #include "Common/StatsCollector.h" +#include "Common/UserPreferences.h" #include "GameLogic/Object.h" #include "GameLogic/PartitionManager.h" #include "GameClient/Display.h" @@ -80,7 +81,7 @@ static const Int edgeScrollSize = 3; static Mouse::MouseCursor prevCursor = Mouse::ARROW; //----------------------------------------------------------------------------- -void LookAtTranslator::setScrolling(Int x) +void LookAtTranslator::setScrolling(ScrollType scrollType) { if (!TheInGameUI->getInputEnabled()) return; @@ -89,7 +90,7 @@ void LookAtTranslator::setScrolling(Int x) m_isScrolling = true; TheInGameUI->setScrolling( TRUE ); TheTacticalView->setMouseLock( TRUE ); - m_scrollType = x; + m_scrollType = scrollType; if(TheStatsCollector) TheStatsCollector->startScrollTime(); } @@ -103,12 +104,27 @@ void LookAtTranslator::stopScrolling( void ) TheMouse->setCursor(prevCursor); m_scrollType = SCROLL_NONE; - // if we have a stats collectore increment the stats + // increment the stats if we have a stats collector if(TheStatsCollector) TheStatsCollector->endScrollTime(); } +//----------------------------------------------------------------------------- +Bool LookAtTranslator::canScrollAtScreenEdge() const +{ + if (!TheMouse->isCursorCaptured()) + return FALSE; + + if ((m_screenEdgeScrollMode & ScreenEdgeScrollMode_Enabled) == 0) + return FALSE; + + if (TheDisplay->getWindowed() && (m_screenEdgeScrollMode & ScreenEdgeScrollMode_FullscreenOnly) != 0) + return FALSE; + + return TRUE; +} + //----------------------------------------------------------------------------- LookAtTranslator::LookAtTranslator() : m_isScrolling(false), @@ -121,12 +137,15 @@ LookAtTranslator::LookAtTranslator() : m_scrollType(SCROLL_NONE) { //Added By Sadullah Nader - //Initializations misssing and needed + //Initializations missing and needed m_anchor.x = m_anchor.y = 0; m_currentPos.x = m_currentPos.y = 0; m_originalAnchor.x = m_originalAnchor.y = 0; // + OptionPreferences prefs; + m_screenEdgeScrollMode = prefs.getScreenEdgeScrollMode(); + DEBUG_ASSERTCRASH(!TheLookAtTranslator, ("Already have a LookAtTranslator - why do you need two?")); TheLookAtTranslator = this; } @@ -163,6 +182,11 @@ void LookAtTranslator::setCurrentPos( const ICoord2D& pos ) m_currentPos = pos; } +void LookAtTranslator::setScreenEdgeScrollMode(ScreenEdgeScrollMode mode) +{ + m_screenEdgeScrollMode = mode; +} + //----------------------------------------------------------------------------- /** * The LookAt Translator is responsible for camera movements. It is directly responsible for @@ -308,7 +332,7 @@ GameMessageDisposition LookAtTranslator::translateGameMessage(const GameMessage } // TheSuperHackers @tweak Ayumi/xezon 26/07/2025 Enables edge scrolling in windowed mode. - if (TheMouse->isCursorCaptured()) + if (canScrollAtScreenEdge()) { if (m_isScrolling) { From daeac94808372337f5f79082e1a624d72e56c1be Mon Sep 17 00:00:00 2001 From: xezon <4720891+xezon@users.noreply.github.com> Date: Fri, 5 Sep 2025 14:31:00 +0200 Subject: [PATCH 2/5] Update user options --- .../Include/Common/UserPreferences.h | 4 +-- .../Include/GameClient/LookAtXlat.h | 6 ++-- .../GUI/GUICallbacks/Menus/OptionsMenu.cpp | 28 +++++++++---------- .../GameClient/MessageStream/LookAtXlat.cpp | 19 ++++++++----- 4 files changed, 31 insertions(+), 26 deletions(-) diff --git a/GeneralsMD/Code/GameEngine/Include/Common/UserPreferences.h b/GeneralsMD/Code/GameEngine/Include/Common/UserPreferences.h index 08946b593b3..7003107e15c 100644 --- a/GeneralsMD/Code/GameEngine/Include/Common/UserPreferences.h +++ b/GeneralsMD/Code/GameEngine/Include/Common/UserPreferences.h @@ -99,8 +99,8 @@ class OptionPreferences : public UserPreferences Bool getDrawScrollAnchor(void); Bool getMoveScrollAnchor(void); CursorCaptureMode getCursorCaptureMode() const; - Bool getScreenEdgeScrollEnabled() const; - Bool getScreenEdgeScrollFullscreenOnly() const; + Bool getScreenEdgeScrollEnabledInWindowedApp() const; + Bool getScreenEdgeScrollEnabledInFullscreenApp() const; ScreenEdgeScrollMode getScreenEdgeScrollMode() const; Bool getSendDelay(void); // convenience function Int getFirewallBehavior(void); // convenience function diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/LookAtXlat.h b/GeneralsMD/Code/GameEngine/Include/GameClient/LookAtXlat.h index 89e8767d279..e67884acecc 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameClient/LookAtXlat.h +++ b/GeneralsMD/Code/GameEngine/Include/GameClient/LookAtXlat.h @@ -36,10 +36,10 @@ typedef UnsignedInt ScreenEdgeScrollMode; enum ScreenEdgeScrollMode_ CPP_11(: ScreenEdgeScrollMode) { - ScreenEdgeScrollMode_Enabled = 1<<0, // Can scroll when touching the edge - ScreenEdgeScrollMode_FullscreenOnly = 1<<1, // Can scroll in fullscreen only + ScreenEdgeScrollMode_EnabledInWindowedApp = 1<<0, // Scroll when touching the edge while the app is windowed + ScreenEdgeScrollMode_EnabledInFullscreenApp = 1<<1, // Scroll when touching the edge while the app is fullscreen - ScreenEdgeScrollMode_Default = ScreenEdgeScrollMode_Enabled | ScreenEdgeScrollMode_FullscreenOnly, + ScreenEdgeScrollMode_Default = ScreenEdgeScrollMode_EnabledInFullscreenApp, }; //----------------------------------------------------------------------------- diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp index 7ae3c4b71dc..679aba7b625 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp @@ -423,35 +423,35 @@ CursorCaptureMode OptionPreferences::getCursorCaptureMode() const return mode; } -Bool OptionPreferences::getScreenEdgeScrollEnabled() const +Bool OptionPreferences::getScreenEdgeScrollEnabledInWindowedApp() const { - OptionPreferences::const_iterator it = find("ScreenEdgeScrollEnabled"); + OptionPreferences::const_iterator it = find("ScreenEdgeScrollEnabledInWindowedApp"); if (it == end()) - return (ScreenEdgeScrollMode_Default & ScreenEdgeScrollMode_Enabled); + return (ScreenEdgeScrollMode_Default & ScreenEdgeScrollMode_EnabledInWindowedApp); - if (stricmp(it->second.str(), "yes") == 0) { + if (stricmp(it->second.str(), "yes") == 0) return TRUE; - } + return FALSE; } -Bool OptionPreferences::getScreenEdgeScrollFullscreenOnly() const +Bool OptionPreferences::getScreenEdgeScrollEnabledInFullscreenApp() const { - OptionPreferences::const_iterator it = find("ScreenEdgeScrollFullscreenOnly"); + OptionPreferences::const_iterator it = find("ScreenEdgeScrollEnabledInFullscreenApp"); if (it == end()) - return (ScreenEdgeScrollMode_Default & ScreenEdgeScrollMode_FullscreenOnly); + return (ScreenEdgeScrollMode_Default & ScreenEdgeScrollMode_EnabledInFullscreenApp); - if (stricmp(it->second.str(), "yes") == 0) { + if (stricmp(it->second.str(), "yes") == 0) return TRUE; - } + return FALSE; } ScreenEdgeScrollMode OptionPreferences::getScreenEdgeScrollMode() const { ScreenEdgeScrollMode mode = 0; - mode |= getScreenEdgeScrollEnabled() ? ScreenEdgeScrollMode_Enabled : 0; - mode |= getScreenEdgeScrollFullscreenOnly() ? ScreenEdgeScrollMode_FullscreenOnly : 0; + mode |= getScreenEdgeScrollEnabledInWindowedApp() ? ScreenEdgeScrollMode_EnabledInWindowedApp : 0; + mode |= getScreenEdgeScrollEnabledInFullscreenApp() ? ScreenEdgeScrollMode_EnabledInFullscreenApp : 0; return mode; } @@ -1287,8 +1287,8 @@ static void saveOptions( void ) // TheSuperHackers @todo Add combo box ? { ScreenEdgeScrollMode mode = pref->getScreenEdgeScrollMode(); - (*pref)["ScreenEdgeScrollEnabled"] = (mode & ScreenEdgeScrollMode_Enabled) ? "yes" : "no"; - (*pref)["ScreenEdgeScrollFullscreenOnly"] = (mode & ScreenEdgeScrollMode_FullscreenOnly) ? "yes" : "no"; + (*pref)["ScreenEdgeScrollEnabledInWindowedApp"] = (mode & ScreenEdgeScrollMode_EnabledInWindowedApp) ? "yes" : "no"; + (*pref)["ScreenEdgeScrollEnabledInFullscreenApp"] = (mode & ScreenEdgeScrollMode_EnabledInFullscreenApp) ? "yes" : "no"; TheLookAtTranslator->setScreenEdgeScrollMode(mode); } diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp index 1516188dfa7..d486d9176b4 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp @@ -114,15 +114,20 @@ void LookAtTranslator::stopScrolling( void ) Bool LookAtTranslator::canScrollAtScreenEdge() const { if (!TheMouse->isCursorCaptured()) - return FALSE; - - if ((m_screenEdgeScrollMode & ScreenEdgeScrollMode_Enabled) == 0) - return FALSE; + return false; - if (TheDisplay->getWindowed() && (m_screenEdgeScrollMode & ScreenEdgeScrollMode_FullscreenOnly) != 0) - return FALSE; + if (TheDisplay->getWindowed()) + { + if ((m_screenEdgeScrollMode & ScreenEdgeScrollMode_EnabledInWindowedApp) == 0) + return false; + } + else + { + if ((m_screenEdgeScrollMode & ScreenEdgeScrollMode_EnabledInFullscreenApp) == 0) + return false; + } - return TRUE; + return true; } //----------------------------------------------------------------------------- From 20a1acd195dc08a061b135d73f4d371952b84695 Mon Sep 17 00:00:00 2001 From: xezon <4720891+xezon@users.noreply.github.com> Date: Wed, 10 Sep 2025 12:09:53 +0200 Subject: [PATCH 3/5] Fix truncation compiler warning --- .../Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp index 679aba7b625..f7e96138bc9 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp @@ -427,7 +427,7 @@ Bool OptionPreferences::getScreenEdgeScrollEnabledInWindowedApp() const { OptionPreferences::const_iterator it = find("ScreenEdgeScrollEnabledInWindowedApp"); if (it == end()) - return (ScreenEdgeScrollMode_Default & ScreenEdgeScrollMode_EnabledInWindowedApp); + return (ScreenEdgeScrollMode_Default & ScreenEdgeScrollMode_EnabledInWindowedApp) != 0; if (stricmp(it->second.str(), "yes") == 0) return TRUE; @@ -439,7 +439,7 @@ Bool OptionPreferences::getScreenEdgeScrollEnabledInFullscreenApp() const { OptionPreferences::const_iterator it = find("ScreenEdgeScrollEnabledInFullscreenApp"); if (it == end()) - return (ScreenEdgeScrollMode_Default & ScreenEdgeScrollMode_EnabledInFullscreenApp); + return (ScreenEdgeScrollMode_Default & ScreenEdgeScrollMode_EnabledInFullscreenApp) != 0; if (stricmp(it->second.str(), "yes") == 0) return TRUE; From decd66ce188336c140108368bfe3626d3b219799 Mon Sep 17 00:00:00 2001 From: xezon <4720891+xezon@users.noreply.github.com> Date: Wed, 10 Sep 2025 12:11:29 +0200 Subject: [PATCH 4/5] Replicate in Generals --- .../Include/Common/UserPreferences.h | 4 ++ .../Include/GameClient/LookAtXlat.h | 23 +++++++++-- .../GUI/GUICallbacks/Menus/OptionsMenu.cpp | 41 +++++++++++++++++++ .../GameClient/MessageStream/LookAtXlat.cpp | 39 +++++++++++++++--- 4 files changed, 98 insertions(+), 9 deletions(-) diff --git a/Generals/Code/GameEngine/Include/Common/UserPreferences.h b/Generals/Code/GameEngine/Include/Common/UserPreferences.h index 22c6cdbc35f..35393244ba2 100644 --- a/Generals/Code/GameEngine/Include/Common/UserPreferences.h +++ b/Generals/Code/GameEngine/Include/Common/UserPreferences.h @@ -39,6 +39,7 @@ #include "Common/STLTypedefs.h" enum CursorCaptureMode CPP_11(: Int); +typedef UnsignedInt ScreenEdgeScrollMode; //----------------------------------------------------------------------------- // PUBLIC TYPES /////////////////////////////////////////////////////////////// @@ -95,6 +96,9 @@ class OptionPreferences : public UserPreferences Bool getDrawScrollAnchor(void); Bool getMoveScrollAnchor(void); CursorCaptureMode getCursorCaptureMode() const; + Bool getScreenEdgeScrollEnabledInWindowedApp() const; + Bool getScreenEdgeScrollEnabledInFullscreenApp() const; + ScreenEdgeScrollMode getScreenEdgeScrollMode() const; Bool getSendDelay(void); // convenience function Int getFirewallBehavior(void); // convenience function Short getFirewallPortAllocationDelta(void); // convenience function diff --git a/Generals/Code/GameEngine/Include/GameClient/LookAtXlat.h b/Generals/Code/GameEngine/Include/GameClient/LookAtXlat.h index 4b4ec7fd644..1d59da88b45 100644 --- a/Generals/Code/GameEngine/Include/GameClient/LookAtXlat.h +++ b/Generals/Code/GameEngine/Include/GameClient/LookAtXlat.h @@ -32,16 +32,28 @@ #include "GameClient/InGameUI.h" +//----------------------------------------------------------------------------- +typedef UnsignedInt ScreenEdgeScrollMode; +enum ScreenEdgeScrollMode_ CPP_11(: ScreenEdgeScrollMode) +{ + ScreenEdgeScrollMode_EnabledInWindowedApp = 1<<0, // Scroll when touching the edge while the app is windowed + ScreenEdgeScrollMode_EnabledInFullscreenApp = 1<<1, // Scroll when touching the edge while the app is fullscreen + + ScreenEdgeScrollMode_Default = ScreenEdgeScrollMode_EnabledInFullscreenApp, +}; + //----------------------------------------------------------------------------- class LookAtTranslator : public GameMessageTranslator { public: LookAtTranslator(); ~LookAtTranslator(); + virtual GameMessageDisposition translateGameMessage(const GameMessage *msg); virtual const ICoord2D* getRMBScrollAnchor(void); // get m_anchor ICoord2D if we're RMB scrolling Bool hasMouseMovedRecently( void ); void setCurrentPos( const ICoord2D& pos ); + void setScreenEdgeScrollMode(ScreenEdgeScrollMode mode); void resetModes(); //Used when disabling input, so when we reenable it we aren't stuck in a mode. @@ -50,7 +62,7 @@ class LookAtTranslator : public GameMessageTranslator { MAX_VIEW_LOCS = 8 }; - enum + enum ScrollType { SCROLL_NONE = 0, SCROLL_RMB, @@ -67,10 +79,13 @@ class LookAtTranslator : public GameMessageTranslator UnsignedInt m_timestamp; // set when button goes down DrawableID m_lastPlaneID; ViewLocation m_viewLocation[ MAX_VIEW_LOCS ]; - Int m_scrollType; - void setScrolling( Int ); - void stopScrolling( void ); + ScrollType m_scrollType; + ScreenEdgeScrollMode m_screenEdgeScrollMode; UnsignedInt m_lastMouseMoveFrame; + + void setScrolling( ScrollType scrollType ); + void stopScrolling( void ); + Bool canScrollAtScreenEdge() const; }; extern LookAtTranslator *TheLookAtTranslator; diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp index b6d74b6f24e..c46a4967ad6 100644 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp +++ b/Generals/Code/GameEngine/Source/GameClient/GUI/GUICallbacks/Menus/OptionsMenu.cpp @@ -44,6 +44,7 @@ #include "GameClient/ClientInstance.h" #include "GameClient/GameClient.h" #include "GameClient/InGameUI.h" +#include "GameClient/LookAtXlat.h" #include "GameClient/WindowLayout.h" #include "GameClient/Gadget.h" #include "GameClient/GadgetCheckBox.h" @@ -390,6 +391,38 @@ CursorCaptureMode OptionPreferences::getCursorCaptureMode() const return mode; } +Bool OptionPreferences::getScreenEdgeScrollEnabledInWindowedApp() const +{ + OptionPreferences::const_iterator it = find("ScreenEdgeScrollEnabledInWindowedApp"); + if (it == end()) + return (ScreenEdgeScrollMode_Default & ScreenEdgeScrollMode_EnabledInWindowedApp) != 0; + + if (stricmp(it->second.str(), "yes") == 0) + return TRUE; + + return FALSE; +} + +Bool OptionPreferences::getScreenEdgeScrollEnabledInFullscreenApp() const +{ + OptionPreferences::const_iterator it = find("ScreenEdgeScrollEnabledInFullscreenApp"); + if (it == end()) + return (ScreenEdgeScrollMode_Default & ScreenEdgeScrollMode_EnabledInFullscreenApp) != 0; + + if (stricmp(it->second.str(), "yes") == 0) + return TRUE; + + return FALSE; +} + +ScreenEdgeScrollMode OptionPreferences::getScreenEdgeScrollMode() const +{ + ScreenEdgeScrollMode mode = 0; + mode |= getScreenEdgeScrollEnabledInWindowedApp() ? ScreenEdgeScrollMode_EnabledInWindowedApp : 0; + mode |= getScreenEdgeScrollEnabledInFullscreenApp() ? ScreenEdgeScrollMode_EnabledInFullscreenApp : 0; + return mode; +} + Bool OptionPreferences::usesSystemMapDir(void) { OptionPreferences::const_iterator it = find("UseSystemMapDir"); @@ -1191,6 +1224,14 @@ static void saveOptions( void ) TheMouse->setCursorCaptureMode(mode); } + // TheSuperHackers @todo Add combo box ? + { + ScreenEdgeScrollMode mode = pref->getScreenEdgeScrollMode(); + (*pref)["ScreenEdgeScrollEnabledInWindowedApp"] = (mode & ScreenEdgeScrollMode_EnabledInWindowedApp) ? "yes" : "no"; + (*pref)["ScreenEdgeScrollEnabledInFullscreenApp"] = (mode & ScreenEdgeScrollMode_EnabledInFullscreenApp) ? "yes" : "no"; + TheLookAtTranslator->setScreenEdgeScrollMode(mode); + } + //------------------------------------------------------------------------------------------------- // scroll speed val val = GadgetSliderGetPosition(sliderScrollSpeed); diff --git a/Generals/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp b/Generals/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp index 6a7235583fb..e8293bda4f5 100644 --- a/Generals/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp +++ b/Generals/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp @@ -35,6 +35,7 @@ #include "Common/PlayerList.h" #include "Common/Recorder.h" #include "Common/StatsCollector.h" +#include "Common/UserPreferences.h" #include "GameLogic/Object.h" #include "GameLogic/PartitionManager.h" #include "GameClient/Display.h" @@ -80,7 +81,7 @@ static const Int edgeScrollSize = 3; static Mouse::MouseCursor prevCursor = Mouse::ARROW; //----------------------------------------------------------------------------- -void LookAtTranslator::setScrolling(Int x) +void LookAtTranslator::setScrolling(ScrollType scrollType) { if (!TheInGameUI->getInputEnabled()) return; @@ -89,7 +90,7 @@ void LookAtTranslator::setScrolling(Int x) m_isScrolling = true; TheInGameUI->setScrolling( TRUE ); TheTacticalView->setMouseLock( TRUE ); - m_scrollType = x; + m_scrollType = scrollType; if(TheStatsCollector) TheStatsCollector->startScrollTime(); } @@ -103,12 +104,32 @@ void LookAtTranslator::stopScrolling( void ) TheMouse->setCursor(prevCursor); m_scrollType = SCROLL_NONE; - // if we have a stats collectore increment the stats + // increment the stats if we have a stats collector if(TheStatsCollector) TheStatsCollector->endScrollTime(); } +//----------------------------------------------------------------------------- +Bool LookAtTranslator::canScrollAtScreenEdge() const +{ + if (!TheMouse->isCursorCaptured()) + return false; + + if (TheDisplay->getWindowed()) + { + if ((m_screenEdgeScrollMode & ScreenEdgeScrollMode_EnabledInWindowedApp) == 0) + return false; + } + else + { + if ((m_screenEdgeScrollMode & ScreenEdgeScrollMode_EnabledInFullscreenApp) == 0) + return false; + } + + return true; +} + //----------------------------------------------------------------------------- LookAtTranslator::LookAtTranslator() : m_isScrolling(false), @@ -121,12 +142,15 @@ LookAtTranslator::LookAtTranslator() : m_scrollType(SCROLL_NONE) { //Added By Sadullah Nader - //Initializations misssing and needed + //Initializations missing and needed m_anchor.x = m_anchor.y = 0; m_currentPos.x = m_currentPos.y = 0; m_originalAnchor.x = m_originalAnchor.y = 0; // + OptionPreferences prefs; + m_screenEdgeScrollMode = prefs.getScreenEdgeScrollMode(); + DEBUG_ASSERTCRASH(!TheLookAtTranslator, ("Already have a LookAtTranslator - why do you need two?")); TheLookAtTranslator = this; } @@ -163,6 +187,11 @@ void LookAtTranslator::setCurrentPos( const ICoord2D& pos ) m_currentPos = pos; } +void LookAtTranslator::setScreenEdgeScrollMode(ScreenEdgeScrollMode mode) +{ + m_screenEdgeScrollMode = mode; +} + //----------------------------------------------------------------------------- /** * The LookAt Translator is responsible for camera movements. It is directly responsible for @@ -309,7 +338,7 @@ GameMessageDisposition LookAtTranslator::translateGameMessage(const GameMessage } // TheSuperHackers @tweak Ayumi/xezon 26/07/2025 Enables edge scrolling in windowed mode. - if (TheMouse->isCursorCaptured()) + if (canScrollAtScreenEdge()) { if (m_isScrolling) { From 5a8dc954fde9a69967c735158ecb3ac21428743b Mon Sep 17 00:00:00 2001 From: xezon <4720891+xezon@users.noreply.github.com> Date: Wed, 10 Sep 2025 12:17:47 +0200 Subject: [PATCH 5/5] Improve code comments --- Generals/Code/GameEngine/Include/GameClient/LookAtXlat.h | 4 +++- .../GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp | 1 - GeneralsMD/Code/GameEngine/Include/GameClient/LookAtXlat.h | 4 +++- .../GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp | 1 - 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Generals/Code/GameEngine/Include/GameClient/LookAtXlat.h b/Generals/Code/GameEngine/Include/GameClient/LookAtXlat.h index 1d59da88b45..6cafbab541f 100644 --- a/Generals/Code/GameEngine/Include/GameClient/LookAtXlat.h +++ b/Generals/Code/GameEngine/Include/GameClient/LookAtXlat.h @@ -33,13 +33,15 @@ #include "GameClient/InGameUI.h" //----------------------------------------------------------------------------- +// TheSuperHackers @feature The Screen Edge Scrolling can now be enabled or +// disabled depending on the App being Windowed or Fullscreen. typedef UnsignedInt ScreenEdgeScrollMode; enum ScreenEdgeScrollMode_ CPP_11(: ScreenEdgeScrollMode) { ScreenEdgeScrollMode_EnabledInWindowedApp = 1<<0, // Scroll when touching the edge while the app is windowed ScreenEdgeScrollMode_EnabledInFullscreenApp = 1<<1, // Scroll when touching the edge while the app is fullscreen - ScreenEdgeScrollMode_Default = ScreenEdgeScrollMode_EnabledInFullscreenApp, + ScreenEdgeScrollMode_Default = ScreenEdgeScrollMode_EnabledInFullscreenApp, // Default based on original game behavior }; //----------------------------------------------------------------------------- diff --git a/Generals/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp b/Generals/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp index e8293bda4f5..d2e09ed4353 100644 --- a/Generals/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp +++ b/Generals/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp @@ -337,7 +337,6 @@ GameMessageDisposition LookAtTranslator::translateGameMessage(const GameMessage break; } - // TheSuperHackers @tweak Ayumi/xezon 26/07/2025 Enables edge scrolling in windowed mode. if (canScrollAtScreenEdge()) { if (m_isScrolling) diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/LookAtXlat.h b/GeneralsMD/Code/GameEngine/Include/GameClient/LookAtXlat.h index e67884acecc..6f9611154f6 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameClient/LookAtXlat.h +++ b/GeneralsMD/Code/GameEngine/Include/GameClient/LookAtXlat.h @@ -33,13 +33,15 @@ #include "GameClient/InGameUI.h" //----------------------------------------------------------------------------- +// TheSuperHackers @feature The Screen Edge Scrolling can now be enabled or +// disabled depending on the App being Windowed or Fullscreen. typedef UnsignedInt ScreenEdgeScrollMode; enum ScreenEdgeScrollMode_ CPP_11(: ScreenEdgeScrollMode) { ScreenEdgeScrollMode_EnabledInWindowedApp = 1<<0, // Scroll when touching the edge while the app is windowed ScreenEdgeScrollMode_EnabledInFullscreenApp = 1<<1, // Scroll when touching the edge while the app is fullscreen - ScreenEdgeScrollMode_Default = ScreenEdgeScrollMode_EnabledInFullscreenApp, + ScreenEdgeScrollMode_Default = ScreenEdgeScrollMode_EnabledInFullscreenApp, // Default based on original game behavior }; //----------------------------------------------------------------------------- diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp index d486d9176b4..c106cdddf8a 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/MessageStream/LookAtXlat.cpp @@ -336,7 +336,6 @@ GameMessageDisposition LookAtTranslator::translateGameMessage(const GameMessage break; } - // TheSuperHackers @tweak Ayumi/xezon 26/07/2025 Enables edge scrolling in windowed mode. if (canScrollAtScreenEdge()) { if (m_isScrolling)