Thanks to visit codestin.com
Credit goes to canreader.github.io

SleakEngine 1.0.0
C++23 multi-backend game engine
Loading...
Searching...
No Matches
SceneBase.cpp
Go to the documentation of this file.
2#include <Core/GameObject.hpp>
3#include <Core/Logger.hpp>
4#include <Camera/Camera.hpp>
6#include <Lighting/Light.hpp>
8#include <Runtime/Skybox.hpp>
13
14namespace Sleak {
15
16/// Walks obj and its children, registering any ColliderComponent found with world.
18 if (!obj || !world) return;
19 auto* collider = obj->GetComponent<ColliderComponent>();
20 if (collider) {
21 world->RegisterCollider(collider);
22 }
23 for (size_t i = 0; i < obj->GetChildren().GetSize(); ++i) {
25 }
26}
27
28/// Walks obj and its children, unregistering any ColliderComponent found from world.
30 if (!obj || !world) return;
31 auto* collider = obj->GetComponent<ColliderComponent>();
32 if (collider) {
33 world->UnregisterCollider(collider);
34 }
35 for (size_t i = 0; i < obj->GetChildren().GetSize(); ++i) {
37 }
38}
39
43 "Scene '{0}' destroyed without Unload(); "
44 "OnDeactivate/OnUnload did not run.",
45 name);
46 }
47
49 delete m_lightManager;
50 m_lightManager = nullptr;
51 delete m_physicsWorld;
52 m_physicsWorld = nullptr;
53 delete m_skybox;
54 m_skybox = nullptr;
55}
56
63
66
67 Deactivate();
68
70
71 OnUnload();
72
74
76 q->ClearAll();
77
78 bInitialized = false;
80}
81
83 if (state == SceneState::Active) return;
84
86
88 bActive = true;
89
90 OnActivate();
91
92 Begin();
93}
94
96 if (state != SceneState::Active) return;
98 bActive = false;
100}
101
103 if (state != SceneState::Active) return;
105 bActive = false;
106}
107
109 if (state != SceneState::Paused) return;
111 bActive = true;
112}
113
115 if (bInitialized) return true;
116
117 if (!m_lightManager) {
120 }
121
122 if (!m_physicsWorld) {
124
125 // Register colliders from objects added before PhysicsWorld existed
126 for (size_t i = 0; i < Objects.GetSize(); ++i) {
127 if (Objects[i]) {
129 }
130 }
131 }
132
133 if (m_skybox && !m_skybox->IsInitialized()) {
135 }
136
137 for (size_t i = 0; i < Objects.GetSize(); ++i) {
138 if (Objects[i]) Objects[i]->Initialize();
139 }
140
141 bInitialized = true;
142 return true;
143}
144
146 for (size_t i = 0; i < Objects.GetSize(); ++i) {
147 if (Objects[i]) Objects[i]->SetActive(true);
148 }
149}
150
151void SceneBase::Update(float deltaTime) {
152 if (!bActive) return;
153
154 // Update objects FIRST so Camera::View/Projection reflect this frame's
155 // rotation/position before any render-side UBO computes InvViewProj.
156 // Why: LightManager::UpdateDeferredCB reads the static Camera matrices
157 // to build InvViewProj for the deferred lighting pass. If it ran
158 // before the camera object updated, InvViewProj was one frame stale
159 // and the lighting pass reconstructed wrong world positions on any
160 // camera rotation, causing whole-terrain shadow flicker.
161 for (size_t i = 0; i < Objects.GetSize(); ++i) {
162 if (Objects[i] && Objects[i]->IsActive() && !Objects[i]->HasParent()) {
163 Objects[i]->Update(deltaTime);
164 }
165 }
166
167 if (m_lightManager)
169
170 if (m_skybox)
171 m_skybox->Render();
172
173 if (m_physicsWorld)
174 m_physicsWorld->Step(deltaTime);
175
177 auto drawColliderShape = [](ColliderComponent* collider, const Math::Vector3D& worldPos, const Math::Vector3D& worldScale) {
178 const auto& shape = collider->GetShape();
179
180 if (auto* aabb = std::get_if<Physics::AABB>(&shape)) {
181 Physics::AABB worldAABB(
182 aabb->min * worldScale + worldPos,
183 aabb->max * worldScale + worldPos);
184 DebugLineRenderer::DrawAABB(worldAABB, 0.0f, 1.0f, 0.0f);
185 } else if (auto* sphere = std::get_if<Physics::BoundingSphere>(&shape)) {
186 Math::Vector3D center = sphere->center * worldScale + worldPos;
187 float maxScale = std::max({worldScale.GetX(), worldScale.GetY(), worldScale.GetZ()});
188 DebugLineRenderer::DrawSphere(center, sphere->radius * maxScale, 0.0f, 1.0f, 0.0f);
189 } else if (auto* capsule = std::get_if<Physics::BoundingCapsule>(&shape)) {
190 Physics::BoundingCapsule worldCapsule = *capsule;
191 worldCapsule.center = capsule->center * worldScale + worldPos;
192 float maxScale = std::max({worldScale.GetX(), worldScale.GetY(), worldScale.GetZ()});
193 worldCapsule.radius = capsule->radius * maxScale;
194 worldCapsule.halfHeight = capsule->halfHeight * maxScale;
195 DebugLineRenderer::DrawCapsule(worldCapsule, 0.0f, 1.0f, 0.0f);
196 }
197 };
198
199 for (size_t i = 0; i < Objects.GetSize(); ++i) {
200 if (!Objects[i]) continue;
201 auto* collider = Objects[i]->GetComponent<ColliderComponent>();
202 if (!collider) continue;
203
204 Math::Vector3D pos(0, 0, 0), scale(1, 1, 1);
205 auto* transform = Objects[i]->GetComponent<TransformComponent>();
206 if (transform) {
207 pos = transform->GetWorldPosition() + collider->GetOffset();
208 scale = transform->GetWorldScale();
209 } else if (auto* cam = dynamic_cast<Camera*>(Objects[i])) {
210 pos = cam->GetPosition() + collider->GetOffset();
211 }
212 drawColliderShape(collider, pos, scale);
213 }
214
215 }
216
218
220}
221
222void SceneBase::FixedUpdate(float fixedDeltaTime) {
223 if (!bActive) return;
224
225 for (size_t i = 0; i < Objects.GetSize(); ++i) {
226 if (Objects[i] && Objects[i]->IsActive() && !Objects[i]->HasParent()) {
227 Objects[i]->FixedUpdate(fixedDeltaTime);
228 }
229 }
230}
231
232void SceneBase::LateUpdate(float deltaTime) {
233 if (!bActive) return;
234
235 for (size_t i = 0; i < Objects.GetSize(); ++i) {
236 if (Objects[i] && Objects[i]->IsActive() && !Objects[i]->HasParent()) {
237 Objects[i]->LateUpdate(deltaTime);
238 }
239 }
240}
241
243 if (!object) return;
244 if (Objects.indexOf(object) != -1) return; // already in scene
245
246 Objects.add(object);
247
248 if (m_lightManager && object->IsLight()) {
250 static_cast<Light*>(object));
251 }
252
253 if (m_physicsWorld) {
255 }
256
257 if (bInitialized && !object->IsActive()) {
258 object->Initialize();
259 if (bActive) object->SetActive(true);
260 }
261}
262
264 if (!object) return;
265 int index = Objects.indexOf(object);
266 if (index == -1) return;
267
268 if (m_lightManager && object->IsLight()) {
269 m_lightManager->UnregisterLight(static_cast<Light*>(object));
270 }
271 if (m_physicsWorld) {
273 }
274
275 int pending = m_pendingDestroy.indexOf(object);
276 if (pending != -1) {
277 m_pendingDestroy.erase(pending);
278 }
279
280 Objects.erase(index);
281 delete object;
282}
283
285 if (!object) return;
286 if (object->IsPendingDestroy()) return;
287
288 object->MarkForDestroy();
289 m_pendingDestroy.add(object);
290
291 const auto& children = object->GetChildren();
292 for (size_t i = 0; i < children.GetSize(); ++i) {
293 if (children[i] && !children[i]->IsPendingDestroy()) {
294 DestroyObject(children[i]);
295 }
296 }
297}
298
299GameObject* SceneBase::FindObjectByName(const std::string& objectName) {
300 for (size_t i = 0; i < Objects.GetSize(); ++i) {
301 if (Objects[i] && Objects[i]->GetName() == objectName) {
302 return Objects[i];
303 }
304 }
305 return nullptr;
306}
307
309 for (size_t i = 0; i < Objects.GetSize(); ++i) {
310 if (Objects[i] && Objects[i]->GetUniqueID() == id) {
311 return Objects[i];
312 }
313 }
314 return nullptr;
315}
316
318 List<GameObject*> result;
319 for (size_t i = 0; i < Objects.GetSize(); ++i) {
320 if (Objects[i] && Objects[i]->GetTag() == tag) {
321 result.add(Objects[i]);
322 }
323 }
324 return result;
325}
326
328 if (m_pendingDestroy.empty()) return;
329
330 for (size_t i = 0; i < m_pendingDestroy.GetSize(); ++i) {
332 if (!obj) continue;
333
334 if (m_lightManager && obj->IsLight()) {
336 static_cast<Light*>(obj));
337 }
338
339 if (m_physicsWorld) {
341 }
342
343 int index = Objects.indexOf(obj);
344 if (index != -1) {
345 Objects.erase(index);
346 }
347
348 delete obj;
349 }
350 m_pendingDestroy.clear();
351}
352
354 // Clear pending list first (those are also in Objects)
355 m_pendingDestroy.clear();
356
357 for (size_t i = 0; i < Objects.GetSize(); ++i) {
358 delete Objects[i];
359 }
360 Objects.clear();
361}
362
364 if (m_skybox) {
365 delete m_skybox;
366 }
367 m_skybox = skybox;
370 }
371}
372
373} // namespace Sleak
#define SLEAK_ERROR(...)
Definition Logger.hpp:22
const Physics::ColliderShape & GetShape() const
Math::Vector3D GetOffset() const
static void Flush(Camera *camera)
Uploads all queued lines and draws them in one pass, then clears the queue.
static void DrawSphere(const Math::Vector3D &center, float radius, float r, float g, float b, float a=1.0f, int segments=16)
Queues a wireframe sphere approximated with segments latitude/longitude rings.
static void DrawAABB(const Physics::AABB &aabb, float r, float g, float b, float a=1.0f)
Queues a wireframe box outline.
static void DrawCapsule(const Physics::BoundingCapsule &capsule, float r, float g, float b, float a=1.0f, int segments=16)
Queues a wireframe capsule outline.
const List< GameObject * > & GetChildren() const
void MarkForDestroy()
Flags the object for deferred destruction on the next scene pass.
bool IsActive() const
bool IsPendingDestroy() const
virtual bool IsLight() const
T * GetComponent()
Finds the first attached component of type T, or nullptr.
void RegisterLight(Light *light)
void Initialize()
Allocates the GPU light buffer; call once before the first UpdateAndBind.
void UpdateAndBind()
Packs every registered light and the fog/ambient parameters into the light buffer and binds it.
void UnregisterLight(Light *light)
Implements a dynamic array-like list for storing and managing a collection of elements.
Definition List.hpp:20
void add(const T &value)
Definition List.hpp:113
void RegisterCollider(ColliderComponent *collider)
void UnregisterCollider(ColliderComponent *collider)
static RenderCommandQueue * GetInstance()
Lazily creates and returns the process-wide singleton instance.
List< GameObject * > FindObjectsByTag(const std::string &tag)
Collects every object whose tag matches.
void Unload()
Deactivates if active, calls OnUnload(), and destroys all owned objects.
Definition SceneBase.cpp:64
void Deactivate()
Marks the scene inactive and calls OnDeactivate().
Definition SceneBase.cpp:95
List< GameObject * > Objects
virtual void Update(float deltaTime)=0
Advances all active, root-level objects by deltaTime, then steps lighting and physics.
virtual void FixedUpdate(float fixedDeltaTime)
Advances all active, root-level objects on the fixed timestep.
void Resume()
Reactivates a paused scene without re-running OnActivate().
void SetSkybox(Skybox *skybox)
Replaces the scene's skybox, deleting the previous one.
void ProcessPendingDestroy()
Actually deletes objects queued by DestroyObject().
GameObject * FindObjectByName(const std::string &name)
Linear search for the first object with a matching name.
virtual void OnLoad()
Override to load scene-specific assets; called once from Load().
Definition SceneBase.hpp:80
void DestroyObject(GameObject *object)
Queues an object for destruction; actually freed on the next ProcessPendingDestroy().
virtual void RemoveObject(GameObject *object)
SceneState state
Camera * m_activeCamera
virtual void OnUnload()
Override to release scene-specific assets; called from Unload().
Definition SceneBase.hpp:82
void DestroyAllObjects()
Destroys every object still owned by the scene, e.g. during Unload().
List< GameObject * > m_pendingDestroy
void Activate()
Marks the scene active and calls OnActivate().
Definition SceneBase.cpp:82
virtual void OnActivate()
Override for logic that should run when the scene becomes active.
Definition SceneBase.hpp:86
LightManager * m_lightManager
GameObject * FindObjectByID(uint64_t id)
Linear search for the object with a matching unique ID.
void Load()
Moves Unloaded -> Loading -> Active, calling OnLoad() and Initialize().
Definition SceneBase.cpp:57
virtual void OnDeactivate()
Override for logic that should run when the scene stops being active.
Definition SceneBase.hpp:88
const std::string & GetName() const
void Pause()
Freezes the scene without tearing it down; leaves it in the Paused state.
virtual void AddObject(GameObject *object)
Takes ownership of object, registering it with lighting and physics as needed.
virtual bool Initialize()
Runs once before the scene's first Begin()/Update().
std::string name
Physics::PhysicsWorld * m_physicsWorld
bool IsActive() const
virtual void Begin()=0
Activates every owned object; runs once after Initialize().
virtual ~SceneBase()
Definition SceneBase.cpp:40
virtual void LateUpdate(float deltaTime)
Advances all active, root-level objects after the main Update pass.
void Render()
Submit render commands for this frame.
Definition Skybox.cpp:123
bool IsInitialized() const
Definition Skybox.hpp:44
void Initialize()
Create GPU resources (shader, buffers, cubemap texture).
Definition Skybox.cpp:40
Represents the position, rotation, and scale of an entity in 3D space.
Root namespace for everything the engine exposes.
Definition Camera.hpp:10
static void RegisterCollidersRecursive(GameObject *obj, Physics::PhysicsWorld *world)
Walks obj and its children, registering any ColliderComponent found with world.
Definition SceneBase.cpp:17
static void UnregisterCollidersRecursive(GameObject *obj, Physics::PhysicsWorld *world)
Walks obj and its children, unregistering any ColliderComponent found from world.
Definition SceneBase.cpp:29