add serialization (use yaml-cpp), add stencil to render outline for selected entity, add play mode, UUIDS, add orthographic and perspective camera, add editor camera
This commit is contained in:
@ -6,6 +6,7 @@
|
||||
#include "ImGuizmo.h"
|
||||
#include "Prism/Core/Input.h"
|
||||
#include "Prism/Renderer/Renderer2D.h"
|
||||
#include "Prism/Script/ScriptEngine.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
@ -119,7 +120,7 @@ namespace Prism
|
||||
}
|
||||
|
||||
EditorLayer::EditorLayer()
|
||||
: m_SceneType(SceneType::Model)
|
||||
: m_SceneType(SceneType::Model), m_EditorCamera(glm::perspectiveFov(glm::radians(45.0f), 1280.0f, 720.0f, 0.1f, 10000.0f))
|
||||
{
|
||||
}
|
||||
|
||||
@ -129,103 +130,16 @@ namespace Prism
|
||||
|
||||
void EditorLayer::OnAttach()
|
||||
{
|
||||
const auto environment = Environment::Load("assets/env/birchwood_4k.hdr");
|
||||
|
||||
// Model Scene
|
||||
{
|
||||
m_Scene = Ref<Scene>::Create("Model Scene");
|
||||
m_CameraEntity = m_Scene->CreateEntity("Camera Entity");
|
||||
m_CameraEntity.AddComponent<CameraComponent>(Camera(glm::perspectiveFov(glm::radians(45.0f), 1280.0f, 720.0f, 0.1f, 10000.0f)));
|
||||
|
||||
m_Scene->SetEnvironment(environment);
|
||||
|
||||
m_MeshEntity = m_Scene->CreateEntity("test Entity");
|
||||
auto mesh = Ref<Mesh>::Create("assets/meshes/TestScene.fbx");
|
||||
// auto mesh = Ref<Mesh>::Create("assets/models/Apollo AE/Apollo AE.fbx");
|
||||
// auto mesh = Ref<Mesh>::Create("assets/models/tafi/塔菲.pmx");
|
||||
m_MeshEntity.AddComponent<MeshComponent>(mesh);
|
||||
|
||||
m_MeshMaterial = mesh->GetMaterial();
|
||||
|
||||
m_MeshEntity.AddComponent<ScriptComponent>("Example.Script");
|
||||
|
||||
// Test Sandbox
|
||||
auto mapGenerator = m_Scene->CreateEntity("Map Generator");
|
||||
mapGenerator.AddComponent<ScriptComponent>("Example.MapGenerator");
|
||||
|
||||
/*
|
||||
auto secondEntity = m_Scene->CreateEntity("Gun Entity");
|
||||
secondEntity->Transform() = glm::translate(glm::mat4(1.0f), { 5, 5, 5 }) * glm::scale(glm::mat4(1.0f), {10, 10, 10});
|
||||
mesh = Ref<Mesh>::Create("assets/models/m1911/M1911Materials.fbx");
|
||||
secondEntity->SetMesh(mesh);
|
||||
*/
|
||||
}
|
||||
|
||||
// Sphere Scene
|
||||
{
|
||||
m_SphereScene = Ref<Scene>::Create("PBR Sphere Scene");
|
||||
auto cameraEntity = m_SphereScene->CreateEntity("camera");
|
||||
cameraEntity.AddComponent<CameraComponent>(Camera(glm::perspectiveFov(glm::radians(45.0f), 1280.0f, 720.0f, 0.1f, 10000.0f)));
|
||||
|
||||
m_SphereScene->SetEnvironment(environment);
|
||||
|
||||
auto sphereMesh = Ref<Mesh>::Create("assets/models/Sphere1m.fbx");
|
||||
m_SphereBaseMaterial = sphereMesh->GetMaterial();
|
||||
|
||||
float x = -4.0f;
|
||||
float roughness = 0.0f;
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
auto sphereEntity = m_SphereScene->CreateEntity();
|
||||
|
||||
Ref<MaterialInstance> mi = Ref<MaterialInstance>::Create(m_SphereBaseMaterial);
|
||||
mi->Set("u_Metalness", 1.0f);
|
||||
mi->Set("u_Roughness", roughness);
|
||||
x += 1.1f;
|
||||
roughness += 0.15f;
|
||||
m_MetalSphereMaterialInstances.push_back(mi);
|
||||
|
||||
/*
|
||||
sphereEntity->SetMesh(sphereMesh);
|
||||
sphereEntity->SetMaterial(mi);
|
||||
sphereEntity->Transform() = glm::translate(glm::mat4(1.0f), glm::vec3(x, 0.0f, 0.0f));
|
||||
*/
|
||||
}
|
||||
|
||||
x = -4.0f;
|
||||
roughness = 0.0f;
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
auto sphereEntity = m_SphereScene->CreateEntity();
|
||||
|
||||
Ref<MaterialInstance> mi(new MaterialInstance(m_SphereBaseMaterial));
|
||||
mi->Set("u_Metalness", 0.0f);
|
||||
mi->Set("u_Roughness", roughness);
|
||||
x += 1.1f;
|
||||
roughness += 0.15f;
|
||||
m_DielectricSphereMaterialInstances.push_back(mi);
|
||||
|
||||
/*
|
||||
sphereEntity->SetMesh(sphereMesh);
|
||||
sphereEntity->SetMaterial(mi);
|
||||
sphereEntity->Transform() = glm::translate(glm::mat4(1.0f), glm::vec3(x, 1.2f, 0.0f));
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
m_ActiveScene = m_Scene;
|
||||
m_SceneHierarchyPanel = CreateScope<SceneHierarchyPanel>(m_ActiveScene);
|
||||
|
||||
|
||||
// Editor
|
||||
m_CheckerboardTex = Texture2D::Create("assets/editor/Checkerboard.tga");
|
||||
m_PlayButtonTex = Texture2D::Create("assets/editor/PlayButton.png");
|
||||
|
||||
// set lights
|
||||
auto& light = m_Scene->GetLight();
|
||||
light.Direction = { -0.5f, -0.5f, 1.0f };
|
||||
light.Radiance = { 1.0f, 1.0f, 1.0f };
|
||||
m_EditorScene = Ref<Scene>::Create();
|
||||
ScriptEngine::SetSceneContext(m_EditorScene);
|
||||
m_SceneHierarchyPanel = CreateScope<SceneHierarchyPanel>(m_EditorScene);
|
||||
m_SceneHierarchyPanel->SetSelectionChangedCallback(std::bind(&EditorLayer::SelectEntity, this, std::placeholders::_1));
|
||||
m_SceneHierarchyPanel->SetEntityDeletedCallback(std::bind(&EditorLayer::OnEntityDeleted, this, std::placeholders::_1));
|
||||
|
||||
m_CurrentlySelectedTransform = &m_MeshEntity.Transform();
|
||||
}
|
||||
|
||||
void EditorLayer::OnDetach()
|
||||
@ -234,72 +148,61 @@ namespace Prism
|
||||
|
||||
void EditorLayer::OnUpdate(const TimeStep deltaTime)
|
||||
{
|
||||
// THINGS TO LOOK AT:
|
||||
// - BRDF LUT
|
||||
// - Tonemapping and proper HDR pipeline
|
||||
using namespace Prism;
|
||||
using namespace glm;
|
||||
|
||||
m_MeshMaterial->Set("u_AlbedoColor", m_AlbedoInput.Color);
|
||||
m_MeshMaterial->Set("u_Metalness", m_MetalnessInput.Value);
|
||||
m_MeshMaterial->Set("u_Roughness", m_RoughnessInput.Value);
|
||||
m_MeshMaterial->Set("u_AlbedoTexToggle", m_AlbedoInput.UseTexture ? 1.0f : 0.0f);
|
||||
m_MeshMaterial->Set("u_NormalTexToggle", m_NormalInput.UseTexture ? 1.0f : 0.0f);
|
||||
m_MeshMaterial->Set("u_MetalnessTexToggle", m_MetalnessInput.UseTexture ? 1.0f : 0.0f);
|
||||
m_MeshMaterial->Set("u_RoughnessTexToggle", m_RoughnessInput.UseTexture ? 1.0f : 0.0f);
|
||||
m_MeshMaterial->Set("u_EnvMapRotation", m_EnvMapRotation);
|
||||
|
||||
m_SphereBaseMaterial->Set("u_AlbedoColor", m_AlbedoInput.Color);
|
||||
// m_SphereBaseMaterial->Set("lights", m_Light);
|
||||
m_SphereBaseMaterial->Set("lights", m_Scene->GetLight());
|
||||
m_SphereBaseMaterial->Set("u_RadiancePrefilter", m_RadiancePrefilter ? 1.0f : 0.0f);
|
||||
m_SphereBaseMaterial->Set("u_AlbedoTexToggle", m_AlbedoInput.UseTexture ? 1.0f : 0.0f);
|
||||
m_SphereBaseMaterial->Set("u_NormalTexToggle", m_NormalInput.UseTexture ? 1.0f : 0.0f);
|
||||
m_SphereBaseMaterial->Set("u_MetalnessTexToggle", m_MetalnessInput.UseTexture ? 1.0f : 0.0f);
|
||||
m_SphereBaseMaterial->Set("u_RoughnessTexToggle", m_RoughnessInput.UseTexture ? 1.0f : 0.0f);
|
||||
m_SphereBaseMaterial->Set("u_EnvMapRotation", m_EnvMapRotation);
|
||||
|
||||
|
||||
if (m_AlbedoInput.TextureMap)
|
||||
m_MeshMaterial->Set("u_AlbedoTexture", m_AlbedoInput.TextureMap);
|
||||
if (m_NormalInput.TextureMap)
|
||||
m_MeshMaterial->Set("u_NormalTexture", m_NormalInput.TextureMap);
|
||||
if (m_MetalnessInput.TextureMap)
|
||||
m_MeshMaterial->Set("u_MetalnessTexture", m_MetalnessInput.TextureMap);
|
||||
if (m_RoughnessInput.TextureMap)
|
||||
m_MeshMaterial->Set("u_RoughnessTexture", m_RoughnessInput.TextureMap);
|
||||
|
||||
/*
|
||||
if (m_AllowViewportCameraEvents)
|
||||
m_Scene->GetCamera().OnUpdate(deltaTime);
|
||||
*/
|
||||
|
||||
m_ActiveScene->OnUpdate(deltaTime);
|
||||
|
||||
if (m_DrawOnTopBoundingBoxes)
|
||||
switch (m_SceneState)
|
||||
{
|
||||
Renderer::BeginRenderPass(SceneRenderer::GetFinalRenderPass(), false);
|
||||
auto viewProj = m_CameraEntity.GetComponent<CameraComponent>().Camera.GetViewProjection();
|
||||
Renderer2D::BeginScene(viewProj, false);
|
||||
Renderer::DrawAABB(m_MeshEntity.GetComponent<MeshComponent>(), m_MeshEntity.GetComponent<TransformComponent>());
|
||||
case SceneState::Edit:
|
||||
{
|
||||
if (m_ViewportPanelFocused)
|
||||
m_EditorCamera.OnUpdate(deltaTime);
|
||||
|
||||
Renderer2D::EndScene();
|
||||
Renderer::EndRenderPass();
|
||||
}
|
||||
m_EditorScene->OnRenderEditor(deltaTime, m_EditorCamera);
|
||||
|
||||
if (!m_SelectionContext.empty())
|
||||
{
|
||||
auto& selection = m_SelectionContext[0];
|
||||
if (m_DrawOnTopBoundingBoxes)
|
||||
{
|
||||
Renderer::BeginRenderPass(SceneRenderer::GetFinalRenderPass(), false);
|
||||
auto viewProj = m_EditorCamera.GetViewProjection();
|
||||
Renderer2D::BeginScene(viewProj, false);
|
||||
// TODO: Renderer::DrawAABB(m_MeshEntity.GetComponent<MeshComponent>(), m_MeshEntity.GetComponent<TransformComponent>());
|
||||
Renderer2D::EndScene();
|
||||
Renderer::EndRenderPass();
|
||||
}
|
||||
|
||||
Renderer::BeginRenderPass(SceneRenderer::GetFinalRenderPass(), false);
|
||||
const auto viewProj = m_CameraEntity.GetComponent<CameraComponent>().Camera.GetViewProjection();
|
||||
Renderer2D::BeginScene(viewProj, false);
|
||||
if (m_SelectionContext.size() && false)
|
||||
{
|
||||
auto& selection = m_SelectionContext[0];
|
||||
|
||||
const glm::vec4 color = (m_SelectionMode == SelectionMode::Entity) ? glm::vec4{ 1.0f, 1.0f, 1.0f, 1.0f } : glm::vec4{ 0.2f, 0.9f, 0.2f, 1.0f };
|
||||
Renderer::DrawAABB(selection.Mesh->BoundingBox, selection.Entity.GetComponent<TransformComponent>().Transform * selection.Mesh->Transform, color);
|
||||
if (selection.Mesh && selection.Entity.HasComponent<MeshComponent>())
|
||||
{
|
||||
Renderer::BeginRenderPass(SceneRenderer::GetFinalRenderPass(), false);
|
||||
auto viewProj = m_EditorCamera.GetViewProjection();
|
||||
Renderer2D::BeginScene(viewProj, false);
|
||||
glm::vec4 color = (m_SelectionMode == SelectionMode::Entity) ? glm::vec4{ 1.0f, 1.0f, 1.0f, 1.0f } : glm::vec4{ 0.2f, 0.9f, 0.2f, 1.0f };
|
||||
Renderer::DrawAABB(selection.Mesh->BoundingBox, selection.Entity.GetComponent<TransformComponent>().Transform * selection.Mesh->Transform, color);
|
||||
Renderer2D::EndScene();
|
||||
Renderer::EndRenderPass();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SceneState::Play:
|
||||
{
|
||||
if (m_ViewportPanelFocused)
|
||||
m_EditorCamera.OnUpdate(deltaTime);
|
||||
|
||||
m_RuntimeScene->OnUpdate(deltaTime);
|
||||
m_RuntimeScene->OnRenderRuntime(deltaTime);
|
||||
break;
|
||||
}
|
||||
case SceneState::Pause:
|
||||
{
|
||||
if (m_ViewportPanelFocused)
|
||||
m_EditorCamera.OnUpdate(deltaTime);
|
||||
|
||||
m_RuntimeScene->OnRenderRuntime(deltaTime);
|
||||
break;
|
||||
}
|
||||
|
||||
Renderer2D::EndScene();
|
||||
Renderer::EndRenderPass();
|
||||
}
|
||||
}
|
||||
|
||||
@ -365,119 +268,80 @@ namespace Prism
|
||||
// Show demo options and help
|
||||
if (ImGui::BeginMenuBar())
|
||||
{
|
||||
if (ImGui::BeginMenu("Options"))
|
||||
if (ImGui::BeginMenu("file"))
|
||||
{
|
||||
// Disabling fullscreen would allow the window to be moved to the front of other windows,
|
||||
// which we can't undo at the moment without finer window depth/z control.
|
||||
ImGui::MenuItem("Fullscreen", NULL, &opt_fullscreen);
|
||||
ImGui::MenuItem("Padding", NULL, &opt_padding);
|
||||
if (ImGui::MenuItem("New Scene"))
|
||||
{
|
||||
|
||||
}
|
||||
if (ImGui::MenuItem("Open Scene..."))
|
||||
{
|
||||
auto& app = Application::Get();
|
||||
std::string filepath = app.OpenFile(R"(Scene file (*.hsc)*.hsc)");
|
||||
if (!filepath.empty())
|
||||
{
|
||||
Ref<Scene> newScene = Ref<Scene>::Create();
|
||||
SceneSerializer serializer(newScene);
|
||||
serializer.Deserialize(filepath);
|
||||
m_EditorScene = newScene;
|
||||
m_SceneHierarchyPanel->SetContext(m_EditorScene);
|
||||
ScriptEngine::SetSceneContext(m_EditorScene);
|
||||
|
||||
m_EditorScene->SetSelectedEntity({});
|
||||
m_SelectionContext.clear();
|
||||
}
|
||||
}
|
||||
if (ImGui::MenuItem("Save Scene..."))
|
||||
{
|
||||
auto& app = Application::Get();
|
||||
std::string filepath = app.SaveFile(R"(Scene file (*.hsc)*.hsc)");
|
||||
SceneSerializer serializer(m_EditorScene);
|
||||
serializer.Serialize(filepath);
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::MenuItem("Flag: NoDockingOverCentralNode", "",
|
||||
(dockspace_flags & ImGuiDockNodeFlags_NoDockingOverCentralNode) != 0))
|
||||
{
|
||||
dockspace_flags ^= ImGuiDockNodeFlags_NoDockingOverCentralNode;
|
||||
}
|
||||
if (ImGui::MenuItem("Flag: NoDockingSplit", "",
|
||||
(dockspace_flags & ImGuiDockNodeFlags_NoDockingSplit) != 0))
|
||||
{
|
||||
dockspace_flags ^= ImGuiDockNodeFlags_NoDockingSplit;
|
||||
}
|
||||
if (ImGui::MenuItem("Flag: NoUndocking", "", (dockspace_flags & ImGuiDockNodeFlags_NoUndocking) != 0))
|
||||
{
|
||||
dockspace_flags ^= ImGuiDockNodeFlags_NoUndocking;
|
||||
}
|
||||
if (ImGui::MenuItem("Flag: NoResize", "", (dockspace_flags & ImGuiDockNodeFlags_NoResize) != 0))
|
||||
{
|
||||
dockspace_flags ^= ImGuiDockNodeFlags_NoResize;
|
||||
}
|
||||
if (ImGui::MenuItem("Flag: AutoHideTabBar", "",
|
||||
(dockspace_flags & ImGuiDockNodeFlags_AutoHideTabBar) != 0))
|
||||
{
|
||||
dockspace_flags ^= ImGuiDockNodeFlags_AutoHideTabBar;
|
||||
}
|
||||
if (ImGui::MenuItem("Flag: PassthruCentralNode", "",
|
||||
(dockspace_flags & ImGuiDockNodeFlags_PassthruCentralNode) != 0, opt_fullscreen))
|
||||
{
|
||||
dockspace_flags ^= ImGuiDockNodeFlags_PassthruCentralNode;
|
||||
}
|
||||
if (ImGui::MenuItem("Reload C# Assembly"))
|
||||
ScriptEngine::ReloadAssembly("assets/scripts/ExampleApp.dll");
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::MenuItem("Close", NULL, false, p_open != false))
|
||||
if (ImGui::MenuItem("Exit"))
|
||||
p_open = false;
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
if (ImGui::BeginMenu("Help"))
|
||||
{
|
||||
ImGui::TextUnformatted(
|
||||
"This demo has nothing to do with enabling docking!" "\n"
|
||||
"This demo only demonstrate the use of ImGui::DockSpace() which allows you to manually\ncreate a docking node _within_ another window."
|
||||
"\n"
|
||||
"Most application can simply call ImGui::DockSpaceOverViewport() and be done with it.");
|
||||
ImGui::Separator();
|
||||
ImGui::TextUnformatted(
|
||||
"When docking is enabled, you can ALWAYS dock MOST window into another! Try it now!" "\n"
|
||||
"- Drag from window title bar or their tab to dock/undock." "\n"
|
||||
"- Drag from window menu button (upper-left button) to undock an entire node (all windows)." "\n"
|
||||
"- Hold SHIFT to disable docking (if io.ConfigDockingWithShift == false, default)" "\n"
|
||||
"- Hold SHIFT to enable docking (if io.ConfigDockingWithShift == true)");
|
||||
ImGui::Separator();
|
||||
ImGui::TextUnformatted("More details:");
|
||||
ImGui::Bullet();
|
||||
ImGui::SameLine();
|
||||
ImGui::TextLinkOpenURL("Docking Wiki page", "https://github.com/ocornut/imgui/wiki/Docking");
|
||||
ImGui::BulletText("Read comments in ShowExampleAppDockSpace()");
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
ImGuiShowHelpMarker(
|
||||
"You can _always_ dock _any_ window into another by holding the SHIFT key while moving a window. Try it now!"
|
||||
"\n"
|
||||
"This demo app has nothing to do with it!" "\n\n"
|
||||
"This demo app only demonstrate the use of ImGui::DockSpace() which allows you to manually create a docking node _within_ another window. This is useful so you can decorate your main application window (e.g. with a menu bar)."
|
||||
"\n\n"
|
||||
"ImGui::DockSpace() comes with one hard constraint: it needs to be submitted _before_ any window which may be docked into it. Therefore, if you use a dock spot as the central point of your application, you'll probably want it to be part of the very first window you are submitting to imgui every frame."
|
||||
"\n\n"
|
||||
"(NB: because of this constraint, the implicit \"Debug\" window can not be docked into an explicit DockSpace() node, because that window is submitted as part of the NewFrame() call. An easy workaround is that you can create your own implicit \"Debug##2\" window after calling DockSpace() and leave it in the window stack for anyone to use.)"
|
||||
);
|
||||
|
||||
ImGui::EndMenuBar();
|
||||
}
|
||||
|
||||
m_SceneHierarchyPanel->OnImGuiRender();
|
||||
|
||||
ScriptEngine::OnImGuiRender();
|
||||
|
||||
ImGui::End();
|
||||
|
||||
#endif
|
||||
|
||||
// Editor Panel ------------------------------------------------------------------------------
|
||||
ImGui::Begin("Model");
|
||||
|
||||
if (ImGui::RadioButton("Spheres", (int*)&m_SceneType, (int)SceneType::Spheres))
|
||||
m_ActiveScene = m_SphereScene;
|
||||
ImGui::SameLine();
|
||||
if (ImGui::RadioButton("Model", (int*)&m_SceneType, (int)SceneType::Model))
|
||||
m_ActiveScene = m_Scene;
|
||||
|
||||
ImGui::Begin("Environment");
|
||||
|
||||
if (ImGui::Button("Load Environment Map"))
|
||||
{
|
||||
std::string filename = Application::Get().OpenFile("*.hdr");
|
||||
if (!filename.empty())
|
||||
m_ActiveScene->SetEnvironment(Environment::Load(filename));
|
||||
m_EditorScene->SetEnvironment(Environment::Load(filename));
|
||||
}
|
||||
|
||||
ImGui::SliderFloat("Skybox LOD", &m_Scene->GetSkyboxLod(), 0.0f, 11.0f);
|
||||
ImGui::SliderFloat("Skybox LOD", &m_EditorScene->GetSkyboxLod(), 0.0f, 11.0f);
|
||||
|
||||
|
||||
ImGui::Columns(2);
|
||||
ImGui::AlignTextToFramePadding();
|
||||
|
||||
auto& light = m_Scene->GetLight();
|
||||
auto& light = m_EditorScene->GetLight();
|
||||
Property("Light Direction", light.Direction);
|
||||
Property("Light Radiance", light.Radiance, PropertyFlag::ColorProperty);
|
||||
Property("Light Multiplier", light.Multiplier, 0.0f, 5.0f);
|
||||
Property("Exposure", m_CameraEntity.GetComponent<CameraComponent>().Camera.GetExposure(), 0.0f, 5.0f);
|
||||
Property("Exposure", m_EditorCamera.GetExposure(), 0.0f, 5.0f);
|
||||
|
||||
Property("Radiance Prefiltering", m_RadiancePrefilter);
|
||||
Property("Env Map Rotation", m_EnvMapRotation, -360.0f, 360.0f);
|
||||
@ -500,6 +364,7 @@ namespace Prism
|
||||
ImGui::Separator();
|
||||
{
|
||||
ImGui::Text("Mesh");
|
||||
/*
|
||||
auto meshComponent = m_MeshEntity.GetComponent<MeshComponent>();
|
||||
std::string fullpath = meshComponent.Mesh ? meshComponent.Mesh->GetFilePath() : "None";
|
||||
size_t found = fullpath.find_last_of("/\\");
|
||||
@ -517,6 +382,7 @@ namespace Prism
|
||||
meshComponent.Mesh = newMesh;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
ImGui::Separator();
|
||||
|
||||
@ -679,14 +545,57 @@ namespace Prism
|
||||
|
||||
ImGui::End();
|
||||
|
||||
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(12, 0));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(12, 4));
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_ItemInnerSpacing, ImVec2(0, 0));
|
||||
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonHovered, ImVec4(0.8f, 0.8f, 0.8f, 0.0f));
|
||||
ImGui::PushStyleColor(ImGuiCol_ButtonActive, ImVec4(0, 0, 0, 0));
|
||||
ImGui::Begin("Toolbar");
|
||||
if (m_SceneState == SceneState::Edit)
|
||||
{
|
||||
if (ImGui::ImageButton("editbutton", (ImTextureID)(m_PlayButtonTex->GetRendererID()), ImVec2(32, 32), ImVec2(0, 0), ImVec2(1, 1), ImVec4(0,0,0,0), ImVec4(0.9f, 0.9f, 0.9f, 1.0f)))
|
||||
{
|
||||
OnScenePlay();
|
||||
}
|
||||
}
|
||||
else if (m_SceneState == SceneState::Play)
|
||||
{
|
||||
if (ImGui::ImageButton("playbutton", (ImTextureID)(m_PlayButtonTex->GetRendererID()), ImVec2(32, 32), ImVec2(0, 0), ImVec2(1, 1), ImVec4(1.0f, 1.0f, 1.0f, 0.2f)))
|
||||
{
|
||||
OnSceneStop();
|
||||
}
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::ImageButton("a", (ImTextureID)(m_PlayButtonTex->GetRendererID()), ImVec2(32, 32), ImVec2(0, 0), ImVec2(1, 1), ImVec4(0, 0, 0, 0), ImVec4(1.0f, 1.0f, 1.0f, 0.6f)))
|
||||
{
|
||||
PM_CORE_INFO("PLAY!");
|
||||
}
|
||||
ImGui::End();
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::PopStyleColor();
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::PopStyleVar();
|
||||
ImGui::PopStyleVar();
|
||||
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(0, 0));
|
||||
ImGui::Begin("Viewport");
|
||||
|
||||
m_ViewportPanelMouseOver = ImGui::IsWindowHovered();
|
||||
m_ViewportPanelFocused = ImGui::IsWindowFocused();
|
||||
|
||||
auto viewportOffset = ImGui::GetCursorPos(); // includes tab bar
|
||||
auto viewportSize = ImGui::GetContentRegionAvail();
|
||||
SceneRenderer::SetViewportSize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y);
|
||||
m_CameraEntity.GetComponent<CameraComponent>().Camera.SetProjectionMatrix(glm::perspectiveFov(glm::radians(45.0f), viewportSize.x, viewportSize.y, 0.1f, 10000.0f));
|
||||
m_CameraEntity.GetComponent<CameraComponent>().Camera.SetViewportSize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y);
|
||||
m_EditorScene->SetViewportSize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y);
|
||||
if (m_RuntimeScene)
|
||||
m_RuntimeScene->SetViewportSize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y);
|
||||
m_EditorCamera.SetProjectionMatrix(glm::perspectiveFov(glm::radians(45.0f), viewportSize.x, viewportSize.y, 0.1f, 10000.0f));
|
||||
m_EditorCamera.SetViewportSize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y);
|
||||
ImGui::Image((ImTextureRef)SceneRenderer::GetFinalColorBufferRendererID(), viewportSize, { 0, 1 }, { 1, 0 });
|
||||
|
||||
|
||||
@ -702,7 +611,7 @@ namespace Prism
|
||||
m_AllowViewportCameraEvents = ImGui::IsMouseHoveringRect(minBound, maxBound);
|
||||
|
||||
// ImGuizmo
|
||||
if (m_GizmoType != -1 && m_CurrentlySelectedTransform)
|
||||
if (m_GizmoType != -1 && !m_SelectionContext.empty())
|
||||
{
|
||||
auto& selection = m_SelectionContext[0];
|
||||
|
||||
@ -712,25 +621,24 @@ namespace Prism
|
||||
ImGuizmo::SetDrawlist();
|
||||
ImGuizmo::SetRect(ImGui::GetWindowPos().x, ImGui::GetWindowPos().y, rw, rh);
|
||||
|
||||
const auto& camera = m_CameraEntity.GetComponent<CameraComponent>().Camera;
|
||||
bool snap = Input::IsKeyPressed(Key::LEFT_CONTROL);
|
||||
|
||||
auto& entityTransform = selection.Entity.Transform();
|
||||
float snapValue[3] = { m_SnapValue, m_SnapValue, m_SnapValue };
|
||||
if (m_SelectionMode == SelectionMode::Entity)
|
||||
{
|
||||
ImGuizmo::Manipulate(glm::value_ptr(camera.GetViewMatrix()),
|
||||
glm::value_ptr(camera.GetProjectionMatrix()),
|
||||
ImGuizmo::Manipulate(glm::value_ptr(m_EditorCamera.GetViewMatrix()),
|
||||
glm::value_ptr(m_EditorCamera.GetProjectionMatrix()),
|
||||
(ImGuizmo::OPERATION)m_GizmoType,
|
||||
ImGuizmo::LOCAL,
|
||||
glm::value_ptr(m_MeshEntity.GetComponent<TransformComponent>().Transform),
|
||||
glm::value_ptr(entityTransform),
|
||||
nullptr,
|
||||
snap ? snapValue : nullptr);
|
||||
}else
|
||||
{
|
||||
glm::mat4 transformBase = entityTransform * selection.Mesh->Transform;
|
||||
ImGuizmo::Manipulate(glm::value_ptr(camera.GetViewMatrix()),
|
||||
glm::value_ptr(camera.GetProjectionMatrix()),
|
||||
ImGuizmo::Manipulate(glm::value_ptr(m_EditorCamera.GetViewMatrix()),
|
||||
glm::value_ptr(m_EditorCamera.GetProjectionMatrix()),
|
||||
(ImGuizmo::OPERATION)m_GizmoType,
|
||||
ImGuizmo::LOCAL,
|
||||
glm::value_ptr(transformBase),
|
||||
@ -748,10 +656,17 @@ namespace Prism
|
||||
|
||||
void EditorLayer::OnEvent(Event& e)
|
||||
{
|
||||
/*
|
||||
if (m_AllowViewportCameraEvents)
|
||||
m_Scene->GetCamera().OnEvent(e);
|
||||
*/
|
||||
if (m_SceneState == SceneState::Edit)
|
||||
{
|
||||
if (m_ViewportPanelMouseOver)
|
||||
m_EditorCamera.OnEvent(e);
|
||||
|
||||
m_EditorScene->OnEvent(e);
|
||||
}
|
||||
else if (m_SceneState == SceneState::Play)
|
||||
{
|
||||
m_RuntimeScene->OnEvent(e);
|
||||
}
|
||||
|
||||
EventDispatcher dispatcher(e);
|
||||
dispatcher.Dispatch<KeyPressedEvent>(PM_BIND_EVENT_FN(EditorLayer::OnKeyPressedEvent));
|
||||
@ -760,35 +675,57 @@ namespace Prism
|
||||
|
||||
bool EditorLayer::OnKeyPressedEvent(KeyPressedEvent& e)
|
||||
{
|
||||
switch (e.GetKeyCode())
|
||||
if (m_ViewportPanelFocused)
|
||||
{
|
||||
case KeyCode::Q:
|
||||
m_GizmoType = -1;
|
||||
break;
|
||||
case KeyCode::W:
|
||||
m_GizmoType = ImGuizmo::OPERATION::TRANSLATE;
|
||||
break;
|
||||
case KeyCode::E:
|
||||
m_GizmoType = ImGuizmo::OPERATION::ROTATE;
|
||||
break;
|
||||
case KeyCode::R:
|
||||
m_GizmoType = ImGuizmo::OPERATION::SCALE;
|
||||
break;
|
||||
case KeyCode::G:
|
||||
// Toggle grid
|
||||
if (Input::IsKeyPressed(KeyCode::LEFT_CONTROL))
|
||||
SceneRenderer::GetOptions().ShowGrid = !SceneRenderer::GetOptions().ShowGrid;
|
||||
break;
|
||||
case KeyCode::B:
|
||||
// Toggle bounding boxes
|
||||
if (Input::IsKeyPressed(KeyCode::LEFT_CONTROL))
|
||||
switch (e.GetKeyCode())
|
||||
{
|
||||
case KeyCode::Q:
|
||||
m_GizmoType = -1;
|
||||
break;
|
||||
case KeyCode::W:
|
||||
m_GizmoType = ImGuizmo::OPERATION::TRANSLATE;
|
||||
break;
|
||||
case KeyCode::E:
|
||||
m_GizmoType = ImGuizmo::OPERATION::ROTATE;
|
||||
break;
|
||||
case KeyCode::R:
|
||||
m_GizmoType = ImGuizmo::OPERATION::SCALE;
|
||||
break;
|
||||
case KeyCode::DELETE:
|
||||
if (m_SelectionContext.size())
|
||||
{
|
||||
const Entity selectedEntity = m_SelectionContext[0].Entity;
|
||||
m_EditorScene->DestroyEntity(selectedEntity);
|
||||
m_SelectionContext.clear();
|
||||
m_EditorScene->SetSelectedEntity({});
|
||||
m_SceneHierarchyPanel->SetSelected({});
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (Input::IsKeyPressed(KeyCode::LEFT_CONTROL))
|
||||
{
|
||||
switch (e.GetKeyCode())
|
||||
{
|
||||
case KeyCode::G:
|
||||
// Toggle grid
|
||||
SceneRenderer::GetOptions().ShowGrid = !SceneRenderer::GetOptions().ShowGrid;
|
||||
break;
|
||||
case KeyCode::B:
|
||||
// Toggle bounding boxes
|
||||
m_UIShowBoundingBoxes = !m_UIShowBoundingBoxes;
|
||||
ShowBoundingBoxes(m_UIShowBoundingBoxes, m_UIShowBoundingBoxesOnTop);
|
||||
break;
|
||||
case KeyCode::D:
|
||||
if (m_SelectionContext.size())
|
||||
{
|
||||
Entity selectedEntity = m_SelectionContext[0].Entity;
|
||||
m_EditorScene->DuplicateEntity(selectedEntity);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -803,10 +740,11 @@ namespace Prism
|
||||
auto [origin, direction] = CastRay(mouseX, mouseY);
|
||||
|
||||
m_SelectionContext.clear();
|
||||
const auto meshEntities = m_Scene->GetAllEntitiesWith<MeshComponent>();
|
||||
m_EditorScene->SetSelectedEntity({});
|
||||
const auto meshEntities = m_EditorScene->GetAllEntitiesWith<MeshComponent>();
|
||||
for (auto e : meshEntities)
|
||||
{
|
||||
Entity entity = { e, m_Scene.Raw() };
|
||||
Entity entity = { e, m_EditorScene.Raw() };
|
||||
auto mesh = entity.GetComponent<MeshComponent>().Mesh;
|
||||
|
||||
if (!mesh)
|
||||
@ -857,6 +795,20 @@ namespace Prism
|
||||
m_DrawOnTopBoundingBoxes = show && onTop;
|
||||
}
|
||||
|
||||
void EditorLayer::SelectEntity(Entity entity)
|
||||
{
|
||||
SelectedSubmesh selection;
|
||||
if (entity.HasComponent<MeshComponent>())
|
||||
{
|
||||
selection.Mesh = &entity.GetComponent<MeshComponent>().Mesh->GetSubmeshes()[0];
|
||||
}
|
||||
selection.Entity = entity;
|
||||
m_SelectionContext.clear();
|
||||
m_SelectionContext.push_back(selection);
|
||||
|
||||
m_EditorScene->SetSelectedEntity(entity);
|
||||
}
|
||||
|
||||
std::pair<float, float> EditorLayer::GetMouseViewportSpace() const
|
||||
{
|
||||
auto [mx, my] = ImGui::GetMousePos(); // Input::GetMousePosition();
|
||||
@ -872,11 +824,11 @@ namespace Prism
|
||||
{
|
||||
const glm::vec4 mouseClipPos = { mx, my, -1.0f, 1.0f };
|
||||
|
||||
const auto inverseProj = glm::inverse(m_CameraEntity.GetComponent<CameraComponent>().Camera.GetProjectionMatrix());
|
||||
const auto inverseView = glm::inverse(glm::mat3(m_CameraEntity.GetComponent<CameraComponent>().Camera.GetViewMatrix()));
|
||||
const auto inverseProj = glm::inverse(m_EditorCamera.GetProjectionMatrix());
|
||||
const auto inverseView = glm::inverse(glm::mat3(m_EditorCamera.GetViewMatrix()));
|
||||
|
||||
const glm::vec4 ray = inverseProj * mouseClipPos;
|
||||
glm::vec3 rayPos = m_CameraEntity.GetComponent<CameraComponent>().Camera.GetPosition();
|
||||
glm::vec3 rayPos = m_EditorCamera.GetPosition();
|
||||
glm::vec3 rayDir = inverseView * glm::vec3(ray);
|
||||
|
||||
return { rayPos, rayDir };
|
||||
@ -885,6 +837,16 @@ namespace Prism
|
||||
void EditorLayer::OnSelected(const SelectedSubmesh& selectionContext)
|
||||
{
|
||||
m_SceneHierarchyPanel->SetSelected(selectionContext.Entity);
|
||||
m_EditorScene->SetSelectedEntity(selectionContext.Entity);
|
||||
}
|
||||
|
||||
void EditorLayer::OnEntityDeleted(Entity e)
|
||||
{
|
||||
if (m_SelectionContext[0].Entity == e)
|
||||
{
|
||||
m_SelectionContext.clear();
|
||||
m_EditorScene->SetSelectedEntity({});
|
||||
}
|
||||
}
|
||||
|
||||
Ray EditorLayer::CastMouseRay()
|
||||
@ -897,4 +859,30 @@ namespace Prism
|
||||
}
|
||||
return Ray::Zero();
|
||||
}
|
||||
|
||||
void EditorLayer::OnScenePlay()
|
||||
{
|
||||
m_SelectionContext.clear();
|
||||
|
||||
m_SceneState = SceneState::Play;
|
||||
|
||||
m_RuntimeScene = Ref<Scene>::Create();
|
||||
m_EditorScene->CopyTo(m_RuntimeScene);
|
||||
|
||||
m_RuntimeScene->OnRuntimeStart();
|
||||
m_SceneHierarchyPanel->SetContext(m_RuntimeScene);
|
||||
}
|
||||
|
||||
void EditorLayer::OnSceneStop()
|
||||
{
|
||||
m_RuntimeScene->OnRuntimeStop();
|
||||
m_SceneState = SceneState::Edit;
|
||||
|
||||
// Unload runtime scene
|
||||
m_RuntimeScene = nullptr;
|
||||
|
||||
m_SelectionContext.clear();
|
||||
ScriptEngine::SetSceneContext(m_EditorScene);
|
||||
m_SceneHierarchyPanel->SetContext(m_EditorScene);
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,7 +27,7 @@ namespace Prism
|
||||
bool OnMouseButtonPressedEvent(MouseButtonPressedEvent& e);
|
||||
|
||||
void ShowBoundingBoxes(bool show, bool onTop = false);
|
||||
|
||||
void SelectEntity(Entity entity);
|
||||
private:
|
||||
std::pair<float, float> GetMouseViewportSpace() const;
|
||||
std::pair<glm::vec3, glm::vec3> CastRay(float mx, float my);
|
||||
@ -35,23 +35,24 @@ namespace Prism
|
||||
struct SelectedSubmesh
|
||||
{
|
||||
Prism::Entity Entity;
|
||||
Submesh* Mesh;
|
||||
float Distance;
|
||||
Submesh* Mesh = nullptr;
|
||||
float Distance = 0.0f;
|
||||
};
|
||||
void OnSelected(const SelectedSubmesh& selectionContext);
|
||||
void OnEntityDeleted(Entity e);
|
||||
Ray CastMouseRay();
|
||||
|
||||
void OnScenePlay();
|
||||
void OnSceneStop();
|
||||
private:
|
||||
Scope<SceneHierarchyPanel> m_SceneHierarchyPanel;
|
||||
|
||||
Ref<Scene> m_Scene;
|
||||
Ref<Scene> m_SphereScene;
|
||||
Ref<Scene> m_ActiveScene;
|
||||
Ref<Scene> m_RuntimeScene, m_EditorScene;
|
||||
|
||||
Entity m_MeshEntity;
|
||||
Entity m_CameraEntity;
|
||||
EditorCamera m_EditorCamera;
|
||||
|
||||
Ref<Material> m_SphereBaseMaterial;
|
||||
|
||||
Ref<Material> m_MeshMaterial;
|
||||
|
||||
std::vector<Ref<MaterialInstance>> m_MetalSphereMaterialInstances;
|
||||
@ -71,14 +72,6 @@ namespace Prism
|
||||
|
||||
std::vector<SelectedSubmesh> m_SelectionContext;
|
||||
glm::mat4* m_RelativeTransform = nullptr;
|
||||
glm::mat4* m_CurrentlySelectedTransform = nullptr;
|
||||
|
||||
// configure button
|
||||
bool m_AllowViewportCameraEvents = false;
|
||||
bool m_DrawOnTopBoundingBoxes = false;
|
||||
|
||||
bool m_UIShowBoundingBoxes = false;
|
||||
bool m_UIShowBoundingBoxesOnTop = false;
|
||||
|
||||
|
||||
struct AlbedoInput
|
||||
@ -119,14 +112,33 @@ namespace Prism
|
||||
|
||||
float m_EnvMapRotation = 0.0f;
|
||||
|
||||
|
||||
// Editor resources
|
||||
Ref<Texture2D> m_CheckerboardTex;
|
||||
Ref<Texture2D> m_PlayButtonTex;
|
||||
|
||||
|
||||
// configure button
|
||||
bool m_AllowViewportCameraEvents = false;
|
||||
bool m_DrawOnTopBoundingBoxes = false;
|
||||
|
||||
bool m_UIShowBoundingBoxes = false;
|
||||
bool m_UIShowBoundingBoxesOnTop = false;
|
||||
|
||||
enum class SceneType : uint32_t
|
||||
{
|
||||
Spheres = 0, Model = 1
|
||||
};
|
||||
SceneType m_SceneType;
|
||||
|
||||
// Editor resources
|
||||
Ref<Texture2D> m_CheckerboardTex;
|
||||
bool m_ViewportPanelMouseOver = false;
|
||||
bool m_ViewportPanelFocused = false;
|
||||
|
||||
enum class SceneState
|
||||
{
|
||||
Edit = 0, Play = 1, Pause = 2
|
||||
};
|
||||
SceneState m_SceneState = SceneState::Edit;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
BIN
Editor/assets/editor/PlayButton.png
Normal file
BIN
Editor/assets/editor/PlayButton.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 357 B |
66
Editor/assets/scenes/PinkSunrise.hsc
Normal file
66
Editor/assets/scenes/PinkSunrise.hsc
Normal file
@ -0,0 +1,66 @@
|
||||
Scene: Scene Name
|
||||
Environment:
|
||||
AssetPath: assets\env\birchwood_4k.hdr
|
||||
Light:
|
||||
Direction: [-0.5, -0.5, 1]
|
||||
Radiance: [1, 1, 1]
|
||||
Multiplier: 1
|
||||
Entities:
|
||||
- Entity: 1289165777996378215
|
||||
TagComponent:
|
||||
Tag: Sphere
|
||||
TransformComponent:
|
||||
Position: [0, 21.9805069, -1.64006281]
|
||||
Rotation: [1, 0, 0, 0]
|
||||
Scale: [0.100000024, 0.100000024, 0.100000024]
|
||||
ScriptComponent:
|
||||
ModuleName: Example.Sink
|
||||
StoredFields:
|
||||
- Name: SinkSpeed
|
||||
Type: 1
|
||||
Data: 5
|
||||
MeshComponent:
|
||||
AssetPath: assets\meshes\Sphere1m.fbx
|
||||
- Entity: 5178862374589434728
|
||||
TagComponent:
|
||||
Tag: Camera
|
||||
TransformComponent:
|
||||
Position: [0, 14.75, 79.75]
|
||||
Rotation: [0.995602965, -0.0936739072, 0, 0]
|
||||
Scale: [1, 0.999999821, 0.999999821]
|
||||
ScriptComponent:
|
||||
ModuleName: Example.BasicController
|
||||
StoredFields:
|
||||
- Name: Speed
|
||||
Type: 1
|
||||
Data: 12
|
||||
CameraComponent:
|
||||
Camera: some camera data...
|
||||
Primary: true
|
||||
- Entity: 9095450049242347594
|
||||
TagComponent:
|
||||
Tag: Test Entity
|
||||
TransformComponent:
|
||||
Position: [0.248109579, -1.90734863e-06, -0.268640995]
|
||||
Rotation: [1, 0, 0, 0]
|
||||
Scale: [1, 1, 1]
|
||||
ScriptComponent:
|
||||
ModuleName: Example.Script
|
||||
StoredFields:
|
||||
- Name: VerticalSpeed
|
||||
Type: 1
|
||||
Data: 0
|
||||
- Name: SinkRate
|
||||
Type: 1
|
||||
Data: 0
|
||||
- Name: Speed
|
||||
Type: 1
|
||||
Data: 1
|
||||
- Name: Rotation
|
||||
Type: 1
|
||||
Data: 0
|
||||
- Name: Velocity
|
||||
Type: 6
|
||||
Data: [0, 0, 0]
|
||||
MeshComponent:
|
||||
AssetPath: assets\meshes\TestScene.fbx
|
||||
27
Editor/assets/shaders/Outline.glsl
Normal file
27
Editor/assets/shaders/Outline.glsl
Normal file
@ -0,0 +1,27 @@
|
||||
// Outline Shader
|
||||
|
||||
#type vertex
|
||||
#version 430
|
||||
|
||||
layout(location = 0) in vec3 a_Position;
|
||||
layout(location = 1) in vec2 a_TexCoord;
|
||||
|
||||
uniform mat4 u_ViewProjection;
|
||||
uniform mat4 u_Transform;
|
||||
|
||||
out vec2 v_TexCoord;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = u_ViewProjection * u_Transform * vec4(a_Position, 1.0);
|
||||
}
|
||||
|
||||
#type fragment
|
||||
#version 430
|
||||
|
||||
layout(location = 0) out vec4 color;
|
||||
|
||||
void main()
|
||||
{
|
||||
color = vec4(1.0, 0.5, 0.0, 1.0);
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
// -----------------------------
|
||||
// -- Hazel Engine PBR shader --
|
||||
// -- From Hazel Engine PBR shader --
|
||||
// -----------------------------
|
||||
// Note: this shader is still very much in progress. There are likely many bugs and future additions that will go in.
|
||||
// Currently heavily updated.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
// -----------------------------
|
||||
// -- Hazel Engine PBR shader --
|
||||
// -- From Hazel Engine PBR shader --
|
||||
// -----------------------------
|
||||
// Note: this shader is still very much in progress. There are likely many bugs and future additions that will go in.
|
||||
// Currently heavily updated.
|
||||
|
||||
Reference in New Issue
Block a user