#pragma once #include #include #include #include #include "Scene.h" #include "Entities/Entity.h" #include "../Rendering/Renderer.h" #include "../Core/MaterialManager.h" #include "../Core/Physics/PhysicsManager.h" #include "../Core/Core.h" #include #include "../../Engine.h" #include "../Core/FileSystem.h" #include "Components/Components.h" #include "Components/BoxCollider.h" #include "Components/LuaScriptComponent.h" #include "Components/WrenScriptComponent.h" #include #include #include #include Ref Scene::New() { return CreateRef(); } Scene::Scene() { m_Systems = std::vector>(); m_EditorCamera = CreateRef(); m_Environement = CreateRef(); m_Interfaces = std::vector>(); // Adding systems m_Systems.push_back(CreateRef(this)); m_Systems.push_back(CreateRef(this)); } 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 }; } } bool Scene::OnInit() { for (auto& system : m_Systems) if(!system->Init()) { return false; } return true; } void Scene::OnExit() { for (auto& system : m_Systems) system->Exit(); } void Scene::Update(Timestep ts) { UpdatePositions(); 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) { UpdatePositions(); m_EditorCamera->Update(ts); for (auto i : m_Interfaces) i->Update(ts); } void Scene::UpdatePositions() { auto transformView = m_Registry.view(); for (auto e : transformView) { auto [parent, transform] = transformView.get(e); Entity currentParent = Entity{ e, this }; Vector3 globalPos = Vector3(); if (parent.HasParent) { while (currentParent.GetComponent().HasParent) { currentParent = currentParent.GetComponent().Parent; globalPos += currentParent.GetComponent().Translation; } transform.GlobalTranslation = globalPos + transform.Translation; } else { transform.GlobalTranslation = transform.Translation; } } } void Scene::DrawShadows() { auto modelView = m_Registry.view(); auto quakeView = m_Registry.view(); auto view = m_Registry.view(); Ref cam = m_EditorCamera; if (Engine::IsPlayMode) { auto view = m_Registry.view(); for (auto e : view) { auto [transform, camera] = view.get(e); cam = camera.CameraInstance; break; } } glm::mat4 perspective = cam->GetPerspective(); Renderer::m_ShadowmapShader->Bind(); for (auto l : view) { auto [lightTransform, light] = view.get(l); if (light.Type != LightType::Directional || !light.CastShadows) continue; light.CalculateViewProjection(cam->GetTransform(), cam->GetPerspective()); for (int i = 0; i < 4; i++) { light.m_Framebuffers[i]->Bind(); Renderer::m_ShadowmapShader->SetUniformMat4f("lightSpaceMatrix", light.mViewProjections[i]); for (auto e : modelView) { auto [transform, model] = modelView.get(e); Renderer::m_ShadowmapShader->SetUniformMat4f("model", transform.GetTransform()); model.Draw(); } Renderer::m_ShadowmapShader->SetUniformMat4f("lightSpaceMatrix", light.mViewProjections[i]); auto quakeView = m_Registry.view(); for (auto e : quakeView) { auto [transform, model] = quakeView.get(e); Renderer::m_ShadowmapShader->SetUniformMat4f("model", transform.GetTransform()); if (model.IsTransparent) continue; for (auto& e : model.Meshes) { e->Draw(false); } } } } } void Scene::DrawInterface(Vector2 screensize) { for (auto i : m_Interfaces) { i->Draw(screensize); } } void Scene::Draw() { // Find the camera of the scene. Ref cam = nullptr; { auto view = m_Registry.view(); for (auto e : view) { auto [transform, camera, parent] = view.get(e); cam = camera.CameraInstance; cam->Translation = transform.GlobalTranslation; break; } } glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); Ref env = GetEnvironment(); if (env->ProceduralSkybox) { env->ProceduralSkybox->Draw(cam); } Renderer::m_Shader->Bind(); env->Push(); glEnable(GL_DEPTH_TEST); // Push lights { auto view = m_Registry.view(); for (auto l : view) { auto [transform, light, parent] = view.get(l); if (light.SyncDirectionWithSky) light.Direction = GetEnvironment()->ProceduralSkybox->GetSunDirection(); light.Draw(transform, m_EditorCamera); } } glEnable(GL_CULL_FACE); glCullFace(GL_FRONT); Renderer::m_Shader->Bind(); Renderer::m_Shader->SetUniform3f("u_EyePosition", cam->GetTranslation().x, cam->GetTranslation().y, cam->GetTranslation().z); Renderer::m_Shader->SetUniform1i("u_ShowNormal", 0); if (cam) { Renderer::m_Shader->SetUniform1f("u_Exposure", cam->Exposure); auto view = m_Registry.view(); for (auto e : view) { auto [transform, model, parent] = view.get(e); Renderer::m_Shader->SetUniformMat4f("u_View", cam->GetTransform()); Renderer::m_Shader->SetUniformMat4f("u_Projection", cam->GetPerspective()); Renderer::m_Shader->SetUniformMat4f("u_Model", transform.GetTransform()); model.Draw(); } auto quakeView = m_Registry.view(); for (auto e : quakeView) { auto [transform, model, parent] = quakeView.get(e); if (model.IsTransparent) continue; Renderer::m_Shader->SetUniformMat4f("u_View", cam->GetTransform()); Renderer::m_Shader->SetUniformMat4f("u_Projection", cam->GetPerspective()); Renderer::m_Shader->SetUniformMat4f("u_Model", transform.GetTransform()); for (auto& e : model.Meshes) { e->Draw(); } } Renderer::m_DebugShader->SetUniformMat4f("u_View", cam->GetTransform()); Renderer::m_DebugShader->SetUniformMat4f("u_Projection", cam->GetPerspective()); PhysicsManager::Get()->DrawDebug(); } } void Scene::EditorDraw() { glDisable(GL_DEPTH_TEST); Ref env = GetEnvironment(); glDisable(GL_CULL_FACE); if (env->ProceduralSkybox) { env->ProceduralSkybox->Draw(m_EditorCamera); } Renderer::m_Shader->Bind(); env->Push(); glEnable(GL_DEPTH_TEST); // Push lights { auto view = m_Registry.view(); for (auto l : view) { auto [transform, light, parent] = view.get(l); if (light.SyncDirectionWithSky) light.Direction = GetEnvironment()->ProceduralSkybox->GetSunDirection(); light.Draw(transform, m_EditorCamera); } } glEnable(GL_CULL_FACE); glCullFace(GL_FRONT); Renderer::m_Shader->Bind(); Renderer::m_Shader->SetUniform1i("u_ShowNormal", 0); if (m_EditorCamera) { Renderer::m_Shader->SetUniform1f("u_Exposure", m_EditorCamera->Exposure); Renderer::m_Shader->SetUniform3f("u_EyePosition", m_EditorCamera->GetTranslation().x, m_EditorCamera->GetTranslation().y, m_EditorCamera->GetTranslation().z); auto view = m_Registry.view(); for (auto e : view) { auto [transform, model, parent] = view.get(e); Renderer::m_Shader->SetUniformMat4f("u_View", m_EditorCamera->GetTransform()); Renderer::m_Shader->SetUniformMat4f("u_Projection", m_EditorCamera->GetPerspective()); Renderer::m_Shader->SetUniformMat4f("u_Model", transform.GetTransform()); model.Draw(); } auto quakeView = m_Registry.view(); for (auto e : quakeView) { auto [transform, model, parent] = quakeView.get(e); Renderer::m_Shader->SetUniformMat4f("u_View", m_EditorCamera->GetTransform()); Renderer::m_Shader->SetUniformMat4f("u_Projection", m_EditorCamera->GetPerspective()); Renderer::m_Shader->SetUniformMat4f("u_Model", transform.GetTransform()); for (auto& e : model.Meshes) { e->Draw(); } } Renderer::m_DebugShader->Bind(); auto boxCollider = m_Registry.view(); for (auto e : boxCollider) { auto [transform, box, parent] = boxCollider.get(e); Renderer::m_DebugShader->SetUniformMat4f("u_View", m_EditorCamera->GetTransform()); Renderer::m_DebugShader->SetUniformMat4f("u_Projection", m_EditorCamera->GetPerspective()); Renderer::m_DebugShader->SetUniformMat4f("u_Model", transform.GetTransform()); TransformComponent t = transform; t.Scale = (box.Size * 2.f) * transform.Scale; Renderer::DrawCube(t, glm::vec4(0.0f, 0.0f, 0.9f, 0.2f)); } auto sphereCollider = m_Registry.view(); for (auto e : sphereCollider) { auto [transform, box, parent] = sphereCollider.get(e); Renderer::m_DebugShader->SetUniformMat4f("u_View", m_EditorCamera->GetTransform()); Renderer::m_DebugShader->SetUniformMat4f("u_Projection", m_EditorCamera->GetPerspective()); Renderer::m_DebugShader->SetUniformMat4f("u_Model", transform.GetTransform()); TransformComponent t = transform; t.Scale = (box.Radius * 2.f) * transform.Scale; Renderer::DrawSphere(t, glm::vec4(0.0f, 0.0f, 0.9f, 0.2f)); } } } 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; } glm::vec3 Scene::GetGlobalPosition(Entity ent) { glm::vec3 globalPos = ent.GetComponent().Translation; Entity currentParent = ent.AddComponent().Parent; while (currentParent.GetHandle() != -1) { globalPos += currentParent.GetComponent().Translation; currentParent = currentParent.GetComponent().Parent; } return globalPos; } 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 }; } } Entity Scene::CreateEmptyEntity() { Entity entity = { m_Registry.create(), this }; return entity; } Entity Scene::CreateEntity(const std::string& name) { Entity entity = { m_Registry.create(), this }; // Must have transform entity.AddComponent(); NameComponent& nameComponent = entity.AddComponent(); nameComponent.Name = name; nameComponent.ID = (int)OS::GetTime(); ParentComponent& parentComponent = entity.AddComponent(); Logger::Log("Created entity: " + nameComponent.Name + "\n"); 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(); } // Getter 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() { return m_Environement; } bool Scene::Save() { if (Path == "") Path = FileSystem::AbsoluteToRelative(FileDialog::SaveFile("*.scene") + ".scene"); return SaveAs(Path); } bool Scene::SaveAs(const std::string& path) { std::ofstream sceneFile; sceneFile.open(FileSystem::Root + path); sceneFile << Serialize().dump(4); sceneFile.close(); Logger::Log("Scene saved successfully"); return true; } void Scene::ReloadInterfaces() { for (auto& i : m_Interfaces) i->Reload(); } void Scene::AddInterface(Ref interface) { this->m_Interfaces.push_back(interface); } json Scene::Serialize() { BEGIN_SERIALIZE(); SERIALIZE_VAL(Name); SERIALIZE_OBJECT(m_Environement) std::vector entities = std::vector(); for (Entity e : GetAllEntities()) entities.push_back(e.Serialize()); SERIALIZE_VAL_LBL("Entities", entities); END_SERIALIZE(); } bool Scene::Deserialize(const std::string& str) { if (str == "") return false; BEGIN_DESERIALIZE(); if (!j.contains("Name")) return false; Name = j["Name"]; 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")) { for (json e : j["Entities"]) { std::string name = e["NameComponent"]["Name"]; Entity ent = CreateEmptyEntity(); ent.Deserialize(e.dump()); } auto view = m_Registry.view(); for (auto e : view) { auto parentC = view.get(e); if (!parentC.HasParent) continue; auto& p = Entity{ e, this }; auto parent = GetEntityByID(parentC.ParentID); parent.AddChild(p); } } } return true; } void Scene::Snapshot() { const auto view = m_Registry.view(); } void Scene::LoadSnapshot() { }