diff --git a/assets b/assets index 95823e12..c5f67434 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 95823e122ab11135170d1d70ab2535ae1d332fdd +Subproject commit c5f674349a915ab1a2b4da632d87a9832d1f6fab diff --git a/include/Engine/Editor/EditorSystem.h b/include/Engine/Editor/EditorSystem.h index 92e237d1..be4cd608 100644 --- a/include/Engine/Editor/EditorSystem.h +++ b/include/Engine/Editor/EditorSystem.h @@ -2,34 +2,69 @@ #include #include "../Core/System.h" #include "../Core/EMousePress.h" +#include "../Core/EMouseRelease.h" +#include "../Core/EMouseMove.h" #include "../Core/ConfigFile.h" #include "../Input/EInputCommand.h" +#include "../Rendering/IRenderer.h" #include "../Rendering/EPicking.h" #include "../Rendering/RenderQueueFactory.h" class EditorSystem : public ImpureSystem { public: - EditorSystem(EventBroker* eventBroker); + EditorSystem(EventBroker* eventBroker, IRenderer* renderer); virtual void Update(World* world, double dt) override; private: + IRenderer* m_Renderer; + World* m_World = nullptr; + bool m_Enabled; bool m_Visible; std::vector m_PickingQueue; + + enum class WidgetMode + { + None, + Translate, + Rotate, + Scale + } m_WidgetMode = WidgetMode::None; + + enum class WidgetSpace + { + Local, + Global + } m_WidgetSpace = WidgetSpace::Global; + EntityID m_Widget = 0; + EntityID m_WidgetX = 0; + EntityID m_WidgetY = 0; + EntityID m_WidgetZ = 0; + EntityID m_WidgetOrigin = 0; + glm::vec3 m_WidgetCurrentAxis; + float m_WidgetPickingDepth = 0.f; + EntityID m_Selection = 0; EntityID m_LastSelection = 0; glm::vec3 m_Position; EventRelay m_EInputCommand; bool OnInputCommand(const Events::InputCommand& e); + EventRelay m_EMouseRelease; + bool OnMouseRelease(const Events::MouseRelease& e); EventRelay m_EMousePress; bool OnMousePress(const Events::MousePress& e); + EventRelay m_EMouseMove; + bool OnMouseMove(const Events::MouseMove& e); EventRelay m_EPicking; bool OnPicking(const Events::Picking& e); + void updateWidget(); + void setWidgetMode(WidgetMode newMode); + void setWidgetSpace(WidgetSpace space); void drawUI(World* world, double dt); bool createDeleteButton(std::string componentType); }; \ No newline at end of file diff --git a/include/Engine/Rendering/EPicking.h b/include/Engine/Rendering/EPicking.h index 044a944b..85c4b629 100644 --- a/include/Engine/Rendering/EPicking.h +++ b/include/Engine/Rendering/EPicking.h @@ -34,6 +34,8 @@ public: EntityID Entity; //World position of the "pick" glm::vec3 Position; + // Depth + float Depth; }; PickData Pick(glm::vec2 screenCoord) const @@ -43,6 +45,7 @@ public: // Invert screen y coordinate screenCoord.y = Resolution.Height - screenCoord.y; ScreenCoords::PixelData data = ScreenCoords::ToPixelData(screenCoord, PickingBuffer, *DepthBuffer); + pickData.Depth = data.Depth; auto it = PickingColorsToEntity->find(glm::vec2(data.Color[0], data.Color[1])); if (it != PickingColorsToEntity->end()) { diff --git a/src/Engine/Editor/EditorSystem.cpp b/src/Engine/Editor/EditorSystem.cpp index a56ba79c..fbad2281 100644 --- a/src/Engine/Editor/EditorSystem.cpp +++ b/src/Engine/Editor/EditorSystem.cpp @@ -2,8 +2,9 @@ #define IMGUI_DEFINE_MATH_OPERATORS #include -EditorSystem::EditorSystem(EventBroker* eventBroker) +EditorSystem::EditorSystem(EventBroker* eventBroker, IRenderer* renderer) : ImpureSystem(eventBroker) + , m_Renderer(renderer) { auto config = ResourceManager::Load("Config.ini"); m_Enabled = config->Get("Debug.EditorEnabled", false); @@ -15,51 +16,52 @@ EditorSystem::EditorSystem(EventBroker* eventBroker) EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &EditorSystem::OnInputCommand); EVENT_SUBSCRIBE_MEMBER(m_EMousePress, &EditorSystem::OnMousePress); + EVENT_SUBSCRIBE_MEMBER(m_EMouseRelease, &EditorSystem::OnMouseRelease); + EVENT_SUBSCRIBE_MEMBER(m_EMouseMove, &EditorSystem::OnMouseMove); EVENT_SUBSCRIBE_MEMBER(m_EPicking, &EditorSystem::OnPicking); } void EditorSystem::Update(World* world, double dt) { + m_World = world; + if (!m_Enabled) { return; } - if (m_Widget == 0) { - m_Widget = world->CreateEntity(); - world->AttachComponent(m_Widget, "Transform"); - auto& model = world->AttachComponent(m_Widget, "Model"); - model["Resource"] = "Models/TranslationWidget.obj"; - } - - if (m_Selection != m_LastSelection) { - - } - - auto& widgetModel = world->GetComponent(m_Widget, "Model"); - widgetModel["Visible"] = m_Visible; - if (m_Selection != 0) { - if (world->HasComponent(m_Selection, "Transform")) { - glm::vec3 pos = RenderQueueFactory::AbsolutePosition(world, m_Selection); - auto widgetTransform = world->GetComponent(m_Widget, "Transform"); - widgetTransform["Position"] = pos; - } else { - m_Selection = 0; - } - } - if (!m_Visible) { return; } + updateWidget(); + drawUI(world, dt); } - bool EditorSystem::OnInputCommand(const Events::InputCommand& e) { if (e.Command == "ToggleEditor" && e.Value > 0) { m_Visible = !m_Visible; } + + if (e.Command == "EditorToolMove" && e.Value > 0) { + setWidgetMode(WidgetMode::Translate); + } + if (e.Command == "EditorToolRotate" && e.Value > 0) { + setWidgetMode(WidgetMode::Rotate); + } + if (e.Command == "EditorToolScale" && e.Value > 0) { + setWidgetMode(WidgetMode::Scale); + } + + if (e.Command == "EditorToggleTransformSpace" && e.Value > 0) { + if (m_WidgetSpace == WidgetSpace::Global) { + setWidgetSpace(WidgetSpace::Local); + } else if (m_WidgetSpace == WidgetSpace::Local) { + setWidgetSpace(WidgetSpace::Global); + } + } + return true; } @@ -71,17 +73,216 @@ bool EditorSystem::OnMousePress(const Events::MousePress& e) return true; } +bool EditorSystem::OnMouseMove(const Events::MouseMove& e) +{ + if (m_Widget == 0) { + return false; + } + + auto widgetTransform = m_World->GetComponent(m_Widget, "Transform"); + glm::vec3 widgetOrientation = widgetTransform["Orientation"]; + + glm::quat totalOrientation = m_Renderer->Camera()->Orientation() * glm::inverse(glm::quat(widgetOrientation)); + + int width; + int height; + glfwGetFramebufferSize(m_Renderer->Window(), &width, &height); + Rectangle res(width, height); + + glm::vec2 delta2(res.Width / 2.f + e.DeltaX, res.Height / 2.f + -e.DeltaY); + glm::vec3 deltaWorld = ScreenCoords::ToWorldPos( + delta2, + m_WidgetPickingDepth, + res, + m_Renderer->Camera()->ProjectionMatrix(), + glm::toMat4(glm::inverse(totalOrientation)) + ); + glm::vec3 origin = ScreenCoords::ToWorldPos( + glm::vec2(res.Width / 2.f, res.Height / 2.f), + m_WidgetPickingDepth, + res, + m_Renderer->Camera()->ProjectionMatrix(), + glm::toMat4(glm::inverse(totalOrientation)) + ); + deltaWorld = deltaWorld - origin; + glm::vec3 movement = deltaWorld * m_WidgetCurrentAxis; + + if (glm::length2(m_WidgetCurrentAxis) > 0.f) { + auto widgetTransform = m_World->GetComponent(m_Widget, "Transform"); + if (m_WidgetMode == WidgetMode::Translate) { + if (m_WidgetSpace == WidgetSpace::Global) { + (glm::vec3&)m_World->GetComponent(m_Selection, "Transform")["Position"] += movement; + } else if (m_WidgetSpace == WidgetSpace::Local) { + auto selectionTransform = m_World->GetComponent(m_Selection, "Transform"); + (glm::vec3&)selectionTransform["Position"] += glm::quat((glm::vec3&)selectionTransform["Orientation"]) * movement; + } + } else if (m_WidgetMode == WidgetMode::Rotate) { + glm::vec3 finalMovement; + finalMovement.x = -deltaWorld.y * m_WidgetCurrentAxis.x; + finalMovement.y = deltaWorld.x * m_WidgetCurrentAxis.y; + finalMovement.z = deltaWorld.y * m_WidgetCurrentAxis.z; + glm::vec3& selectionOrientation = m_World->GetComponent(m_Selection, "Transform")["Orientation"]; + if (m_WidgetSpace == WidgetSpace::Global) { + glm::quat currentOrientation = glm::quat(selectionOrientation); + glm::quat deltaOrientation(finalMovement); + selectionOrientation = glm::eulerAngles(deltaOrientation * currentOrientation); // (currentOrientation * deltaOrientation) * glm::vec3(0, 0, -1); + } else if (m_WidgetSpace == WidgetSpace::Local) { + glm::quat currentOrientation(selectionOrientation); + glm::quat deltaOrientation(finalMovement); + selectionOrientation = glm::eulerAngles(currentOrientation * deltaOrientation); // (currentOrientation * deltaOrientation) * glm::vec3(0, 0, -1); + widgetTransform["Orientation"] = selectionOrientation; + } + } else if (m_WidgetMode == WidgetMode::Scale) { + glm::vec3& scaleX = m_World->GetComponent(m_WidgetX, "Transform")["Scale"]; + glm::vec3& scaleY = m_World->GetComponent(m_WidgetY, "Transform")["Scale"]; + glm::vec3& scaleZ = m_World->GetComponent(m_WidgetZ, "Transform")["Scale"]; + if (m_WidgetCurrentAxis.x > 0) { + scaleX.x += movement.x; + } + if (m_WidgetCurrentAxis.y > 0) { + scaleY.y += movement.y; + } + if (m_WidgetCurrentAxis.z > 0) { + scaleZ.z += movement.z; + } + if (m_WidgetCurrentAxis.x > 0 && m_WidgetCurrentAxis.y > 0 && m_WidgetCurrentAxis.z > 0) { + float max = glm::max(scaleX.x, glm::max(scaleY.y, scaleZ.z)); + (glm::vec3&)m_World->GetComponent(m_WidgetOrigin, "Transform")["Scale"] = glm::vec3(max); + } + (glm::vec3&)m_World->GetComponent(m_Selection, "Transform")["Scale"] += movement; + } + } + + return true; +} + +bool EditorSystem::OnMouseRelease(const Events::MouseRelease& e) +{ + if (glm::length2(m_WidgetCurrentAxis) > 0.f) { + m_WidgetCurrentAxis = glm::vec3(0.f); + //setWidgetMode(m_WidgetMode); + } + + return true; +} + bool EditorSystem::OnPicking(const Events::Picking& e) { for (auto& pos : m_PickingQueue) { auto result = e.Pick(pos); - LOG_INFO("Selected %i", result.Entity); - m_Selection = result.Entity; + EntityID entity = result.Entity; + if (glm::length2(m_WidgetCurrentAxis) > 0.f) { + } else { + LOG_INFO("Selected %i", entity); + if (entity != 0) { + EntityID parent = m_World->GetParent(entity); + if (parent == m_Widget) { + m_WidgetCurrentAxis = glm::vec3( + (entity == m_WidgetX) || (entity == m_WidgetOrigin), + (entity == m_WidgetY) || (entity == m_WidgetOrigin), + (entity == m_WidgetZ) || (entity == m_WidgetOrigin) + ); + m_WidgetPickingDepth = result.Depth; + + //auto widgetTransform = m_World->GetComponent(m_Widget, "Transform"); + //auto selectionTransform = m_World->GetComponent(m_Selection, "Transform"); + //widgetTransform["Position"] = (glm::vec3)selectionTransform["Position"]; + } else { + m_Selection = entity; + } + } else { + m_Selection = 0; + } + } } m_PickingQueue.clear(); return true; }; + +void EditorSystem::updateWidget() +{ + if (m_Widget == 0) { + m_Widget = m_World->CreateEntity(); + m_World->AttachComponent(m_Widget, "Transform"); + m_WidgetX = m_World->CreateEntity(m_Widget); + m_World->AttachComponent(m_WidgetX, "Transform"); + m_World->AttachComponent(m_WidgetX, "Model"); + m_WidgetY = m_World->CreateEntity(m_Widget); + m_World->AttachComponent(m_WidgetY, "Transform"); + m_World->AttachComponent(m_WidgetY, "Model"); + m_WidgetZ = m_World->CreateEntity(m_Widget); + m_World->AttachComponent(m_WidgetZ, "Transform"); + m_World->AttachComponent(m_WidgetZ, "Model"); + m_WidgetOrigin = m_World->CreateEntity(m_Widget); + m_World->AttachComponent(m_WidgetOrigin, "Transform"); + m_World->AttachComponent(m_WidgetOrigin, "Model"); + setWidgetMode(WidgetMode::Translate); + } + + if (m_Selection != 0) { + auto widgetTransform = m_World->GetComponent(m_Widget, "Transform"); + auto selectionTransform = m_World->GetComponent(m_Selection, "Transform"); + widgetTransform["Position"] = (glm::vec3)selectionTransform["Position"]; + } +} + +void EditorSystem::setWidgetMode(WidgetMode newMode) +{ + if (m_Widget == 0) { + return; + } + + auto widgetTransform = m_World->GetComponent(m_Widget, "Transform"); + widgetTransform["Orientation"] = glm::vec3(0.f); + m_World->GetComponent(m_WidgetX, "Transform")["Scale"] = glm::vec3(1.f); + m_World->GetComponent(m_WidgetY, "Transform")["Scale"] = glm::vec3(1.f); + m_World->GetComponent(m_WidgetZ, "Transform")["Scale"] = glm::vec3(1.f); + m_World->GetComponent(m_WidgetOrigin, "Transform")["Scale"] = glm::vec3(1.f); + + if (newMode == WidgetMode::Translate) { + m_World->GetComponent(m_WidgetX, "Model")["Resource"] = "Models/TranslationWidgetX.obj"; + m_World->GetComponent(m_WidgetY, "Model")["Resource"] = "Models/TranslationWidgetY.obj"; + m_World->GetComponent(m_WidgetZ, "Model")["Resource"] = "Models/TranslationWidgetZ.obj"; + m_World->GetComponent(m_WidgetOrigin, "Model")["Visible"] = false; + if (m_Selection != 0) { + if (m_WidgetSpace == WidgetSpace::Local) { + auto selectionTransform = m_World->GetComponent(m_Selection, "Transform"); + widgetTransform["Orientation"] = (glm::vec3)selectionTransform["Orientation"]; + } + } + } else if (newMode == WidgetMode::Scale) { + m_World->GetComponent(m_WidgetX, "Model")["Resource"] = "Models/ScaleWidgetX.obj"; + m_World->GetComponent(m_WidgetY, "Model")["Resource"] = "Models/ScaleWidgetY.obj"; + m_World->GetComponent(m_WidgetZ, "Model")["Resource"] = "Models/ScaleWidgetZ.obj"; + m_World->GetComponent(m_WidgetOrigin, "Model")["Visible"] = true; + m_World->GetComponent(m_WidgetOrigin, "Model")["Resource"] = "Models/ScaleWidgetOrigin.obj"; + if (m_Selection != 0) { + auto selectionTransform = m_World->GetComponent(m_Selection, "Transform"); + widgetTransform["Orientation"] = (glm::vec3)selectionTransform["Orientation"]; + } + } else if (newMode == WidgetMode::Rotate) { + m_World->GetComponent(m_WidgetX, "Model")["Resource"] = "Models/RotationWidgetX.obj"; + m_World->GetComponent(m_WidgetY, "Model")["Resource"] = "Models/RotationWidgetY.obj"; + m_World->GetComponent(m_WidgetZ, "Model")["Resource"] = "Models/RotationWidgetZ.obj"; + m_World->GetComponent(m_WidgetOrigin, "Model")["Visible"] = false; + if (m_Selection != 0) { + auto selectionTransform = m_World->GetComponent(m_Selection, "Transform"); + if (m_WidgetSpace == WidgetSpace::Local) { + widgetTransform["Orientation"] = (glm::vec3)selectionTransform["Orientation"]; + } + } + } + m_WidgetMode = newMode; +} + + +void EditorSystem::setWidgetSpace(WidgetSpace space) +{ + m_WidgetSpace = space; + setWidgetMode(m_WidgetMode); +} + void EditorSystem::drawUI(World* world, double dt) { ImGui::ShowTestWindow(); @@ -102,24 +303,32 @@ void EditorSystem::drawUI(World* world, double dt) ImGui::SameLine(); if (ImGui::Button("Move")) { - auto& model = world->GetComponent(m_Widget, "Model"); - model["Resource"] = "Models/TranslationWidget.obj"; + setWidgetMode(WidgetMode::Translate); } ImGui::SameLine(); if (ImGui::Button("Rotate")) { - auto& model = world->GetComponent(m_Widget, "Model"); - model["Resource"] = "Models/RotationWidget.obj"; + setWidgetMode(WidgetMode::Rotate); } ImGui::SameLine(); if (ImGui::Button("Scale")) { - auto& model = world->GetComponent(m_Widget, "Model"); - model["Resource"] = "Models/ScaleWidget.obj"; + setWidgetMode(WidgetMode::Scale); + } + ImGui::SameLine(); + if (m_WidgetSpace == WidgetSpace::Global) { + if (ImGui::Button("(Global)")) { + setWidgetSpace(WidgetSpace::Local); + } + } else if (m_WidgetSpace == WidgetSpace::Local) { + if (ImGui::Button("(Local)")) { + setWidgetSpace(WidgetSpace::Global); + } } ImGui::EndMainMenuBar(); } - if (ImGui::Begin("Components")) { + std::string title = std::string("Components #") + std::to_string(m_Selection) + std::string("###Components"); + if (ImGui::Begin(title.c_str())) { if (m_Selection != 0) { auto& pools = world->GetComponentPools(); diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index 68402469..06810412 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -135,12 +135,10 @@ void Renderer::Update(double dt) void Renderer::Draw(RenderQueueCollection& rq) { m_PickingPass->Draw(rq); - //DrawScreenQuad(m_PickingPass->PickingTexture()); + DrawScreenQuad(m_PickingPass->PickingTexture()); //CullLights(); glClearColor(255.f / 255, 163.f / 255, 176.f / 255, 1.f); - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); m_DrawScenePass->Draw(rq); GLERROR("Renderer::Draw m_DrawScenePass->Draw"); diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 061ac835..7f7559e0 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -52,7 +52,7 @@ Game::Game(int argc, char* argv[]) m_SystemPipeline = new SystemPipeline(m_EventBroker); m_SystemPipeline->AddSystem(); m_SystemPipeline->AddSystem(); - m_SystemPipeline->AddSystem(); + m_SystemPipeline->AddSystem(m_Renderer); m_LastTime = glfwGetTime();