summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVitaliy <numzer0@yandex.ru>2021-03-05 18:28:08 +0300
committerSmallJoker <mk939@ymail.com>2021-03-05 16:30:01 +0100
commitabb0c99a6c5ab38637d1370449ec072c7caa8803 (patch)
tree1b4b757dd3fe1b8a5881e787fa730ee56a154499
parentcafad6ac03348aa77e8ee4bb035840e73de4b2a9 (diff)
downloadminetest-abb0c99a6c5ab38637d1370449ec072c7caa8803.tar.gz
minetest-abb0c99a6c5ab38637d1370449ec072c7caa8803.tar.bz2
minetest-abb0c99a6c5ab38637d1370449ec072c7caa8803.zip
Pause animations while game is paused (#10658)
Pauses all mesh animations while game is paused.
-rw-r--r--src/client/game.cpp40
1 files changed, 40 insertions, 0 deletions
diff --git a/src/client/game.cpp b/src/client/game.cpp
index 15fa2af23..60ecb7d3e 100644
--- a/src/client/game.cpp
+++ b/src/client/game.cpp
@@ -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 @@ private:
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 @@ private:
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();
}
/****************************************************************************/