diff --git a/code/Spray/EffectComponent.cpp b/code/Spray/EffectComponent.cpp index c32d10de22..6760b4f5c2 100644 --- a/code/Spray/EffectComponent.cpp +++ b/code/Spray/EffectComponent.cpp @@ -32,11 +32,14 @@ T_IMPLEMENT_RTTI_CLASS(L"traktor.spray.EffectComponent", EffectComponent, world: EffectComponent::EffectComponent(const resource::Proxy< Effect >& effect) : m_transform(Transform::identity()) , m_effect(effect) -, m_counter(0) -, m_enable(true) { + m_effectInstance = m_effect->createInstance(); + T_FATAL_ASSERT(m_effectInstance != nullptr); + m_context.deltaTime = 0.0f; m_context.random = RandomGeometry(g_randomSeed.next()); + + updateTechniques(); } EffectComponent::EffectComponent(const resource::Proxy< Effect >& effect, EffectInstance* effectInstance, const Context& context) @@ -44,8 +47,6 @@ EffectComponent::EffectComponent(const resource::Proxy< Effect >& effect, Effect , m_effect(effect) , m_effectInstance(effectInstance) , m_context(context) -, m_counter(0) -, m_enable(true) { // Do not recreate instance if we've been provided one. if (effectInstance != nullptr) @@ -96,11 +97,17 @@ void EffectComponent::update(const world::UpdateParams& update) if ((m_counter++ % c_updateDenom) != 0) return; - if (m_effect.changed() || !m_effectInstance) + if (m_effect.changed() && m_effectInstance != nullptr) { + const bool loopEnable = m_effectInstance->getLoopEnable(); + m_effectInstance = m_effect->createInstance(); if (m_effectInstance) + { + m_effectInstance->setLoopEnable(loopEnable); updateTechniques(); + } + m_effect.consume(); } @@ -142,7 +149,12 @@ Aabb3 EffectComponent::getWorldBoundingBox() const void EffectComponent::reset() { - m_effectInstance = m_effect->createInstance(); + if (m_effectInstance != nullptr) + { + const bool loopEnable = m_effectInstance->getLoopEnable(); + m_effectInstance = m_effect->createInstance(); + m_effectInstance->setLoopEnable(loopEnable); + } } void EffectComponent::setLoopEnable(bool loopEnable) @@ -158,10 +170,10 @@ bool EffectComponent::getLoopEnable() const bool EffectComponent::isFinished() const { - if (!m_effect) + if (!m_effect || !m_effectInstance) return true; - if (!m_effectInstance || m_effectInstance->getLoopEnable()) + if (m_effectInstance->getLoopEnable()) return false; return m_effectInstance->getTime() >= m_effect->getDuration(); diff --git a/code/Spray/EffectComponent.h b/code/Spray/EffectComponent.h index 9455dd9263..32c90764bd 100644 --- a/code/Spray/EffectComponent.h +++ b/code/Spray/EffectComponent.h @@ -90,8 +90,8 @@ class T_DLLCLASS EffectComponent : public world::IEntityComponent Ref< EffectInstance > m_effectInstance; SmallSet< render::handle_t > m_techniques; Context m_context; - uint32_t m_counter; - bool m_enable; + uint32_t m_counter = 0; + bool m_enable = true; void updateTechniques(); }; diff --git a/code/Spray/Types.h b/code/Spray/Types.h index e2bd4ae382..7dc6adc68a 100644 --- a/code/Spray/Types.h +++ b/code/Spray/Types.h @@ -53,7 +53,6 @@ struct Context float deltaTime = 0.0f; RandomGeometry random; world::Entity* owner = nullptr; - //world::EntityEventManager* eventManager = nullptr; VirtualSourceCallback* virtualSourceCallback = nullptr; }; diff --git a/code/World/World.cpp b/code/World/World.cpp index a3c85c8886..a8047a5559 100644 --- a/code/World/World.cpp +++ b/code/World/World.cpp @@ -23,6 +23,9 @@ World::World() void World::destroy() { + T_FATAL_ASSERT(m_deferredAdd.empty()); + T_FATAL_ASSERT(m_deferredRemove.empty()); + for (auto component : m_components) component->destroy(); m_components.clear(); @@ -66,15 +69,23 @@ IWorldComponent* World::getComponent(const TypeInfo& componentType) const void World::addEntity(Entity* entity) { T_FATAL_ASSERT(entity->m_world == nullptr); - m_entities.push_back(entity); + if (m_update) + m_deferredAdd.push_back(entity); + else + m_entities.push_back(entity); entity->m_world = this; } void World::removeEntity(Entity* entity) { T_FATAL_ASSERT(entity->m_world == this); - const bool removed = m_entities.remove(entity); - T_FATAL_ASSERT(removed); + if (m_update) + m_deferredRemove.push_back(entity); + else + { + const bool removed = m_entities.remove(entity); + T_FATAL_ASSERT(removed); + } entity->m_world = nullptr; } @@ -127,9 +138,29 @@ void World::update(const UpdateParams& update) for (auto component : m_components) component->update(this, update); - RefArray< Entity > entities = m_entities; - for (auto entity : entities) - entity->update(update); + m_update = true; + for (auto entity : m_entities) + { + if (entity->m_world != nullptr) + entity->update(update); + } + m_update = false; + + if (!m_deferredAdd.empty()) + { + m_entities.insert(m_entities.end(), m_deferredAdd.begin(), m_deferredAdd.end()); + m_deferredAdd.resize(0); + } + + if (!m_deferredRemove.empty()) + { + for (auto entity : m_deferredRemove) + { + const bool removed = m_entities.remove(entity); + T_FATAL_ASSERT(removed); + } + m_deferredRemove.resize(0); + } } } diff --git a/code/World/World.h b/code/World/World.h index 10dbd886ff..a51d0c6c5b 100644 --- a/code/World/World.h +++ b/code/World/World.h @@ -102,6 +102,9 @@ class T_DLLCLASS World : public Object private: RefArray< IWorldComponent > m_components; RefArray< Entity > m_entities; + RefArray< Entity > m_deferredAdd; + RefArray< Entity > m_deferredRemove; + bool m_update = false; }; }