diff --git a/Generals/Code/GameEngine/Include/GameClient/AnimateWindowManager.h b/Generals/Code/GameEngine/Include/GameClient/AnimateWindowManager.h index aad9e80b7a2..a0c16ee1045 100644 --- a/Generals/Code/GameEngine/Include/GameClient/AnimateWindowManager.h +++ b/Generals/Code/GameEngine/Include/GameClient/AnimateWindowManager.h @@ -178,10 +178,13 @@ class AnimateWindowManager : public SubsystemInterface Bool isReversed(); ///< Returns whether or not we're in our reversed state. Bool isEmpty(); private: + void step(); ///< Runs a single base-rate step of all registered window animations + AnimateWindowList m_winList; ///< A list of AnimationWindows that we don't care if their finished animating AnimateWindowList m_winMustFinishList; ///< A list of AnimationWindows that we do care about Bool m_needsUpdate; ///< If we're done animating all our monitored windows, then this will be false Bool m_reverse; ///< Are we in a reverse state? + Real m_frameAccumulator; ///< Carries fractional base-rate frames between updates ProcessAnimateWindowSlideFromRight *m_slideFromRight; ///< Holds the process in which the windows slide from the right ProcessAnimateWindowSlideFromRightFast *m_slideFromRightFast; ProcessAnimateWindowSlideFromTop *m_slideFromTop; ///< Holds the process in which the windows slide from the Top diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/AnimateWindowManager.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/AnimateWindowManager.cpp index c2b73a16b11..f2ea185ecbf 100644 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/AnimateWindowManager.cpp +++ b/Generals/Code/GameEngine/Source/GameClient/GUI/AnimateWindowManager.cpp @@ -57,6 +57,7 @@ #include "GameClient/GameWindow.h" #include "GameClient/Display.h" #include "GameClient/ProcessAnimateWindow.h" +#include "Common/FramePacer.h" //----------------------------------------------------------------------------- // DEFINES //////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------------- @@ -133,6 +134,7 @@ AnimateWindowManager::AnimateWindowManager() m_winList.clear(); m_needsUpdate = FALSE; m_reverse = FALSE; + m_frameAccumulator = 0.0f; m_winMustFinishList.clear(); } AnimateWindowManager::~AnimateWindowManager() @@ -159,6 +161,7 @@ void AnimateWindowManager::init() clearWinList(m_winMustFinishList); m_needsUpdate = FALSE; m_reverse = FALSE; + m_frameAccumulator = 0.0f; } void AnimateWindowManager::reset() @@ -168,9 +171,23 @@ void AnimateWindowManager::reset() clearWinList(m_winMustFinishList); m_needsUpdate = FALSE; m_reverse = FALSE; + m_frameAccumulator = 0.0f; } +// TheSuperHackers @tweak bobtista 27/06/2026 Decouple GUI window-move animations from the render frame rate void AnimateWindowManager::update() +{ + m_frameAccumulator += TheFramePacer->getBaseOverUpdateFpsRatio(); + Int steps = (Int)m_frameAccumulator; + m_frameAccumulator -= (Real)steps; + + while (steps-- > 0) + { + step(); + } +} + +void AnimateWindowManager::step() { ProcessAnimateWindow *processAnim = nullptr; diff --git a/Generals/Code/GameEngine/Source/GameClient/GUI/Shell/Shell.cpp b/Generals/Code/GameEngine/Source/GameClient/GUI/Shell/Shell.cpp index fff2cf12c94..d8170c95f2c 100644 --- a/Generals/Code/GameEngine/Source/GameClient/GUI/Shell/Shell.cpp +++ b/Generals/Code/GameEngine/Source/GameClient/GUI/Shell/Shell.cpp @@ -205,9 +205,6 @@ void Shell::update() } - // Update the animate window manager - m_animateWindowManager->update(); - m_schemeManager->update(); // mark last time we ran the updates @@ -215,6 +212,9 @@ void Shell::update() } + // TheSuperHackers @tweak bobtista 08/07/2026 Update the animate window manager every frame, it paces itself now + m_animateWindowManager->update(); + } //------------------------------------------------------------------------------------------------- diff --git a/GeneralsMD/Code/GameEngine/Include/GameClient/AnimateWindowManager.h b/GeneralsMD/Code/GameEngine/Include/GameClient/AnimateWindowManager.h index f232411213e..447d60699a4 100644 --- a/GeneralsMD/Code/GameEngine/Include/GameClient/AnimateWindowManager.h +++ b/GeneralsMD/Code/GameEngine/Include/GameClient/AnimateWindowManager.h @@ -178,10 +178,13 @@ class AnimateWindowManager : public SubsystemInterface Bool isReversed(); ///< Returns whether or not we're in our reversed state. Bool isEmpty(); private: + void step(); ///< Runs a single base-rate step of all registered window animations + AnimateWindowList m_winList; ///< A list of AnimationWindows that we don't care if their finished animating AnimateWindowList m_winMustFinishList; ///< A list of AnimationWindows that we do care about Bool m_needsUpdate; ///< If we're done animating all our monitored windows, then this will be false Bool m_reverse; ///< Are we in a reverse state? + Real m_frameAccumulator; ///< Carries fractional base-rate frames between updates ProcessAnimateWindowSlideFromRight *m_slideFromRight; ///< Holds the process in which the windows slide from the right ProcessAnimateWindowSlideFromRightFast *m_slideFromRightFast; ProcessAnimateWindowSlideFromTop *m_slideFromTop; ///< Holds the process in which the windows slide from the Top diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/AnimateWindowManager.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/AnimateWindowManager.cpp index 151464bdc04..53efa416793 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/AnimateWindowManager.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/AnimateWindowManager.cpp @@ -57,6 +57,7 @@ #include "GameClient/GameWindow.h" #include "GameClient/Display.h" #include "GameClient/ProcessAnimateWindow.h" +#include "Common/FramePacer.h" //----------------------------------------------------------------------------- // DEFINES //////////////////////////////////////////////////////////////////// //----------------------------------------------------------------------------- @@ -133,6 +134,7 @@ AnimateWindowManager::AnimateWindowManager() m_winList.clear(); m_needsUpdate = FALSE; m_reverse = FALSE; + m_frameAccumulator = 0.0f; m_winMustFinishList.clear(); } AnimateWindowManager::~AnimateWindowManager() @@ -159,6 +161,7 @@ void AnimateWindowManager::init() clearWinList(m_winMustFinishList); m_needsUpdate = FALSE; m_reverse = FALSE; + m_frameAccumulator = 0.0f; } void AnimateWindowManager::reset() @@ -168,9 +171,23 @@ void AnimateWindowManager::reset() clearWinList(m_winMustFinishList); m_needsUpdate = FALSE; m_reverse = FALSE; + m_frameAccumulator = 0.0f; } +// TheSuperHackers @tweak bobtista 27/06/2026 Decouple GUI window-move animations from the render frame rate void AnimateWindowManager::update() +{ + m_frameAccumulator += TheFramePacer->getBaseOverUpdateFpsRatio(); + Int steps = (Int)m_frameAccumulator; + m_frameAccumulator -= (Real)steps; + + while (steps-- > 0) + { + step(); + } +} + +void AnimateWindowManager::step() { ProcessAnimateWindow *processAnim = nullptr; diff --git a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/Shell/Shell.cpp b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/Shell/Shell.cpp index e7d1333905b..f4114c88ca4 100644 --- a/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/Shell/Shell.cpp +++ b/GeneralsMD/Code/GameEngine/Source/GameClient/GUI/Shell/Shell.cpp @@ -205,9 +205,6 @@ void Shell::update() } - // Update the animate window manager - m_animateWindowManager->update(); - m_schemeManager->update(); // mark last time we ran the updates @@ -215,6 +212,9 @@ void Shell::update() } + // TheSuperHackers @tweak bobtista 08/07/2026 Update the animate window manager every frame, it paces itself now + m_animateWindowManager->update(); + } //-------------------------------------------------------------------------------------------------