#pragma once #include "src/Scene/Systems/ScriptingSystem.h" #include "src/Scene/Systems/PhysicsSystem.h" #include "src/Scene/Systems/TransformSystem.h" #include "src/Scene/Systems/QuakeMapBuilder.h" #include "src/Rendering/SceneRenderer.h" #include "Scene.h" #include "Entities/Entity.h" #include "src/Rendering/Renderer.h" #include "src/Rendering/Textures/MaterialManager.h" #include "src/Core/Physics/PhysicsManager.h" #include "src/Core/Core.h" #include #include "Engine.h" #include "src/Core/FileSystem.h" #include "src/Scene/Components/Components.h" #include "src/Scene/Components/BoxCollider.h" #include "src/Scene/Components/WrenScriptComponent.h" #include "src/Scene/Components/BSPBrushComponent.h" #include "src/Scene/Components/InterfaceComponent.h" #include #include #include #include "src/Core/OS.h" namespace Nuake { Ref Scene::New() { return CreateRef(); } Scene::Scene() { m_Systems = std::vector>(); m_EditorCamera = CreateRef(); m_Environement = CreateRef(); // Adding systems - Order is important m_Systems.push_back(CreateRef(this)); m_Systems.push_back(CreateRef(this)); m_Systems.push_back(CreateRef(this)); mSceneRenderer = new SceneRenderer(); mSceneRenderer->Init(); } Scene::~Scene() { } std::string Scene::GetName() { return this->Name; } bool Scene::SetName(std::string& newName) { if (newName == "") return false; this->Name = newName; return true; } Entity Scene::GetEntity(int handle) { return Entity((entt::entity)handle, this); } Entity Scene::GetEntityByID(int id) { auto idView = m_Registry.view(); for (auto e : idView) { NameComponent& nameC = idView.get(e); if (nameC.ID == id) { return Entity{ e, this }; } } assert("Entity not found"); } bool Scene::OnInit() { for (auto& system : m_Systems) { Logger::Log("Init system"); if (!system->Init()) { return false; } } return true; } void Scene::OnExit() { for (auto& system : m_Systems) { system->Exit(); } } void Scene::Update(Timestep ts) { for (auto& system : m_Systems) { system->Update(ts); } } void Scene::FixedUpdate(Timestep ts) { for (auto& system : m_Systems) { system->FixedUpdate(ts); } } void Scene::EditorUpdate(Timestep ts) { } void Scene::Draw(FrameBuffer& framebuffer) { Ref cam = nullptr; Matrix4 camTransform = Matrix4(); { auto view = m_Registry.view(); for (auto e : view) { auto [transform, camera, parent] = view.get(e); cam = camera.CameraInstance; cam->Translation = transform.GetGlobalPosition(); cam->SetDirection(glm::rotate(glm::inverse(transform.GetGlobalRotation()), glm::vec3(1.0, 0.0, 0.0))); camTransform = transform.GetGlobalTransform(); break; } } if (!cam) { return; } mSceneRenderer->BeginRenderScene(cam->GetPerspective(), cam->GetTransform(), cam->Translation); mSceneRenderer->RenderScene(*this, framebuffer); } void Scene::Draw(FrameBuffer& framebuffer, const Matrix4& projection, const Matrix4& view) { mSceneRenderer->BeginRenderScene(m_EditorCamera->GetPerspective(), m_EditorCamera->GetTransform(), m_EditorCamera->Translation); mSceneRenderer->RenderScene(*this, framebuffer); } std::vector Scene::GetAllEntities() { std::vector allEntities; auto view = m_Registry.view(); for (auto& e : view) { Entity newEntity(e, this); // Check if valid for deleted entities. if (newEntity.IsValid()) { allEntities.push_back(newEntity); } } return allEntities; } Entity Scene::GetEntity(const std::string& name) { std::vector allEntities; auto view = m_Registry.view(); for (auto e : view) { auto [transform, namec] = view.get(e); if (namec.Name == name) return Entity{ e, this }; } return Entity(); } Entity Scene::CreateEntity(const std::string& name) { return CreateEntity(name, (int)OS::GetTime()); } Entity Scene::CreateEntity(const std::string& name, int id) { Entity entity = { m_Registry.create(), this }; entity.AddComponent(); entity.AddComponent(); entity.AddComponent(); NameComponent& nameComponent = entity.AddComponent(); nameComponent.Name = name; nameComponent.ID = id; Logger::Log("Created entity: " + nameComponent.Name, LOG_TYPE::VERBOSE); return entity; } void Scene::DestroyEntity(Entity entity) { ParentComponent& parentC = entity.GetComponent(); std::vector copyChildrens = parentC.Children; if (parentC.HasParent) { // Remove self from parents children lists. ParentComponent& parent = parentC.Parent.GetComponent(); parent.RemoveChildren(entity); } for (auto& c : copyChildrens) { Logger::Log("Deleting entity " + std::to_string(c.GetHandle())); DestroyEntity(c); } Logger::Log("Deleted entity" + std::to_string(entity.GetHandle()) + " - " + entity.GetComponent().Name); entity.Destroy(); m_Registry.shrink_to_fit(); } Ref Scene::GetCurrentCamera() { if (Engine::IsPlayMode) { Ref cam = nullptr; { auto view = m_Registry.view(); for (auto e : view) { auto [transform, camera] = view.get(e); cam = camera.CameraInstance; break; } } if (!cam) cam = m_EditorCamera; return cam; } return m_EditorCamera; } Ref Scene::GetEnvironment() const { return m_Environement; } void Scene::SetEnvironment(Ref env) { m_Environement = env; } bool Scene::Save() { if (Path == "") Path = FileSystem::AbsoluteToRelative(FileDialog::SaveFile("*.scene") + ".scene"); return SaveAs(Path); } bool Scene::SaveAs(const std::string& path) { std::string fileContent = Serialize().dump(4); FileSystem::BeginWriteFile(FileSystem::Root + path); FileSystem::WriteLine(fileContent); FileSystem::EndWriteFile(); Logger::Log("Scene saved successfully"); return true; } template void Scene::CopyComponent(entt::registry& dst, entt::registry& src) { auto view = src.view(); for (auto e : view) { int id = src.get(e).ID; auto& component = src.get(e); auto idView = dst.view(); for (auto de : idView) { if (idView.get(de).ID == src.get(e).ID) { dst.emplace_or_replace(de, component); } } } } Ref Scene::Copy() { Ref sceneCopy = CreateRef(); sceneCopy->Path = Path; json serializedScene = Serialize(); sceneCopy->Deserialize(serializedScene.dump()); return sceneCopy; } json Scene::Serialize() { BEGIN_SERIALIZE(); SERIALIZE_VAL(Name); SERIALIZE_OBJECT(m_Environement) SERIALIZE_VAL(Path) std::vector entities = std::vector(); for (Entity e : GetAllEntities()) entities.push_back(e.Serialize()); SERIALIZE_VAL_LBL("Entities", entities); SERIALIZE_OBJECT(m_EditorCamera); END_SERIALIZE(); } bool Scene::Deserialize(const std::string& str) { if (str == "") return false; BEGIN_DESERIALIZE(); if (!j.contains("Name")) return false; m_Registry.clear(); Name = j["Name"]; if (j.contains("")) { Path = j["Path"]; } m_Environement = CreateRef(); if (j.contains("m_Environement")) { m_Environement = CreateRef(); std::string env = j["m_Environement"].dump(); m_Environement->Deserialize(env); } // Parse entities if (!j.contains("Entities")) { return 0; } for (json e : j["Entities"]) { std::string name = e["NameComponent"]["Name"]; Entity ent = { m_Registry.create(), this }; ent.Deserialize(e.dump()); } if (j.contains("m_EditorCamera")) { m_EditorCamera->Deserialize(j["m_EditorCamera"].dump()); } auto view = m_Registry.view(); for (auto e : view) { auto& parentComponent = view.get(e); if (!parentComponent.HasParent) continue; auto& entity = Entity{ e, this }; auto parentEntity = GetEntityByID(parentComponent.ParentID); parentEntity.AddChild(entity); } return true; } }