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