diff --git a/data/gfx/smoke_short_burst.xml b/data/gfx/smoke_short_burst.xml new file mode 100644 index 000000000..1d9aa96cc --- /dev/null +++ b/data/gfx/smoke_short_burst.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/animations/animation_base.cpp b/src/animations/animation_base.cpp index 8a808d259..3a8037007 100644 --- a/src/animations/animation_base.cpp +++ b/src/animations/animation_base.cpp @@ -93,6 +93,8 @@ void AnimationBase::reset() */ void AnimationBase::update(float dt, Vec3 *xyz, Vec3 *hpr, Vec3 *scale) { + TrackObject::update(dt); + // Don't do anything if the animation is disabled if(!m_playing) return; m_current_time += dt; diff --git a/src/modes/cutscene_world.cpp b/src/modes/cutscene_world.cpp index bee2a8b42..bd12ef54c 100644 --- a/src/modes/cutscene_world.cpp +++ b/src/modes/cutscene_world.cpp @@ -76,7 +76,26 @@ void CutsceneWorld::init() TrackObject* curr; for_in(curr, objects) { - if (curr->getType() == "sfx-emitter" && !curr->getTriggerCondition().empty()) + if (curr->getType() == "particle-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_particles_to_trigger[frame / FPS].push_back(curr); + } + } + else if (curr->getType() == "sfx-emitter" && !curr->getTriggerCondition().empty()) { const std::string& condition = curr->getTriggerCondition(); @@ -153,6 +172,17 @@ const std::string& CutsceneWorld::getIdent() const */ void CutsceneWorld::update(float dt) { + /* + { + PtrVector& objects = m_track->getTrackObjectManager()->getObjects(); + TrackObject* curr; + for_in(curr, objects) + { + printf("* %s\n", curr->getType().c_str()); + } + } + **/ + m_time += dt; if (m_time < 2.0f) @@ -168,7 +198,6 @@ void CutsceneWorld::update(float dt) dynamic_cast(m_race_gui)->setFadeLevel(0.0f); } - float currFrame = m_time * 25.0f; // We assume 25 FPS const std::vector& subtitles = m_track->getSubtitles(); @@ -232,9 +261,27 @@ void CutsceneWorld::update(float dt) } } + for (std::map >::iterator it = m_particles_to_trigger.begin(); + it != m_particles_to_trigger.end(); ) + { + if (m_time >= it->first) + { + std::vector objects = it->second; + for (unsigned int i = 0; i < objects.size(); i++) + { + objects[i]->triggerParticles(); + } + m_particles_to_trigger.erase(it++); + } + else + { + it++; + } + } + for (std::map >::iterator it = m_sounds_to_stop.begin(); it != m_sounds_to_stop.end(); ) - { + { if (m_time >= it->first) { std::vector objects = it->second; @@ -248,7 +295,7 @@ void CutsceneWorld::update(float dt) { it++; } - } + } } // update //----------------------------------------------------------------------------- diff --git a/src/modes/cutscene_world.hpp b/src/modes/cutscene_world.hpp index 3aa3923a7..d67ab0bde 100644 --- a/src/modes/cutscene_world.hpp +++ b/src/modes/cutscene_world.hpp @@ -40,6 +40,7 @@ class CutsceneWorld : public World std::map > m_sounds_to_trigger; std::map > m_sounds_to_stop; + std::map > m_particles_to_trigger; float m_duration; bool m_aborted; diff --git a/src/tracks/track_object.cpp b/src/tracks/track_object.cpp index b0c62a417..6530234fc 100644 --- a/src/tracks/track_object.cpp +++ b/src/tracks/track_object.cpp @@ -81,6 +81,7 @@ TrackObject::TrackObject(const XMLNode &xml_node) if (xml_node.getName() == "particle-emitter") { + m_type = "particle-emitter"; std::string path; irr::core::vector3df emitter_origin; xml_node.get("kind", &path); @@ -89,6 +90,8 @@ TrackObject::TrackObject(const XMLNode &xml_node) int clip_distance = -1; xml_node.get("clip_distance", &clip_distance); + xml_node.get("conditions", &m_trigger_condition); + try { ParticleKind* kind = ParticleKindManager::get()->getParticles( path.c_str() ); @@ -114,6 +117,11 @@ TrackObject::TrackObject(const XMLNode &xml_node) m_node = emitter->getNode(); // FIXME: this leaks m_emitter = emitter; } + + if (m_trigger_condition.size() > 0) + { + m_emitter->setCreationRateAbsolute(0.0f); + } } catch (std::runtime_error& e) { @@ -423,7 +431,6 @@ void TrackObject::OnAnimationEnd(scene::IAnimatedMeshSceneNode* node) // ---------------------------------------------------------------------------- void TrackObject::update(float dt) { - if (m_sound != NULL) { // muting when too far is implemented manually since not supported by OpenAL @@ -431,6 +438,11 @@ void TrackObject::update(float dt) // moved m_sound->position(m_init_xyz); } + + if (m_emitter != NULL) + { + m_emitter->update(dt); + } } // update // ---------------------------------------------------------------------------- @@ -477,3 +489,14 @@ void TrackObject::stopSound() // ---------------------------------------------------------------------------- +void TrackObject::triggerParticles() +{ + if (m_emitter != NULL) + { + m_emitter->setCreationRateAbsolute(1.0f); + m_emitter->setParticleType(m_emitter->getParticlesInfo()); + } +} + +// ---------------------------------------------------------------------------- + diff --git a/src/tracks/track_object.hpp b/src/tracks/track_object.hpp index 5fa94ad8b..49743518a 100644 --- a/src/tracks/track_object.hpp +++ b/src/tracks/track_object.hpp @@ -156,6 +156,7 @@ public: void triggerSound(bool loop=false); void stopSound(); + void triggerParticles(); virtual void onTriggerItemApproached(Item* who);