From aced31cbfa1766d20e91456e67b309754e1f6206 Mon Sep 17 00:00:00 2001 From: auria Date: Sat, 16 Jun 2012 23:35:51 +0000 Subject: [PATCH] Add support for playing sounds at given points during the cutscene git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@11310 178a84e3-b1eb-0310-8ba1-8eac791a3b58 --- src/modes/cutscene_world.cpp | 50 +++++++++++++++++++++++++++-- src/modes/cutscene_world.hpp | 4 +++ src/tracks/track_object.cpp | 12 ++++++- src/tracks/track_object.hpp | 10 +++++- src/tracks/track_object_manager.hpp | 1 + src/utils/string_utils.cpp | 8 +++++ src/utils/string_utils.hpp | 1 + 7 files changed, 81 insertions(+), 5 deletions(-) diff --git a/src/modes/cutscene_world.cpp b/src/modes/cutscene_world.cpp index 809772d43..359cd1d21 100644 --- a/src/modes/cutscene_world.cpp +++ b/src/modes/cutscene_world.cpp @@ -59,6 +59,32 @@ void CutsceneWorld::init() core::vector3df(0.0f, 0.0f, 0.0f)); m_camera->setFOV(0.61f); m_camera->bindTargetAndRotation(true); // no "look-at" + + // --- Build list of sounds to play at certain frames + PtrVector& objects = m_track->getTrackObjectManager()->getObjects(); + TrackObject* curr; + for_in(curr, objects) + { + if (curr->getType() == "sfx-emitter" && !curr->getTriggerCondition().empty()) + { + const std::string& condition = curr->getTriggerCondition(); + + if (StringUtils::startsWith(condition, "frame ")) + { + std::string frameStr = condition.substr(6); // remove 'frame ' prefix + int frame; + + if (!StringUtils::fromString(frameStr, frame)) + { + fprintf(stderr, "[CutsceneWorld] Invalid condition '%s'\n", condition.c_str()); + continue; + } + + float FPS = 25.0f; // for now we assume the cutscene is saved at 25 FPS + m_sounds_to_trigger[frame / FPS].push_back(curr); + } + } + } } // CutsceneWorld //----------------------------------------------------------------------------- @@ -91,11 +117,12 @@ const std::string& CutsceneWorld::getIdent() const */ void CutsceneWorld::update(float dt) { + m_time += dt; World::update(dt); World::updateTrack(dt); - const PtrVector& objects = m_track->getTrackObjectManager()->getObjects(); - const TrackObject* curr; + PtrVector& objects = m_track->getTrackObjectManager()->getObjects(); + TrackObject* curr; for_in(curr, objects) { if (curr->getType() == "cutscene_camera") @@ -106,10 +133,27 @@ void CutsceneWorld::update(float dt) Vec3 rot2(rot); rot2.setPitch(rot2.getPitch() + 90.0f); m_camera->setRotation(rot2.toIrrVector()); - break; //printf("Camera %f %f %f\n", curr->getNode()->getPosition().X, curr->getNode()->getPosition().Y, curr->getNode()->getPosition().Z); } } + + for (std::map>::iterator it = m_sounds_to_trigger.begin(); + it != m_sounds_to_trigger.end(); ) + { + if (m_time >= it->first) + { + std::vector objects = it->second; + for (unsigned int i = 0; i < objects.size(); i++) + { + objects[i]->triggerSound(); + } + m_sounds_to_trigger.erase(it++); + } + else + { + it++; + } + } } // update //----------------------------------------------------------------------------- diff --git a/src/modes/cutscene_world.hpp b/src/modes/cutscene_world.hpp index 6a4702613..64e326cee 100644 --- a/src/modes/cutscene_world.hpp +++ b/src/modes/cutscene_world.hpp @@ -28,6 +28,8 @@ #include +class TrackObject; + /** * \brief An implementation of World, to provide animated 3D cutscenes * \ingroup modes @@ -37,6 +39,8 @@ class CutsceneWorld : public World scene::ICameraSceneNode* m_camera; + std::map> m_sounds_to_trigger; + public: CutsceneWorld(); diff --git a/src/tracks/track_object.cpp b/src/tracks/track_object.cpp index e9d420453..db324cf1a 100644 --- a/src/tracks/track_object.cpp +++ b/src/tracks/track_object.cpp @@ -83,6 +83,8 @@ TrackObject::TrackObject(const XMLNode &xml_node) xml_node.get("distance", &trigger_distance); + xml_node.get("conditions", &m_trigger_condition); + // first try track dir, then global dir std::string soundfile = file_manager->getModelFile(sound); if (!file_manager->fileExists(soundfile)) @@ -100,7 +102,7 @@ TrackObject::TrackObject(const XMLNode &xml_node) if (m_sound != NULL) { m_sound->position(m_init_xyz); - if (!trigger_when_near) + if (!trigger_when_near && m_trigger_condition.empty()) { m_sound->setLoop(true); m_sound->play(); @@ -335,3 +337,11 @@ void TrackObject::onTriggerItemApproached(Item* who) } } } + +// ---------------------------------------------------------------------------- + +/** if this is a sound object, play the object */ +void TrackObject::triggerSound() +{ + if (m_sound != NULL) m_sound->play(); +} \ No newline at end of file diff --git a/src/tracks/track_object.hpp b/src/tracks/track_object.hpp index 1e04127c4..24e99d49a 100644 --- a/src/tracks/track_object.hpp +++ b/src/tracks/track_object.hpp @@ -63,6 +63,9 @@ private: /** End frame of the animation to be played. */ unsigned int m_frame_end; + /** Currently used for sound effects only, in cutscenes only atm */ + std::string m_trigger_condition; + virtual void OnAnimationEnd(scene::IAnimatedMeshSceneNode* node); protected: @@ -82,7 +85,7 @@ protected: /** The initial scale of the object. */ core::vector3df m_init_scale; - /** If a sound is attached to this objectt and/or this is a sound emitter object */ + /** If a sound is attached to this object and/or this is a sound emitter object */ SFXBase* m_sound; /** LOD group this object is part of, if it is LOD */ @@ -128,6 +131,11 @@ public: const std::string& getType() const { return m_type; } + /** Currently used for sound effects only, in cutscenes only atm */ + const std::string& getTriggerCondition() const { return m_trigger_condition; } + + void triggerSound(); + virtual void onTriggerItemApproached(Item* who); }; // TrackObject diff --git a/src/tracks/track_object_manager.hpp b/src/tracks/track_object_manager.hpp index e902ea4af..f7a3386d4 100644 --- a/src/tracks/track_object_manager.hpp +++ b/src/tracks/track_object_manager.hpp @@ -79,6 +79,7 @@ public: void assingLodNodes(const std::vector& lod); + PtrVector& getObjects() { return m_all_objects; } const PtrVector& getObjects() const { return m_all_objects; } }; // class TrackObjectManager diff --git a/src/utils/string_utils.cpp b/src/utils/string_utils.cpp index 8ee847c48..826158978 100644 --- a/src/utils/string_utils.cpp +++ b/src/utils/string_utils.cpp @@ -42,6 +42,14 @@ namespace StringUtils rhs.c_str() )==0; } // hasSuffix + bool startsWith(const std::string& str, const std::string& prefix) + { + if (str.length() < prefix.length()) + return false; + else + return strncmp(str.c_str(), prefix.c_str(), prefix.size())==0; + } + //------------------------------------------------------------------------- /** Returns the path of a filename, i.e. everything till the last '/'. */ diff --git a/src/utils/string_utils.hpp b/src/utils/string_utils.hpp index 4e16d450f..2bcacf8f8 100644 --- a/src/utils/string_utils.hpp +++ b/src/utils/string_utils.hpp @@ -29,6 +29,7 @@ namespace StringUtils { bool hasSuffix(const std::string& lhs, const std::string rhs); + bool startsWith(const std::string& str, const std::string& prefix); /** Return the filename part of a path */ std::string getBasename(const std::string& filename);