./
Coverage:
low: ≥ 0%
medium: ≥ 75.0%
high: ≥ 90.0%
Lines:
0 / 49
0.0%
Branches:
0 / 38
0.0%
Functions:
0 / 17
0.0%

apps/runner/src/eu/runner/entity.h
Line Branch Exec Source
1 #pragma once
2 #include <algorithm>
3 #include <set>
4
5 namespace eu::imgui
6 {
7 struct PropTable;
8 }
9
10 namespace eu::runner
11 {
12 struct Entity;
13 struct Component;
14 struct SpatialComponent;
15 struct EntitySystem;
16 struct World;
17
18 enum class UpdateStage
19 {
20 start_frame,
21 before_physics,
22 physics,
23 after_physics,
24 before_render,
25 end_frame
26 };
27 constexpr unsigned int update_stage_count = static_cast<unsigned int>(UpdateStage::end_frame) + 1;
28
29 struct UpdateStageAndPrio
30 {
31 UpdateStage stage;
32 int prio;
33 };
34
35 template<typename TSystem>
36 struct SystemWithPrio
37 {
38 TSystem* system;
39 int prio;
40 };
41
42 ✗ constexpr std::size_t cast(UpdateStage s)
43 {
44 ✗ return static_cast<std::size_t>(s);
45 }
46
47 template<typename TSystem>
48 struct UpdateHandler
49 {
50 std::array<std::vector<SystemWithPrio<TSystem>>, update_stage_count> stages;
51
52 ✗ void add(TSystem* system)
53 {
54
0/4
eu::runner::UpdateHandler<eu::runner::WorldSystem>::add(eu::runner::WorldSystem*):
✗ Branch 2 → 3 not taken.
✗ Branch 2 → 10 not taken.
eu::runner::UpdateHandler<eu::runner::EntitySystem>::add(eu::runner::EntitySystem*):
✗ Branch 2 → 3 not taken.
✗ Branch 2 → 10 not taken.
✗ const UpdateStageAndPrio s = system->get_stage();
55
56 ✗ auto& systems = stages[cast(s.stage)];
57
58
0/4
eu::runner::UpdateHandler<eu::runner::WorldSystem>::add(eu::runner::WorldSystem*):
✗ Branch 5 → 6 not taken.
✗ Branch 5 → 10 not taken.
eu::runner::UpdateHandler<eu::runner::EntitySystem>::add(eu::runner::EntitySystem*):
✗ Branch 5 → 6 not taken.
✗ Branch 5 → 10 not taken.
✗ systems.emplace_back(system, s.prio);
59
0/4
eu::runner::UpdateHandler<eu::runner::WorldSystem>::add(eu::runner::WorldSystem*):
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 10 not taken.
eu::runner::UpdateHandler<eu::runner::EntitySystem>::add(eu::runner::EntitySystem*):
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 10 not taken.
✗ std::sort(systems.begin(), systems.end(), [](const auto& lhs, const auto& rhs)
60 {
61 ✗ return lhs.prio < rhs.prio;
62 });
63 ✗ }
64
65 ✗ void update(UpdateStage stage, float dt)
66 {
67 ✗ auto& systems = stages[cast(stage)];
68
0/4
eu::runner::UpdateHandler<eu::runner::WorldSystem>::update(eu::runner::UpdateStage, float):
✗ Branch 18 → 6 not taken.
✗ Branch 18 → 19 not taken.
eu::runner::UpdateHandler<eu::runner::EntitySystem>::update(eu::runner::UpdateStage, float):
✗ Branch 18 → 6 not taken.
✗ Branch 18 → 19 not taken.
✗ for (auto& sys : systems)
69 {
70
0/4
eu::runner::UpdateHandler<eu::runner::WorldSystem>::update(eu::runner::UpdateStage, float):
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 20 not taken.
eu::runner::UpdateHandler<eu::runner::EntitySystem>::update(eu::runner::UpdateStage, float):
✗ Branch 8 → 9 not taken.
✗ Branch 8 → 20 not taken.
✗ sys.system->update(dt);
71 }
72 ✗ }
73 };
74
75 struct Entity
76 {
77 Entity(const std::string& n, std::set<Hsh>&& t);
78 ✗ ~Entity() = default;
79
80 Entity(const Entity&) = delete;
81 Entity(Entity&&) = delete;
82 void operator=(const Entity&) = delete;
83 void operator=(Entity&&) = delete;
84
85 const std::string name;
86
87 // todo(Gustav): split HshSt into 2, one with a primary hash and one without
88 World* world = nullptr;
89 std::vector<std::unique_ptr<Component>> components;
90 std::vector<std::unique_ptr<EntitySystem>> systems;
91 UpdateHandler<EntitySystem> updates;
92
93 void add_component(std::unique_ptr<Component> c);
94 void add_system(std::unique_ptr<EntitySystem> system);
95 [[nodiscard]] bool has_tag(const Hsh& h) const;
96
97 [[nodiscard]] SpatialComponent* get_root() const;
98 void set_root(SpatialComponent* c);
99
100 void imgui();
101
102 private:
103 SpatialComponent* root = nullptr;
104 std::set<Hsh> tags;
105 };
106
107 struct Component
108 {
109 ✗ Component() = default;
110 ✗ virtual ~Component() = default;
111
112 Component(const Component& rhs) = delete;
113 Component(Component&&) = delete;
114 void operator=(const Component& rhs) = delete;
115 void operator=(Component&&) = delete;
116
117 static const HshSt& type();
118 virtual const HshSt& get_type();
119
120 virtual const char* display() = 0;
121 virtual void imgui(const imgui::PropTable& table) = 0;
122 };
123 #define EU_DEC_COMPONENT_TYPE() static const HshSt& type(); const HshSt& get_type() override
124 #define EU_IMP_COMPONENT_TYPE(COMP, PAREN) \
125 const eu::HshSt& COMP::type() { const static auto s = PAREN::type().combine(Hsh{#COMP}); return s; }\
126 const eu::HshSt& COMP::get_type() { return type(); }
127
128 template<typename T>
129 concept ComponentLike = std::is_base_of_v<Component, T> && requires
130 {
131 { T::type() } -> std::same_as<const HshSt&>;
132 };
133
134 ✗ template<ComponentLike TComp> TComp* component_cast(Component* c)
135 {
136
0/18
TargetComponent* eu::runner::component_cast<TargetComponent>(eu::runner::Component*):
✗ Branch 2 → 3 not taken.
✗ Branch 2 → 8 not taken.
✗ Branch 6 → 7 not taken.
✗ Branch 6 → 8 not taken.
✗ Branch 9 → 10 not taken.
✗ Branch 9 → 11 not taken.
MeshSpatialComponent* eu::runner::component_cast<MeshSpatialComponent>(eu::runner::Component*):
✗ Branch 2 → 3 not taken.
✗ Branch 2 → 8 not taken.
✗ Branch 6 → 7 not taken.
✗ Branch 6 → 8 not taken.
✗ Branch 9 → 10 not taken.
✗ Branch 9 → 11 not taken.
CameraSpatialComponent* eu::runner::component_cast<CameraSpatialComponent>(eu::runner::Component*):
✗ Branch 2 → 3 not taken.
✗ Branch 2 → 8 not taken.
✗ Branch 6 → 7 not taken.
✗ Branch 6 → 8 not taken.
✗ Branch 9 → 10 not taken.
✗ Branch 9 → 11 not taken.
✗ if (c && c->get_type().is(TComp::type()))
137 {
138 ✗ return static_cast<TComp*>(c);
139 }
140 else
141 {
142 ✗ return nullptr;
143 }
144 }
145
146 struct SpatialComponent : Component
147 {
148 void set_transform(const m4& t);
149 [[nodiscard]] const m4& get_transform() const;
150
151 EU_DEC_COMPONENT_TYPE();
152
153 void imgui(const imgui::PropTable& table) override;
154 private:
155 m4 transform = m4_identity;
156 // todo(gustav): add hierarchy
157 };
158
159 // essentially a named update
160 struct EntitySystem
161 {
162 ✗ EntitySystem() = default;
163 ✗ virtual ~EntitySystem() = default;
164
165 EntitySystem(const EntitySystem& rhs) = delete;
166 EntitySystem(EntitySystem&&) = delete;
167 void operator=(const EntitySystem& rhs) = delete;
168 void operator=(EntitySystem&&) = delete;
169
170 virtual UpdateStageAndPrio get_stage() = 0;
171
172 virtual void add_component(Component* component) = 0;
173 virtual void on_root_changed(SpatialComponent* root) = 0;
174
175 virtual void update(float dt) = 0;
176
177 virtual const char* display() = 0;
178 virtual void imgui(const imgui::PropTable& table) = 0;
179 };
180
181 struct WorldSystem
182 {
183 ✗ WorldSystem() = default;
184 ✗ virtual ~WorldSystem() = default;
185
186 WorldSystem(const WorldSystem& rhs) = delete;
187 WorldSystem(WorldSystem&&) = delete;
188 void operator=(const WorldSystem& rhs) = delete;
189 void operator=(WorldSystem&&) = delete;
190
191 virtual UpdateStageAndPrio get_stage() = 0;
192
193 virtual void add_component(Entity* entity, Component* component) = 0;
194 virtual void on_root_changed(Entity* entity, SpatialComponent* component) = 0;
195
196 virtual const char* display() = 0;
197 virtual void update(float dt) = 0;
198 virtual void imgui(const imgui::PropTable& table) = 0;
199 };
200
201 struct World
202 {
203 std::vector<std::unique_ptr<Entity>> entities;
204 std::vector<std::unique_ptr<WorldSystem>> systems;
205 UpdateHandler<WorldSystem> updates;
206
207 Entity* add_entity(const std::string& name, std::set<Hsh>&& tags);
208
209 void add_system(std::unique_ptr<WorldSystem> sys);
210 void on_add_component(Entity* entity, Component* component);
211 void on_root_changed(Entity* entity, SpatialComponent* component);
212
213 void update(UpdateStage stage, float dt);
214 void gui();
215 };
216
217 }
218
219
220 /**
221 * @}
222 */
223