Oxygen Engine
Modern C++ 3D Engine using OpenGL
Loading...
Searching...
No Matches
component.h
1#ifndef OE_SCENE_COMPONENT_H
2#define OE_SCENE_COMPONENT_H
3
4#include <memory>
5#include <string>
6#include <vector>
7#include <unordered_map>
8#include <algorithm>
9
10namespace oe::component
11{
43 {
44 public:
56 virtual void onUpdate(const double, const int8_t = 0)
57 {}
58
66 bool is_active = true;
67
68 virtual ~Component()
69 {}
70 };
71
72 template <typename Entity, typename ComponentType>
73 class ComponentList;
74
78 template <typename Entity>
80 {
81 public:
82 const std::string& getName() const
83 {
84 return _name;
85 }
86
87 protected:
88 EntityComponent(Entity& entity):
89 _entity(entity)
90 {}
91
92 Entity& _entity;
93
94 private:
95 std::string _name = {};
96
97 template <typename E, typename C>
98 friend class ComponentList;
99 };
100
104 template <typename Entity, typename ComponentType = EntityComponent<Entity>>
106 {
107 using ComponentContainer = std::vector<std::shared_ptr<ComponentType>>;
108
109 public:
110 ComponentList(Entity& entity):
111 _entity(entity)
112 {}
113
117 template <typename T = ComponentType, typename ...Args>
118 std::shared_ptr<T> addNamed(const std::string& name, Args&& ...args)
119 {
120 if (name.length() == 0)
121 {
122 throw std::invalid_argument("Component name is missing!");
123 }
124
125 if (_component_by_keys.count(name) != 0)
126 {
127 throw std::invalid_argument("Component " + name + "already exists!");
128 }
129
130 std::shared_ptr<T> result = std::make_shared<T>(_entity, std::forward<Args>(args)...);
131
132 _components.push_back(result);
133
134 result->_name = name;
135 _component_by_keys[name] = result;
136
137 return result;
138 }
139
143 template <typename T = ComponentType, typename ...Args>
144 std::shared_ptr<T> add(Args&& ...args)
145 {
146 std::shared_ptr<T> result = std::make_shared<T>(_entity, std::forward<Args>(args)...);
147
148 _components.push_back(result);
149
150 return result;
151 }
152
156 template <typename T = ComponentType>
157 const T* getComponentByName(const std::string& name) const noexcept
158 {
159 if (_component_by_keys.count(name))
160 {
161 return dynamic_cast<T*>(_component_by_keys.at(name).get());
162 }
163
164 return nullptr;
165 }
166
170 template <typename T = ComponentType>
171 T* getComponentByName(const std::string& name) noexcept
172 {
173 if (_component_by_keys.count(name))
174 {
175 return dynamic_cast<T*>(_component_by_keys.at(name).get());
176 }
177
178 return nullptr;
179 }
180
184 template <typename T>
185 const T* getComponentByType() const noexcept
186 {
187 for (auto it = _components.begin(); it != _components.end(); it++)
188 {
189 if (auto result = dynamic_cast<const T*>(it->get()))
190 return result;
191 }
192
193 return nullptr;
194 }
195
199 template <typename T>
200 T* getComponentByType() noexcept
201 {
202 for (auto it = _components.begin(); it != _components.end(); it++)
203 {
204 if (auto result = dynamic_cast<T*>(it->get()))
205 return result;
206 }
207
208 return {};
209 }
210
214 void remove(const std::string& name)
215 {
216 // Find if the component exists
217 if (!_component_by_keys.count(name))
218 return;
219
220 std::shared_ptr<Component> component = _component_by_keys[name];
221
222 // Remove the from the key list
223 _component_by_keys.erase(name);
224
225 // Remove the from the list
226 _components.erase(std::remove_if(
227 _components.begin(),
228 _components.end(),
229 [component](const auto& c) {return c == component;}
230 ), _components.end());
231 }
232
243 void update(const double delta, const int8_t flags = 0) const
244 {
245 for (auto it = _components.begin(); it != _components.end(); it++)
246 {
247 (*it)->onUpdate(delta, flags);
248 }
249 }
250
254 typename ComponentContainer::iterator begin() noexcept
255 {
256 return _components.begin();
257 }
258
262 typename ComponentContainer::iterator end() noexcept
263 {
264 return _components.end();
265 }
266
270 const typename ComponentContainer::const_iterator begin() const noexcept
271 {
272 return _components.begin();
273 }
274
278 const typename ComponentContainer::const_iterator end() const noexcept
279 {
280 return _components.end();
281 }
282
286 const typename ComponentContainer::const_iterator cbegin() const noexcept
287 {
288 return _components.begin();
289 }
290
294 const typename ComponentContainer::const_iterator cend() const noexcept
295 {
296 return _components.end();
297 }
298
299 private:
300 Entity& _entity;
301
302 ComponentContainer _components;
303 std::unordered_map<std::string, std::shared_ptr<ComponentType>> _component_by_keys;
304 };
305
309 template <typename Entity, typename ComponentType>
311 {
312 public:
313 HasComponents(Entity& entity):
314 _components(entity)
315 {
316 }
317
322 {
323 return _components;
324 }
325
330 {
331 return _components;
332 }
333
337 template <typename T = ComponentType, typename ...Args>
338 std::shared_ptr<T> addComponent(Args&&... args)
339 {
340 return _components. template add<T, Args...>(std::forward<Args>(args)...);
341 }
342
346 template <typename T = ComponentType, typename ...Args>
347 std::shared_ptr<T> addNamedComponent(const std::string& name, Args&&... args)
348 {
349 return _components. template addNamed<T, Args...>(name, std::forward<Args>(args)...);
350 }
351
355 void removeComponent(const std::string& name)
356 {
357 _components.remove(name);
358 }
359
363 template <typename T>
364 const T* getComponentByType() const noexcept
365 {
366 return _components. template getComponentByType<T>();
367 }
368
372 template <typename T>
373 T* getComponentByType() noexcept
374 {
375 return _components. template getComponentByType<T>();
376 }
377
381 template <typename T = ComponentType>
382 T* getComponentByName(const std::string& name) noexcept
383 {
384 return _components. template getComponentByName<T>(name);
385 }
386
390 template <typename T = ComponentType>
391 const T* getComponentByName(const std::string& name) const noexcept
392 {
393 return _components. template getComponentByName<T>(name);
394 }
395
396 protected:
398
399 };
400}
401#endif
Component holder that can be bound to an entity.
Definition component.h:106
ComponentContainer::iterator end() noexcept
Definition component.h:262
ComponentContainer::iterator begin() noexcept
Definition component.h:254
const ComponentContainer::const_iterator cend() const noexcept
Definition component.h:294
std::shared_ptr< T > add(Args &&...args)
Add a new a component.
Definition component.h:144
const ComponentContainer::const_iterator end() const noexcept
Definition component.h:278
void update(const double delta, const int8_t flags=0) const
Update all components.
Definition component.h:243
void remove(const std::string &name)
Remove a component.
Definition component.h:214
const T * getComponentByName(const std::string &name) const noexcept
Fetch a component when you know its name (const version)
Definition component.h:157
T * getComponentByName(const std::string &name) noexcept
Fetch a component when you know its name.
Definition component.h:171
std::shared_ptr< T > addNamed(const std::string &name, Args &&...args)
Add a new a component.
Definition component.h:118
const T * getComponentByType() const noexcept
Fetch a component by its type (const version)
Definition component.h:185
const ComponentContainer::const_iterator cbegin() const noexcept
Definition component.h:286
const ComponentContainer::const_iterator begin() const noexcept
Definition component.h:270
T * getComponentByType() noexcept
Fetch a component by its type.
Definition component.h:200
Scene component that can be attached to an entity.
Definition component.h:43
bool is_active
Toggle to check if the Component is active, actual meaning heavily depends of the component type.
Definition component.h:66
virtual void onUpdate(const double, const int8_t=0)
Run actions on entity update.
Definition component.h:56
Component bound to a specific entity.
Definition component.h:80
Util class to add components handling to an entity.
Definition component.h:311
void removeComponent(const std::string &name)
Remove a component.
Definition component.h:355
T * getComponentByType() noexcept
Fetch a component by its type.
Definition component.h:373
const ComponentList< Entity, ComponentType > & getComponents() const noexcept
Get components bound to the entity.
Definition component.h:329
T * getComponentByName(const std::string &name) noexcept
Fetch a component when you know its name.
Definition component.h:382
ComponentList< Entity, ComponentType > & getComponents() noexcept
Get components bound to the entity.
Definition component.h:321
std::shared_ptr< T > addComponent(Args &&... args)
Add a new a component.
Definition component.h:338
std::shared_ptr< T > addNamedComponent(const std::string &name, Args &&... args)
Add a new a component.
Definition component.h:347
const T * getComponentByType() const noexcept
Fetch a component by its type.
Definition component.h:364
const T * getComponentByName(const std::string &name) const noexcept
Fetch a component when you know its name.
Definition component.h:391
Scene / node components (camera, lighting, ...)
Definition pipeline.h:9