Add ECS framework
This commit is contained in:
@@ -178,6 +178,10 @@
|
||||
<ClCompile Include="src\copium\core\Device.cpp" />
|
||||
<ClCompile Include="src\copium\core\Vulkan.cpp" />
|
||||
<ClCompile Include="src\copium\core\Window.cpp" />
|
||||
<ClCompile Include="src\copium\ecs\ComponentPoolBase.cpp" />
|
||||
<ClCompile Include="src\copium\ecs\ECSManager.cpp" />
|
||||
<ClCompile Include="src\copium\ecs\Entity.cpp" />
|
||||
<ClCompile Include="src\copium\ecs\EntitySet.cpp" />
|
||||
<ClCompile Include="src\copium\event\Event.cpp" />
|
||||
<ClCompile Include="src\copium\event\EventDispatcher.cpp" />
|
||||
<ClCompile Include="src\copium\event\KeyPressEvent.cpp" />
|
||||
@@ -236,6 +240,12 @@
|
||||
<ClInclude Include="src\copium\core\Device.h" />
|
||||
<ClInclude Include="src\copium\core\Vulkan.h" />
|
||||
<ClInclude Include="src\copium\core\Window.h" />
|
||||
<ClInclude Include="src\copium\ecs\ComponentPool.h" />
|
||||
<ClInclude Include="src\copium\ecs\ComponentPoolBase.h" />
|
||||
<ClInclude Include="src\copium\ecs\Config.h" />
|
||||
<ClInclude Include="src\copium\ecs\ECSManager.h" />
|
||||
<ClInclude Include="src\copium\ecs\Entity.h" />
|
||||
<ClInclude Include="src\copium\ecs\EntitySet.h" />
|
||||
<ClInclude Include="src\copium\event\Event.h" />
|
||||
<ClInclude Include="src\copium\event\EventDispatcher.h" />
|
||||
<ClInclude Include="src\copium\event\EventHandler.h" />
|
||||
|
||||
@@ -186,6 +186,18 @@
|
||||
<ClCompile Include="src\copium\util\BoundingBox.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\copium\ecs\ECSManager.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\copium\ecs\EntitySet.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\copium\ecs\ComponentPoolBase.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\copium\ecs\Entity.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="src\copium\sampler\DepthAttachment.h">
|
||||
@@ -380,5 +392,23 @@
|
||||
<ClInclude Include="src\copium\util\BoundingBox.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\copium\ecs\ComponentPool.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\copium\ecs\Config.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\copium\ecs\ECSManager.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\copium\ecs\Entity.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\copium\ecs\EntitySet.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\copium\ecs\ComponentPoolBase.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,90 @@
|
||||
#pragma once
|
||||
|
||||
#include "copium/ecs/Config.h"
|
||||
#include "copium/ecs/EntitySet.h"
|
||||
#include "copium/ecs/ComponentPoolBase.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace Copium
|
||||
{
|
||||
template <typename Component>
|
||||
class ComponentPool : public ComponentPoolBase
|
||||
{
|
||||
using Iterator = typename std::vector<Component>::iterator;
|
||||
private:
|
||||
std::vector<Component> components;
|
||||
|
||||
public:
|
||||
ComponentPool(EntityID entity, const Component& component)
|
||||
{
|
||||
Emplace(entity, component);
|
||||
}
|
||||
|
||||
Component& Emplace(EntityID entity, const Component& component)
|
||||
{
|
||||
components.push_back(component);
|
||||
entities.Emplace(entity);
|
||||
return components.back();
|
||||
}
|
||||
|
||||
void Pop()
|
||||
{
|
||||
components.pop_back();
|
||||
entities.Pop();
|
||||
}
|
||||
|
||||
bool Erase(EntityID entity)
|
||||
{
|
||||
size_t index = entities.Find(entity);
|
||||
if (!entities.Erase(entity))
|
||||
return false;
|
||||
components.erase(components.begin() + index);
|
||||
return true;
|
||||
}
|
||||
|
||||
Component& At(size_t index)
|
||||
{
|
||||
return operator[](index);
|
||||
}
|
||||
|
||||
size_t Find(EntityID entity)
|
||||
{
|
||||
return entities.Find(entity);
|
||||
}
|
||||
|
||||
Component* FindComponent(EntityID entity)
|
||||
{
|
||||
size_t index = Find(entity);
|
||||
if (index < Size())
|
||||
return &components[index];
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Component& operator[](size_t index)
|
||||
{
|
||||
CP_ASSERT(index < components.size(), "Index Out of Bound Exception");
|
||||
return components[index];
|
||||
}
|
||||
|
||||
size_t Size()
|
||||
{
|
||||
return components.size();
|
||||
}
|
||||
|
||||
Iterator Back()
|
||||
{
|
||||
return components.back();
|
||||
}
|
||||
|
||||
Iterator begin()
|
||||
{
|
||||
return components.begin();
|
||||
}
|
||||
|
||||
Iterator end()
|
||||
{
|
||||
return components.end();
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#include "copium/ecs/ComponentPoolBase.h"
|
||||
|
||||
namespace Copium
|
||||
{
|
||||
std::vector<EntityID>& ComponentPoolBase::GetEntities()
|
||||
{
|
||||
return entities.GetList();
|
||||
}
|
||||
|
||||
const std::vector<EntityID>& ComponentPoolBase::GetEntities() const
|
||||
{
|
||||
return entities.GetList();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include "copium/ecs/Config.h"
|
||||
#include "copium/ecs/EntitySet.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace Copium
|
||||
{
|
||||
class ComponentPoolBase
|
||||
{
|
||||
protected:
|
||||
EntitySet entities;
|
||||
public:
|
||||
virtual ~ComponentPoolBase() = default;
|
||||
|
||||
virtual size_t Size() = 0;
|
||||
virtual void Pop() = 0;
|
||||
virtual bool Erase(EntityID entity) = 0;
|
||||
std::vector<EntityID>& GetEntities();
|
||||
const std::vector<EntityID>& GetEntities() const;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <numeric>
|
||||
|
||||
namespace Copium
|
||||
{
|
||||
using EntityID = uint32_t;
|
||||
const static uint32_t MAX_NUM_ENTITIES = std::numeric_limits<uint32_t>::max();
|
||||
const static uint32_t INVALID_ENTITY = 0;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
#include "copium/ecs/ECSManager.h"
|
||||
|
||||
#include "copium/util/Common.h"
|
||||
|
||||
namespace Copium
|
||||
{
|
||||
ECSManager::~ECSManager()
|
||||
{
|
||||
for (auto&& components : componentPool)
|
||||
{
|
||||
delete components.second;
|
||||
}
|
||||
componentPool.clear();
|
||||
}
|
||||
|
||||
size_t ECSManager::GetEntityCount() const
|
||||
{
|
||||
return entities.size();
|
||||
}
|
||||
|
||||
EntityID ECSManager::CreateEntity()
|
||||
{
|
||||
CP_ASSERT(currentEntityId != MAX_NUM_ENTITIES, "No more entities available");
|
||||
entities.emplace(currentEntityId);
|
||||
currentEntityId++;
|
||||
return currentEntityId - 1;
|
||||
}
|
||||
|
||||
void ECSManager::DestroyEntity(EntityID entity)
|
||||
{
|
||||
auto it = entities.find(entity);
|
||||
CP_ASSERT(it != entities.end(), "Entity does not exist in ECSManager (entity=%u)", entity);
|
||||
entities.erase(it);
|
||||
for (auto&& pool : componentPool)
|
||||
{
|
||||
pool.second->Erase(entity);
|
||||
}
|
||||
}
|
||||
|
||||
bool ECSManager::ValidEntity(EntityID entity)
|
||||
{
|
||||
return entities.find(entity) != entities.end();
|
||||
}
|
||||
|
||||
void ECSManager::Each(std::function<void(EntityID)> function)
|
||||
{
|
||||
for (auto e : entities)
|
||||
function(e);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,196 @@
|
||||
#pragma once
|
||||
|
||||
|
||||
#include "copium/ecs/ComponentPool.h"
|
||||
#include "copium/ecs/Config.h"
|
||||
#include "copium/util/Common.h"
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <typeindex>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
namespace Copium
|
||||
{
|
||||
class ECSManager final
|
||||
{
|
||||
private:
|
||||
std::unordered_set<EntityID> entities;
|
||||
std::map<std::type_index, ComponentPoolBase*> componentPool;
|
||||
int currentEntityId = 1;
|
||||
public:
|
||||
~ECSManager();
|
||||
|
||||
EntityID CreateEntity();
|
||||
void DestroyEntity(EntityID entity);
|
||||
size_t GetEntityCount() const;
|
||||
bool ValidEntity(EntityID entity);
|
||||
void Each(std::function<void(EntityID)> function);
|
||||
|
||||
template <typename... Components>
|
||||
std::tuple<Components&...> AddComponents(EntityID entity, Components&&... components)
|
||||
{
|
||||
return std::forward_as_tuple(AddComponent(entity, Components(components))...);
|
||||
}
|
||||
|
||||
template <typename Component, typename... Args>
|
||||
Component& AddComponent(EntityID entity, Args&&... args)
|
||||
{
|
||||
return AddComponent(entity, Component(args...));
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
Component& AddComponent(EntityID entity, const Component& component)
|
||||
{
|
||||
auto pool = GetComponentPool<Component>();
|
||||
|
||||
if (pool)
|
||||
{
|
||||
CP_ASSERT(!HasComponent<Component>(entity), "Component already exists in entity (entity=%u, Component=%s)", entity, typeid(Component).name());
|
||||
return pool->Emplace(entity, component);
|
||||
}
|
||||
else
|
||||
{
|
||||
ComponentPool<Component>* pool{new ComponentPool{entity, component}};
|
||||
auto ret = componentPool.emplace(GetComponentId<Component>(), pool);
|
||||
return pool->At(0);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
void RemoveComponent(EntityID entity)
|
||||
{
|
||||
auto pool = GetComponentPoolAssure<Component>();
|
||||
CP_ASSERT(pool->Erase(entity), "Entity did not contain component (entity=%u, Component=%s)", entity, typeid(Component).name());
|
||||
}
|
||||
|
||||
template <typename... Components>
|
||||
void RemoveComponents(EntityID entity)
|
||||
{
|
||||
(RemoveComponent<Components>(entity), ...);
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
Component& GetComponent(EntityID entity)
|
||||
{
|
||||
auto pool = GetComponentPoolAssure<Component>();
|
||||
Component* component = pool->FindComponent(entity);
|
||||
ASSERT(component, "Entity did not contain component (entity=%u, Component=%s)", entity, typeid(Component).name());
|
||||
return *component;
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
bool HasComponent(EntityID entity)
|
||||
{
|
||||
auto pool = GetComponentPool<Component>();
|
||||
if (pool)
|
||||
return pool->Find(entity) != pool->Size();
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename... Components>
|
||||
bool HasComponents(EntityID entity)
|
||||
{
|
||||
return (HasComponent<Components>(entity) && ...);
|
||||
}
|
||||
|
||||
template <typename... Components>
|
||||
bool HasAnyComponent(EntityID entity)
|
||||
{
|
||||
return (HasComponent<Components>(entity) || ...);
|
||||
}
|
||||
|
||||
template <typename Component, typename... Components, typename Func>
|
||||
void Each(Func function)
|
||||
{
|
||||
auto pool = GetComponentPool<Component>();
|
||||
if (pool)
|
||||
{
|
||||
size_t i = 0;
|
||||
for (auto entity : pool->GetEntities())
|
||||
{
|
||||
if (HasComponents<Components...>(entity))
|
||||
{
|
||||
std::apply(function, std::forward_as_tuple(entity, pool->At(i), GetComponent<Components>(entity)...));
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
void Each(std::function<void(EntityID, Component&)> function)
|
||||
{
|
||||
auto pool = GetComponentPool<Component>();
|
||||
if (pool)
|
||||
{
|
||||
size_t i = 0;
|
||||
for (auto e : pool->GetEntities())
|
||||
{
|
||||
function(e, pool->At(i));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Component, typename... Components, typename Func>
|
||||
EntityID Find(Func function)
|
||||
{
|
||||
auto pool = GetComponentPool<Component>();
|
||||
if (pool)
|
||||
{
|
||||
size_t i = 0;
|
||||
for (auto entity : pool->GetEntities())
|
||||
{
|
||||
if (HasComponents<Components...>(entity))
|
||||
{
|
||||
if (std::apply(function, std::forward_as_tuple(entity, pool->At(i), GetComponent<Components>(entity)...)))
|
||||
return entity;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
EntityID Find(std::function<bool(EntityID, Component&)> function)
|
||||
{
|
||||
auto pool = GetComponentPool<Component>();
|
||||
if (pool)
|
||||
{
|
||||
size_t i = 0;
|
||||
for (auto e : pool->GetEntities())
|
||||
{
|
||||
if (function(e, pool->At(i)))
|
||||
return e;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
std::type_index GetComponentId()
|
||||
{
|
||||
return std::type_index(typeid(T));
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename Component>
|
||||
ComponentPool<Component>* GetComponentPool()
|
||||
{
|
||||
auto it = componentPool.find(GetComponentId<Component>());
|
||||
return it == componentPool.end() ? nullptr : static_cast<ComponentPool<Component>*>(it->second);
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
ComponentPool<Component>* GetComponentPoolAssure()
|
||||
{
|
||||
auto it = componentPool.find(GetComponentId<Component>());
|
||||
CP_ASSERT(it != componentPool.end(), "Component has not been added to an entity (Component=%s)", typeid(Component).name());
|
||||
return static_cast<ComponentPool<Component>*>(it->second);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
#include "copium/ecs/Entity.h"
|
||||
|
||||
namespace Copium
|
||||
{
|
||||
Entity::Entity()
|
||||
: manager{nullptr}, id{INVALID_ENTITY}
|
||||
{}
|
||||
|
||||
Entity::Entity(ECSManager* manager)
|
||||
: manager{manager}, id{INVALID_ENTITY}
|
||||
{}
|
||||
|
||||
Entity::Entity(ECSManager* manager, EntityID id)
|
||||
: manager{manager}, id{id}
|
||||
{}
|
||||
|
||||
Entity::operator EntityID() const
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
void Entity::operator=(EntityID entityId)
|
||||
{
|
||||
id = entityId;
|
||||
}
|
||||
|
||||
bool Entity::operator==(const Entity& entity)
|
||||
{
|
||||
return id == entity.id;
|
||||
}
|
||||
|
||||
bool Entity::operator!=(const Entity& entity)
|
||||
{
|
||||
return id != entity.id;
|
||||
}
|
||||
|
||||
Entity::operator bool() const
|
||||
{
|
||||
if (id == INVALID_ENTITY)
|
||||
return false;
|
||||
if (manager)
|
||||
return manager->ValidEntity(id);
|
||||
return false;
|
||||
}
|
||||
|
||||
void Entity::Invalidate()
|
||||
{
|
||||
id = INVALID_ENTITY;
|
||||
}
|
||||
|
||||
void Entity::Destroy()
|
||||
{
|
||||
if (*this)
|
||||
manager->DestroyEntity(id);
|
||||
}
|
||||
|
||||
void Entity::SetID(EntityID aId)
|
||||
{
|
||||
id = aId;
|
||||
}
|
||||
|
||||
EntityID Entity::GetID() const
|
||||
{
|
||||
return id;
|
||||
}
|
||||
|
||||
ECSManager* Entity::GetManager() const
|
||||
{
|
||||
return manager;
|
||||
}
|
||||
|
||||
Entity Entity::Create(ECSManager* manager)
|
||||
{
|
||||
return {manager, manager->CreateEntity()};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
#pragma once
|
||||
|
||||
#include "copium/ecs/Config.h"
|
||||
#include "copium/ecs/ECSManager.h"
|
||||
|
||||
namespace Copium
|
||||
{
|
||||
class Entity
|
||||
{
|
||||
friend class ECSManager;
|
||||
|
||||
private:
|
||||
ECSManager* manager;
|
||||
EntityID id;
|
||||
|
||||
public:
|
||||
Entity();
|
||||
Entity(ECSManager* manager);
|
||||
Entity(ECSManager* manager, EntityID id);
|
||||
|
||||
operator EntityID() const;
|
||||
void operator=(EntityID entityId);
|
||||
bool operator==(const Entity& entity);
|
||||
bool operator!=(const Entity& entity);
|
||||
operator bool() const;
|
||||
|
||||
void Invalidate();
|
||||
void Destroy();
|
||||
void SetID(EntityID aId);
|
||||
EntityID GetID() const;
|
||||
ECSManager* GetManager() const;
|
||||
|
||||
static Entity Create(ECSManager* manager);
|
||||
|
||||
template <typename Component, typename... Args>
|
||||
inline Component& AddComponent(Args... args)
|
||||
{
|
||||
return manager->AddComponent<Component>(id, args...);
|
||||
}
|
||||
|
||||
template <typename... Components>
|
||||
std::tuple<Components&...> AddComponents(Components&&... components)
|
||||
{
|
||||
return manager->AddComponents(id, components...);
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
inline void RemoveComponent()
|
||||
{
|
||||
return manager->RemoveComponent<Component>(id);
|
||||
}
|
||||
|
||||
template <typename... Components>
|
||||
inline void RemoveComponents()
|
||||
{
|
||||
return manager->RemoveComponents<Components...>(id);
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
inline Component& GetComponent() const
|
||||
{
|
||||
return manager->GetComponent<Component>(id);
|
||||
}
|
||||
|
||||
template <typename Component>
|
||||
inline bool HasComponent() const
|
||||
{
|
||||
return manager->HasComponent<Component>(id);
|
||||
}
|
||||
|
||||
template <typename... Components>
|
||||
inline bool HasComponents() const
|
||||
{
|
||||
return manager->HasComponents<Components...>(id);
|
||||
}
|
||||
|
||||
template <typename... Components>
|
||||
inline bool HasAnyComponent() const
|
||||
{
|
||||
return manager->HasAnyComponent<Components...>(id);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
#include "copium/ecs/EntitySet.h"
|
||||
|
||||
namespace Copium
|
||||
{
|
||||
bool EntitySet::Emplace(EntityID entity)
|
||||
{
|
||||
auto res = entitiesMap.emplace(entity, entitiesList.size());
|
||||
|
||||
// Check if already exists
|
||||
if (!res.second)
|
||||
return false;
|
||||
|
||||
entitiesList.push_back(entity);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EntitySet::Erase(EntityID entity)
|
||||
{
|
||||
auto it = entitiesMap.find(entity);
|
||||
if (it == entitiesMap.end())
|
||||
return false;
|
||||
size_t componentPos = it->second;
|
||||
entitiesList.erase(entitiesList.begin() + it->second);
|
||||
entitiesMap.erase(it);
|
||||
|
||||
for (auto&& entityPos : entitiesMap)
|
||||
{
|
||||
if (entityPos.second > componentPos)
|
||||
{
|
||||
entityPos.second--;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EntitySet::Pop()
|
||||
{
|
||||
if (entitiesList.size() == 0)
|
||||
return false;
|
||||
entitiesMap.erase(entitiesMap.find(entitiesList.back()));
|
||||
entitiesList.pop_back();
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t EntitySet::Find(EntityID entity)
|
||||
{
|
||||
auto it = entitiesMap.find(entity);
|
||||
if (it == entitiesMap.end())
|
||||
return entitiesList.size();
|
||||
return it->second;
|
||||
}
|
||||
|
||||
size_t EntitySet::Size() const
|
||||
{
|
||||
return entitiesList.size();
|
||||
}
|
||||
|
||||
std::vector<EntityID>& EntitySet::GetList() { return entitiesList; }
|
||||
const std::vector<EntityID>& EntitySet::GetList() const { return entitiesList; }
|
||||
|
||||
std::vector<EntityID>::iterator EntitySet::begin() { return entitiesList.begin(); }
|
||||
std::vector<EntityID>::iterator EntitySet::end() { return entitiesList.end(); }
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include "copium/ecs/Config.h"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace Copium
|
||||
{
|
||||
class EntitySet
|
||||
{
|
||||
private:
|
||||
std::vector<EntityID> entitiesList;
|
||||
std::unordered_map<EntityID, size_t> entitiesMap; // Maps the entity id to a component index
|
||||
public:
|
||||
bool Emplace(EntityID entity);
|
||||
bool Erase(EntityID entity);
|
||||
bool Pop();
|
||||
size_t Find(EntityID entity);
|
||||
size_t Size() const;
|
||||
std::vector<EntityID>& GetList();
|
||||
const std::vector<EntityID>& GetList() const;
|
||||
|
||||
std::vector<EntityID>::iterator begin();
|
||||
std::vector<EntityID>::iterator end();
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user