Pause animations while game is paused (#10658)

Pauses all mesh animations while game is paused.
master
Vitaliy 2021-03-05 18:28:08 +03:00 committed by luk3yx
parent db15e61216
commit 40bdb9c609
1 changed files with 39 additions and 0 deletions

View 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"
@ -651,6 +652,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
@ -806,6 +809,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);
@ -884,6 +890,7 @@ private:
std::string wield_name;
bool *reconnect_requested;
scene::ISceneNode *skybox;
PausedNodesList paused_animated_nodes;
bool simple_singleplayer_mode;
/* End 'cache' */
@ -2574,6 +2581,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);
@ -2581,6 +2591,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},
@ -4387,6 +4424,8 @@ void Game::showPauseMenu()
formspec->doPause = true;
runData.pause_game_timer = 0;
if (simple_singleplayer_mode)
pauseAnimation();
}
/****************************************************************************/