mirror of
https://github.com/rwengine/openrw.git
synced 2024-11-22 02:12:45 +01:00
Clean animation and audio after cutscene
This commit is contained in:
parent
df0bda35e1
commit
056864e1d7
@ -212,7 +212,16 @@ void SoundManager::playSound(const std::string& name) {
|
||||
if (sound != sounds.end()) {
|
||||
auto vol = getCalculatedVolumeOfMusic();
|
||||
sound->second.setGain(vol);
|
||||
return sound->second.play();
|
||||
sound->second.play();
|
||||
}
|
||||
}
|
||||
|
||||
void SoundManager::eraseSound(const std::string& name) {
|
||||
auto sound = sounds.find(name);
|
||||
if (sound != sounds.end()) {
|
||||
sounds.erase(sound);
|
||||
} else {
|
||||
RW_MESSAGE("Tried to erase no existing sound " << name);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -59,6 +59,9 @@ public:
|
||||
/// Play sound with selected name
|
||||
void playSound(const std::string& name);
|
||||
|
||||
/// Erase sound with selected name
|
||||
void eraseSound(const std::string& name);
|
||||
|
||||
/// Effect same as playSound with one parametr,
|
||||
/// but this function works for sfx and
|
||||
/// allows also for setting position,
|
||||
|
@ -522,16 +522,20 @@ bool GameData::loadModel(ModelID model) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void GameData::loadIFP(const std::string& name) {
|
||||
void GameData::loadIFP(const std::string& name, bool cutsceneAnimation) {
|
||||
auto f = index.openFile(name);
|
||||
|
||||
if (f.data) {
|
||||
LoaderIFP loader;
|
||||
if (loader.loadFromMemory(f.data.get())) {
|
||||
if (LoaderIFP loader{}; loader.loadFromMemory(f.data.get())) {
|
||||
if (cutsceneAnimation) {
|
||||
animationsCutscene.insert(loader.animations.begin(),
|
||||
loader.animations.end());
|
||||
} else {
|
||||
animations.insert(loader.animations.begin(),
|
||||
loader.animations.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GameData::loadDynamicObjects(const std::string& name) {
|
||||
|
@ -160,7 +160,7 @@ public:
|
||||
/**
|
||||
* Loads an IFP file containing animations
|
||||
*/
|
||||
void loadIFP(const std::string& name);
|
||||
void loadIFP(const std::string& name, bool cutsceneAnimation = false);
|
||||
|
||||
/**
|
||||
* Loads data from an object definition dat.
|
||||
@ -289,10 +289,15 @@ public:
|
||||
std::vector<TextureAtlas*> atlases;
|
||||
|
||||
/**
|
||||
* Loaded Animations
|
||||
* Loaded Animations (doesn't contain animations of cutscene)
|
||||
*/
|
||||
AnimationSet animations;
|
||||
|
||||
/**
|
||||
* Loaded Animations (only) for cutscene
|
||||
*/
|
||||
AnimationSet animationsCutscene;
|
||||
|
||||
/**
|
||||
* Pedestrian Animation Groups
|
||||
*/
|
||||
|
@ -3,25 +3,26 @@
|
||||
#include <bitset>
|
||||
#include <cstdint>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
|
||||
#include <data/VehicleGenerator.hpp>
|
||||
#include <engine/GameData.hpp>
|
||||
#include <engine/GameInputState.hpp>
|
||||
#include <engine/GameWorld.hpp>
|
||||
#include <engine/ScreenText.hpp>
|
||||
#include <fonts/GameTexts.hpp>
|
||||
#include <objects/ObjectTypes.hpp>
|
||||
#include <script/ScriptTypes.hpp>
|
||||
#include "data/CutsceneData.hpp"
|
||||
#include "data/VehicleGenerator.hpp"
|
||||
#include "engine/GameData.hpp"
|
||||
#include "engine/GameInputState.hpp"
|
||||
#include "engine/GameWorld.hpp"
|
||||
#include "engine/ScreenText.hpp"
|
||||
#include "objects/ObjectTypes.hpp"
|
||||
#include "script/ScriptTypes.hpp"
|
||||
|
||||
class GameWorld;
|
||||
class GameObject;
|
||||
class ScriptMachine;
|
||||
struct CutsceneData;
|
||||
|
||||
struct SystemTime {
|
||||
uint16_t year;
|
||||
@ -316,7 +317,9 @@ public:
|
||||
|
||||
bool skipCutscene = false;
|
||||
bool isIntroPlaying = false;
|
||||
CutsceneData* currentCutscene = nullptr;
|
||||
|
||||
std::optional<CutsceneData> currentCutscene;
|
||||
|
||||
float cutsceneStartTime{-1.f};
|
||||
/** Flag for rendering cutscene letterbox */
|
||||
bool isCinematic = false;
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "data/WeaponData.hpp"
|
||||
|
||||
#include "loaders/LoaderCutsceneDAT.hpp"
|
||||
#include "loaders/LoaderIFP.hpp"
|
||||
#include "loaders/LoaderIPL.hpp"
|
||||
|
||||
#include "objects/CharacterObject.hpp"
|
||||
@ -750,15 +751,14 @@ void GameWorld::PhysicsTickCallback(btDynamicsWorld* physWorld,
|
||||
void GameWorld::loadCutscene(const std::string& name) {
|
||||
auto datfile = data->index.openFile(name + ".dat");
|
||||
|
||||
CutsceneData* cutscene = new CutsceneData;
|
||||
state->currentCutscene = CutsceneData();
|
||||
|
||||
if (datfile.data) {
|
||||
LoaderCutsceneDAT loaderdat;
|
||||
loaderdat.load(cutscene->tracks, datfile);
|
||||
loaderdat.load(state->currentCutscene->tracks, datfile);
|
||||
}
|
||||
|
||||
data->loadIFP(name + ".ifp");
|
||||
|
||||
data->loadIFP(name + ".ifp", true);
|
||||
cutsceneAudioLoaded = data->loadAudioStream(name + ".mp3");
|
||||
|
||||
if (!cutsceneAudioLoaded) {
|
||||
@ -769,10 +769,6 @@ void GameWorld::loadCutscene(const std::string& name) {
|
||||
logger->warning("Data", "Failed to load cutscene audio: " + name);
|
||||
}
|
||||
|
||||
if (state->currentCutscene) {
|
||||
delete state->currentCutscene;
|
||||
}
|
||||
state->currentCutscene = cutscene;
|
||||
state->currentCutscene->meta.name = name;
|
||||
logger->info("World", "Loaded cutscene: " + name);
|
||||
}
|
||||
@ -788,20 +784,32 @@ void GameWorld::startCutscene() {
|
||||
}
|
||||
|
||||
void GameWorld::clearCutscene() {
|
||||
eraseCutsceneObjects();
|
||||
eraseCutsceneSound();
|
||||
eraseCutsceneAnimations();
|
||||
|
||||
state->currentCutscene = std::nullopt;
|
||||
state->isCinematic = false;
|
||||
state->cutsceneStartTime = -1.f;
|
||||
}
|
||||
|
||||
void GameWorld::eraseCutsceneObjects() {
|
||||
for (auto& p : cutscenePool.objects) {
|
||||
destroyObjectQueued(p.second.get());
|
||||
}
|
||||
}
|
||||
|
||||
void GameWorld::eraseCutsceneSound() {
|
||||
if (cutsceneAudio.length() > 0) {
|
||||
sound.stopMusic(cutsceneAudio);
|
||||
sound.eraseSound(cutsceneAudio);
|
||||
cutsceneAudio = "";
|
||||
sound.resumeAllSounds();
|
||||
}
|
||||
}
|
||||
|
||||
delete state->currentCutscene;
|
||||
state->currentCutscene = nullptr;
|
||||
state->isCinematic = false;
|
||||
state->cutsceneStartTime = -1.f;
|
||||
void GameWorld::eraseCutsceneAnimations() {
|
||||
data->animationsCutscene.clear();
|
||||
}
|
||||
|
||||
bool GameWorld::isCutsceneDone() {
|
||||
|
@ -358,6 +358,10 @@ public:
|
||||
void clearCutscene();
|
||||
bool isCutsceneDone();
|
||||
|
||||
void eraseCutsceneObjects();
|
||||
void eraseCutsceneSound();
|
||||
void eraseCutsceneAnimations();
|
||||
|
||||
std::string cutsceneAudio;
|
||||
bool cutsceneAudioLoaded;
|
||||
std::string missionAudio;
|
||||
|
@ -7883,19 +7883,21 @@ void opcode_02e5(const ScriptArguments& args, const ScriptModelID model, ScriptO
|
||||
@arg object Player
|
||||
@arg arg2
|
||||
*/
|
||||
void opcode_02e6(const ScriptArguments& args, const ScriptObject object, const ScriptString arg2) {
|
||||
void opcode_02e6(const ScriptArguments& args, const ScriptObject object,
|
||||
const ScriptString arg2) {
|
||||
RW_UNUSED(object);
|
||||
RW_UNUSED(arg2);
|
||||
/// @todo make animation data-driven rather than oop
|
||||
auto cutscene = args.getObject<CutsceneObject>(0);
|
||||
std::string animName = arg2;
|
||||
std::transform(animName.begin(), animName.end(), animName.begin(), ::tolower);
|
||||
auto anim = args.getWorld()->data->animations[animName];
|
||||
if( anim ) {
|
||||
std::transform(animName.begin(), animName.end(), animName.begin(),
|
||||
::tolower);
|
||||
auto anim = args.getWorld()->data->animationsCutscene.at(animName);
|
||||
if (anim) {
|
||||
cutscene->animator->playAnimation(AnimIndexMovement, anim, 1.f, false);
|
||||
}
|
||||
else {
|
||||
args.getWorld()->logger->error("SCM", "Failed to load cutscene anim: " + animName);
|
||||
} else {
|
||||
args.getWorld()->logger->error(
|
||||
"SCM", "Failed to load cutscene anim: " + animName);
|
||||
}
|
||||
}
|
||||
|
||||
@ -7915,7 +7917,7 @@ void opcode_02e7(const ScriptArguments& args) {
|
||||
@arg arg1
|
||||
*/
|
||||
void opcode_02e8(const ScriptArguments& args, ScriptInt& arg1) {
|
||||
auto cutscene = args.getState()->currentCutscene;
|
||||
auto& cutscene = args.getState()->currentCutscene;
|
||||
if (args.getState()->skipCutscene) {
|
||||
arg1 = cutscene ? cutscene->tracks.duration * 1000 : 0.f;
|
||||
}
|
||||
|
@ -380,7 +380,7 @@ const ViewCamera& IngameState::getCamera(float alpha) {
|
||||
auto world = getWorld();
|
||||
|
||||
if (state->currentCutscene && state->cutsceneStartTime >= 0.f) {
|
||||
auto cutscene = state->currentCutscene;
|
||||
auto& cutscene = state->currentCutscene;
|
||||
float cutsceneTime =
|
||||
std::min(world->getGameTime() - state->cutsceneStartTime,
|
||||
cutscene->tracks.duration);
|
||||
|
Loading…
Reference in New Issue
Block a user