#pragma once #include "Scene.h" #include "Entities/Entity.h" #include "Entities/Components.h" #include "../Rendering/Renderer.h" #include "../Core/MaterialManager.h" #include "../Core/Physics/PhysicsManager.h" #include "../Core/Core.h" #include #include "Entities/Components/BoxCollider.h" #include "../../Engine.h" #include "../Core/FileSystem.h" #include "../Scene/Entities/Components/LuaScriptComponent.h" #include #include #include "../Scene/Entities/Components/WrenScriptComponent.h" Ref Scene::New() { return CreateRef(); } Scene::Scene() { m_EditorCamera = CreateRef(); m_Environement = CreateRef(); m_Interfaces = std::vector>(); } Scene::~Scene() {} std::string Scene::GetName() { return this->Name; } bool Scene::SetName(std::string& newName) { if (newName == "") return false; this->Name = newName; return true; } void Scene::OnInit() { ScriptingEngine::Init(); // Create physic world. auto view = m_Registry.view(); for (auto e : view) { auto [transform, rigidbody] = view.get(e); Entity ent = Entity({ e, this }); if (ent.HasComponent()) { float mass = rigidbody.mass; BoxColliderComponent& boxComponent = ent.GetComponent(); Ref boxShape = CreateRef(boxComponent.Size); Ref btRigidbody = CreateRef(mass, transform.Translation, boxShape); rigidbody.m_Rigidbody = btRigidbody; btRigidbody->SetKinematic(rigidbody.IsKinematic); PhysicsManager::Get()->RegisterBody(btRigidbody); } } // character controllers auto ccview = m_Registry.view(); for (auto e : ccview) { auto [transform, cc] = ccview.get(e); cc.CharacterController = CreateRef(cc.Height, cc.Radius, cc.Mass); Entity ent = Entity({ e, this }); PhysicsManager::Get()->RegisterCharacterController(cc.CharacterController); } auto quakeMapview = m_Registry.view(); for (auto e : quakeMapview) { auto [transform, quake] = quakeMapview.get(e); if (quake.HasCollisions) { for (auto m : quake.m_Meshes) { Ref meshShape = CreateRef(m); Ref btRigidbody = CreateRef(0.0f, transform.Translation, meshShape); PhysicsManager::Get()->RegisterBody(btRigidbody); } } } // Instanciate scripts. { auto entities = m_Registry.view(); for (auto& e : entities) { WrenScriptComponent& wren = entities.get(e); if (wren.Script != "" && wren.Class != "") wren.WrenScript = CreateRef(wren.Script, wren.Class, true); if (wren.WrenScript != nullptr) { wren.WrenScript->SetScriptableEntityID((int)e); wren.WrenScript->CallInit(); } } } } void Scene::OnExit() { PhysicsManager::Get()->Reset(); // destroy scripts. auto entities = m_Registry.view(); for (auto& e : entities) { WrenScriptComponent& wren = entities.get(e); if (wren.WrenScript != nullptr) { wren.WrenScript->CallExit(); } } ScriptingEngine::Close(); } // update entities and some components. void Scene::Update(Timestep ts) { // Update scripts { m_Registry.view().each([=](auto entity, auto& nsc) { nsc.Instance->OnUpdate(ts); }); } // destroy scripts. auto entities = m_Registry.view(); for (auto& e : entities) { WrenScriptComponent& wren = entities.get(e); if (wren.WrenScript != nullptr) wren.WrenScript->CallUpdate(ts); } // Update rigidbodies PhysicsManager::Get()->Step(ts); auto physicGroup = m_Registry.view(); for (auto e : physicGroup) { auto [transform, rb] = physicGroup.get(e); rb.SyncTransformComponent(&m_Registry.get(e)); } auto ccGroup = m_Registry.view(); for (auto e : ccGroup) { auto [transform, rb] = ccGroup.get(e); rb.SyncWithTransform(m_Registry.get(e)); } } void Scene::EditorUpdate(Timestep ts) { m_EditorCamera->Update(ts); for (auto i : m_Interfaces) { i->Update(ts); } } void Scene::DrawShadows() { auto modelView = m_Registry.view(); auto quakeView = m_Registry.view(); auto view = m_Registry.view(); Ref cam = nullptr; if (Engine::IsPlayMode) { auto view = m_Registry.view(); for (auto e : view) { auto [transform, camera] = view.get(e); cam = camera.CameraInstance; break; } } else { cam = m_EditorCamera; } glm::mat4 perspective = cam->GetPerspective(); for (auto l : view) { auto [lightTransform, light] = view.get(l); if (light.Type != LightType::Directional) continue; light.BeginDrawShadow(); for (auto e : modelView) { auto [transform, model] = modelView.get(e); glm::vec3 pos = lightTransform.Translation; glm::mat4 lightView = glm::lookAt(pos, pos - light.GetDirection(), glm::vec3(0.0f, 1.0f, 0.0f)); Renderer::m_ShadowmapShader->SetUniformMat4f("lightSpaceMatrix", light.GetProjection() * lightView); Renderer::m_ShadowmapShader->SetUniformMat4f("model", transform.GetTransform()); model.Draw(); } for (auto e : quakeView) { auto [transform, model] = quakeView.get(e); glm::vec3 pos = lightTransform.Translation; glm::mat4 lightView = glm::lookAt(pos, pos - light.GetDirection(), glm::vec3(0.0f, 1.0f, 0.0f)); Renderer::m_ShadowmapShader->SetUniformMat4f("lightSpaceMatrix", light.GetProjection() * lightView); Renderer::m_ShadowmapShader->SetUniformMat4f("model", transform.GetTransform()); model.Draw(); } light.EndDrawShadow(); } } 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); TransformComponent copyT = transform; if (parent.HasParent) { Entity currentParent = Entity{ e, this }; glm::vec3 globalOffset = copyT.Translation; while (currentParent.GetComponent().HasParent) { currentParent = currentParent.GetComponent().Parent; globalOffset += currentParent.GetComponent().Translation; } copyT.Translation = globalOffset; } cam = camera.CameraInstance; cam->Translation = copyT.Translation; break; } } 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); TransformComponent copyT = transform; if (parent.HasParent) { Entity currentParent = Entity{ l, this }; glm::vec3 globalOffset = copyT.Translation; while (currentParent.GetComponent().HasParent) { currentParent = currentParent.GetComponent().Parent; globalOffset += currentParent.GetComponent().Translation; } copyT.Translation = globalOffset; } if (light.SyncDirectionWithSky) light.Direction = GetEnvironment()->ProceduralSkybox->GetSunDirection(); light.Draw(copyT, m_EditorCamera); } } Renderer::m_Shader->Bind(); 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); TransformComponent copyT = transform; if (parent.HasParent) { Entity currentParent = Entity{ e, this }; glm::vec3 globalOffset = copyT.Translation; while (currentParent.GetComponent().HasParent) { currentParent = currentParent.GetComponent().Parent; globalOffset += currentParent.GetComponent().Translation; } copyT.Translation = globalOffset; } Renderer::m_Shader->SetUniformMat4f("u_View", cam->GetTransform()); Renderer::m_Shader->SetUniformMat4f("u_Projection", cam->GetPerspective()); Renderer::m_Shader->SetUniformMat4f("u_Model", copyT.GetTransform()); model.Draw(); } auto quakeView = m_Registry.view(); for (auto e : quakeView) { auto [transform, model, parent] = quakeView.get(e); TransformComponent copyT = transform; if (parent.HasParent) { Entity currentParent = Entity{ e, this }; glm::vec3 globalOffset = copyT.Translation; while (currentParent.GetComponent().HasParent) { currentParent = currentParent.GetComponent().Parent; globalOffset += currentParent.GetComponent().Translation; } copyT.Translation = globalOffset; } Renderer::m_Shader->SetUniformMat4f("u_View", cam->GetTransform()); Renderer::m_Shader->SetUniformMat4f("u_Projection", cam->GetPerspective()); Renderer::m_Shader->SetUniformMat4f("u_Model", copyT.GetTransform()); model.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(); 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); TransformComponent copyT = transform; if (parent.HasParent) { Entity currentParent = Entity{ l, this }; glm::vec3 globalOffset = copyT.Translation; while (currentParent.GetComponent().HasParent) { currentParent = currentParent.GetComponent().Parent; globalOffset += currentParent.GetComponent().Translation; } copyT.Translation = globalOffset; } if (light.SyncDirectionWithSky) light.Direction = GetEnvironment()->ProceduralSkybox->GetSunDirection(); light.Draw(copyT, m_EditorCamera); } } Renderer::m_Shader->Bind(); Renderer::m_Shader->SetUniform1i("u_ShowNormal", 0); if (m_EditorCamera) { Renderer::m_Shader->SetUniform1f("u_Exposure", m_EditorCamera->Exposure); auto view = m_Registry.view(); for (auto e : view) { auto [transform, model, parent] = view.get(e); TransformComponent copyT = transform; if (parent.HasParent) { Entity currentParent = Entity{ e, this }; glm::vec3 globalOffset = copyT.Translation; while (currentParent.GetComponent().HasParent) { currentParent = currentParent.GetComponent().Parent; globalOffset += currentParent.GetComponent().Translation; } copyT.Translation = globalOffset; } Renderer::m_Shader->SetUniformMat4f("u_View", m_EditorCamera->GetTransform()); Renderer::m_Shader->SetUniformMat4f("u_Projection", m_EditorCamera->GetPerspective()); Renderer::m_Shader->SetUniformMat4f("u_Model", copyT.GetTransform()); model.Draw(); } auto quakeView = m_Registry.view(); for (auto e : quakeView) { auto [transform, model, parent] = quakeView.get(e); TransformComponent copyT = transform; if (parent.HasParent) { Entity currentParent = Entity{ e, this }; glm::vec3 globalOffset = copyT.Translation; while (currentParent.GetComponent().HasParent) { currentParent = currentParent.GetComponent().Parent; globalOffset += currentParent.GetComponent().Translation; } copyT.Translation = globalOffset; } Renderer::m_Shader->SetUniformMat4f("u_View", m_EditorCamera->GetTransform()); Renderer::m_Shader->SetUniformMat4f("u_Projection", m_EditorCamera->GetPerspective()); Renderer::m_Shader->SetUniformMat4f("u_Model", copyT.GetTransform()); model.Draw(); } auto boxCollider = m_Registry.view(); for (auto e : boxCollider) { auto [transform, box, parent] = boxCollider.get(e); TransformComponent copyT = transform; if (parent.HasParent) { Entity currentParent = Entity{ e, this }; glm::vec3 globalOffset = copyT.Translation; while (currentParent.GetComponent().HasParent) { currentParent = currentParent.GetComponent().Parent; globalOffset += currentParent.GetComponent().Translation; } copyT.Translation = globalOffset; } Renderer::m_DebugShader->SetUniformMat4f("u_View", m_EditorCamera->GetTransform()); Renderer::m_DebugShader->SetUniformMat4f("u_Projection", m_EditorCamera->GetPerspective()); Renderer::m_DebugShader->SetUniformMat4f("u_Model", copyT.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); TransformComponent copyT = transform; if (parent.HasParent) { Entity currentParent = Entity{ e, this }; glm::vec3 globalOffset = copyT.Translation; while (currentParent.GetComponent().HasParent) { currentParent = currentParent.GetComponent().Parent; globalOffset += currentParent.GetComponent().Translation; } copyT.Translation = globalOffset; } 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) { allEntities.push_back(Entity(e, this)); } 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; ParentComponent& parentComponent = entity.AddComponent(); Logger::Log("Created entity: " + nameComponent.Name + "\n"); return entity; } void Scene::DestroyEntity(Entity entity) { entity.Destroy(); } // 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()); } } } return true; }