Easys
A minimalist, header-only C++ ECS library for efficient and fuss-free entity and component management.
Loading...
Searching...
No Matches
registry.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <any>
4#include <stdexcept>
5#include <typeindex>
6#include <unordered_map>
7#include <vector>
8
9#include "entity.hpp"
10#include "sparse_set.hpp"
11
12namespace Easys {
13
14template <typename... AllComponentTypes>
15class Registry {
16 private:
17 mutable std::tuple<SparseSet<Entity, AllComponentTypes>...> componentSets;
18
19 public:
20 template <typename ComponentType>
21 inline void addComponent(const Entity entity, const ComponentType& component)
22 {
23 auto& componentSet = getComponentSet<ComponentType>();
24 componentSet.set(entity, std::move(component));
25 }
26
27 template <typename ComponentType>
28 inline void removeComponent(const Entity entity)
29 {
30 auto& componentSet = getComponentSet<ComponentType>();
31 componentSet.remove(entity);
32 }
33
34 inline void removeComponents(const Entity entity)
35 {
36 forEachComponentType<AllComponentTypes...>(
37 [&]<typename Component>()
38 {
39 removeComponent<Component>(entity);
40 });
41 }
42
43 template <typename... ComponentTypes>
44 inline void removeComponents(const Entity entity)
45 {
46 forEachComponentType<ComponentTypes...>(
47 [&]<typename Component>()
48 {
49 removeComponent<Component>(entity);
50 });
51 }
52
53 template <typename ComponentType>
54 inline ComponentType& getComponent(const Entity entity)
55 {
56 auto& componentSet = getComponentSet<ComponentType>();
57 // could be optimized with direct access. get() calls contains() internally
58 return componentSet.get(entity);
59 }
60
61 template <typename ComponentType>
62 inline const ComponentType& getComponent(const Entity entity) const
63 {
64 const auto& componentSet = getComponentSet<ComponentType>();
65 // could be optimized with direct access. get() calls contains() internally
66 return componentSet.get(entity);
67 }
68
69 template <typename ComponentType>
70 inline bool hasComponent(const Entity entity) const
71 {
72 return getComponentSet<ComponentType>().contains(entity);
73 }
74
75 template <typename ComponentType>
76 inline const std::vector<Entity>& getEntitiesByComponent() const
77 {
78 return getComponentSet<ComponentType>().getKeys();
79 }
80
81 template <typename... ComponentTypes>
82 inline std::vector<Entity> getEntitiesByComponents() const
83 {
84 std::vector<Entity> entities;
85 bool isFirstComponentType = true;
86
87 // Iterate over each component type and intersect entities
88 forEachComponentType<ComponentTypes...>(
89 [this, &entities, &isFirstComponentType]<typename T>()
90 {
91 if (isFirstComponentType)
92 {
93 entities = getEntitiesByComponent<T>();
94 isFirstComponentType = false;
95 }
96
97 else
98 {
99 std::vector<Easys::Entity> newEntities;
100 newEntities.reserve(entities.size());
101
102 for (const auto& e : entities)
103 {
104 if (hasComponent<T>(e))
105 {
106 newEntities.push_back(e);
107 }
108 }
109
110 entities = std::move(newEntities);
111 }
112 });
113
114 return entities;
115 }
116
117 inline size_t size() const
118 {
119 size_t totalSize = 0;
120
121 forEachComponentType<AllComponentTypes...>(
122 [this, &totalSize]<typename T>()
123 {
124 totalSize += getComponentSet<T>().size();
125 });
126
127 return totalSize;
128 }
129
130 template <typename... ComponentTypes>
131 inline size_t size() const
132 {
133 size_t totalSize = 0;
134
135 forEachComponentType<ComponentTypes...>(
136 [this, &totalSize]<typename T>()
137 {
138 totalSize += getComponentSet<T>().size();
139 });
140
141 return totalSize;
142 }
143
144 inline void clear()
145 {
146 forEachComponentType<AllComponentTypes...>(
147 [this]<typename T>()
148 {
149 getComponentSet<T>().clear();
150 });
151 }
152
153 template <typename... ComponentTypes>
154 inline void clear()
155 {
156 forEachComponentType<ComponentTypes...>(
157 [this]<typename T>()
158 {
159 getComponentSet<T>().clear();
160 });
161 }
162
163 private:
164 template <typename T>
165 static constexpr bool isRegisteredComponent = (std::is_same_v<T, AllComponentTypes> || ...);
166
167 template <typename... ComponentTypes, typename Func>
168 inline void forEachComponentType(Func&& f) const
169 {
170 // MSVC does not support multiple expressions in a fold statement so we use this small helper
171 auto staticAssertAndCall = [&f]<typename T>()
172 {
173 static_assert(isRegisteredComponent<T>, "Tried to access an unregistered component type in ECS.");
174 f.template operator()<T>();
175 };
176
177 (staticAssertAndCall.template operator()<ComponentTypes>(), ...);
178 }
179
180 template <typename ComponentType>
181 inline SparseSet<Entity, ComponentType>& getComponentSet()
182 {
183 static_assert(isRegisteredComponent<ComponentType>, "Tried to access an unregistered component type.");
184 return std::get<SparseSet<Entity, ComponentType>>(componentSets);
185 }
186
187 template <typename ComponentType>
188 inline const SparseSet<Entity, ComponentType>& getComponentSet() const
189 {
190 static_assert(isRegisteredComponent<ComponentType>, "Tried to access an unregistered component type.");
191 return std::get<SparseSet<Entity, ComponentType>>(componentSets);
192 }
193};
194
195} // namespace Easys
Definition registry.hpp:15
ComponentType & getComponent(const Entity entity)
Definition registry.hpp:54
size_t size() const
Definition registry.hpp:117
const ComponentType & getComponent(const Entity entity) const
Definition registry.hpp:62
std::vector< Entity > getEntitiesByComponents() const
Definition registry.hpp:82
void removeComponents(const Entity entity)
Definition registry.hpp:44
void clear()
Definition registry.hpp:154
void addComponent(const Entity entity, const ComponentType &component)
Definition registry.hpp:21
void clear()
Definition registry.hpp:144
bool hasComponent(const Entity entity) const
Definition registry.hpp:70
const std::vector< Entity > & getEntitiesByComponent() const
Definition registry.hpp:76
void removeComponents(const Entity entity)
Definition registry.hpp:34
void removeComponent(const Entity entity)
Definition registry.hpp:28
size_t size() const
Definition registry.hpp:131
Definition ecs.hpp:12
EASYS_ENTITY_TYPE Entity
Definition entity.hpp:11