Sdk/EntityList: Automatically remove entities from lists on destruction
This commit is contained in:
parent
3d25501f9f
commit
bb3eebb9cc
|
|
@ -17,14 +17,17 @@
|
||||||
namespace Ndk
|
namespace Ndk
|
||||||
{
|
{
|
||||||
class BaseComponent;
|
class BaseComponent;
|
||||||
|
class BaseSystem;
|
||||||
class Entity;
|
class Entity;
|
||||||
|
class EntityList;
|
||||||
class World;
|
class World;
|
||||||
|
|
||||||
using EntityHandle = Nz::ObjectHandle<Entity>;
|
using EntityHandle = Nz::ObjectHandle<Entity>;
|
||||||
|
|
||||||
class NDK_API Entity : public Nz::HandledObject<Entity>
|
class NDK_API Entity : public Nz::HandledObject<Entity>
|
||||||
{
|
{
|
||||||
friend class BaseSystem;
|
friend BaseSystem;
|
||||||
|
friend EntityList;
|
||||||
friend World;
|
friend World;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
@ -78,13 +81,16 @@ namespace Ndk
|
||||||
|
|
||||||
inline Nz::Bitset<>& GetRemovedComponentBits();
|
inline Nz::Bitset<>& GetRemovedComponentBits();
|
||||||
|
|
||||||
|
inline void RegisterEntityList(EntityList* list);
|
||||||
inline void RegisterSystem(SystemIndex index);
|
inline void RegisterSystem(SystemIndex index);
|
||||||
|
|
||||||
inline void SetWorld(World* world) noexcept;
|
inline void SetWorld(World* world) noexcept;
|
||||||
|
|
||||||
|
inline void UnregisterEntityList(EntityList* list);
|
||||||
inline void UnregisterSystem(SystemIndex index);
|
inline void UnregisterSystem(SystemIndex index);
|
||||||
|
|
||||||
std::vector<std::unique_ptr<BaseComponent>> m_components;
|
std::vector<std::unique_ptr<BaseComponent>> m_components;
|
||||||
|
std::vector<EntityList*> m_containedInLists;
|
||||||
Nz::Bitset<> m_componentBits;
|
Nz::Bitset<> m_componentBits;
|
||||||
Nz::Bitset<> m_removedComponentBits;
|
Nz::Bitset<> m_removedComponentBits;
|
||||||
Nz::Bitset<> m_systemBits;
|
Nz::Bitset<> m_systemBits;
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
#include <Nazara/Core/Error.hpp>
|
#include <Nazara/Core/Error.hpp>
|
||||||
#include <Nazara/Core/StringStream.hpp>
|
#include <Nazara/Core/StringStream.hpp>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <cassert>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
|
@ -257,11 +258,10 @@ namespace Ndk
|
||||||
return m_removedComponentBits;
|
return m_removedComponentBits;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
inline void Entity::RegisterEntityList(EntityList* list)
|
||||||
* \brief Registers a system for the entity
|
{
|
||||||
*
|
m_containedInLists.push_back(list);
|
||||||
* \param index Index of the system
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
inline void Entity::RegisterSystem(SystemIndex index)
|
inline void Entity::RegisterSystem(SystemIndex index)
|
||||||
{
|
{
|
||||||
|
|
@ -289,6 +289,16 @@ namespace Ndk
|
||||||
* \param index Index of the system
|
* \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)
|
inline void Entity::UnregisterSystem(SystemIndex index)
|
||||||
{
|
{
|
||||||
m_systemBits.UnboundedReset(index);
|
m_systemBits.UnboundedReset(index);
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,8 @@ namespace Ndk
|
||||||
{
|
{
|
||||||
class NDK_API EntityList
|
class NDK_API EntityList
|
||||||
{
|
{
|
||||||
|
friend Entity;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
class iterator;
|
class iterator;
|
||||||
friend iterator;
|
friend iterator;
|
||||||
|
|
@ -23,7 +25,7 @@ namespace Ndk
|
||||||
inline EntityList();
|
inline EntityList();
|
||||||
inline EntityList(const EntityList& entityList);
|
inline EntityList(const EntityList& entityList);
|
||||||
inline EntityList(EntityList&& entityList) noexcept;
|
inline EntityList(EntityList&& entityList) noexcept;
|
||||||
~EntityList() = default;
|
inline ~EntityList();
|
||||||
|
|
||||||
inline void Clear();
|
inline void Clear();
|
||||||
|
|
||||||
|
|
@ -46,6 +48,7 @@ namespace Ndk
|
||||||
private:
|
private:
|
||||||
inline std::size_t FindNext(std::size_t currentId) const;
|
inline std::size_t FindNext(std::size_t currentId) const;
|
||||||
inline World* GetWorld() const;
|
inline World* GetWorld() const;
|
||||||
|
inline void NotifyEntityDestruction(const Entity* entity);
|
||||||
|
|
||||||
Nz::Bitset<Nz::UInt64> m_entityBits;
|
Nz::Bitset<Nz::UInt64> m_entityBits;
|
||||||
World* m_world;
|
World* m_world;
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@
|
||||||
#include <NDK/EntityList.hpp>
|
#include <NDK/EntityList.hpp>
|
||||||
#include <Nazara/Core/Error.hpp>
|
#include <Nazara/Core/Error.hpp>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include "EntityList.hpp"
|
|
||||||
|
|
||||||
namespace Ndk
|
namespace Ndk
|
||||||
{
|
{
|
||||||
|
|
@ -30,6 +29,8 @@ namespace Ndk
|
||||||
m_entityBits(entityList.m_entityBits),
|
m_entityBits(entityList.m_entityBits),
|
||||||
m_world(entityList.m_world)
|
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_entityBits(std::move(entityList.m_entityBits)),
|
||||||
m_world(entityList.m_world)
|
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()
|
inline void EntityList::Clear()
|
||||||
{
|
{
|
||||||
|
for (const Ndk::EntityHandle& entity : *this)
|
||||||
|
entity->UnregisterEntityList(this);
|
||||||
|
|
||||||
m_entityBits.Clear();
|
m_entityBits.Clear();
|
||||||
m_world = nullptr;
|
m_world = nullptr;
|
||||||
}
|
}
|
||||||
|
|
@ -88,16 +103,19 @@ namespace Ndk
|
||||||
*
|
*
|
||||||
* \remark If entity is already contained, no action is performed
|
* \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 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)
|
inline void EntityList::Insert(Entity* entity)
|
||||||
{
|
{
|
||||||
NazaraAssert(entity, "Invalid entity");
|
NazaraAssert(entity, "Invalid entity");
|
||||||
NazaraAssert(!m_world || entity->GetWorld() == m_world, "Incompatible world");
|
|
||||||
|
if (!Has(entity))
|
||||||
|
{
|
||||||
|
entity->RegisterEntityList(this);
|
||||||
|
|
||||||
m_entityBits.UnboundedSet(entity->GetId(), true);
|
m_entityBits.UnboundedSet(entity->GetId(), true);
|
||||||
m_world = entity->GetWorld();
|
m_world = entity->GetWorld();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* \brief Removes the entity from the set
|
* \brief Removes the entity from the set
|
||||||
|
|
@ -111,7 +129,12 @@ namespace Ndk
|
||||||
*/
|
*/
|
||||||
inline void EntityList::Remove(Entity* entity)
|
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
|
// STL Interface
|
||||||
|
|
@ -140,14 +163,23 @@ namespace Ndk
|
||||||
m_entityBits = entityList.m_entityBits;
|
m_entityBits = entityList.m_entityBits;
|
||||||
m_world = entityList.m_world;
|
m_world = entityList.m_world;
|
||||||
|
|
||||||
|
for (const Ndk::EntityHandle& entity : *this)
|
||||||
|
entity->RegisterEntityList(this);
|
||||||
|
|
||||||
return *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_entityBits = std::move(entityList.m_entityBits);
|
||||||
m_world = entityList.m_world;
|
m_world = entityList.m_world;
|
||||||
|
|
||||||
|
for (const Ndk::EntityHandle& entity : *this)
|
||||||
|
{
|
||||||
|
entity->UnregisterEntityList(&entityList);
|
||||||
|
entity->RegisterEntityList(this);
|
||||||
|
}
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -161,6 +193,13 @@ namespace Ndk
|
||||||
return m_world;
|
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) :
|
inline EntityList::iterator::iterator(const EntityList* list, std::size_t nextId) :
|
||||||
m_nextEntityId(nextId),
|
m_nextEntityId(nextId),
|
||||||
|
|
@ -216,6 +255,6 @@ namespace Ndk
|
||||||
|
|
||||||
using std::swap;
|
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) :
|
Entity::Entity(Entity&& entity) :
|
||||||
HandledObject(std::move(entity)),
|
HandledObject(std::move(entity)),
|
||||||
m_components(std::move(entity.m_components)),
|
m_components(std::move(entity.m_components)),
|
||||||
|
m_containedInLists(std::move(entity.m_containedInLists)),
|
||||||
m_componentBits(std::move(entity.m_componentBits)),
|
m_componentBits(std::move(entity.m_componentBits)),
|
||||||
m_removedComponentBits(std::move(entity.m_removedComponentBits)),
|
m_removedComponentBits(std::move(entity.m_removedComponentBits)),
|
||||||
m_systemBits(std::move(entity.m_systemBits)),
|
m_systemBits(std::move(entity.m_systemBits)),
|
||||||
|
|
@ -176,9 +177,15 @@ namespace Ndk
|
||||||
m_components.clear();
|
m_components.clear();
|
||||||
m_componentBits.Reset();
|
m_componentBits.Reset();
|
||||||
|
|
||||||
// And then free every handle
|
// Free every handle
|
||||||
UnregisterAllHandles();
|
UnregisterAllHandles();
|
||||||
|
|
||||||
|
// Remove from every list
|
||||||
|
for (EntityList* list : m_containedInLists)
|
||||||
|
list->NotifyEntityDestruction(this);
|
||||||
|
|
||||||
|
m_containedInLists.clear();
|
||||||
|
|
||||||
m_valid = false;
|
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>())
|
if (entity->HasComponent<GraphicsComponent>())
|
||||||
{
|
{
|
||||||
GraphicsComponent& gfxComponent = entity->GetComponent<GraphicsComponent>();
|
GraphicsComponent& gfxComponent = entity->GetComponent<GraphicsComponent>();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue