From 322aedaf72832ba24a65c96d5a8f31ceed6de41a Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Tue, 15 Dec 2015 18:01:20 +0100 Subject: [PATCH 01/14] Basic transformation widgets --- assets | 2 +- include/Engine/Editor/EditorSystem.h | 37 +++- include/Engine/Rendering/EPicking.h | 3 + src/Engine/Editor/EditorSystem.cpp | 277 +++++++++++++++++++++++---- src/Engine/Rendering/Renderer.cpp | 4 +- src/Game/Game.cpp | 2 +- 6 files changed, 285 insertions(+), 40 deletions(-) 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(); From bd6adcc15773b4ce9d6144954379a45a5563ecb0 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Wed, 16 Dec 2015 12:05:31 +0100 Subject: [PATCH 02/14] Added SetParent to World --- include/Engine/Core/World.h | 3 +++ src/Engine/Core/World.cpp | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/include/Engine/Core/World.h b/include/Engine/Core/World.h index da31d369..92378816 100644 --- a/include/Engine/Core/World.h +++ b/include/Engine/Core/World.h @@ -31,6 +31,8 @@ public: const ComponentPool* GetComponents(std::string componentType); // Get entity parent EntityID GetParent(EntityID entity); + // Change the parent of an entity + void SetParent(EntityID entity, EntityID parent); // Get all component pools const std::unordered_map& GetComponentPools() const { return m_ComponentPools; } // Get the entity children map @@ -40,6 +42,7 @@ private: EntityID m_CurrentEntityID = 1; std::unordered_map m_EntityParents; + // TODO: This should be a more effective structure std::unordered_multimap m_EntityChildren; std::unordered_map m_ComponentPools; diff --git a/src/Engine/Core/World.cpp b/src/Engine/Core/World.cpp index 7ee5e6a7..5443d388 100644 --- a/src/Engine/Core/World.cpp +++ b/src/Engine/Core/World.cpp @@ -99,6 +99,22 @@ EntityID World::GetParent(EntityID entity) return m_EntityParents.at(entity); } + +void World::SetParent(EntityID entity, EntityID parent) +{ + EntityID lastParent = m_EntityParents.at(entity); + auto parentChildren = m_EntityChildren.equal_range(lastParent); + for (auto it = parentChildren.first; it != parentChildren.second; it++) { + if (it->second == entity) { + m_EntityChildren.erase(it); + break; + } + } + + m_EntityParents[entity] = parent; + m_EntityChildren.insert(std::make_pair(parent, entity)); +} + EntityID World::generateEntityID() { // TODO: Make EntityID generation smarter From 661532e355e7144f044460fd365c31d8077231fe Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Wed, 16 Dec 2015 12:05:55 +0100 Subject: [PATCH 03/14] Slightly more usable entity tree --- include/Engine/Editor/EditorSystem.h | 1 + src/Engine/Editor/EditorSystem.cpp | 76 ++++++++++++++++++++++++---- 2 files changed, 67 insertions(+), 10 deletions(-) diff --git a/include/Engine/Editor/EditorSystem.h b/include/Engine/Editor/EditorSystem.h index be4cd608..021a14ca 100644 --- a/include/Engine/Editor/EditorSystem.h +++ b/include/Engine/Editor/EditorSystem.h @@ -67,4 +67,5 @@ private: void setWidgetSpace(WidgetSpace space); void drawUI(World* world, double dt); bool createDeleteButton(std::string componentType); + void changeParent(EntityID entity, EntityID newParent); }; \ No newline at end of file diff --git a/src/Engine/Editor/EditorSystem.cpp b/src/Engine/Editor/EditorSystem.cpp index fbad2281..e224ca6b 100644 --- a/src/Engine/Editor/EditorSystem.cpp +++ b/src/Engine/Editor/EditorSystem.cpp @@ -414,23 +414,62 @@ void EditorSystem::drawUI(World* world, double dt) ImGui::End(); if (ImGui::Begin("Entitites")) { + static EntityID draggingEntity = 0; auto entityChildren = world->GetEntityChildren(); std::function recurse = [&](EntityID parent) { auto range = entityChildren.equal_range(parent); for (auto it = range.first; it != range.second; it++) { + + ImVec2 pos = ImGui::GetCursorScreenPos(); + float width = ImGui::GetContentRegionAvailWidth(); + ImRect bb(pos + ImVec2(20, 0), pos + ImVec2(width, 13)); + auto window = ImGui::GetCurrentWindow(); + if (m_Selection == it->second) { + const ImU32 col = window->Color(ImGuiCol_HeaderActive); + window->DrawList->AddRectFilled(bb.Min, bb.Max, col); + } + ImGuiID id = window->GetID((std::string("#SelectButton") + std::to_string(it->second)).c_str()); + bool hovered = false; + bool held = false; + if (ImGui::ButtonBehavior(bb, id, &hovered, &held)) { + m_Selection = it->second; + } + if (held) { + ImVec2 entityDragDelta = ImGui::GetMouseDragDelta(0); + if (std::abs(entityDragDelta.x) > 0 && std::abs(entityDragDelta.y) > 0) { + if (draggingEntity == 0) { + draggingEntity = it->second; + LOG_DEBUG("Started drag of entity %i", draggingEntity); + } + ImGui::SetNextWindowPos(ImGui::GetIO().MousePos + ImVec2(20, 0)); + ImGui::Begin("Change parent", nullptr, ImVec2(0, 0), 0.3f, ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoSavedSettings); + ImGui::Text("#%i", draggingEntity); + ImGui::End(); + } + } + ImGui::SetNextTreeNodeOpened(true, ImGuiSetCond_Once); if (ImGui::TreeNode((std::string("#") + std::to_string(it->second)).c_str())) { - if (ImGui::IsItemHovered() && ImGui::IsMouseClicked(0)) { - m_Selection = it->second; + if (draggingEntity != 0 && ImGui::IsItemHoveredRect() && ImGui::IsMouseReleased(0)) { + LOG_DEBUG("Changed parent of %i to %i", draggingEntity, it->second); + changeParent(draggingEntity, it->second); + draggingEntity = 0; } - ImGui::SameLine(); - if (ImGui::Button("Add")) { - EntityID entity = world->CreateEntity(it->second); - world->AttachComponent(entity, "Transform"); - } - ImGui::SameLine(); - if (ImGui::Button("Delete")) { - world->DeleteEntity(it->second); + + if (ImGui::BeginPopupContextItem("item context menu")) { + if (ImGui::Button("Add")) { + EntityID entity = world->CreateEntity(it->second); + world->AttachComponent(entity, "Transform"); + } + ImGui::SameLine(); + if (ImGui::Button("Delete")) { + world->DeleteEntity(it->second); + ImGui::CloseCurrentPopup(); + if (m_Selection == it->second) { + m_Selection = 0; + } + } + ImGui::EndPopup(); } recurse(it->second); ImGui::TreePop(); @@ -459,3 +498,20 @@ bool EditorSystem::createDeleteButton(std::string componentType) window->DrawList->AddCircleFilled(bb.GetCenter(), 7.f, col, 16); return pressed; } + +void EditorSystem::changeParent(EntityID entity, EntityID newParent) +{ + if (entity == newParent) { + return; + } + + // An entity can't be a child to one of its own children + auto children = m_World->GetEntityChildren().equal_range(entity); + for (auto it = children.first; it != children.second; it++) { + if (it->second == newParent) { + return; + } + } + + m_World->SetParent(entity, newParent); +} From dbbbb7b4e7518a4e56955986e33a3a78c65b5abb Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Wed, 16 Dec 2015 17:20:56 +0100 Subject: [PATCH 04/14] Working rotations and translations relative to global and local space for children --- deps | 2 +- resources/Schema/Components/Transform.xml | 2 +- resources/Schema/Entities/EditorTestWorld.xml | 23 +++++++++++- src/Engine/Core/EntityXMLFile.cpp | 4 +- src/Engine/Editor/EditorSystem.cpp | 37 +++++++++++++------ 5 files changed, 51 insertions(+), 17 deletions(-) diff --git a/deps b/deps index f20b9cc1..e6399158 160000 --- a/deps +++ b/deps @@ -1 +1 @@ -Subproject commit f20b9cc13bffa39c3b5144bacc5eacd34d43052c +Subproject commit e63991581a268f3eb85f86782d0bdf3687695795 diff --git a/resources/Schema/Components/Transform.xml b/resources/Schema/Components/Transform.xml index 276b89e7..00202aa4 100644 --- a/resources/Schema/Components/Transform.xml +++ b/resources/Schema/Components/Transform.xml @@ -1,5 +1,5 @@ - + \ No newline at end of file diff --git a/resources/Schema/Entities/EditorTestWorld.xml b/resources/Schema/Entities/EditorTestWorld.xml index 6e1c0be5..7fa8e96a 100755 --- a/resources/Schema/Entities/EditorTestWorld.xml +++ b/resources/Schema/Entities/EditorTestWorld.xml @@ -2,7 +2,10 @@ - + + + + @@ -19,12 +22,28 @@ - + + An error + + + + + + + + + An error + + + + + + \ No newline at end of file diff --git a/src/Engine/Core/EntityXMLFile.cpp b/src/Engine/Core/EntityXMLFile.cpp index bf8daceb..c6e00a1b 100644 --- a/src/Engine/Core/EntityXMLFile.cpp +++ b/src/Engine/Core/EntityXMLFile.cpp @@ -431,12 +431,12 @@ float EntityXMLFile::getFloatAttribute(const xercesc::DOMElement* element, const { using namespace xercesc; XSValue::Status status; - XSValue* val = XSValue::getActualValue(element->getAttribute(XSTR(attribute)), xercesc::XSValue::DataType::dt_float, status); + XSValue* val = XSValue::getActualValue(element->getAttribute(XSTR(attribute)), xercesc::XSValue::DataType::dt_double, status); if (val == nullptr) { LOG_ERROR("Element \"%s\" doesn't have an \"%s\" attribute!", XSTR(element->getTagName()), attribute); return 0.f; } else { - return val->fData.fValue.f_float; + return static_cast(val->fData.fValue.f_double); } } diff --git a/src/Engine/Editor/EditorSystem.cpp b/src/Engine/Editor/EditorSystem.cpp index e224ca6b..d27a463b 100644 --- a/src/Engine/Editor/EditorSystem.cpp +++ b/src/Engine/Editor/EditorSystem.cpp @@ -111,26 +111,37 @@ bool EditorSystem::OnMouseMove(const Events::MouseMove& e) 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; + EntityID parent = m_World->GetParent(m_Selection); + glm::quat inverseParentOrientation; + if (parent != 0) { + inverseParentOrientation = glm::inverse(RenderQueueFactory::AbsoluteOrientation(m_World, parent)); + } + (glm::vec3&)m_World->GetComponent(m_Selection, "Transform")["Position"] += inverseParentOrientation * 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; + (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); + EntityID parent = m_World->GetParent(m_Selection); + glm::quat parentOrientation; + if (parent != 0) { + parentOrientation = RenderQueueFactory::AbsoluteOrientation(m_World, parent); + } + glm::vec3& selectionOrientation = m_World->GetComponent(m_Selection, "Transform")["Orientation"]; + //glm::quat currentOrientation = RenderQueueFactory::AbsoluteOrientation(m_World, m_Selection); + glm::quat currentOrientation = parentOrientation * glm::quat(selectionOrientation); glm::quat deltaOrientation(finalMovement); - selectionOrientation = glm::eulerAngles(deltaOrientation * currentOrientation); // (currentOrientation * deltaOrientation) * glm::vec3(0, 0, -1); + selectionOrientation = glm::eulerAngles(glm::inverse(parentOrientation) * (deltaOrientation * currentOrientation)); } else if (m_WidgetSpace == WidgetSpace::Local) { + glm::vec3& selectionOrientation = m_World->GetComponent(m_Selection, "Transform")["Orientation"]; glm::quat currentOrientation(selectionOrientation); glm::quat deltaOrientation(finalMovement); - selectionOrientation = glm::eulerAngles(currentOrientation * deltaOrientation); // (currentOrientation * deltaOrientation) * glm::vec3(0, 0, -1); - widgetTransform["Orientation"] = selectionOrientation; + selectionOrientation = glm::eulerAngles(currentOrientation * deltaOrientation); } } else if (m_WidgetMode == WidgetMode::Scale) { glm::vec3& scaleX = m_World->GetComponent(m_WidgetX, "Transform")["Scale"]; @@ -189,6 +200,7 @@ bool EditorSystem::OnPicking(const Events::Picking& e) //widgetTransform["Position"] = (glm::vec3)selectionTransform["Position"]; } else { m_Selection = entity; + setWidgetMode(m_WidgetMode); } } else { m_Selection = 0; @@ -222,8 +234,11 @@ void EditorSystem::updateWidget() 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"]; + glm::vec3 selectionPosition = RenderQueueFactory::AbsolutePosition(m_World, m_Selection); + widgetTransform["Position"] = selectionPosition; + if (m_WidgetSpace == WidgetSpace::Local) { + widgetTransform["Orientation"] = glm::eulerAngles(RenderQueueFactory::AbsoluteOrientation(m_World, m_Selection)); + } } } @@ -248,7 +263,7 @@ void EditorSystem::setWidgetMode(WidgetMode newMode) if (m_Selection != 0) { if (m_WidgetSpace == WidgetSpace::Local) { auto selectionTransform = m_World->GetComponent(m_Selection, "Transform"); - widgetTransform["Orientation"] = (glm::vec3)selectionTransform["Orientation"]; + widgetTransform["Orientation"] = glm::eulerAngles(RenderQueueFactory::AbsoluteOrientation(m_World, m_Selection)); } } } else if (newMode == WidgetMode::Scale) { @@ -269,7 +284,7 @@ void EditorSystem::setWidgetMode(WidgetMode newMode) if (m_Selection != 0) { auto selectionTransform = m_World->GetComponent(m_Selection, "Transform"); if (m_WidgetSpace == WidgetSpace::Local) { - widgetTransform["Orientation"] = (glm::vec3)selectionTransform["Orientation"]; + widgetTransform["Orientation"] = glm::eulerAngles(RenderQueueFactory::AbsoluteOrientation(m_World, m_Selection)); } } } From a914a7f924ffa0815e7f405dce6a5d7a8f5d790f Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Wed, 16 Dec 2015 17:22:35 +0100 Subject: [PATCH 05/14] Switched to deps/master branch --- deps | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deps b/deps index e6399158..1ae6ba5b 160000 --- a/deps +++ b/deps @@ -1 +1 @@ -Subproject commit e63991581a268f3eb85f86782d0bdf3687695795 +Subproject commit 1ae6ba5b1297ed71b560aee211b9f0007ba52547 From d4f5856304764696770c8598d5155c01eb072ec7 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Thu, 17 Dec 2015 10:44:34 +0100 Subject: [PATCH 06/14] Component attributes no longer get set on the wrong entity when switching selection while editing a field --- src/Engine/Editor/EditorSystem.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Engine/Editor/EditorSystem.cpp b/src/Engine/Editor/EditorSystem.cpp index d27a463b..2463aec6 100644 --- a/src/Engine/Editor/EditorSystem.cpp +++ b/src/Engine/Editor/EditorSystem.cpp @@ -199,6 +199,7 @@ bool EditorSystem::OnPicking(const Events::Picking& e) //auto selectionTransform = m_World->GetComponent(m_Selection, "Transform"); //widgetTransform["Position"] = (glm::vec3)selectionTransform["Position"]; } else { + ImGui::SetActiveID(0, nullptr); m_Selection = entity; setWidgetMode(m_WidgetMode); } From b87f5592916614a380efe56f11a7db9b710c3d12 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Thu, 17 Dec 2015 10:46:49 +0100 Subject: [PATCH 07/14] Updated default configs with editor stuff --- resources/DefaultConfig.ini | 1 + resources/DefaultInput.ini | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/resources/DefaultConfig.ini b/resources/DefaultConfig.ini index 0d95de03..208f413c 100644 --- a/resources/DefaultConfig.ini +++ b/resources/DefaultConfig.ini @@ -1,6 +1,7 @@ [Debug] LogLevel=1 LoadMap= +EditorEnabled=false [Video] Fullscreen=false diff --git a/resources/DefaultInput.ini b/resources/DefaultInput.ini index 3be67287..b0b9e3d0 100644 --- a/resources/DefaultInput.ini +++ b/resources/DefaultInput.ini @@ -14,3 +14,8 @@ R=Reload Space=Jump LeftControl=Crouch LeftShift=Sprint +F1=ToggleEditor +1=EditorToolMove +2=EditorToolRotate +3=EditorToolScale +X=EditorToggleTransformSpace \ No newline at end of file From c8460e0a6c6bad967cfe2c0cdf3ce8cc56c75385 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Thu, 17 Dec 2015 10:55:54 +0100 Subject: [PATCH 08/14] It's no use --- src/Engine/Rendering/Renderer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index 06810412..21ff6c5a 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -135,7 +135,7 @@ 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); From 800065400541c4650dfbd0719d555d69f5bb2008 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Thu, 17 Dec 2015 15:28:05 +0100 Subject: [PATCH 09/14] Model loading now fetches material opacity value properly --- src/Engine/Rendering/RawModel.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Engine/Rendering/RawModel.cpp b/src/Engine/Rendering/RawModel.cpp index 5aec7f22..95a75a15 100644 --- a/src/Engine/Rendering/RawModel.cpp +++ b/src/Engine/Rendering/RawModel.cpp @@ -76,13 +76,15 @@ RawModel::RawModel(std::string fileName) } // Material diffuse color - aiColor4D diffuse; + aiColor3D diffuse; material->Get(AI_MATKEY_COLOR_DIFFUSE, diffuse); - desc.DiffuseVertexColor = glm::vec4(diffuse.r, diffuse.g, diffuse.b, diffuse.a); + float opacity; + material->Get(AI_MATKEY_OPACITY, opacity); + desc.DiffuseVertexColor = glm::vec4(diffuse.r, diffuse.g, diffuse.b, opacity); // Material specular color - aiColor4D specular; + aiColor3D specular; material->Get(AI_MATKEY_COLOR_SPECULAR, specular); - desc.SpecularVertexColor = glm::vec4(specular.r, specular.g, specular.b, specular.a); + desc.SpecularVertexColor = glm::vec4(specular.r, specular.g, specular.b, 1.f); m_Vertices.push_back(desc); } From c1b9404e524138c47edf83b2965221b44642bc66 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Thu, 17 Dec 2015 13:26:12 +0100 Subject: [PATCH 10/14] Created a FileDropped event for when a file is dropped onto the client by the OS --- include/Engine/Core/EFileDropped.h | 16 ++++++++++++++++ include/Engine/Core/InputManager.h | 3 +++ src/Engine/Core/InputManager.cpp | 18 ++++++++++++++++++ 3 files changed, 37 insertions(+) create mode 100644 include/Engine/Core/EFileDropped.h diff --git a/include/Engine/Core/EFileDropped.h b/include/Engine/Core/EFileDropped.h new file mode 100644 index 00000000..1ad22a2f --- /dev/null +++ b/include/Engine/Core/EFileDropped.h @@ -0,0 +1,16 @@ +#ifndef EFileDropped_h__ +#define EFileDropped_h__ + +#include "EventBroker.h" + +namespace Events +{ + +struct FileDropped : Event +{ + std::string Path; +}; + +} + +#endif \ No newline at end of file diff --git a/include/Engine/Core/InputManager.h b/include/Engine/Core/InputManager.h index 0d53169e..3b035dbe 100644 --- a/include/Engine/Core/InputManager.h +++ b/include/Engine/Core/InputManager.h @@ -16,6 +16,7 @@ #include "ELockMouse.h" #include "EGamepadAxis.h" #include "EGamepadButton.h" +#include "EFileDropped.h" class InputManager { @@ -71,6 +72,8 @@ private: static void GLFWCharCallback(GLFWwindow* window, unsigned int c); static std::vector> GLFWScrollCallbackQueue; static void GLFWScrollCallback(GLFWwindow* window, double xoffset, double yoffset); + static std::vector GLFWDropCallbackQueue; + static void GLFWDropCallback(GLFWwindow* window, int count, const char* paths[]); }; #endif diff --git a/src/Engine/Core/InputManager.cpp b/src/Engine/Core/InputManager.cpp index cb901cb8..50dcac7c 100644 --- a/src/Engine/Core/InputManager.cpp +++ b/src/Engine/Core/InputManager.cpp @@ -2,6 +2,7 @@ std::vector InputManager::GLFWCharCallbackQueue; std::vector> InputManager::GLFWScrollCallbackQueue; +std::vector InputManager::GLFWDropCallbackQueue; void InputManager::Initialize() { @@ -10,6 +11,7 @@ void InputManager::Initialize() //m_LastGamepadButtonState = std::array(); glfwSetCharCallback(m_GLFWWindow, &InputManager::GLFWCharCallback); glfwSetScrollCallback(m_GLFWWindow, &InputManager::GLFWScrollCallback); + glfwSetDropCallback(m_GLFWWindow, &InputManager::GLFWDropCallback); EVENT_SUBSCRIBE_MEMBER(m_ELockMouse, &InputManager::OnLockMouse); EVENT_SUBSCRIBE_MEMBER(m_EUnlockMouse, &InputManager::OnUnlockMouse); @@ -95,6 +97,14 @@ void InputManager::Update(double dt) } GLFWScrollCallbackQueue.clear(); + // File drop + for (auto& path : GLFWDropCallbackQueue) { + Events::FileDropped e; + e.Path = path; + m_EventBroker->Publish(e); + } + GLFWDropCallbackQueue.clear(); + // // Lock mouse while holding LMB // if (m_CurrentMouseState[GLFW_MOUSE_BUTTON_LEFT]) // { @@ -229,6 +239,14 @@ void InputManager::GLFWScrollCallback(GLFWwindow* window, double xoffset, double GLFWScrollCallbackQueue.push_back(std::make_pair(xoffset, yoffset)); } + +void InputManager::GLFWDropCallback(GLFWwindow* window, int count, const char* paths[]) +{ + for (int i = 0; i < count; i++) { + GLFWDropCallbackQueue.push_back(std::string(paths[i])); + } +} + bool InputManager::OnLockMouse(const Events::LockMouse &event) { m_MouseLocked = true; From cf6dde6c092955e135111486304716d22f9619d9 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Thu, 17 Dec 2015 13:26:55 +0100 Subject: [PATCH 11/14] Boost dependency updated to version 1.60! --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7b04f8ed..7c5f2268 100644 --- a/README.md +++ b/README.md @@ -17,4 +17,4 @@ Libraries that are too big to be bundled with the project. | Project | Version | License | Root folder environment variable (Windows) | | ---------------------------------------------------------- | ----------- | --------------------------------------------------------------------------- | ------------------------------------------ | -| **[Boost](http://www.boost.org)** | 1.59.0+ | [Boost Software License, Version 1.0](http://www.boost.org/LICENSE_1_0.txt) | BOOST_ROOT | +| **[Boost](http://www.boost.org)** | 1.60.0+ | [Boost Software License, Version 1.0](http://www.boost.org/LICENSE_1_0.txt) | BOOST_ROOT | From a655f0bae5f428361f41ca5c8e4da689c537baba Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Thu, 17 Dec 2015 13:28:31 +0100 Subject: [PATCH 12/14] Drag-and-drop asset picking and base work for showing component field tooltips in the editor --- assets | 2 +- include/Engine/Editor/EditorSystem.h | 5 ++++ src/Engine/Editor/EditorSystem.cpp | 42 +++++++++++++++++++++++----- 3 files changed, 41 insertions(+), 8 deletions(-) diff --git a/assets b/assets index c5f67434..673d4a4e 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit c5f674349a915ab1a2b4da632d87a9832d1f6fab +Subproject commit 673d4a4e4c5a3f5bc9fedf82234e8f8751f63a44 diff --git a/include/Engine/Editor/EditorSystem.h b/include/Engine/Editor/EditorSystem.h index 021a14ca..6709775d 100644 --- a/include/Engine/Editor/EditorSystem.h +++ b/include/Engine/Editor/EditorSystem.h @@ -1,5 +1,6 @@ #include #include +#include #include "../Core/System.h" #include "../Core/EMousePress.h" #include "../Core/EMouseRelease.h" @@ -8,6 +9,7 @@ #include "../Input/EInputCommand.h" #include "../Rendering/IRenderer.h" #include "../Rendering/EPicking.h" +#include "../Core/EFileDropped.h" #include "../Rendering/RenderQueueFactory.h" class EditorSystem : public ImpureSystem @@ -50,6 +52,7 @@ private: EntityID m_Selection = 0; EntityID m_LastSelection = 0; glm::vec3 m_Position; + std::string m_LastDroppedFile; EventRelay m_EInputCommand; bool OnInputCommand(const Events::InputCommand& e); @@ -61,6 +64,8 @@ private: bool OnMouseMove(const Events::MouseMove& e); EventRelay m_EPicking; bool OnPicking(const Events::Picking& e); + EventRelay m_EFileDropped; + bool OnFileDropped(const Events::FileDropped& e); void updateWidget(); void setWidgetMode(WidgetMode newMode); diff --git a/src/Engine/Editor/EditorSystem.cpp b/src/Engine/Editor/EditorSystem.cpp index 2463aec6..32f5b162 100644 --- a/src/Engine/Editor/EditorSystem.cpp +++ b/src/Engine/Editor/EditorSystem.cpp @@ -19,6 +19,7 @@ EditorSystem::EditorSystem(EventBroker* eventBroker, IRenderer* renderer) EVENT_SUBSCRIBE_MEMBER(m_EMouseRelease, &EditorSystem::OnMouseRelease); EVENT_SUBSCRIBE_MEMBER(m_EMouseMove, &EditorSystem::OnMouseMove); EVENT_SUBSCRIBE_MEMBER(m_EPicking, &EditorSystem::OnPicking); + EVENT_SUBSCRIBE_MEMBER(m_EFileDropped, &EditorSystem::OnFileDropped); } void EditorSystem::Update(World* world, double dt) @@ -36,6 +37,11 @@ void EditorSystem::Update(World* world, double dt) updateWidget(); drawUI(world, dt); + + // Clear drop queue if it wasn't handled by any UI element + if (!m_LastDroppedFile.empty()) { + m_LastDroppedFile = ""; + } } bool EditorSystem::OnInputCommand(const Events::InputCommand& e) @@ -212,6 +218,12 @@ bool EditorSystem::OnPicking(const Events::Picking& e) return true; }; +bool EditorSystem::OnFileDropped(const Events::FileDropped& e) +{ + m_LastDroppedFile = boost::filesystem::path(e.Path).lexically_relative(boost::filesystem::current_path()).string(); + std::replace(m_LastDroppedFile.begin(), m_LastDroppedFile.end(), '\\', '/'); + return true; +} void EditorSystem::updateWidget() { @@ -389,37 +401,53 @@ void EditorSystem::drawUI(World* world, double dt) const std::string& field = pair.first; const std::string& type = pair.second; + ImGui::PushID(field.c_str()); if (type == "Vector") { auto& val = component.Property(field); if (field == "Scale") { - ImGui::DragFloat3(field.c_str(), glm::value_ptr(val), 0.1f, 0.f, std::numeric_limits::max()); + ImGui::DragFloat3("", glm::value_ptr(val), 0.1f, 0.f, std::numeric_limits::max()); } else if (field == "Orientation") { glm::vec3 tempVal = glm::fmod(val, glm::vec3(glm::two_pi())); - if (ImGui::SliderFloat3(field.c_str(), glm::value_ptr(tempVal), 0.f, glm::two_pi())) { + if (ImGui::SliderFloat3("", glm::value_ptr(tempVal), 0.f, glm::two_pi())) { val = tempVal; } } else { - ImGui::DragFloat3(field.c_str(), glm::value_ptr(val), 0.1f, std::numeric_limits::lowest(), std::numeric_limits::max()); + ImGui::DragFloat3("", glm::value_ptr(val), 0.1f, std::numeric_limits::lowest(), std::numeric_limits::max()); } } else if (type == "Color") { auto& val = component.Property(field); - ImGui::ColorEdit4(field.c_str(), glm::value_ptr(val), true); + ImGui::ColorEdit4("", glm::value_ptr(val), true); } else if (type == "string") { std::string& val = component.Property(field); char tempString[1024]; memcpy(tempString, val.c_str(), std::min(val.length() + 1, sizeof(tempString))); - if (ImGui::InputText(field.c_str(), tempString, sizeof(tempString))) { + if (ImGui::InputText("", tempString, sizeof(tempString))) { val = std::string(tempString); LOG_DEBUG("%s::%s changed!", componentType.c_str(), field.c_str()); } + // DROP STUFF + if (ImGui::IsItemHovered() && !m_LastDroppedFile.empty()) { + val = m_LastDroppedFile; + m_LastDroppedFile = ""; + } + } else if (type == "double") { float tempVal = static_cast(component.Property(field)); - if (ImGui::InputFloat(field.c_str(), &tempVal, 0.01f, 1.f)) { + if (ImGui::InputFloat("", &tempVal, 0.01f, 1.f)) { component.SetProperty(field, static_cast(tempVal)); } } else if (type == "bool") { auto& val = component.Property(field); - ImGui::Checkbox(field.c_str(), &val); + ImGui::Checkbox("", &val); + } else { + ImGui::TextDisabled(type.c_str()); + } + ImGui::PopID(); + + ImGui::SameLine(); + ImGui::Text(field.c_str()); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("field annotation goes here"); } } } From 00f6056f7c28631d1fdab1166e1d3850909464b6 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Thu, 17 Dec 2015 14:16:08 +0100 Subject: [PATCH 13/14] Uniform scaling when dragging scaling widget origin --- src/Engine/Editor/EditorSystem.cpp | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/Engine/Editor/EditorSystem.cpp b/src/Engine/Editor/EditorSystem.cpp index 32f5b162..ed615a50 100644 --- a/src/Engine/Editor/EditorSystem.cpp +++ b/src/Engine/Editor/EditorSystem.cpp @@ -153,6 +153,13 @@ bool EditorSystem::OnMouseMove(const Events::MouseMove& e) 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 && m_WidgetCurrentAxis.y > 0 && m_WidgetCurrentAxis.z > 0) { + float movementLength = glm::length(movement); + float dot = glm::dot((glm::vec3)widgetOrientation, movement); + movement = glm::vec3(movementLength) * glm::sign(dot); + (glm::vec3&)m_World->GetComponent(m_WidgetOrigin, "Transform")["Scale"] += movement; + } if (m_WidgetCurrentAxis.x > 0) { scaleX.x += movement.x; } @@ -162,14 +169,19 @@ bool EditorSystem::OnMouseMove(const Events::MouseMove& e) 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; } } + + /*LOG_DEBUG("DELTA %f", e.DeltaX); + if (e.X < 0) { + glfwSetCursorPos(m_Renderer->Window(), width - 1, e.Y); + } + if (e.X >= width) { + glfwSetCursorPos(m_Renderer->Window(), 0, e.Y); + }*/ + return true; } @@ -287,7 +299,7 @@ void EditorSystem::setWidgetMode(WidgetMode newMode) 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"]; + widgetTransform["Orientation"] = glm::eulerAngles(RenderQueueFactory::AbsoluteOrientation(m_World, m_Selection)); } } else if (newMode == WidgetMode::Rotate) { m_World->GetComponent(m_WidgetX, "Model")["Resource"] = "Models/RotationWidgetX.obj"; From e9128efd136b928d6c20f17a04bfbdb77437d0f2 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Thu, 17 Dec 2015 14:26:20 +0100 Subject: [PATCH 14/14] Translation widget planes --- include/Engine/Editor/EditorSystem.h | 3 +++ src/Engine/Editor/EditorSystem.cpp | 33 +++++++++++++++++++++++----- 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/include/Engine/Editor/EditorSystem.h b/include/Engine/Editor/EditorSystem.h index 6709775d..779b7f97 100644 --- a/include/Engine/Editor/EditorSystem.h +++ b/include/Engine/Editor/EditorSystem.h @@ -43,8 +43,11 @@ private: EntityID m_Widget = 0; EntityID m_WidgetX = 0; + EntityID m_WidgetPlaneX = 0; EntityID m_WidgetY = 0; + EntityID m_WidgetPlaneY = 0; EntityID m_WidgetZ = 0; + EntityID m_WidgetPlaneZ = 0; EntityID m_WidgetOrigin = 0; glm::vec3 m_WidgetCurrentAxis; float m_WidgetPickingDepth = 0.f; diff --git a/src/Engine/Editor/EditorSystem.cpp b/src/Engine/Editor/EditorSystem.cpp index ed615a50..a43ca900 100644 --- a/src/Engine/Editor/EditorSystem.cpp +++ b/src/Engine/Editor/EditorSystem.cpp @@ -85,6 +85,9 @@ bool EditorSystem::OnMouseMove(const Events::MouseMove& e) return false; } + if (m_Selection == 0) { + return false; + } auto widgetTransform = m_World->GetComponent(m_Widget, "Transform"); glm::vec3 widgetOrientation = widgetTransform["Orientation"]; @@ -207,9 +210,9 @@ bool EditorSystem::OnPicking(const Events::Picking& e) 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) + (entity == m_WidgetX) || (entity == m_WidgetOrigin) || (entity == m_WidgetPlaneY || entity == m_WidgetPlaneZ), + (entity == m_WidgetY) || (entity == m_WidgetOrigin) || (entity == m_WidgetPlaneX || entity == m_WidgetPlaneZ), + (entity == m_WidgetZ) || (entity == m_WidgetOrigin) || (entity == m_WidgetPlaneX || entity == m_WidgetPlaneY) ); m_WidgetPickingDepth = result.Depth; @@ -245,12 +248,24 @@ void EditorSystem::updateWidget() m_WidgetX = m_World->CreateEntity(m_Widget); m_World->AttachComponent(m_WidgetX, "Transform"); m_World->AttachComponent(m_WidgetX, "Model"); + m_WidgetPlaneX = m_World->CreateEntity(m_Widget); + m_World->AttachComponent(m_WidgetPlaneX, "Transform"); + m_World->AttachComponent(m_WidgetPlaneX, "Model"); + m_World->GetComponent(m_WidgetPlaneX, "Model")["Resource"] = "Models/WidgetPlaneX.obj"; m_WidgetY = m_World->CreateEntity(m_Widget); m_World->AttachComponent(m_WidgetY, "Transform"); m_World->AttachComponent(m_WidgetY, "Model"); + m_WidgetPlaneY = m_World->CreateEntity(m_Widget); + m_World->AttachComponent(m_WidgetPlaneY, "Transform"); + m_World->AttachComponent(m_WidgetPlaneY, "Model"); + m_World->GetComponent(m_WidgetPlaneY, "Model")["Resource"] = "Models/WidgetPlaneY.obj"; m_WidgetZ = m_World->CreateEntity(m_Widget); m_World->AttachComponent(m_WidgetZ, "Transform"); m_World->AttachComponent(m_WidgetZ, "Model"); + m_WidgetPlaneZ = m_World->CreateEntity(m_Widget); + m_World->AttachComponent(m_WidgetPlaneZ, "Transform"); + m_World->AttachComponent(m_WidgetPlaneZ, "Model"); + m_World->GetComponent(m_WidgetPlaneZ, "Model")["Resource"] = "Models/WidgetPlaneZ.obj"; m_WidgetOrigin = m_World->CreateEntity(m_Widget); m_World->AttachComponent(m_WidgetOrigin, "Transform"); m_World->AttachComponent(m_WidgetOrigin, "Model"); @@ -276,15 +291,24 @@ void EditorSystem::setWidgetMode(WidgetMode newMode) 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_WidgetPlaneX, "Model")["Visible"] = false; m_World->GetComponent(m_WidgetY, "Transform")["Scale"] = glm::vec3(1.f); + m_World->GetComponent(m_WidgetPlaneY, "Model")["Visible"] = false; m_World->GetComponent(m_WidgetZ, "Transform")["Scale"] = glm::vec3(1.f); + m_World->GetComponent(m_WidgetPlaneZ, "Model")["Visible"] = false; m_World->GetComponent(m_WidgetOrigin, "Transform")["Scale"] = glm::vec3(1.f); + m_World->GetComponent(m_WidgetOrigin, "Model")["Visible"] = false; 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; + // Temporarily disabled for local space until I can figure out what's wrong with the math + if (m_WidgetSpace != WidgetSpace::Local) { + m_World->GetComponent(m_WidgetPlaneX, "Model")["Visible"] = true; + m_World->GetComponent(m_WidgetPlaneY, "Model")["Visible"] = true; + m_World->GetComponent(m_WidgetPlaneZ, "Model")["Visible"] = true; + } if (m_Selection != 0) { if (m_WidgetSpace == WidgetSpace::Local) { auto selectionTransform = m_World->GetComponent(m_Selection, "Transform"); @@ -305,7 +329,6 @@ void EditorSystem::setWidgetMode(WidgetMode newMode) 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) {