Loading...
Searching...
No Matches
Scene.cpp
Go to the documentation of this file.
1#include "Scene.h"
2
3#include <utility>
4
5#include "../graphics/Skybox.h"
6#include "hellfire/ecs/CameraComponent.h"
7
8namespace hellfire {
9 Scene::Scene(std::string name) : name_(std::move(name)), is_playing_(false) {
10 environment_ = std::make_unique<SceneEnvironment>();
11
12 auto *skybox = new Skybox();
13 // skybox->set_cubemap_faces({
14 // "assets/skyboxes/px.png", // +X
15 // "assets/skyboxes/nx.png", // -X
16 // "assets/skyboxes/py.png", // +Y
17 // "assets/skyboxes/ny.png", // -Y
18 // "assets/skyboxes/pz.png", // +Z
19 // "assets/skyboxes/nz.png" // -Z
20 // });
21
23 "assets/skyboxes/space_right.png",
24 "assets/skyboxes/space_left.png",
25 "assets/skyboxes/space_top.png",
26 "assets/skyboxes/space_bottom.png",
27 "assets/skyboxes/space_front.png",
28 "assets/skyboxes/space_back.png"
29 });
30
31 environment_->set_skybox(*skybox);
32 }
33
35 entities_.clear();
36 }
37
38 EntityID Scene::create_entity(const std::string &name) {
39 std::string unique_name = generate_unique_name(name);
40
41 EntityID id = next_id_++;
42 auto entity = std::make_unique<Entity>(id, unique_name);
43
44 entity->add_component<TransformComponent>();
45
46 entities_[id] = std::move(entity);
47 root_entities_.push_back(id);
48
49 // Initialize scripts
50 entities_[id]->initialize_scripts();
51
52 return id;
53 }
54
55 void Scene::destroy_entity(EntityID id) {
56 const auto it = entities_.find(id);
57 if (it == entities_.end()) return;
58
59 // Cleanup scripts first
60 it->second->cleanup_scripts();
61
62 if (id == default_camera_entity_id_) {
64 }
65
66 // Recursively destroy children
67 const std::vector<EntityID> children = get_children(id);
68 for (const EntityID child_id: children) {
69 destroy_entity(child_id);
70 }
71
72 // Remove from parent's children list
73 if (const auto parent_it = parent_map_.find(id); parent_it != parent_map_.end()) {
74 const EntityID parent_id = parent_it->second;
75 auto &siblings = children_map_[parent_id];
76 std::erase(siblings, id);
77 parent_map_.erase(parent_it);
78 } else {
79 // Remove from roots
80 std::erase(root_entities_, id);
81 }
82
83 // Remove children mapping
84 children_map_.erase(id);
85
86 // Delete the entity
87 entities_.erase(it);
88 }
89
90 Entity *Scene::get_entity(EntityID id) {
91 const auto it = entities_.find(id);
92 return it != entities_.end() ? it->second.get() : nullptr;
93 }
94
95 const Entity *Scene::get_entity(EntityID id) const {
96 const auto it = entities_.find(id);
97 return it != entities_.end() ? it->second.get() : nullptr;
98 }
99
100 bool Scene::is_descendant(EntityID potential_descendant, EntityID potential_ancestor) {
101 if (potential_descendant == potential_ancestor) return true;
102
103 // Check all children recursively
104 const auto it = children_map_.find(potential_ancestor);
105 if (it == children_map_.end()) return false;
106
107 for (const EntityID child: it->second) {
108 if (is_descendant(potential_descendant, child)) return true;
109 }
110
111 return false;
112 }
113
114 void Scene::set_parent(EntityID child_id, EntityID parent_id) {
115 if (entities_.find(child_id) == entities_.end()) return;
116 if (parent_id != 0 && entities_.find(parent_id) == entities_.end()) return;
117
118 // Prevent cycles: children cannot become parent of its own ancestor
119 if (parent_id != 0 && is_descendant(parent_id, child_id)) return;
120
121 // Remove from current parent
122 if (auto it = parent_map_.find(child_id); it != parent_map_.end()) {
123 EntityID old_parent = it->second;
124 auto &siblings = children_map_[old_parent];
125 siblings.erase(std::remove(siblings.begin(), siblings.end(), child_id), siblings.end());
126 } else {
127 // Was a root entity
128 root_entities_.erase(std::remove(root_entities_.begin(), root_entities_.end(), child_id),
129 root_entities_.end());
130 }
131
132 // Set new parent
133 if (parent_id != 0) {
134 parent_map_[child_id] = parent_id;
135 children_map_[parent_id].push_back(child_id);
136 } else {
137 // Moving to root
138 parent_map_.erase(child_id);
139 root_entities_.push_back(child_id);
140 }
141 }
142
143 void Scene::set_as_root(EntityID entity_id) {
144 set_parent(entity_id, 0);
145 }
146
147 EntityID Scene::get_parent(EntityID entity_id) const {
148 const auto it = parent_map_.find(entity_id);
149 return it != parent_map_.end() ? it->second : 0;
150 }
151
152 bool Scene::has_parent(EntityID entity_id) const {
153 const auto it = parent_map_.find(entity_id);
154 return it != parent_map_.end();
155 }
156
157 std::vector<EntityID> Scene::get_children(EntityID parent_id) const {
158 const auto it = children_map_.find(parent_id);
159 return it != children_map_.end() ? it->second : std::vector<EntityID>{};
160 }
161
163 for (const EntityID root_id: root_entities_) {
164 if (const Entity *entity = get_entity(root_id)) {
165 entity->initialize_scripts();
166 }
167 }
168 }
169
170 void Scene::update(float delta_time) {
171 for (const EntityID root_id: root_entities_) {
172 update_hierarchy(root_id, delta_time);
173 }
175 }
176
178 for (const EntityID root_id: root_entities_) {
179 update_world_matrices_recursive(root_id, glm::mat4(1.0f));
180 }
181 }
182
183 Entity *Scene::find_entity_by_name(const std::string &name) {
184 for (const auto &[id, entity]: entities_) {
185 if (entity->get_name() == name)
186 return entity.get();
187 }
188 return nullptr;
189 }
190
191 void Scene::set_default_camera(const EntityID camera_id) {
192 Entity *entity = get_entity(camera_id);
193 if (entity && entity->has_component<CameraComponent>()) {
194 default_camera_entity_id_ = camera_id;
195 }
196 }
197
199 if (default_camera_entity_id_ == 0) return nullptr;
200 const Entity *entity = const_cast<Scene *>(this)->get_entity(default_camera_entity_id_);
201 return entity ? entity->get_component<CameraComponent>() : nullptr;
202 }
203
205 std::vector<EntityID> cameras;
206 for (const auto &[id, entity]: entities_) {
207 if (entity->has_component<CameraComponent>()) {
208 cameras.push_back(id);
209 }
210 }
211 return cameras;
212 }
213
214
215 std::string Scene::generate_unique_name(const std::string &base_name) {
216 // Check if base name exists
217 bool name_exists = false;
218 for (const auto &[id, entity]: entities_) {
219 if (entity->get_name() == base_name) {
220 name_exists = true;
221 break;
222 }
223 }
224
225 // If base name is unique, use it
226 if (!name_exists) {
227 name_counters_[base_name] = 0;
228 return base_name;
229 }
230
231 // Otherwise, find next available number
232 int &counter = name_counters_[base_name];
233 std::string unique_name;
234
235 do {
236 counter++;
237 unique_name = base_name + " (" + std::to_string(counter) + ")";
238
239 // Check if this numbered name exists
240 name_exists = false;
241 for (const auto &entity: entities_ | std::views::values) {
242 if (entity->get_name() == unique_name) {
243 name_exists = true;
244 break;
245 }
246 }
247 } while (name_exists);
248
249 return unique_name;
250 }
251
252 void Scene::save() {
253 }
254
255 void Scene::update_hierarchy(EntityID entity_id, float delta_time) {
256 Entity *entity = get_entity(entity_id);
257 if (!entity) return;
258
259 if (is_playing_) {
260 entity->update_scripts(delta_time);
261 }
262
263 for (EntityID child_id: get_children(entity_id)) {
264 update_hierarchy(child_id, delta_time);
265 }
266 }
267
268 void Scene::update_world_matrices_recursive(EntityID entity_id, const glm::mat4 &parent_world) {
269 Entity *entity = get_entity(entity_id);
270 if (!entity) return;
271
272 TransformComponent *transform = entity->get_component<TransformComponent>();
273 if (!transform) {
274 std::cerr << "CRITICAL: Entity '" << entity->get_name()
275 << "' (ID: " << entity_id << ") missing TransformComponent!\n";
276 assert(false);
277 return;
278 }
279
281 transform->update_world_matrix(parent_world);
282
283 // Recurse into children with this entity's world matrix
284 const glm::mat4 &this_world = transform->get_world_matrix();
285 for (EntityID child_id: get_children(entity_id)) {
286 update_world_matrices_recursive(child_id, this_world);
287 }
288 }
289
290 void Scene::find_entities_recursive(EntityID entity_id, const std::function<bool(Entity *)> &predicate,
291 std::vector<EntityID> &results) {
292 Entity *entity = get_entity(entity_id);
293 if (!entity) return;
294
295 if (predicate(entity)) {
296 results.push_back(entity_id);
297 }
298
299 for (EntityID child_id: get_children(entity_id)) {
300 find_entities_recursive(child_id, predicate, results);
301 }
302 }
303}
const std::string & get_name() const
Definition Entity.h:46
void update_scripts(float delta_time) const
Definition Entity.cpp:22
Manages a collection of entities and their hierarchical relationships.
Definition Scene.h:24
Entity * find_entity_by_name(const std::string &name)
Finds an entity by its name.
Definition Scene.cpp:183
Scene(std::string name="Unnamed")
Constructs a new Scene with an optional name.
Definition Scene.cpp:9
const Entity * get_entity(EntityID id) const
Retrieves an entity by its ID (const version)
Definition Scene.cpp:95
virtual void initialize()
Initializes the scene Called once when the scene is first loaded or created.
Definition Scene.cpp:162
void set_as_root(EntityID entity_id)
Makes an entity a root entity (removes parent)
Definition Scene.cpp:143
std::string name_
Definition Scene.h:197
virtual void update(float delta_time)
Updates all entities in the scene.
Definition Scene.cpp:170
EntityID get_parent(EntityID entity_id) const
Gets the parent ID of an entity.
Definition Scene.cpp:147
bool is_playing_
Definition Scene.h:198
bool has_parent(EntityID entity_id) const
Checks if an entity has a parent.
Definition Scene.cpp:152
EntityID default_camera_entity_id_
Definition Scene.h:196
CameraComponent * get_default_camera() const
Definition Scene.cpp:198
void set_parent(EntityID child_id, EntityID parent_id)
Sets the parent of an entity.
Definition Scene.cpp:114
void update_world_matrices()
Updates world transformation matrices for all entities Propagates transformations through the entity ...
Definition Scene.cpp:177
virtual ~Scene()
Destructor.
Definition Scene.cpp:34
EntityID next_id_
Definition Scene.h:195
std::string generate_unique_name(const std::string &base_name)
Definition Scene.cpp:215
Entity * get_entity(EntityID id)
Retrieves an entity by its ID.
Definition Scene.cpp:90
void destroy_entity(EntityID id)
Destroys an entity and removes it from the scene.
Definition Scene.cpp:55
std::vector< EntityID > get_children(EntityID parent_id) const
Gets all children of a parent entity.
Definition Scene.cpp:157
std::vector< EntityID > get_camera_entities() const
Definition Scene.cpp:204
void find_entities_recursive(EntityID entity_id, const std::function< bool(Entity *)> &predicate, std::vector< EntityID > &results)
Definition Scene.cpp:290
bool is_descendant(EntityID potential_descendant, EntityID potential_ancestor)
Checks if one entity is a descendant of another.
Definition Scene.cpp:100
void update_world_matrices_recursive(unsigned int entity_id, const glm::mat4 &parent_world)
Definition Scene.cpp:268
void update_hierarchy(EntityID entity_id, float delta_time)
Definition Scene.cpp:255
EntityID create_entity(const std::string &name="GameObject")
Creates a new entity in the scene.
Definition Scene.cpp:38
void set_cubemap_faces(const std::array< std::string, 6 > &faces)
Definition Skybox.cpp:16
Skybox()=default