]> git.lizzy.rs Git - dragonfireclient.git/commitdiff
Pause animations while game is paused (#10658)
authorVitaliy <numzer0@yandex.ru>
Fri, 5 Mar 2021 15:28:08 +0000 (18:28 +0300)
committerSmallJoker <mk939@ymail.com>
Fri, 5 Mar 2021 15:30:01 +0000 (16:30 +0100)
Pauses all mesh animations while game is paused.

src/client/game.cpp

index 15fa2af23fa321250c50ef55615d960a6a0b8496..60ecb7d3e5c680291d00c03aa178bd19d2e4de35 100644 (file)
@@ -68,6 +68,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include "util/pointedthing.h"
 #include "util/quicktune_shortcutter.h"
 #include "irrlicht_changes/static_text.h"
+#include "irr_ptr.h"
 #include "version.h"
 #include "script/scripting_client.h"
 #include "hud.h"
@@ -647,6 +648,8 @@ struct ClientEventHandler
  THE GAME
  ****************************************************************************/
 
+using PausedNodesList = std::vector<std::pair<irr_ptr<scene::IAnimatedMeshSceneNode>, float>>;
+
 /* This is not intended to be a public class. If a public class becomes
  * desirable then it may be better to create another 'wrapper' class that
  * hides most of the stuff in this class (nothing in this class is required
@@ -796,6 +799,9 @@ class Game {
        void showDeathFormspec();
        void showPauseMenu();
 
+       void pauseAnimation();
+       void resumeAnimation();
+
        // ClientEvent handlers
        void handleClientEvent_None(ClientEvent *event, CameraOrientation *cam);
        void handleClientEvent_PlayerDamage(ClientEvent *event, CameraOrientation *cam);
@@ -873,6 +879,7 @@ class Game {
        std::string *error_message;
        bool *reconnect_requested;
        scene::ISceneNode *skybox;
+       PausedNodesList paused_animated_nodes;
 
        bool simple_singleplayer_mode;
        /* End 'cache' */
@@ -2484,6 +2491,9 @@ inline void Game::step(f32 *dtime)
        if (can_be_and_is_paused) { // This is for a singleplayer server
                *dtime = 0;             // No time passes
        } else {
+               if (simple_singleplayer_mode && !paused_animated_nodes.empty())
+                       resumeAnimation();
+
                if (server)
                        server->step(*dtime);
 
@@ -2491,6 +2501,33 @@ inline void Game::step(f32 *dtime)
        }
 }
 
+static void pauseNodeAnimation(PausedNodesList &paused, scene::ISceneNode *node) {
+       if (!node)
+               return;
+       for (auto &&child: node->getChildren())
+               pauseNodeAnimation(paused, child);
+       if (node->getType() != scene::ESNT_ANIMATED_MESH)
+               return;
+       auto animated_node = static_cast<scene::IAnimatedMeshSceneNode *>(node);
+       float speed = animated_node->getAnimationSpeed();
+       if (!speed)
+               return;
+       paused.push_back({grab(animated_node), speed});
+       animated_node->setAnimationSpeed(0.0f);
+}
+
+void Game::pauseAnimation()
+{
+       pauseNodeAnimation(paused_animated_nodes, smgr->getRootSceneNode());
+}
+
+void Game::resumeAnimation()
+{
+       for (auto &&pair: paused_animated_nodes)
+               pair.first->setAnimationSpeed(pair.second);
+       paused_animated_nodes.clear();
+}
+
 const ClientEventHandler Game::clientEventHandler[CLIENTEVENT_MAX] = {
        {&Game::handleClientEvent_None},
        {&Game::handleClientEvent_PlayerDamage},
@@ -4230,6 +4267,9 @@ void Game::showPauseMenu()
                        fs_src, txt_dst, client->getFormspecPrepend(), sound);
        formspec->setFocus("btn_continue");
        formspec->doPause = true;
+
+       if (simple_singleplayer_mode)
+               pauseAnimation();
 }
 
 /****************************************************************************/