From 0d50ede6f56208140caf73ce7f7c71e512dcc988 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Sun, 17 Jan 2016 07:34:20 +0100 Subject: [PATCH] Base work on reimplementing editor GUI --- include/Engine/Editor/EditorGUI.h | 65 +++++++++++++++ include/Engine/Editor/EditorSystem.h | 5 +- include/Engine/Editor/EditorUI.h | 8 -- resources/Schema/Entities/Test.xml | 3 +- resources/Schema/Types/Entity.xsd | 4 +- src/Engine/Editor/EditorGUI.cpp | 114 +++++++++++++++++++++++++++ src/Engine/Editor/EditorSystem.cpp | 13 ++- src/Engine/Editor/EditorUI.cpp | 0 8 files changed, 198 insertions(+), 14 deletions(-) create mode 100644 include/Engine/Editor/EditorGUI.h delete mode 100644 include/Engine/Editor/EditorUI.h create mode 100644 src/Engine/Editor/EditorGUI.cpp delete mode 100644 src/Engine/Editor/EditorUI.cpp diff --git a/include/Engine/Editor/EditorGUI.h b/include/Engine/Editor/EditorGUI.h new file mode 100644 index 00000000..6c8b3499 --- /dev/null +++ b/include/Engine/Editor/EditorGUI.h @@ -0,0 +1,65 @@ +#ifndef EditorGUI_h__ +#define EditorGUI_h__ + +#include +#define IMGUI_DEFINE_MATH_OPERATORS +#include +#include +#include +#include "../Common.h" + +#include "../Core/EventBroker.h" +#include "../Core/World.h" +#include "../Core/EntityWrapper.h" + +class EditorGUI +{ +public: + EditorGUI(EventBroker* eventBroker) + : m_EventBroker(eventBroker) + { } + + void Draw(World* world); + + void SelectEntity(EntityWrapper entity); + + // Called when an entity is selected in the entity tree + typedef std::function OnEntitySelectedCallback_t; + void SetEntitySelectedCallback(OnEntitySelectedCallback_t f) { m_OnEntitySelected = f; } + // Called when the user means to import an entity file. + // Expects an EntityWrapper of the newly created entity in return. + typedef std::function OnEntityImport_t; + void SetEntityImportCallback(OnEntityImport_t f) { m_OnEntityImport = f; } + // Called when the user means to save an entity to file. + // Expects a bool indicating whether the save was successful or not in return. + typedef std::function OnEntitySave_t; + void SetEntitySaveCallback(OnEntitySave_t f) { m_OnEntitySave = f; } + // Called when the user means to create a new entity. + // @param EntityWrapper The parent of the entity to be created + // @return EntityWrapper The newly created entity + typedef std::function OnEntityCreate_t; + void SetEntityCreateCallback(OnEntityCreate_t f) { m_OnEntityCreate = f; } + // Called when the user means to delete an entity. + typedef std::function OnEntityDelete_t; + void SetEntityCreateCallback(OnEntityDelete_t f) { m_OnEntityDelete = f; } + +private: + EventBroker* m_EventBroker; + + // State variables + EntityWrapper m_CurrentSelection = EntityWrapper::Invalid; + + // Callbacks + OnEntitySelectedCallback_t m_OnEntitySelected = nullptr; + OnEntityImport_t m_OnEntityImport = nullptr; + OnEntitySave_t m_OnEntitySave = nullptr; + OnEntityCreate_t m_OnEntityCreate = nullptr; + OnEntityDelete_t m_OnEntityDelete = nullptr; + + void drawMenu(); + void drawEntities(World* world); + void drawEntitiesRecursive(World* world, EntityID parent); + bool drawEntityNode(EntityWrapper entity); +}; + +#endif \ No newline at end of file diff --git a/include/Engine/Editor/EditorSystem.h b/include/Engine/Editor/EditorSystem.h index 43022009..7b908872 100644 --- a/include/Engine/Editor/EditorSystem.h +++ b/include/Engine/Editor/EditorSystem.h @@ -8,6 +8,7 @@ #include "../Core/ResourceManager.h" #include "../Core/EntityFilePreprocessor.h" #include "../Core/EntityFileParser.h" +#include "EditorGUI.h" class EditorSystem : public ImpureSystem { @@ -23,8 +24,10 @@ private: World* m_EditorWorld; SystemPipeline* m_EditorWorldSystemPipeline; Camera* m_EditorCamera; - EntityWrapper m_Widget = EntityWrapper::Invalid; EntityWrapper m_Camera = EntityWrapper::Invalid; DebugCameraInputController* m_DebugCameraInputController; + EditorGUI* m_EditorGUI; + + void OnEntitySelected(EntityWrapper entity); }; \ No newline at end of file diff --git a/include/Engine/Editor/EditorUI.h b/include/Engine/Editor/EditorUI.h deleted file mode 100644 index 18299865..00000000 --- a/include/Engine/Editor/EditorUI.h +++ /dev/null @@ -1,8 +0,0 @@ -#include -#include - -class EditorUI -{ -public: - EditorUI(); -}; \ No newline at end of file diff --git a/resources/Schema/Entities/Test.xml b/resources/Schema/Entities/Test.xml index 5f57dbb7..42e2660e 100644 --- a/resources/Schema/Entities/Test.xml +++ b/resources/Schema/Entities/Test.xml @@ -13,7 +13,7 @@ - + @@ -23,5 +23,6 @@ + diff --git a/resources/Schema/Types/Entity.xsd b/resources/Schema/Types/Entity.xsd index 47c4d614..3b0a1c88 100644 --- a/resources/Schema/Types/Entity.xsd +++ b/resources/Schema/Types/Entity.xsd @@ -38,9 +38,7 @@ - - - + diff --git a/src/Engine/Editor/EditorGUI.cpp b/src/Engine/Editor/EditorGUI.cpp new file mode 100644 index 00000000..66896474 --- /dev/null +++ b/src/Engine/Editor/EditorGUI.cpp @@ -0,0 +1,114 @@ +#include "Editor/EditorGUI.h" + +void EditorGUI::Draw(World* world) +{ + drawMenu(); + drawEntities(world); +} + +void EditorGUI::SelectEntity(EntityWrapper entity) +{ + m_CurrentSelection = entity; + if (m_OnEntitySelected != nullptr) { + m_OnEntitySelected(entity); + } +} + +void EditorGUI::drawMenu() +{ + +} + +void EditorGUI::drawEntities(World* world) +{ + if (!ImGui::Begin("Entities")) { + return; + } + + drawEntitiesRecursive(world, EntityID_Invalid); + + ImGui::End(); +} + +void EditorGUI::drawEntitiesRecursive(World* world, EntityID parent) +{ + auto entityChildren = world->GetEntityChildren(); + auto range = entityChildren.equal_range(parent); + for (auto it = range.first; it != range.second; it++) { + if (EditorGUI::drawEntityNode(EntityWrapper(world, it->second))) { + drawEntitiesRecursive(world, it->second); + ImGui::TreePop(); + } + } +} + +bool EditorGUI::drawEntityNode(EntityWrapper entity) +{ + ImVec2 pos = ImGui::GetCursorScreenPos(); + float width = ImGui::GetContentRegionAvailWidth(); + ImRect bb(pos + ImVec2(20, 0), pos + ImVec2(width, 13)); + auto window = ImGui::GetCurrentWindow(); + if (m_CurrentSelection == entity) { + 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(entity)).c_str()); + bool hovered = false; + bool held = false; + if (ImGui::ButtonBehavior(bb, id, &hovered, &held)) { + SelectEntity(entity); + } + //if (held) { + // ImVec2 entityDragDelta = ImGui::GetMouseDragDelta(0); + // if (std::abs(entityDragDelta.x) > 0 && std::abs(entityDragDelta.y) > 0) { + // if (m_UIDraggingEntity == EntityID_Invalid) { + // m_UIDraggingEntity = entity; + // LOG_DEBUG("Started drag of entity %i", m_UIDraggingEntity); + // } + // 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", m_UIDraggingEntity); + // ImGui::End(); + // } + //} + + ImGui::SetNextTreeNodeOpened(true, ImGuiSetCond_Once); + std::string nodeTitle; + const std::string& entityName = entity.World->GetName(entity); + if (!entityName.empty()) { + nodeTitle = entityName; + } else { + nodeTitle = std::string("#") + std::to_string(entity.ID); + } + if (ImGui::TreeNode(nodeTitle.c_str())) { + //if (m_UIDraggingEntity != EntityID_Invalid && ImGui::IsItemHoveredRect() && ImGui::IsMouseReleased(0)) { + // LOG_DEBUG("Changed parent of %i to %i", m_UIDraggingEntity, entity); + // changeParent(m_UIDraggingEntity, entity); + // m_UIDraggingEntity = EntityID_Invalid; + //} + + if (ImGui::BeginPopupContextItem("item context menu")) { + if (ImGui::Button("Add")) { + if (m_OnEntityCreate != nullptr) { + EntityWrapper newEntity = m_OnEntityCreate(EntityWrapper(entity.World, EntityID_Invalid)); + ImGui::CloseCurrentPopup(); + SelectEntity(newEntity); + } + } + ImGui::SameLine(); + if (ImGui::Button("Delete")) { + if (m_OnEntityDelete != nullptr) { + m_OnEntityDelete(entity); + ImGui::CloseCurrentPopup(); + } + if (!m_CurrentSelection.Valid()) { + SelectEntity(EntityWrapper::Invalid); + } + } + ImGui::EndPopup(); + } + return true; + } else { + return false; + } +} diff --git a/src/Engine/Editor/EditorSystem.cpp b/src/Engine/Editor/EditorSystem.cpp index ec385e9b..2d0a4b55 100644 --- a/src/Engine/Editor/EditorSystem.cpp +++ b/src/Engine/Editor/EditorSystem.cpp @@ -24,6 +24,9 @@ EditorSystem::EditorSystem(EventBroker* eventBroker, IRenderer* renderer, Render m_EditorWorld->AttachComponent(m_Camera.ID, "Camera"); m_DebugCameraInputController = new DebugCameraInputController(m_EventBroker, -1); + m_EditorGUI = new EditorGUI(m_EventBroker); + m_EditorGUI->SetEntitySelectedCallback(std::bind(&EditorSystem::OnEntitySelected, this, std::placeholders::_1)); + Events::SetCamera e; e.CameraEntity = m_Camera; m_EventBroker->Publish(e); @@ -31,6 +34,7 @@ EditorSystem::EditorSystem(EventBroker* eventBroker, IRenderer* renderer, Render EditorSystem::~EditorSystem() { + delete m_EditorGUI; delete m_DebugCameraInputController; delete m_EditorWorldSystemPipeline; delete m_EditorWorld; @@ -40,7 +44,14 @@ void EditorSystem::Update(World* world, double dt) { m_EditorWorldSystemPipeline->Update(m_EditorWorld, dt); + m_EditorGUI->Draw(world); + m_DebugCameraInputController->Update(dt); m_Camera["Transform"]["Position"] = m_DebugCameraInputController->Position(); m_Camera["Transform"]["Orientation"] = glm::eulerAngles(m_DebugCameraInputController->Orientation()); -} \ No newline at end of file +} + +void EditorSystem::OnEntitySelected(EntityWrapper entity) +{ + m_Widget["Transform"]["Position"] = Transform::AbsolutePosition(entity.World, entity.ID); +} diff --git a/src/Engine/Editor/EditorUI.cpp b/src/Engine/Editor/EditorUI.cpp deleted file mode 100644 index e69de29b..00000000