VOX
A little voxel engine
Loading...
Searching...
No Matches
Manager.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <typeindex>
4#include <unordered_map>
5#include <memory>
6#include <exception>
7#include <string>
8#include <functional>
9#include <tuple>
10#include <utility>
11#include <iostream>
12
13#include "ecs_CONSTANTS.hpp"
14#include "ecs_FWD.hpp"
15#include "ecs_utils.hpp"
16#include "ecs_Exceptions.hpp"
17
18#include "ComponentStorage.hpp"
19#include "SparseSet.hpp"
20#include "View.hpp"
21
22namespace ecs
23{
32 template <ValidEntity entityType = ecs::entity>
33 class Manager
34 {
35 public:
36 template <ValidEntity entity, typename... ComponentTypes>
37 friend class View;
38
40 template <typename ComponentType>
42
45
46 Manager(Manager & other) = delete;
47 Manager(Manager && other) = delete;
48 Manager & operator=(Manager & other) = delete;
49 Manager & operator=(Manager && other) = delete;
50
51 /*************************************************************\
52 * ENTITY
53 \*************************************************************/
54
61 std::pair<bool, entityType> createEntity()
62 {
63 if (m_entities.size() == ecs::MAX_ENTITIES)
64 return {false, 0};
65 //check if there are any dead entities to reuse
66 if (m_dead_entity_head != 0)
67 {
68 entityType dead_entity = m_dead_entity_head;
69 auto dead_index = getEntityIndex(dead_entity);
70
71 //set the new dead entity head to the next dead entity
72 //see doc for more info
73 m_dead_entity_head = m_entities[dead_index];
74
75 IncreaseEntityVersion(dead_entity);
76 m_entities[dead_index] = dead_entity;
77 return {true, dead_entity};
78 }
79 else
80 {
81 auto new_entity = createNewEntity();
82 m_entities.push_back(new_entity);
83 return {true, new_entity};
84 }
85 }
86
94 void removeEntity(entityType entity)
95 {
96 if (!isAlive(entity))
98
99 auto index = getEntityIndex(entity);
100
101 std::swap(m_entities[index], m_dead_entity_head);
102
103 //temporary would like to find a way to have it in O(1)
104 for (auto & [type, set] : m_components)
105 set->remove(entity);
106 }
107
108 bool isAlive(entityType entity) const
109 {
110 auto index = getEntityIndex(entity);
111
112 if (index >= m_entities.size())
113 return false;
114
115 if (m_entities[index] != entity)
116 return false;
117 return true;
118 }
119
126 static constexpr uint32_t getEntityVersion(const entityType & entity)
127 {
128 return entity & 0xF;
129 }
130
137 static constexpr uint32_t getEntityIndex(const entityType & entity)
138 {
139 return entity >> 4;
140 }
141
142 /*************************************************************\
143 * COMPONENT-ENTITY RELATION
144 \*************************************************************/
145
153 template <typename ComponentType>
154 void add(entityType entity, ComponentType component)
155 {
156 using ComponentSetType = ComponentStorage<entityType, ComponentType>;
157 ComponentSetType & set = getSet<ComponentType>();
158
159 set.insert(entity, component);
160 }
161
169 template <typename... ComponentTypes>
170 void add(entityType entity, ComponentTypes... components)
171 {
172 (add<ComponentTypes>(entity, components), ...);
173 }
174
181 template <typename... ComponentTypes>
182 void remove(entityType entity)
183 {
184 (_remove_component<ComponentTypes>(entity), ...);
185 }
186
197 template <typename ComponentType>
198 ComponentType & getComponent(entityType entity)
199 {
200 using ComponentSetType = ComponentStorage<entityType, ComponentType>;
201 ComponentSetType & set = getSet<ComponentType>();
202
203 return set.get(entity);
204 }
205
217 template <typename... ComponentTypes>
218 std::tuple<ComponentTypes &...> getComponents(entityType entity)
219 {
220 return {getComponent<ComponentTypes>(entity)...};
221 }
222
230 template <typename ComponentType>
231 ComponentType * tryGetComponent(entityType entity)
232 {
233 using ComponentSetType = ComponentStorage<entityType, ComponentType>;
234 ComponentSetType & set = getSet<ComponentType>();
235
236 return set.tryGet(entity);
237 }
238
246 template <typename... ComponentTypes>
247 std::tuple<ComponentTypes *...> tryGetComponents(entityType entity)
248 {
249 return std::make_tuple(tryGetComponent<ComponentTypes>(entity)...);
250 }
251
252 /*************************************************************\
253 * VIEWS
254 \*************************************************************/
262 template <typename... ComponentTypes>
263 View<entityType, ComponentTypes...> view()
264 {
265 return View<entityType, ComponentTypes...>(*this);
266 }
267
268 /*************************************************************\
269 * EXCEPTIONS
270 \*************************************************************/
271
272 class EntityDoesNotExist : public std::exception
273 {
274 public:
276 : m_entity(entity) {}
277 const char * what() const noexcept override { return std::string("Entity does not exist " + std::to_string(m_entity)).c_str(); }
278 entityType getEntity() const { return m_entity; }
279 private:
280 entityType m_entity;
281 };
282
283 class EntityAlreadyExists : public std::exception
284 {
285 public:
287 : m_entity(entity) {}
288 const char * what() const noexcept override { return std::string("Entity already exists " + std::to_string(m_entity)).c_str(); }
289 entityType getEntity() const { return m_entity; }
290 private:
291 entityType m_entity;
292
293 };
294
295 class ComponentDoesNotExist : public std::exception
296 {
297 public:
298 template <typename ComponentType>
300 : m_type(typeid(ComponentType)) {}
301 const char * what() const noexcept override
302 {
303 std::string message = "Component does not exist ";
304 message += m_type.name();
305 return message.c_str();
306 }
307 const std::type_index & getType() const { return m_type; }
308 private:
309 std::type_index m_type;
310 };
311
312 class ComponentAlreadyExists : public std::exception
313 {
314 public:
315 template <typename ComponentType>
317 : m_type(typeid(ComponentType)) {}
318 const char * what() const noexcept override
319 {
320 std::string message = "Component already exists ";
321 message += m_type.name();
322 return message.c_str();
323 }
324 const std::type_index & getType() const { return m_type; }
325 private:
326 std::type_index m_type;
327 };
328
329 private:
330 std::vector<entityType> m_entities;
331
332 entityType m_dead_entity_head = 0;
333
334 std::unordered_map<std::type_index, std::shared_ptr<entitySet>> m_components;
335
336 /*************************************************\
337 * ENTITY UTILS
338 \*************************************************/
339
345 void IncreaseEntityVersion(entityType & entity)
346 {
347 entity += (getEntityVersion(entity) + 1) & 0xF;
348 }
349
355 entityType createNewEntity()
356 {
357 return m_entities.size() << 4 | 1;
358 }
359
360 /*************************************************\
361 * COMPONENT UTILS
362 \*************************************************/
363 template <typename ComponentType>
364 componentSet<ComponentType> & getSet()
365 {
366 return *getSetPtr<ComponentType>();
367 }
368
376 template <typename ComponentType>
377 std::shared_ptr<componentSet<ComponentType>> getSetPtr()
378 {
379 using componentSetType = componentSet<ComponentType>;
380 const std::type_index type = std::type_index(typeid(ComponentType));
381
382 auto it = m_components.find(type);
383 if (it == m_components.end())
384 {
385 auto ret_pair = m_components.insert({type, std::make_shared<componentSetType>()});
386 it = ret_pair.first;
387 }
388 return std::static_pointer_cast<componentSetType>(it->second);
389 }
390
397 template <typename ComponentType>
398 void _remove_component(entityType entity)
399 {
400 using ComponentSetType = ComponentStorage<entityType, ComponentType>;
401 ComponentSetType & set = getSet<ComponentType>();
402
403 set.remove(entity);
404 }
405 };
406}
Definition: ComponentStorage.hpp:12
Definition: Manager.hpp:313
const std::type_index & getType() const
Definition: Manager.hpp:324
ComponentAlreadyExists()
Definition: Manager.hpp:316
const char * what() const noexcept override
Definition: Manager.hpp:318
Definition: Manager.hpp:296
const std::type_index & getType() const
Definition: Manager.hpp:307
ComponentDoesNotExist()
Definition: Manager.hpp:299
const char * what() const noexcept override
Definition: Manager.hpp:301
Definition: Manager.hpp:284
EntityAlreadyExists(entityType entity)
Definition: Manager.hpp:286
entityType getEntity() const
Definition: Manager.hpp:289
const char * what() const noexcept override
Definition: Manager.hpp:288
Definition: Manager.hpp:273
const char * what() const noexcept override
Definition: Manager.hpp:277
EntityDoesNotExist(entityType entity)
Definition: Manager.hpp:275
entityType getEntity() const
Definition: Manager.hpp:278
This class is the main class of the ECS system you can use it to create entitites,...
Definition: Manager.hpp:34
ComponentType & getComponent(entityType entity)
get a component attached to an entity
Definition: Manager.hpp:198
SparseSet< entityType > entitySet
Definition: Manager.hpp:39
std::tuple< ComponentTypes *... > tryGetComponents(entityType entity)
try to get multiple components attached to an entity as a tuple
Definition: Manager.hpp:247
void removeEntity(entityType entity)
Remove an entity from the manager.
Definition: Manager.hpp:94
void remove(entityType entity)
remove any components from an entity
Definition: Manager.hpp:182
Manager(Manager &other)=delete
Manager & operator=(Manager &&other)=delete
void add(entityType entity, ComponentType component)
add a component to an entity
Definition: Manager.hpp:154
std::pair< bool, entityType > createEntity()
Create a new entity.
Definition: Manager.hpp:61
Manager()
Definition: Manager.hpp:43
Manager(Manager &&other)=delete
~Manager()
Definition: Manager.hpp:44
std::tuple< ComponentTypes &... > getComponents(entityType entity)
Get multiple components attached to an entity as a tuple.
Definition: Manager.hpp:218
static constexpr uint32_t getEntityVersion(const entityType &entity)
Get the version of the entity, see the entity doc for more info.
Definition: Manager.hpp:126
View< entityType, ComponentTypes... > view()
get an iterable view of entities that have all the components listed in the tparams
Definition: Manager.hpp:263
Manager & operator=(Manager &other)=delete
static constexpr uint32_t getEntityIndex(const entityType &entity)
Get the index of the entity in the entity array, see the entity doc for more info.
Definition: Manager.hpp:137
void add(entityType entity, ComponentTypes... components)
add multiple components to an entity
Definition: Manager.hpp:170
ComponentType * tryGetComponent(entityType entity)
Try to get a component attached to an entity.
Definition: Manager.hpp:231
bool isAlive(entityType entity) const
Definition: Manager.hpp:108
Definition: SparseSet.hpp:20
Definition: View.hpp:110
Definition: ecs_utils.hpp:11
Definition: ComponentStorage.hpp:9
constexpr size_t MAX_ENTITIES
Definition: ecs_CONSTANTS.hpp:8
uint32_t entity
Definition: ecs_CONSTANTS.hpp:10