From bb3eebb9ccf21adc9e29ce4f9eb0f99952791888 Mon Sep 17 00:00:00 2001 From: Lynix Date: Sun, 14 May 2017 22:13:31 +0200 Subject: [PATCH] Sdk/EntityList: Automatically remove entities from lists on destruction --- SDK/include/NDK/Entity.hpp | 8 +++- SDK/include/NDK/Entity.inl | 20 +++++++--- SDK/include/NDK/EntityList.hpp | 5 ++- SDK/include/NDK/EntityList.inl | 55 ++++++++++++++++++++++++---- SDK/src/NDK/Entity.cpp | 9 ++++- SDK/src/NDK/Systems/RenderSystem.cpp | 6 --- 6 files changed, 81 insertions(+), 22 deletions(-) diff --git a/SDK/include/NDK/Entity.hpp b/SDK/include/NDK/Entity.hpp index e386100f8..5419da0d2 100644 --- a/SDK/include/NDK/Entity.hpp +++ b/SDK/include/NDK/Entity.hpp @@ -17,14 +17,17 @@ namespace Ndk { class BaseComponent; + class BaseSystem; class Entity; + class EntityList; class World; using EntityHandle = Nz::ObjectHandle; class NDK_API Entity : public Nz::HandledObject { - friend class BaseSystem; + friend BaseSystem; + friend EntityList; friend World; public: @@ -78,13 +81,16 @@ namespace Ndk inline Nz::Bitset<>& GetRemovedComponentBits(); + inline void RegisterEntityList(EntityList* list); inline void RegisterSystem(SystemIndex index); inline void SetWorld(World* world) noexcept; + inline void UnregisterEntityList(EntityList* list); inline void UnregisterSystem(SystemIndex index); std::vector> m_components; + std::vector m_containedInLists; Nz::Bitset<> m_componentBits; Nz::Bitset<> m_removedComponentBits; Nz::Bitset<> m_systemBits; diff --git a/SDK/include/NDK/Entity.inl b/SDK/include/NDK/Entity.inl index e6f997226..adb2153d8 100644 --- a/SDK/include/NDK/Entity.inl +++ b/SDK/include/NDK/Entity.inl @@ -6,6 +6,7 @@ #include #include #include +#include #include #include @@ -257,11 +258,10 @@ namespace Ndk return m_removedComponentBits; } - /*! - * \brief Registers a system for the entity - * - * \param index Index of the system - */ + inline void Entity::RegisterEntityList(EntityList* list) + { + m_containedInLists.push_back(list); + } inline void Entity::RegisterSystem(SystemIndex index) { @@ -289,6 +289,16 @@ namespace Ndk * \param index Index of the system */ + inline void Entity::UnregisterEntityList(EntityList* list) + { + auto it = std::find(m_containedInLists.begin(), m_containedInLists.end(), list); + assert(it != m_containedInLists.end()); + + // Swap and pop idiom + *it = m_containedInLists.back(); + m_containedInLists.pop_back(); + } + inline void Entity::UnregisterSystem(SystemIndex index) { m_systemBits.UnboundedReset(index); diff --git a/SDK/include/NDK/EntityList.hpp b/SDK/include/NDK/EntityList.hpp index 76097f87b..b659b15fb 100644 --- a/SDK/include/NDK/EntityList.hpp +++ b/SDK/include/NDK/EntityList.hpp @@ -15,6 +15,8 @@ namespace Ndk { class NDK_API EntityList { + friend Entity; + public: class iterator; friend iterator; @@ -23,7 +25,7 @@ namespace Ndk inline EntityList(); inline EntityList(const EntityList& entityList); inline EntityList(EntityList&& entityList) noexcept; - ~EntityList() = default; + inline ~EntityList(); inline void Clear(); @@ -46,6 +48,7 @@ namespace Ndk private: inline std::size_t FindNext(std::size_t currentId) const; inline World* GetWorld() const; + inline void NotifyEntityDestruction(const Entity* entity); Nz::Bitset m_entityBits; World* m_world; diff --git a/SDK/include/NDK/EntityList.inl b/SDK/include/NDK/EntityList.inl index f5a751323..d178d2b09 100644 --- a/SDK/include/NDK/EntityList.inl +++ b/SDK/include/NDK/EntityList.inl @@ -5,7 +5,6 @@ #include #include #include -#include "EntityList.hpp" namespace Ndk { @@ -30,6 +29,8 @@ namespace Ndk m_entityBits(entityList.m_entityBits), m_world(entityList.m_world) { + for (const Ndk::EntityHandle& entity : *this) + entity->RegisterEntityList(this); } /*! @@ -39,6 +40,17 @@ namespace Ndk m_entityBits(std::move(entityList.m_entityBits)), m_world(entityList.m_world) { + for (const Ndk::EntityHandle& entity : *this) + { + entity->UnregisterEntityList(&entityList); + entity->RegisterEntityList(this); + } + } + + inline EntityList::~EntityList() + { + for (const Ndk::EntityHandle& entity : *this) + entity->UnregisterEntityList(this); } @@ -49,6 +61,9 @@ namespace Ndk */ inline void EntityList::Clear() { + for (const Ndk::EntityHandle& entity : *this) + entity->UnregisterEntityList(this); + m_entityBits.Clear(); m_world = nullptr; } @@ -88,15 +103,18 @@ namespace Ndk * * \remark If entity is already contained, no action is performed * \remark If any entity has been inserted since construction (or last Clear call), the entity must belong to the same world as the previously inserted entities - * \remark It's up to the programmer to remove an entity from this list before its deletion */ inline void EntityList::Insert(Entity* entity) { NazaraAssert(entity, "Invalid entity"); - NazaraAssert(!m_world || entity->GetWorld() == m_world, "Incompatible world"); - m_entityBits.UnboundedSet(entity->GetId(), true); - m_world = entity->GetWorld(); + if (!Has(entity)) + { + entity->RegisterEntityList(this); + + m_entityBits.UnboundedSet(entity->GetId(), true); + m_world = entity->GetWorld(); + } } /*! @@ -111,7 +129,12 @@ namespace Ndk */ inline void EntityList::Remove(Entity* entity) { - m_entityBits.UnboundedSet(entity->GetId(), false); + if (Has(entity)) + { + m_entityBits.Reset(entity->GetId()); + + entity->UnregisterEntityList(this); + } } // STL Interface @@ -140,14 +163,23 @@ namespace Ndk m_entityBits = entityList.m_entityBits; m_world = entityList.m_world; + for (const Ndk::EntityHandle& entity : *this) + entity->RegisterEntityList(this); + return *this; } - inline EntityList& EntityList::operator=(EntityList && entityList) noexcept + inline EntityList& EntityList::operator=(EntityList&& entityList) noexcept { m_entityBits = std::move(entityList.m_entityBits); m_world = entityList.m_world; + for (const Ndk::EntityHandle& entity : *this) + { + entity->UnregisterEntityList(&entityList); + entity->RegisterEntityList(this); + } + return *this; } @@ -161,6 +193,13 @@ namespace Ndk return m_world; } + inline void EntityList::NotifyEntityDestruction(const Entity* entity) + { + assert(Has(entity)); + + m_entityBits.Reset(entity->GetId()); + } + inline EntityList::iterator::iterator(const EntityList* list, std::size_t nextId) : m_nextEntityId(nextId), @@ -216,6 +255,6 @@ namespace Ndk using std::swap; - std::swap(lhs.m_nextEntityId, rhs.m_nextEntityId); + swap(lhs.m_nextEntityId, rhs.m_nextEntityId); } } diff --git a/SDK/src/NDK/Entity.cpp b/SDK/src/NDK/Entity.cpp index 7419ac627..fab08b237 100644 --- a/SDK/src/NDK/Entity.cpp +++ b/SDK/src/NDK/Entity.cpp @@ -23,6 +23,7 @@ namespace Ndk Entity::Entity(Entity&& entity) : HandledObject(std::move(entity)), m_components(std::move(entity.m_components)), + m_containedInLists(std::move(entity.m_containedInLists)), m_componentBits(std::move(entity.m_componentBits)), m_removedComponentBits(std::move(entity.m_removedComponentBits)), m_systemBits(std::move(entity.m_systemBits)), @@ -176,9 +177,15 @@ namespace Ndk m_components.clear(); m_componentBits.Reset(); - // And then free every handle + // Free every handle UnregisterAllHandles(); + // Remove from every list + for (EntityList* list : m_containedInLists) + list->NotifyEntityDestruction(this); + + m_containedInLists.clear(); + m_valid = false; } diff --git a/SDK/src/NDK/Systems/RenderSystem.cpp b/SDK/src/NDK/Systems/RenderSystem.cpp index 44b0d1bba..022621596 100644 --- a/SDK/src/NDK/Systems/RenderSystem.cpp +++ b/SDK/src/NDK/Systems/RenderSystem.cpp @@ -57,12 +57,6 @@ namespace Ndk } } - m_directionalLights.Remove(entity); - m_drawables.Remove(entity); - m_lights.Remove(entity); - m_particleGroups.Remove(entity); - m_pointSpotLights.Remove(entity); - if (entity->HasComponent()) { GraphicsComponent& gfxComponent = entity->GetComponent();