Divide Framework 0.1
A free and open-source 3D Framework under heavy development
Loading...
Searching...
No Matches
ComponentManager.h
Go to the documentation of this file.
1/*
2 Author : Tobias Stein
3 Date : 7th September, 2017
4 File : ComponentManager.h
5
6 Manages all component container.
7
8 All Rights Reserved. (c) Copyright 2016.
9*/
10
11#pragma once
12#ifndef ECS__COMPONENT_MANAGER_H__
13#define ECS__COMPONENT_MANAGER_H__
14
15
16#include "API.h"
17#include "Engine.h"
18
19#include "IComponent.h"
20
21#include "util/FamilyTypeID.h"
22
24
25
26
27namespace ECS
28{
29 template<class U>
31 static std::atomic_bool s_ComponentsChanged;
32 };
33
34 template<class U>
35 std::atomic_bool ComponentMonitor<U>::s_ComponentsChanged = false;
36
38 {
39 friend class IComponent;
40
42
43
44
46 {
47 public:
48
50 {}
51
52 virtual const char* GetComponentContainerTypeName() const = 0;
53
54 virtual void DestroyComponent(IComponent* object) = 0;
55 };
56
57 public:
58 template<class T>
59 class ComponentContainer : public Memory::MemoryChunkAllocator<T, COMPONENT_T_CHUNK_SIZE>, public IComponentContainer
60 {
63
64
65 public:
66
67 ComponentContainer() : Memory::MemoryChunkAllocator<T, COMPONENT_T_CHUNK_SIZE>("ComponentManager")
68 {}
69
71 {}
72
73 virtual const char* GetComponentContainerTypeName() const override
74 {
75 static const char* COMPONENT_TYPE_NAME{ typeid(T).name() };
76 return COMPONENT_TYPE_NAME;
77 }
78
79 virtual void DestroyComponent(IComponent* object) override
80 {
81 // call d'tor
82 object->~IComponent();
83
84 this->DestroyObject(object);
85
87 }
88
89 }; // class ComponentContainer
90
91 private:
92
95
96 using ComponentContainerRegistry = eastl::unordered_map<ComponentTypeId, IComponentContainer*>;
97
99
100
101 using ComponentLookupTable = eastl::vector<IComponent*>;
103
104 using EntityComponentMap = eastl::vector<eastl::vector<ComponentId>>;
106
107
108 ComponentId AqcuireComponentId(IComponent* component);
109 void ReleaseComponentId(ComponentId id);
110
111 void MapEntityComponent(EntityId entityId, ComponentId componentId, ComponentTypeId componentTypeId);
112 void UnmapEntityComponent(EntityId entityId, ComponentId componentId, ComponentTypeId componentTypeId);
113
114 public:
115
116 template<class T>
118
121
141
142 template<class T, class ...ARGS>
143 T* AddComponent(const EntityId entityId, ARGS&&... args)
144 {
145 // hash operator for hashing entity and component ids
146 static constexpr eastl::hash<ComponentId> ENTITY_COMPONENT_ID_HASHER { eastl::hash<ComponentId>() };
147
148 const ComponentTypeId CTID = T::STATIC_COMPONENT_TYPE_ID;
149
150 // aqcuire memory for new component object of type T
151 void* pObjectMemory = GetComponentContainer<T>()->CreateObject();
152
153 const ComponentId componentId = this->AqcuireComponentId((T*)pObjectMemory);
154 ((T*)pObjectMemory)->m_ComponentID = componentId;
155
156 // create component inplace
157 IComponent* component = new (pObjectMemory)T(std::forward<ARGS>(args)...);
158
159 component->m_Owner = entityId;
160 component->m_HashValue = ENTITY_COMPONENT_ID_HASHER(entityId) ^ (ENTITY_COMPONENT_ID_HASHER(componentId) << 1);
161
162 // create mapping from entity id its component id
163 MapEntityComponent(entityId, componentId, CTID);
164
166
167 return static_cast<T*>(component);
168 }
169
184
185 template<class T>
186 void RemoveComponent(const EntityId entityId)
187 {
188 const ComponentTypeId CTID = T::STATIC_COMPONENT_TYPE_ID;
189
190 const ComponentId componentId = this->m_EntityComponentMap[entityId.index][CTID];
191 assert(componentId != INVALID_COMPONENT_ID && "FATAL: Trying to remove a component which is not used by this entity!");
192
193
194 IComponent* component = this->m_ComponentLUT[componentId];
195
196 assert(component != nullptr && "FATAL: Trying to remove a component which is not used by this entity!");
197
198 // release object memory
199 GetComponentContainer<T>()->DestroyObject(component);
200
201 // unmap entity id to component id
202 UnmapEntityComponent(entityId, componentId, CTID);
203
205 }
206
207 void RemoveAllComponents(const EntityId entityId)
208 {
209 static const size_t NUM_COMPONENTS = this->m_EntityComponentMap[0].size();
210
211 for (ComponentTypeId componentTypeId = 0; componentTypeId < NUM_COMPONENTS; ++componentTypeId)
212 {
213 const ComponentId componentId = this->m_EntityComponentMap[entityId.index][componentTypeId];
214 if (componentId == INVALID_COMPONENT_ID)
215 continue;
216
217 IComponent* component = this->m_ComponentLUT[componentId];
218 if (component != nullptr)
219 {
220 // get appropriate component container
221 const auto it = this->m_ComponentContainerRegistry.find(componentTypeId);
222 if (it != this->m_ComponentContainerRegistry.end())
223 it->second->DestroyComponent(component);
224 else
225 assert(false && "Trying to release a component that wasn't created by ComponentManager!");
226
227 // unmap entity id to component id
228 UnmapEntityComponent(entityId, componentId, componentTypeId);
229 }
230 }
231 }
232
233 void PassDataToAllComponents(const EntityId entityId, const CustomEvent& data) {
234 static const size_t NUM_COMPONENTS = this->m_EntityComponentMap[0].size();
235
236 for (ComponentTypeId componentTypeId = 0; componentTypeId < NUM_COMPONENTS; ++componentTypeId)
237 {
238 const ComponentId componentId = this->m_EntityComponentMap[entityId.index][componentTypeId];
239 if (componentId == INVALID_COMPONENT_ID)
240 continue;
241
242 if (IComponent* component = this->m_ComponentLUT[componentId]) {
243 component->OnData(data);
244 }
245 }
246 }
264
265 template<class T>
266 T* GetComponent(const EntityId entityId)
267 {
268 const ComponentTypeId CTID = T::STATIC_COMPONENT_TYPE_ID;
269
270 const ComponentId componentId = this->m_EntityComponentMap[entityId.index][CTID];
271
272 // entity has no component of type T
273 if (componentId == INVALID_COMPONENT_ID)
274 return nullptr;
275
276 return static_cast<T*>(this->m_ComponentLUT[componentId]);
277 }
278
293 template<class T>
295 {
296 const ComponentTypeId CID = T::STATIC_COMPONENT_TYPE_ID;
297
298 const auto it = this->m_ComponentContainerRegistry.find(CID);
299 ComponentContainer<T>* cc = nullptr;
300
301 if (it == this->m_ComponentContainerRegistry.end())
302 {
303 cc = new ComponentContainer<T>();
304 this->m_ComponentContainerRegistry[CID] = cc;
305 }
306 else
307 cc = static_cast<ComponentContainer<T>*>(it->second);
308
309 assert(cc != nullptr && "Failed to create ComponentContainer<T>!");
310 return cc;
311 }
312
328
329 template<class T>
331 {
332 return GetComponentContainer<T>()->begin();
333 }
334
350
351 template<class T>
353 {
354 return GetComponentContainer<T>()->end();
355 }
356
357 template<class T>
358 inline size_t size() const noexcept {
359 return GetComponentContainer<T>()->size();
360 }
361 }; // ComponentManager
362
363
364 template<class T> T* GetComponent( ComponentManager* mgr, const EntityId id )
365 {
366 return mgr->GetComponent<T>( id );
367 }
368
369 template<class T, class ...P> T* AddComponent( ComponentManager* mgr, const EntityId id, P&&... param )
370 {
371 return mgr->AddComponent<T>( id, std::forward<P>( param )... );
372 }
373
374 template<class T> void RemoveComponent( ComponentManager* mgr, const EntityId id )
375 {
376 mgr->RemoveComponent<T>( id );
377 }
378
379} // namespace ECS
380
381#endif // ECS__COMPONENT_MANAGER_H__
#define COMPONENT_T_CHUNK_SIZE
Definition: API.h:26
#define DECLARE_LOGGER
Definition: LoggerMacro.h:15
#define ECS_API
Definition: Platform.h:16
ComponentContainer(const ComponentContainer &)=delete
virtual void DestroyComponent(IComponent *object) override
virtual const char * GetComponentContainerTypeName() const override
ComponentContainer & operator=(ComponentContainer &)=delete
virtual const char * GetComponentContainerTypeName() const =0
virtual void DestroyComponent(IComponent *object)=0
TComponentIterator< T > begin()
void PassDataToAllComponents(const EntityId entityId, const CustomEvent &data)
T * AddComponent(const EntityId entityId, ARGS &&... args)
ComponentManager & operator=(ComponentManager &)=delete
ComponentContainerRegistry m_ComponentContainerRegistry
size_t size() const noexcept
EntityComponentMap m_EntityComponentMap
eastl::vector< eastl::vector< ComponentId > > EntityComponentMap
eastl::vector< IComponent * > ComponentLookupTable
ComponentContainer< T > * GetComponentContainer()
typename ComponentContainer< T >::iterator TComponentIterator
ComponentLookupTable m_ComponentLUT
T * GetComponent(const EntityId entityId)
void RemoveAllComponents(const EntityId entityId)
ComponentManager(const ComponentManager &)=delete
void RemoveComponent(const EntityId entityId)
eastl::unordered_map< ComponentTypeId, IComponentContainer * > ComponentContainerRegistry
TComponentIterator< T > end()
ComponentId m_HashValue
Definition: IComponent.h:35
EntityId m_Owner
Definition: IComponent.h:39
ObjectID ComponentId
Definition: IComponent.h:21
TypeID ComponentTypeId
Definition: IComponent.h:22
T * AddComponent(ComponentManager *mgr, const EntityId id, P &&... param)
T * GetComponent(ComponentManager *mgr, const EntityId id)
void RemoveComponent(ComponentManager *mgr, const EntityId id)
static std::atomic_bool s_ComponentsChanged