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