fix: alot of stuff changed. Mostly bugfixxes / architechture changes

This commit is contained in:
2026-08-09 02:24:17 +02:00
parent 4b6f773c0c
commit 05384debbf
98 changed files with 5461 additions and 1751 deletions
+186 -86
View File
@@ -1,163 +1,263 @@
#include <destrum/Scene/Scene.h>
#include <destrum/ObjectModel/GameObject.h>
#include <destrum/Util/DeltaTime.h>
#include <algorithm>
#include <functional>
#include <SDL_scancode.h>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>
// #include "ServiceLocator.h"
// #include "Input/InputManager.h"
// #include "Managers/Renderer.h"
unsigned int Scene::m_idCounter = 0;
Scene::Scene(const std::string& name) : m_name(name) {
namespace {
class IterationGuard {
public:
explicit IterationGuard(Scene& scene) : m_Scene(scene) {
m_Scene.BeginIteration();
}
~IterationGuard() {
m_Scene.EndIteration();
}
private:
Scene& m_Scene;
};
}
Scene::~Scene() = default;
Scene::Scene(const std::string& name)
: m_name(name),
m_id(++m_idCounter) {
}
// void Scene::Add(std::shared_ptr<GameObject> object) {
// // m_objects.emplace_back(std::move(object));
// m_pendingAdditions.emplace_back(std::move(object));
// }
Scene::~Scene() {
Unload();
RemoveAll();
}
GameObject* Scene::CreateGameObject(std::string name)
{
auto obj = std::make_shared<GameObject>(std::move(name));
GameObject* rawPtr = obj.get();
obj->SetScene(this);
m_pendingAdditions.emplace_back(std::move(obj));
GameObject* Scene::CreateGameObject(std::string name) {
auto object = std::make_shared<GameObject>(std::move(name));
GameObject* rawPtr = object.get();
object->SetScene(this);
m_pendingAdditions.emplace_back(std::move(object));
return rawPtr;
}
void Scene::Remove(GameObject* object) {
std::erase_if(m_objects, [object](const std::shared_ptr<GameObject>& obj) {
return obj.get() == object;
});
if (object == nullptr) {
return;
}
std::erase_if(m_pendingAdditions, [object](const std::shared_ptr<GameObject>& obj) {
return obj.get() == object;
});
const auto containsObject = [object](const auto& objects) {
return std::any_of(objects.begin(), objects.end(), [object](const auto& candidate) {
return candidate != nullptr && candidate.get() == object;
});
};
if (!containsObject(m_objects) && !containsObject(m_pendingAdditions)) {
return;
}
object->Destroy();
if (IsIterating()) {
return;
}
const auto eraseDestroyed = [](auto& objects) {
for (const auto& candidate : objects) {
if (candidate != nullptr && candidate->IsBeingDestroyed()) {
candidate->SetScene(nullptr);
}
}
std::erase_if(objects, [](const auto& candidate) {
return candidate == nullptr || candidate->IsBeingDestroyed();
});
};
// Destroying an object also marks its descendants. Remove all of those
// marked entries together, after destruction has finished.
eraseDestroyed(m_objects);
eraseDestroyed(m_pendingAdditions);
}
void Scene::RemoveAll() {
for (const auto& object : m_objects) {
if (object != nullptr) {
object->Destroy();
}
}
for (const auto& object : m_pendingAdditions) {
if (object != nullptr) {
object->Destroy();
}
}
if (IsIterating()) {
return;
}
for (const auto& object : m_objects) {
if (object != nullptr) {
object->SetScene(nullptr);
}
}
for (const auto& object : m_pendingAdditions) {
if (object != nullptr) {
object->SetScene(nullptr);
}
}
m_objects.clear();
m_pendingAdditions.clear();
}
void Scene::Load() {
OnSceneLoaded.Invoke();
if (m_registerBindings) {
m_registerBindings();
}
LoadBindings();
}
void Scene::Update() {
void Scene::Update(float dt) {
CommitPendingAdditions();
IterationGuard iteration(*this);
for (const auto& object : m_objects) {
if (object->IsActiveInHierarchy()) {
object->Update();
if (object != nullptr && !object->IsBeingDestroyed() && object->IsActiveInHierarchy()) {
object->Update(dt);
}
}
}
void Scene::FixedUpdate(float dt) {
for (const auto& object: m_objects) {
if (object->IsActiveInHierarchy()) {
object->FixedUpdate();
CommitPendingAdditions();
IterationGuard iteration(*this);
for (const auto& object : m_objects) {
if (object != nullptr && !object->IsBeingDestroyed() && object->IsActiveInHierarchy()) {
object->FixedUpdate(dt);
}
}
m_Physics.FixedUpdate(dt);
}
void Scene::LateUpdate() {
for (const auto& object: m_objects) {
if (object->IsActiveInHierarchy()) {
object->LateUpdate();
void Scene::LateUpdate(float dt) {
IterationGuard iteration(*this);
for (const auto& object : m_objects) {
if (object != nullptr && !object->IsBeingDestroyed() && object->IsActiveInHierarchy()) {
object->LateUpdate(dt);
}
}
}
void Scene::Render(const RenderContext& ctx) const {
for (const auto& object: m_objects) {
if (object->IsActiveInHierarchy()) {
void Scene::Render(const RenderContext& ctx) {
IterationGuard iteration(*this);
for (const auto& object : m_objects) {
if (object != nullptr && !object->IsBeingDestroyed() && object->IsActiveInHierarchy()) {
object->Render(ctx);
}
}
}
void Scene::RenderImgui() {
}
void Scene::CleanupDestroyedGameObjects() {
if (m_BeingUnloaded) {
//Scene is gone anyways, kill everything
m_objects.clear();
if (IsIterating()) {
return;
}
for (const auto& gameObject: m_objects) {
//First check if a gameobjects components needs to be destroyed
gameObject->CleanupComponents();
const auto cleanup = [](auto& objects) {
for (const auto& object : objects) {
if (object != nullptr && object->IsBeingDestroyed()) {
object->Destroy();
}
}
for (const auto& object : objects) {
if (object != nullptr && !object->IsBeingDestroyed()) {
object->CleanupComponents();
}
}
for (const auto& object : objects) {
if (object != nullptr && object->IsBeingDestroyed()) {
object->SetScene(nullptr);
}
}
std::erase_if(objects, [](const auto& object) {
return object == nullptr || object->IsBeingDestroyed();
});
};
cleanup(m_objects);
cleanup(m_pendingAdditions);
}
void Scene::BeginIteration() {
++m_IterationDepth;
}
void Scene::EndIteration() {
if (m_IterationDepth == 0) {
return;
}
// //Strange for loop since im deleting during looping over it
// for (auto it = m_objects.begin(); it != m_objects.end();) {
// if ((*it)->IsBeingDestroyed()) {
// it = m_objects.erase(it);
// } else {
// ++it;
// }
// }
std::erase_if(m_objects, [] (const std::shared_ptr<GameObject>& gameObject) {
return gameObject->IsBeingDestroyed();
});
--m_IterationDepth;
if (m_IterationDepth == 0) {
CleanupDestroyedGameObjects();
}
}
void Scene::Unload() {
if (m_unregisterBindings) {
m_unregisterBindings();
if (m_BeingUnloaded) {
return;
}
UnloadBindings();
m_BeingUnloaded = true;
}
void Scene::DestroyGameObjects() {
if (m_BeingUnloaded) {
for (auto& obj : m_pendingAdditions) {
m_objects.emplace_back(std::move(obj));
for (const auto& object : m_objects) {
if (object != nullptr) {
object->Destroy();
}
m_pendingAdditions.clear();
//Scene is gone anyways, kill everything
for (const auto& gameObject: m_objects) {
gameObject->Destroy();
}
for (const auto& object : m_pendingAdditions) {
if (object != nullptr) {
object->Destroy();
}
} else {
assert(m_BeingUnloaded && "Scene is being cleared but not unloaded? Weird");
}
}
void Scene::CommitPendingAdditions() {
if (m_pendingAdditions.empty()) {
if (m_pendingAdditions.empty() || IsIterating()) {
return;
}
for (auto& obj : m_pendingAdditions) {
m_objects.emplace_back(std::move(obj));
for (auto& object : m_pendingAdditions) {
if (object != nullptr && !object->IsBeingDestroyed()) {
m_Physics.RegisterGameObject(*object);
m_objects.emplace_back(std::move(object));
}
}
m_pendingAdditions.clear();
}
std::erase_if(m_pendingAdditions, [](const auto& object) {
return object == nullptr || object->IsBeingDestroyed();
});
}
void Scene::RefreshPhysics() {
for (const auto& object : m_objects) {
if (object != nullptr) {
m_Physics.RefreshGameObject(*object);
}
}
for (const auto& object : m_pendingAdditions) {
if (object != nullptr) {
m_Physics.RefreshGameObject(*object);
}
}
}