Sparkle 0.0.1
Loading...
Searching...
No Matches
spk_entity.hpp
1#pragma once
2
3#include "structure/design_pattern/spk_activable_object.hpp"
4#include "structure/design_pattern/spk_inherence_object.hpp"
5
6#include "structure/system/event/spk_keyboard_event.hpp"
7#include "structure/system/event/spk_mouse_event.hpp"
8#include "structure/system/event/spk_paint_event.hpp"
9#include "structure/system/event/spk_system_event.hpp"
10#include "structure/system/event/spk_update_event.hpp"
11
12#include <atomic>
13#include <mutex>
14#include <set>
15#include <span>
16#include <string>
17#include <type_traits>
18#include <vector>
19
20#include "structure/design_pattern/spk_contract_provider.hpp"
21#include "structure/engine/spk_component.hpp"
22
23#include "type/spk_binary_operator.hpp"
24
25namespace spk
26{
27 class GameEngine;
28
33 class Entity : public spk::InherenceObject<Entity>, public spk::ActivableObject
34 {
35 public:
40
41 private:
42 std::wstring _name;
43 std::set<std::wstring> _tags;
44
45 std::atomic<int> _priority = 0;
46
47 mutable std::recursive_mutex _componentMutex;
48 mutable std::recursive_mutex _childMutex;
49
50 std::vector<std::unique_ptr<Component>> _components;
51 GameEngine *_engine = nullptr;
52
53 template <typename T>
54 void _sortByPriority(std::vector<T> &p_container, std::recursive_mutex &p_mutex)
55 {
56 std::unique_lock<std::recursive_mutex> mutexLock(p_mutex);
57
58 std::sort(
59 p_container.begin(),
60 p_container.end(),
61 [](const T &p_a, const T &p_b) {
62 int priorityA = p_a->priority();
63 int priorityB = p_b->priority();
64
65 bool aNoPriority = (priorityA < 0);
66 bool bNoPriority = (priorityB < 0);
67
68 if (aNoPriority && bNoPriority)
69 {
70 return (false);
71 }
72
73 if (aNoPriority != bNoPriority)
74 {
75 return (!aNoPriority);
76 }
77
78 return (priorityA > priorityB);
79 });
80 }
81
82 template <typename TCallback>
83 void _forEachChild(TCallback &&p_callback)
84 {
85 std::vector<Entity *> childSnapshot;
86
87 {
88 std::lock_guard<std::recursive_mutex> lock(_childMutex);
89 childSnapshot.assign(children().begin(), children().end());
90 }
91
92 for (auto child : childSnapshot)
93 {
94 if (child != nullptr)
95 {
96 if constexpr (std::is_same_v<std::invoke_result_t<TCallback, Entity *>, bool>)
97 {
98 if (p_callback(child) == false)
99 {
100 break;
101 }
102 }
103 else
104 {
105 p_callback(child);
106 }
107 }
108 }
109 }
110
111 template <typename TCallback>
112 void _forEachComponent(TCallback &&p_callback)
113 {
114 std::vector<spk::Component *> componentSnapshot;
115
116 {
117 std::lock_guard<std::recursive_mutex> lock(_componentMutex);
118 componentSnapshot.reserve(_components.size());
119 for (const auto &component : _components)
120 {
121 if (component != nullptr)
122 {
123 componentSnapshot.emplace_back(component.get());
124 }
125 }
126 }
127
128 for (auto component : componentSnapshot)
129 {
130 if (component != nullptr)
131 {
132 if constexpr (std::is_same_v<std::invoke_result_t<TCallback, spk::Component *>, bool>)
133 {
134 if (p_callback(component) == false)
135 {
136 break;
137 }
138 }
139 else
140 {
141 p_callback(component);
142 }
143 }
144 }
145 }
146
147 public:
153 Entity(const std::wstring &p_name, Entity *p_owner = nullptr);
154
156 Entity();
157
158 Entity(const Entity &) = delete;
159 Entity &operator=(const Entity &) = delete;
160
161 ~Entity() override;
162
167 virtual void setName(const std::wstring &p_name);
172 void setPriority(const int &p_priority);
173
178 void addTag(const std::wstring &p_tag);
183 void removeTag(const std::wstring &p_tag);
185 void clearTags();
191 bool containTag(const std::wstring &p_tag) const;
192
197 void setEngine(GameEngine *p_engine);
202 GameEngine *engine();
207 const GameEngine *engine() const;
208
213 const std::wstring &name() const;
218 const std::set<std::wstring> &tags() const;
223 int priority() const;
228 size_t componentCount() const;
229
231 void removeAllComponents();
232
237 void addChild(Entity *p_child) override;
242 void removeChild(Entity *p_child) override;
244 void clearChildren();
249 std::vector<Entity *> &children() override;
254 const std::vector<Entity *> &children() const override;
255
263 template <typename TComponentType, typename... TArgs>
264 TComponentType &addComponent(TArgs &&...p_args)
265 {
266 static_assert(std::is_base_of_v<Component, TComponentType>, "TComponentType must inherit from Component");
267 std::unique_ptr<TComponentType> newUniquePtr = std::make_unique<TComponentType>(std::forward<TArgs>(p_args)...);
268 TComponentType *newComponent = newUniquePtr.get();
269
270 {
271 std::unique_lock<std::recursive_mutex> lock(_componentMutex);
272
273 _components.emplace_back(std::move(newUniquePtr));
274 }
275
276 newComponent->_setOwner(this);
277
278 newComponent->start();
279 newComponent->activate();
281
282 return (*newComponent);
283 }
284
289 void removeComponent(const std::wstring &p_name);
290
297 template <typename TComponentType>
298 TComponentType *getComponent(const std::wstring &p_name = L"")
299 {
300 std::unique_lock<std::recursive_mutex> lock(_componentMutex);
301
302 for (std::unique_ptr<Component> &component : _components)
303 {
304 TComponentType *castedComponent = dynamic_cast<TComponentType *>(component.get());
305 if (castedComponent != nullptr)
306 {
307 if (p_name.empty() || castedComponent->name() == p_name)
308 {
309 return (castedComponent);
310 }
311 }
312 }
313
314 return (nullptr);
315 }
316
322 template <typename TComponentType>
323 std::vector<TComponentType *> getComponents()
324 {
325 std::unique_lock<std::recursive_mutex> lock(_componentMutex);
326 std::vector<TComponentType *> result;
327
328 for (std::unique_ptr<Component> &component : _components)
329 {
330 TComponentType *castedComponent = dynamic_cast<TComponentType *>(component.get());
331 if (castedComponent != nullptr)
332 {
333 result.emplace_back(castedComponent);
334 }
335 }
336
337 return (result);
338 }
339
346 template <typename TComponentType>
347 const TComponentType *getComponent(const std::wstring &p_name = L"") const
348 {
349 std::unique_lock<std::recursive_mutex> lock(_componentMutex);
350 for (const std::unique_ptr<Component> &component : _components)
351 {
352 TComponentType *castedComponent = dynamic_cast<TComponentType *>(component.get());
353 if (castedComponent != nullptr)
354 {
355 if (p_name.empty() || castedComponent->name() == p_name)
356 {
357 return (castedComponent);
358 }
359 }
360 }
361
362 return (nullptr);
363 }
364
370 template <typename TComponentType>
371 std::vector<const TComponentType *> getComponents() const
372 {
373 std::unique_lock<std::recursive_mutex> lock(_componentMutex);
374 std::vector<const TComponentType *> result;
375
376 for (const std::unique_ptr<Component> &component : _components)
377 {
378 const TComponentType *castedComponent = dynamic_cast<const TComponentType *>(component.get());
379 if (castedComponent != nullptr)
380 {
381 result.emplace_back(castedComponent);
382 }
383 }
384
385 return (result);
386 }
387
392 virtual void handleGeometryChange(const spk::Extend2D &p_geometry) final;
397 virtual void handlePaintEvent(spk::PaintEvent &p_event) final;
402 virtual void handleKeyPressEvent(spk::KeyPressEvent &p_event) final;
407 virtual void handleKeyReleaseEvent(spk::KeyReleaseEvent &p_event) final;
412 virtual void handleGlyphEvent(spk::GlyphEvent &p_event) final;
417 virtual void handleMousePressEvent(spk::MousePressEvent &p_event) final;
422 virtual void handleMouseReleaseEvent(spk::MouseReleaseEvent &p_event) final;
427 virtual void handleMouseDoubleClickEvent(spk::MouseDoubleClickEvent &p_event) final;
432 virtual void handleMouseMotionEvent(spk::MouseMotionEvent &p_event) final;
437 virtual void handleMouseWheelEvent(spk::MouseWheelEvent &p_event) final;
442 virtual void handleEnterResizeModeEvent(spk::EnterResizeModeEvent &p_event) final;
447 virtual void handleResizeEvent(spk::ResizeEvent &p_event) final;
452 virtual void handleExitResizeModeEvent(spk::ExitResizeModeEvent &p_event) final;
457 virtual void handleQuitEvent(spk::QuitEvent &p_event) final;
462 virtual void handleMoveEvent(spk::MoveEvent &p_event) final;
467 virtual void handleFullScreenModeEvent(spk::FullScreenModeEvent &p_event) final;
472 virtual void handleMaximizedModeEvent(spk::MaximizedModeEvent &p_event) final;
477 virtual void handleFocusEvent(spk::FocusEvent &p_event) final;
482 virtual void handleUpdateEvent(spk::UpdateEvent &p_event) final;
483
485 void sortChildren();
487 void sortComponent();
488
494 Entity *getChild(const std::wstring &p_name);
500 const Entity *getChild(const std::wstring &p_name) const;
506 std::vector<Entity *> getChildren(const std::wstring &p_name);
512 std::vector<const Entity *> getChildren(const std::wstring &p_name) const;
518 bool contains(const std::wstring &p_name) const;
524 size_t count(const std::wstring &p_name) const;
525
531 Entity *getChildByTag(const std::wstring &p_tag);
537 const Entity *getChildByTag(const std::wstring &p_tag) const;
543 std::vector<Entity *> getChildrenByTag(const std::wstring &p_tag);
549 std::vector<const Entity *> getChildrenByTag(const std::wstring &p_tag) const;
555 bool containsTag(const std::wstring &p_tag) const;
561 size_t countTag(const std::wstring &p_tag) const;
562
569 Entity *getChildByTags(
570 const std::span<const std::wstring> &p_tags, spk::BinaryOperator p_binaryOperator = spk::BinaryOperator::And);
577 const Entity *getChildByTags(
578 const std::span<const std::wstring> &p_tags, spk::BinaryOperator p_binaryOperator = spk::BinaryOperator::And) const;
585 std::vector<Entity *> getChildrenByTags(
586 const std::span<const std::wstring> &p_tags, spk::BinaryOperator p_binaryOperator = spk::BinaryOperator::And);
593 std::vector<const Entity *> getChildrenByTags(
594 const std::span<const std::wstring> &p_tags, spk::BinaryOperator p_binaryOperator = spk::BinaryOperator::And) const;
601 bool containsTags(const std::span<const std::wstring> &p_tags, spk::BinaryOperator p_binaryOperator = spk::BinaryOperator::And) const;
608 size_t countTags(const std::span<const std::wstring> &p_tags, spk::BinaryOperator p_binaryOperator = spk::BinaryOperator::And) const;
609 };
610}
Stateful helper toggling between activated/deactivated states.
Definition spk_activable_object.hpp:20
StatefulObject< ActivationStatus >::Contract Contract
Subscription handle controlling callback lifetime.
Definition spk_activable_object.hpp:23
StatefulObject< ActivationStatus >::Job Job
Callback signature executed on activation state changes.
Definition spk_activable_object.hpp:25
Hierarchical game object containing components and children.
Definition spk_entity.hpp:34
const TComponentType * getComponent(const std::wstring &p_name=L"") const
Returns the first component matching the type and optional name.
Definition spk_entity.hpp:347
TComponentType * getComponent(const std::wstring &p_name=L"")
Returns the first component matching the type and optional name.
Definition spk_entity.hpp:298
spk::ActivableObject::Job Job
Job callback type for activation callbacks.
Definition spk_entity.hpp:39
void sortComponent()
Sorts components by priority.
Definition spk_entity.cpp:708
std::vector< TComponentType * > getComponents()
Returns all components matching the type.
Definition spk_entity.hpp:323
TComponentType & addComponent(TArgs &&...p_args)
Creates and adds a component of the given type.
Definition spk_entity.hpp:264
std::vector< const TComponentType * > getComponents() const
Returns all components matching the type.
Definition spk_entity.hpp:371
spk::ActivableObject::Contract Contract
Contract type for activation callbacks.
Definition spk_entity.hpp:37
Entity(const std::wstring &p_name, Entity *p_owner=nullptr)
Creates an entity with a name and optional owner.
Definition spk_entity.cpp:5
Root container that manages entities and dispatches events.
Definition spk_game_engine.hpp:22
Provides parent/child ownership links for tree structures.
Definition spk_inherence_object.hpp:22
Signals the window enters resize mode.
Definition spk_system_event.hpp:16
Signals the window exits resize mode.
Definition spk_system_event.hpp:34
Axis-aligned rectangle defined by an anchor point and size.
Definition spk_extend_2d.hpp:24
Reports focus gain or loss.
Definition spk_system_event.hpp:80
Requests or reports fullscreen state.
Definition spk_system_event.hpp:60
Character input event.
Definition spk_keyboard_event.hpp:38
Keyboard key press event.
Definition spk_keyboard_event.hpp:14
Keyboard key release event.
Definition spk_keyboard_event.hpp:26
Requests or reports maximized state.
Definition spk_system_event.hpp:70
Mouse button double-click event.
Definition spk_mouse_event.hpp:38
Mouse move event carrying current position.
Definition spk_mouse_event.hpp:50
Mouse button press event.
Definition spk_mouse_event.hpp:14
Mouse button release event.
Definition spk_mouse_event.hpp:26
Mouse wheel scroll event.
Definition spk_mouse_event.hpp:62
Reports a window move event.
Definition spk_system_event.hpp:50
Event emitted when a drawable region needs repainting.
Definition spk_paint_event.hpp:19
Signals application quit.
Definition spk_system_event.hpp:42
Reports a window/client-area resize.
Definition spk_system_event.hpp:24
Carries per-frame update timing and input state snapshot.
Definition spk_update_event.hpp:15