22 for (
size_t i = 0; i < children.GetSize(); ++i) {
23 if (children[i] && !children[i]->IsOwnedByScene())
29template <
typename Pred>
31 if (!obj)
return nullptr;
32 if (pred(obj))
return obj;
34 for (
size_t i = 0; i < children.GetSize(); ++i) {
35 if (!children[i] || children[i]->IsOwnedByScene())
continue;
46 if (lights && o->IsLight())
60 if (lights && o->IsLight())
73 "Scene '{0}' destroyed without Unload(); "
74 "OnDeactivate/OnUnload did not run.",
162 if (newLights || newWorld) {
163 for (
size_t i = 0; i <
Objects.GetSize(); ++i) {
172 for (
size_t i = 0; i <
Objects.GetSize(); ++i) {
182 for (
size_t i = 0; i <
Objects.GetSize(); ++i) {
197 for (
size_t i = 0; i <
Objects.GetSize(); ++i) {
214 const auto& shape = collider->
GetShape();
216 if (
auto* aabb = std::get_if<Physics::AABB>(&shape)) {
218 aabb->min * worldScale + worldPos,
219 aabb->max * worldScale + worldPos);
221 }
else if (
auto* sphere = std::get_if<Physics::BoundingSphere>(&shape)) {
223 float maxScale = std::max({worldScale.GetX(), worldScale.GetY(), worldScale.GetZ()});
225 }
else if (
auto* capsule = std::get_if<Physics::BoundingCapsule>(&shape)) {
227 worldCapsule.
center = capsule->center * worldScale + worldPos;
228 float maxScale = std::max({worldScale.GetX(), worldScale.GetY(), worldScale.GetZ()});
229 worldCapsule.
radius = capsule->radius * maxScale;
230 worldCapsule.
halfHeight = capsule->halfHeight * maxScale;
237 if (!collider)
return;
242 pos = transform->GetWorldPosition() + collider->
GetOffset();
243 scale = transform->GetWorldScale();
244 }
else if (
auto* cam =
dynamic_cast<Camera*
>(obj)) {
245 pos = cam->GetPosition() + collider->
GetOffset();
247 drawColliderShape(collider, pos, scale);
250 for (
size_t i = 0; i <
Objects.GetSize(); ++i) {
263 for (
size_t i = 0; i <
Objects.GetSize(); ++i) {
265 Objects[i]->FixedUpdate(fixedDeltaTime);
273 for (
size_t i = 0; i <
Objects.GetSize(); ++i) {
275 Objects[i]->LateUpdate(deltaTime);
282 if (
Objects.indexOf(
object) != -1)
return;
285 object->m_ownedByScene =
true;
290 object->Initialize();
296 if (
Objects.indexOf(
object) == -1)
return;
299 for (
size_t i = 0; i < children.
GetSize(); ++i) {
300 if (children[i] && children[i]->IsOwnedByScene())
323 const auto& children =
object->GetChildren();
324 for (
size_t i = 0; i < children.GetSize(); ++i) {
325 if (children[i] && !children[i]->IsPendingDestroy()) {
332 auto match = [&](
GameObject* o) {
return o->GetName() == objectName; };
333 for (
size_t i = 0; i <
Objects.GetSize(); ++i) {
340 auto match = [&](
GameObject* o) {
return o->GetUniqueID() == id; };
341 for (
size_t i = 0; i <
Objects.GetSize(); ++i) {
350 if (o->GetTag() == tag) result.
add(o);
352 for (
size_t i = 0; i <
Objects.GetSize(); ++i) {
363 for (
size_t i = 0; i < pending.
GetSize(); ++i) {
366 int index =
Objects.indexOf(obj);
367 if (index != -1)
Objects.erase(index);
371 for (
size_t i = 0; i < pending.
GetSize(); ++i) {
372 if (pending[i]) pending[i]->SetParent(
nullptr);
374 for (
size_t i = 0; i < pending.
GetSize(); ++i) {
384 for (
size_t i = 0; i < objects.
GetSize(); ++i) {
387 for (
size_t i = 0; i < objects.
GetSize(); ++i) {
388 if (objects[i]) objects[i]->SetParent(
nullptr);
390 for (
size_t i = 0; i < objects.
GetSize(); ++i) {
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 ¢er, 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 IsPendingDestroy() const
bool IsInitialized() const
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.
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, children included.
void Unload()
Deactivates if active, calls OnUnload(), and destroys all owned objects.
void Deactivate()
Marks the scene inactive and calls OnDeactivate().
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)
First object with a matching name, children included.
virtual void OnLoad()
Override to load scene-specific assets; called once from Load().
void DestroyObject(GameObject *object)
Queues an object for destruction; actually freed on the next ProcessPendingDestroy().
virtual void RemoveObject(GameObject *object)
virtual void OnUnload()
Override to release scene-specific assets; called from Unload().
void DestroyAllObjects()
Destroys every object still owned by the scene, e.g. during Unload().
List< GameObject * > m_pendingDestroy
void Activate()
Marks the scene active, calls OnActivate(), then Begin() once.
virtual void OnActivate()
Override for logic that should run when the scene becomes active.
LightManager * m_lightManager
GameObject * FindObjectByID(uint64_t id)
Object with a matching unique ID, children included.
void Load()
Moves Unloaded -> Loading -> Active, calling OnLoad() and Initialize().
virtual void OnDeactivate()
Override for logic that should run when the scene stops being active.
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().
Physics::PhysicsWorld * m_physicsWorld
virtual void Begin()=0
Activates every owned object; runs once per Load().
virtual void LateUpdate(float deltaTime)
Advances all active, root-level objects after the main Update pass.
void Render()
Submit render commands for this frame.
bool IsInitialized() const
void Initialize()
Create GPU resources (shader, buffers, cubemap texture).
Root namespace for everything the engine exposes.
static GameObject * FindOwned(GameObject *obj, const Pred &pred)
Depth-first search of obj and the descendants it owns.
static void UnregisterTree(GameObject *obj, LightManager *lights, Physics::PhysicsWorld *world)
Unregisters lights and colliders in obj's owned subtree.
static void ForEachOwned(GameObject *obj, Fn &fn)
Calls fn on obj and the descendants it owns, skipping scene owned ones.
static void RegisterTree(GameObject *obj, LightManager *lights, Physics::PhysicsWorld *world)