Sdk/EntityList: Automatically remove entities from lists on destruction
This commit is contained in:
parent
3d25501f9f
commit
bb3eebb9cc
|
|
@ -17,14 +17,17 @@
|
|||
namespace Ndk
|
||||
{
|
||||
class BaseComponent;
|
||||
class BaseSystem;
|
||||
class Entity;
|
||||
class EntityList;
|
||||
class World;
|
||||
|
||||
using EntityHandle = Nz::ObjectHandle<Entity>;
|
||||
|
||||
class NDK_API Entity : public Nz::HandledObject<Entity>
|
||||
{
|
||||
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<std::unique_ptr<BaseComponent>> m_components;
|
||||
std::vector<EntityList*> m_containedInLists;
|
||||
Nz::Bitset<> m_componentBits;
|
||||
Nz::Bitset<> m_removedComponentBits;
|
||||
Nz::Bitset<> m_systemBits;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include <Nazara/Core/Error.hpp>
|
||||
#include <Nazara/Core/StringStream.hpp>
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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<Nz::UInt64> m_entityBits;
|
||||
World* m_world;
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@
|
|||
#include <NDK/EntityList.hpp>
|
||||
#include <Nazara/Core/Error.hpp>
|
||||
#include <algorithm>
|
||||
#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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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>())
|
||||
{
|
||||
GraphicsComponent& gfxComponent = entity->GetComponent<GraphicsComponent>();
|
||||
|
|
|
|||
Loading…
Reference in New Issue