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