OGL Engine 1.2.0-dev
Loading...
Searching...
No Matches
registry.hpp
Go to the documentation of this file.
1
8#pragma once
9
10#include <unordered_map>
11#include <queue>
12#include <stdexcept>
13#include <set>
14#include <iostream>
15
16#include "../defs.hpp"
17#include "../constants.hpp"
18#include "componentstorage.hpp"
19
21
22// Forward declaration
23namespace Engine::Scene { class Scene; }
24
25namespace Engine::ECS {
27 inline size_t nextComponentTypeId = 0;
28
32 class Registry {
33 friend class Scene::Scene;
34
35 // Templates qui permettent de checker si un composant possède un ::BaseType
36 template<typename, typename = std::void_t<>>
37 struct HasBaseType : std::false_type {};
38
39 template<typename T>
40 struct HasBaseType<T, std::void_t<typename T::BaseType>> : std::true_type {};
41
42 template<typename T, bool = HasBaseType<T>::value>
43 struct BaseOrSelf {
44 using type = T;
45 };
46
47 template<typename T>
48 struct BaseOrSelf<T, true> {
49 using type = typename T::BaseType;
50 };
51
52 private:
54 Scene::Scene* mScene;
55
57 std::unordered_map<size_t, IComponentStorage*> mStorages;
59 std::unordered_map<EntityID, std::set<std::string>> mTags;
66 std::queue<EntityID> mAvailableEntityIDs;
71 std::set<EntityID> mLivingEntities;
72
79 template<typename T>
80 ComponentStorage<T>* GetOrCreateStorage() {
81 size_t tid = GetComponentTypeID<T>();
82
83 if(mStorages.find(tid) == mStorages.end()) {
84 mStorages[tid] = new ComponentStorage<T>();
85 }
86
87 return static_cast<ComponentStorage<T>*>(mStorages[tid]);
88 }
89
96 template<typename T>
97 ComponentStorage<T>* GetStorage() {
98 size_t tid = GetComponentTypeID<T>();
99
100 if(mStorages.find(tid) != mStorages.end()) {
101 return static_cast<ComponentStorage<T>*>(mStorages[tid]);
102 }
103
104 return nullptr;
105 }
106
107 public:
113 Registry();
114
119 void Print();
120
127
128 /* ECS Registry Public Section => Lifecycle of entities and systems */
129
136
143 template<typename... Components>
145 EntityID id = CreateEntity();
146 (AddComponent<Components>(id), ...); // C++17 fold expression
147 return id;
148 }
149
156 void DestroyEntity(EntityID entityID);
157
165 bool IsValidEntity(EntityID entityID);
166
173 void Clear();
174
183 template <typename... TComponents>
184 std::vector<EntityID> GetEntityIDsWith() {
185 std::vector<EntityID> result;
186
187 if(sizeof...(TComponents) == 0) return result;
188
189 // On récupère le premier stockage pour itérer sur une base minimale
190 auto* baseStorage = GetStorage<std::tuple_element_t<0, std::tuple<TComponents...>>>();
191 if(!baseStorage) return result;
192
193 for (const auto& [entityID, _] : baseStorage->GetRaw()) {
194 if ((HasComponent<TComponents>(entityID) && ...)) {
195 result.push_back(entityID);
196 }
197 }
198
199 return result;
200 }
201
208 EntityID GetEntityIDWithTag(std::string targetTag);
209
216 std::vector<EntityID> GetEntityIDsWithTag(std::string targetTag);
217
218 /* COMPONENT MANAGER PUBLIC SECTION */
227 template <typename T, typename... Args>
228 void AddComponent(EntityID entityID, Args&&... args) {
229 using Base = typename BaseOrSelf<T>::type;
230
231 GetOrCreateStorage<Base>()->Add(entityID, new T(std::forward<Args>(args)...));
232 }
233
240 template <typename T>
241 void RemoveComponent(EntityID entityID) {
242 using Base = typename BaseOrSelf<T>::type;
243
244 auto storage = GetStorage<Base>();
245 if (storage) {
246 storage->Remove(entityID);
247 }
248 }
249
259 template <typename T>
260 inline size_t GetComponentTypeID() {
261 static const size_t tid = nextComponentTypeId++;
262 return tid;
263 }
264
272 template <typename T>
273 T& GetComponent(EntityID entityID) {
274 using Base = typename BaseOrSelf<T>::type;
275
276 auto* storage = GetStorage<Base>();
277 if(!storage) throw std::runtime_error("Registry::GetComponent<T>: no storage for component type");
278 return static_cast<T&>(storage->GetRef(entityID));
279 }
280
288 template<typename T>
289 std::vector<T*> GetComponents(EntityID entityID) {
290 using Base = typename BaseOrSelf<T>::type;
291
292 auto* storage = GetStorage<Base>();
293 if(!storage) throw std::runtime_error("Registry::GetComponents<T>: no storage for component type");
294 return (storage->GetMany(entityID));
295 }
296
305 template <typename T>
306 bool HasComponent(EntityID entityID) {
307 using Base = typename BaseOrSelf<T>::type;
308
309 auto *storage = GetStorage<Base>();
310 return storage && !!storage->Get(entityID);
311 }
312
313 // Tags management
320 void AddTag(EntityID entityID, std::string tag);
321
330 bool HasTag(EntityID entityID, std::string tag);
331
338 std::set<std::string> GetTags(EntityID entityID);
339
346 void AddChild(EntityID parentID, EntityID childID);
347
355 void RemoveChild(EntityID parentID, EntityID childID, bool removeComponents = true);
356 };
357}
void DestroyEntity(EntityID entityID)
Supprime l'entité référencée par l'identifiant donné
Definition registry.cpp:31
std::vector< T * > GetComponents(EntityID entityID)
Renvoie un vector de pointeurs vers tous les composants du type donné présents.
Definition registry.hpp:289
std::vector< EntityID > GetEntityIDsWith()
Renvoie un tableau d'EntityIDs sous condition.
Definition registry.hpp:184
void AddChild(EntityID parentID, EntityID childID)
Ajoute les composants Parent/Children de manière automatique pour créer une relation parent/enfant.
Definition registry.cpp:91
T & GetComponent(EntityID entityID)
Renvoie le component référencé par l'EntityID donné
Definition registry.hpp:273
bool HasComponent(EntityID entityID)
Vérifie si une entité possède un component.
Definition registry.hpp:306
EntityID CreateEntity()
Créé une nouvelle entité et renvoie l'identifiant qui lui a été attribué
Definition registry.cpp:22
EntityID CreateEntityWith()
Créé une nouvelle entité avec les composants voulus.
Definition registry.hpp:144
void Print()
Affiche un print du registre dans la console.
Definition registry.cpp:12
size_t GetComponentTypeID()
Renvoie une identifiant unique pour chaque type de composant.
Definition registry.hpp:260
Registry()
Créé un objet Registry.
Definition registry.cpp:5
void RemoveComponent(EntityID entityID)
Supprime le composant de type T associé à l'entité à l'EntityID donné
Definition registry.hpp:241
std::set< std::string > GetTags(EntityID entityID)
Renvoie les tags associés à une entité donnée.
Definition registry.cpp:67
bool IsValidEntity(EntityID entityID)
Renvoie true si l'entité est valide et utilisable, false sinon.
Definition registry.cpp:41
EntityID GetEntityIDWithTag(std::string targetTag)
Renvoie le premier EntityID trouvé pour le tag donné
Definition registry.cpp:71
friend class Scene::Scene
Definition registry.hpp:33
void Clear()
Nettoie le registre dans son entiereté.
Definition registry.cpp:45
bool HasTag(EntityID entityID, std::string tag)
Vérifie si une entité possède un tag.
Definition registry.cpp:63
std::vector< EntityID > GetEntityIDsWithTag(std::string targetTag)
Renvoie une liste d'entityID qui possèdent le tag donné
Definition registry.cpp:80
Scene::Scene & GetScene()
Renvoie la scène courante.
Definition registry.cpp:18
void AddComponent(EntityID entityID, Args &&... args)
Ajoute un nouveau component.
Definition registry.hpp:228
void AddTag(EntityID entityID, std::string tag)
Ajoute un tag à une entité
Definition registry.cpp:59
void RemoveChild(EntityID parentID, EntityID childID, bool removeComponents=true)
Brise la relation parent/enfant entre deux entités, si elle existe.
Definition registry.cpp:103
Classe qui encapsule un registre de composants ECS, et des fonctions de lifcecycle.
Definition scene.hpp:36
Définit des constantes utilisables un peu partout dans le code du moteur.
Définit des types de données utilisés dans le moteur.
Système de logs console/fichier.
Definition component.hpp:11
size_t nextComponentTypeId
Le prochain identifiant de composant pour les storages.
Definition registry.hpp:27
Definition registry.hpp:23
std::uint32_t EntityID
Définition de type pour mieux identifier les EntityID.
Definition defs.hpp:13