From 9f447afbdb92dc136d0ad3be9f2d39e1e58deaa3 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Sun, 17 Jan 2016 06:20:27 +0100 Subject: [PATCH 01/38] Added EntityWrapper::Valid and bool overload to be check if an entity is valid and still exists in the world more easily --- include/Engine/Core/EntityWrapper.h | 6 ++++-- src/Engine/Core/EntityWrapper.cpp | 29 ++++++++++++++++++++++++++--- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/include/Engine/Core/EntityWrapper.h b/include/Engine/Core/EntityWrapper.h index 55b64c6f..e4be8d78 100644 --- a/include/Engine/Core/EntityWrapper.h +++ b/include/Engine/Core/EntityWrapper.h @@ -23,10 +23,12 @@ struct EntityWrapper static const EntityWrapper Invalid; bool HasComponent(const std::string& componentName); + bool Valid(); - ComponentWrapper operator[](const std::string& componentName); + ComponentWrapper operator[](const char* componentName); bool operator==(const EntityWrapper& e); - explicit operator EntityID(); + explicit operator EntityID() const; + operator bool(); }; #endif diff --git a/src/Engine/Core/EntityWrapper.cpp b/src/Engine/Core/EntityWrapper.cpp index 7b321a63..c3c5cf27 100644 --- a/src/Engine/Core/EntityWrapper.cpp +++ b/src/Engine/Core/EntityWrapper.cpp @@ -13,18 +13,41 @@ bool EntityWrapper::HasComponent(const std::string& componentName) return World->HasComponent(ID, componentName); } -ComponentWrapper EntityWrapper::operator[](const std::string& componentName) +bool EntityWrapper::Valid() +{ + if (this->World == nullptr) { + return false; + } + + if (this->ID == EntityID_Invalid) { + return false; + } + + if (!this->World->ValidEntity(this->ID)) { + this->ID = EntityID_Invalid; + return false; + } + + return true; +} + +ComponentWrapper EntityWrapper::operator[](const char* componentName) { if (World->HasComponent(ID, componentName)) { return World->GetComponent(ID, componentName); } else { - LOG_WARNING("EntityWrapper implicitly attached \"%s\" component to #%i as a result of a fetch request!", componentName.c_str(), ID); + LOG_WARNING("EntityWrapper implicitly attached \"%s\" component to #%i as a result of a fetch request!", componentName, ID); return World->AttachComponent(ID, componentName); } } -EntityWrapper::operator EntityID() +EntityWrapper::operator EntityID() const { return this->ID; } +EntityWrapper::operator bool() +{ + return this->Valid(); +} + From 6ec22587583ff7a7344cab5e5eec536edcb0cc13 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Sun, 17 Jan 2016 06:22:35 +0100 Subject: [PATCH 02/38] Added UniformScale component which keeps an entity's scale at a uniform value relative to the screen. --- include/Engine/Core/UniformScaleSystem.h | 22 ++++++++++++++++++ resources/Schema/Components.xsd | 1 + resources/Schema/Components/UniformScale.xml | 4 ++++ resources/Schema/Components/UniformScale.xsd | 16 +++++++++++++ resources/Schema/Types/Entity.xsd | 1 + src/Engine/Core/UniformScaleSystem.cpp | 24 ++++++++++++++++++++ 6 files changed, 68 insertions(+) create mode 100644 include/Engine/Core/UniformScaleSystem.h create mode 100755 resources/Schema/Components/UniformScale.xml create mode 100755 resources/Schema/Components/UniformScale.xsd create mode 100644 src/Engine/Core/UniformScaleSystem.cpp diff --git a/include/Engine/Core/UniformScaleSystem.h b/include/Engine/Core/UniformScaleSystem.h new file mode 100644 index 00000000..f44409f0 --- /dev/null +++ b/include/Engine/Core/UniformScaleSystem.h @@ -0,0 +1,22 @@ +#ifndef UniformScaleSystem_h__ +#define UniformScaleSystem_h__ + +#include "../GLM.h" +#include "System.h" +#include "../Rendering/ESetCamera.h" + +class UniformScaleSystem : public PureSystem +{ +public: + UniformScaleSystem(EventBroker* eventBroker); + + virtual void UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& cUniformScale, double dt) override; + +private: + EntityWrapper m_Camera = EntityWrapper::Invalid; + + EventRelay m_ESetCamera; + bool OnSetCamera(const Events::SetCamera& e); +}; + +#endif \ No newline at end of file diff --git a/resources/Schema/Components.xsd b/resources/Schema/Components.xsd index 8d837aea..b9c8647c 100644 --- a/resources/Schema/Components.xsd +++ b/resources/Schema/Components.xsd @@ -18,4 +18,5 @@ + \ No newline at end of file diff --git a/resources/Schema/Components/UniformScale.xml b/resources/Schema/Components/UniformScale.xml new file mode 100755 index 00000000..0eed72d4 --- /dev/null +++ b/resources/Schema/Components/UniformScale.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/resources/Schema/Components/UniformScale.xsd b/resources/Schema/Components/UniformScale.xsd new file mode 100755 index 00000000..cbd218ea --- /dev/null +++ b/resources/Schema/Components/UniformScale.xsd @@ -0,0 +1,16 @@ + + + + + + + + Keeps an entity at an uniform scale relative to the camera + + + + + + + + diff --git a/resources/Schema/Types/Entity.xsd b/resources/Schema/Types/Entity.xsd index 1aaa8497..47c4d614 100644 --- a/resources/Schema/Types/Entity.xsd +++ b/resources/Schema/Types/Entity.xsd @@ -27,6 +27,7 @@ + diff --git a/src/Engine/Core/UniformScaleSystem.cpp b/src/Engine/Core/UniformScaleSystem.cpp new file mode 100644 index 00000000..8cf670fc --- /dev/null +++ b/src/Engine/Core/UniformScaleSystem.cpp @@ -0,0 +1,24 @@ +#include "Core/UniformScaleSystem.h" + +UniformScaleSystem::UniformScaleSystem(EventBroker* eventBroker) + : System(eventBroker) + , PureSystem("UniformScale") +{ + EVENT_SUBSCRIBE_MEMBER(m_ESetCamera, &UniformScaleSystem::OnSetCamera); +} + +void UniformScaleSystem::UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& cUniformScale, double dt) +{ + if (!m_Camera.Valid()) { + return; + } + + float distance = glm::length((glm::vec3)entity["Transform"]["Position"] - (glm::vec3&)m_Camera["Transform"]["Position"]); + entity["Transform"]["Scale"] = (glm::vec3&)cUniformScale["Scale"] * distance; +} + +bool UniformScaleSystem::OnSetCamera(const Events::SetCamera& e) +{ + m_Camera = e.CameraEntity; + return false; +} \ No newline at end of file From e2357b86259f58d7c03a7a5edfe66a547ec00826 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Sun, 17 Jan 2016 06:23:13 +0100 Subject: [PATCH 03/38] Fixed absolute position not taking scale into account --- src/Engine/Core/Transform.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Engine/Core/Transform.cpp b/src/Engine/Core/Transform.cpp index cbc405a3..8acac937 100644 --- a/src/Engine/Core/Transform.cpp +++ b/src/Engine/Core/Transform.cpp @@ -7,7 +7,7 @@ glm::vec3 Transform::AbsolutePosition(World* world, EntityID entity) while (entity != EntityID_Invalid) { ComponentWrapper transform = world->GetComponent(entity, "Transform"); EntityID parent = world->GetParent(entity); - position += Transform::AbsoluteOrientation(world, parent) * (glm::vec3)transform["Position"]; + position += Transform::AbsoluteScale(world, parent) * Transform::AbsoluteOrientation(world, parent) * (glm::vec3)transform["Position"]; entity = parent; } From e34856468a823d2cbf80bf0f2a65c66e78b31124 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Sun, 17 Jan 2016 06:27:45 +0100 Subject: [PATCH 04/38] Removed DrawScenePass, since it doesn't seem to be used --- include/Engine/Rendering/DrawScenePass.h | 42 ------------- include/Engine/Rendering/DrawScenePassState.h | 15 ----- include/Engine/Rendering/Renderer.h | 2 - src/Engine/Rendering/DrawScenePass.cpp | 62 ------------------- src/Engine/Rendering/DrawScenePassState.cpp | 20 ------ src/Engine/Rendering/Renderer.cpp | 1 - 6 files changed, 142 deletions(-) delete mode 100644 include/Engine/Rendering/DrawScenePass.h delete mode 100644 include/Engine/Rendering/DrawScenePassState.h delete mode 100644 src/Engine/Rendering/DrawScenePass.cpp delete mode 100644 src/Engine/Rendering/DrawScenePassState.cpp diff --git a/include/Engine/Rendering/DrawScenePass.h b/include/Engine/Rendering/DrawScenePass.h deleted file mode 100644 index ca2463cf..00000000 --- a/include/Engine/Rendering/DrawScenePass.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef DrawScenePass_h__ -#define DrawScenePass_h__ - -#include "IRenderer.h" -#include "DrawScenePassState.h" -#include "FrameBuffer.h" -#include "ShaderProgram.h" -#include "Util/UnorderedMapVec2.h" -#include "Texture.h" - -class DrawScenePass -{ -public: - DrawScenePass(IRenderer* renderer); - ~DrawScenePass() { } - void InitializeTextures(); - void InitializeFrameBuffers(); - void InitializeShaderPrograms(); - - void Draw(RenderScene& scene); - - //Getters - - -private: - void GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filtering, glm::vec2 dimensions, GLint internalFormat, GLint format, GLenum type) const; - - static bool DepthSort(const std::shared_ptr &i, const std::shared_ptr &j) - { - return (i->Depth < j->Depth); - }; - - Texture* m_WhiteTexture; - - const IRenderer* m_Renderer; - - ShaderProgram* m_BasicForwardProgram; - - -}; - -#endif \ No newline at end of file diff --git a/include/Engine/Rendering/DrawScenePassState.h b/include/Engine/Rendering/DrawScenePassState.h deleted file mode 100644 index 7ce74006..00000000 --- a/include/Engine/Rendering/DrawScenePassState.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef DrawScenePassState_h__ -#define DrawScenePassState_h__ - -#include "Rendering/RenderState.h" - -class DrawScenePassState : public RenderState -{ -public: - DrawScenePassState(); - ~DrawScenePassState(); -private: - -}; - -#endif \ No newline at end of file diff --git a/include/Engine/Rendering/Renderer.h b/include/Engine/Rendering/Renderer.h index 0bfe76f7..2bc93268 100644 --- a/include/Engine/Rendering/Renderer.h +++ b/include/Engine/Rendering/Renderer.h @@ -11,7 +11,6 @@ #include "FrameBuffer.h" #include "../Core/World.h" #include "PickingPass.h" -#include "DrawScenePass.h" #include "LightCullingPass.h" #include "DrawFinalPass.h" #include "../Core/EventBroker.h" @@ -45,7 +44,6 @@ private: Model* m_UnitQuad; Model* m_UnitSphere; - DrawScenePass* m_DrawScenePass; PickingPass* m_PickingPass; LightCullingPass* m_LightCullingPass; ImGuiRenderPass* m_ImGuiRenderPass; diff --git a/src/Engine/Rendering/DrawScenePass.cpp b/src/Engine/Rendering/DrawScenePass.cpp deleted file mode 100644 index 7871f1dd..00000000 --- a/src/Engine/Rendering/DrawScenePass.cpp +++ /dev/null @@ -1,62 +0,0 @@ -#include "Rendering/DrawScenePass.h" - -DrawScenePass::DrawScenePass(IRenderer* renderer) -{ - m_Renderer = renderer; - InitializeTextures(); - InitializeShaderPrograms(); -} - -void DrawScenePass::InitializeTextures() -{ - m_WhiteTexture = ResourceManager::Load("Textures/Core/Blank.png"); -} - -void DrawScenePass::InitializeShaderPrograms() -{ - m_BasicForwardProgram = ResourceManager::Load("#BasicForwardProgram"); - - m_BasicForwardProgram->AddShader(std::shared_ptr(new VertexShader("Shaders/BasicForward.vert.glsl"))); - m_BasicForwardProgram->AddShader(std::shared_ptr(new FragmentShader("Shaders/BasicForward.frag.glsl"))); - m_BasicForwardProgram->Compile(); - m_BasicForwardProgram->Link(); -} - -void DrawScenePass::Draw(RenderScene& scene) -{ - //glBindFramebuffer(GL_FRAMEBUFFER, 0); - GLERROR("DrawScenePass::Draw: Pre"); - - DrawScenePassState state = DrawScenePassState(); - m_BasicForwardProgram->Bind(); - - for (auto &job : scene.ForwardJobs) { - auto modelJob = std::dynamic_pointer_cast(job); - if (modelJob) { - GLuint ShaderHandle = m_BasicForwardProgram->GetHandle(); - - //TODO: Kolla upp "header/include/common" shader saken så man slipper skicka in asmycket uniforms - glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "M"), 1, GL_FALSE, glm::value_ptr(modelJob->Matrix)); - glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); - glUniformMatrix4fv(glGetUniformLocation(ShaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); - glUniform4fv(glGetUniformLocation(ShaderHandle, "Color"), 1, glm::value_ptr(modelJob->Color)); - - //TODO: Renderer: bättre textur felhantering samt fler texturer stöd - if (modelJob->DiffuseTexture != nullptr) { - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, modelJob->DiffuseTexture->m_Texture); - } else { - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, m_WhiteTexture->m_Texture); - } - - glBindVertexArray(modelJob->Model->VAO); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelJob->Model->ElementBuffer); - glDrawElementsBaseVertex(GL_TRIANGLES, modelJob->EndIndex - modelJob->StartIndex + 1, GL_UNSIGNED_INT, 0, modelJob->StartIndex); - - //continue; - } - - } - GLERROR("DrawScenePass::Draw: End"); -} diff --git a/src/Engine/Rendering/DrawScenePassState.cpp b/src/Engine/Rendering/DrawScenePassState.cpp deleted file mode 100644 index 2d643697..00000000 --- a/src/Engine/Rendering/DrawScenePassState.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "Rendering/DrawScenePassState.h" - - -DrawScenePassState::DrawScenePassState() -{ - GLERROR("---"); - BindFramebuffer(0); - GLERROR("---"); - Enable(GL_DEPTH_TEST); - Enable(GL_CULL_FACE); - Enable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - // ClearColor(glm::vec4(255.f / 255, 163.f / 255, 176.f / 255, 0.f)); - // Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); -} - -DrawScenePassState::~DrawScenePassState() -{ - -} diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index 9ae317ca..2f4c0ba2 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -161,7 +161,6 @@ void Renderer::GenerateTexture(GLuint* texture, GLenum wrapping, GLenum filterin void Renderer::InitializeRenderPasses() { - m_DrawScenePass = new DrawScenePass(this); m_PickingPass = new PickingPass(this, m_EventBroker); m_LightCullingPass = new LightCullingPass(this); m_DrawFinalPass = new DrawFinalPass(this, m_LightCullingPass); From 4786986abdfc2a5ef1250e93044fde8cab2cd4f7 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Sun, 17 Jan 2016 06:29:25 +0100 Subject: [PATCH 05/38] Rendering pipeline fixes across the board and base work on refactored editor --- include/Engine/Editor/EditorRenderSystem.h | 27 + include/Engine/Editor/EditorSystem.h | 96 +-- include/Engine/Editor/EditorSystemOld.h | 94 +++ include/Engine/Editor/EditorUI.h | 8 + .../Rendering/DebugCameraInputController.h | 7 +- include/Engine/Rendering/DrawFinalPass.h | 1 - include/Engine/Rendering/ESetCamera.h | 10 +- include/Engine/Rendering/IRenderer.h | 11 - include/Engine/Rendering/RenderJob.h | 1 - include/Engine/Rendering/RenderQueue.h | 3 +- include/Engine/Rendering/RenderState.h | 2 +- include/Engine/Rendering/RenderSystem.h | 21 +- resources/Schema/Components/Camera.xml | 1 - resources/Schema/Components/Camera.xsd | 1 - resources/Schema/Components/PointLight.xsd | 2 +- resources/Schema/Entities/EditorWidget.xml | 79 ++ resources/Schema/Entities/Test.xml | 2 +- src/Engine/Editor/EditorRenderSystem.cpp | 87 ++ src/Engine/Editor/EditorSystem.cpp | 760 +----------------- src/Engine/Editor/EditorSystemOld.cpp | 738 +++++++++++++++++ src/Engine/Editor/EditorUI.cpp | 0 src/Engine/Rendering/DrawFinalPass.cpp | 5 +- src/Engine/Rendering/DrawFinalPassState.cpp | 1 - src/Engine/Rendering/RenderState.cpp | 15 +- src/Engine/Rendering/RenderSystem.cpp | 145 +--- src/Engine/Rendering/Renderer.cpp | 15 +- src/Game/Game.cpp | 4 +- 27 files changed, 1134 insertions(+), 1002 deletions(-) create mode 100644 include/Engine/Editor/EditorRenderSystem.h create mode 100644 include/Engine/Editor/EditorSystemOld.h create mode 100644 include/Engine/Editor/EditorUI.h create mode 100755 resources/Schema/Entities/EditorWidget.xml create mode 100644 src/Engine/Editor/EditorRenderSystem.cpp create mode 100644 src/Engine/Editor/EditorSystemOld.cpp create mode 100644 src/Engine/Editor/EditorUI.cpp diff --git a/include/Engine/Editor/EditorRenderSystem.h b/include/Engine/Editor/EditorRenderSystem.h new file mode 100644 index 00000000..c593e29a --- /dev/null +++ b/include/Engine/Editor/EditorRenderSystem.h @@ -0,0 +1,27 @@ +#ifndef EditorRenderSystem_h__ +#define EditorRenderSystem_h__ + +#include "../Core/System.h" +#include "../Rendering/IRenderer.h" +#include "../Rendering/ModelJob.h" +#include "../Rendering/Camera.h" +#include "../Rendering/ESetCamera.h" + +class EditorRenderSystem : public ImpureSystem +{ +public: + EditorRenderSystem(EventBroker* eventBroker, IRenderer* renderer, RenderFrame* renderFrame); + + virtual void Update(World* world, double dt) override; + +private: + IRenderer* m_Renderer; + RenderFrame* m_RenderFrame; + Camera* m_EditorCamera; + EntityWrapper m_CurrentCamera = EntityWrapper::Invalid; + + EventRelay m_ESetCamera; + bool OnSetCamera(Events::SetCamera& e); +}; + +#endif \ No newline at end of file diff --git a/include/Engine/Editor/EditorSystem.h b/include/Engine/Editor/EditorSystem.h index 05e106d9..43022009 100644 --- a/include/Engine/Editor/EditorSystem.h +++ b/include/Engine/Editor/EditorSystem.h @@ -1,94 +1,30 @@ -#include -#include -#include -#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 "../Core/Transform.h" -#include "../Core/EFileDropped.h" +#include "../Rendering/Camera.h" +#include "../Rendering/DebugCameraInputController.h" +#include "../Rendering/ESetCamera.h" +#include "../Core/World.h" +#include "../Core/SystemPipeline.h" +#include "../Core/ResourceManager.h" #include "../Core/EntityFilePreprocessor.h" #include "../Core/EntityFileParser.h" -#include "../Core/EntityFileWriter.h" class EditorSystem : public ImpureSystem { public: - EditorSystem(EventBroker* eventBroker, IRenderer* renderer); + EditorSystem(EventBroker* eventBroker, IRenderer* renderer, RenderFrame* renderFrame); + ~EditorSystem(); - virtual void Update(World* world, double dt) override; + void Update(World* world, double dt); private: IRenderer* m_Renderer; - World* m_World = nullptr; - Camera* m_Camera = nullptr; + RenderFrame* m_RenderFrame; + World* m_EditorWorld; + SystemPipeline* m_EditorWorldSystemPipeline; + Camera* m_EditorCamera; - bool m_Enabled; - bool m_Visible; - boost::filesystem::path m_DefaultEntityDir; - boost::filesystem::path m_CurrentFile; - 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 = EntityID_Invalid; - EntityID m_WidgetX = EntityID_Invalid; - EntityID m_WidgetPlaneX = EntityID_Invalid; - EntityID m_WidgetY = EntityID_Invalid; - EntityID m_WidgetPlaneY = EntityID_Invalid; - EntityID m_WidgetZ = EntityID_Invalid; - EntityID m_WidgetPlaneZ = EntityID_Invalid; - EntityID m_WidgetOrigin = EntityID_Invalid; - glm::vec3 m_WidgetCurrentAxis; - float m_WidgetPickingDepth = 0.f; - glm::vec3 m_WidgetPickingPosition = glm::vec3(0); - - EntityID m_Selection = EntityID_Invalid; - EntityID m_LastSelection = EntityID_Invalid; - EntityID m_UIDraggingEntity = EntityID_Invalid; - glm::vec3 m_Position; - std::string m_LastDroppedFile; - - static boost::filesystem::path openDialog(boost::filesystem::path defaultPath); - static boost::filesystem::path saveDialog(boost::filesystem::path defaultPath); - - 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_EFileDropped; - bool OnFileDropped(const Events::FileDropped& e); - - void Picking(); - void createWidget(); - void updateWidget(); - void setWidgetMode(WidgetMode newMode); - void setWidgetSpace(WidgetSpace space); - void drawUI(World* world, double dt); - bool createDeleteButton(std::string componentType); - bool createEntityNode(World* world, EntityID entity); - void changeParent(EntityID entity, EntityID newParent); - void fileImport(World* world); - void fileSave(World* world); - void fileSaveAs(World* world); + EntityWrapper m_Widget = EntityWrapper::Invalid; + EntityWrapper m_Camera = EntityWrapper::Invalid; + DebugCameraInputController* m_DebugCameraInputController; }; \ No newline at end of file diff --git a/include/Engine/Editor/EditorSystemOld.h b/include/Engine/Editor/EditorSystemOld.h new file mode 100644 index 00000000..b2d7df0c --- /dev/null +++ b/include/Engine/Editor/EditorSystemOld.h @@ -0,0 +1,94 @@ +#include +#include +#include +#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 "../Core/Transform.h" +#include "../Core/EFileDropped.h" +#include "../Core/EntityFilePreprocessor.h" +#include "../Core/EntityFileParser.h" +#include "../Core/EntityFileWriter.h" + +class EditorSystemOld : public ImpureSystem +{ +public: + EditorSystemOld(EventBroker* eventBroker, IRenderer* renderer); + + virtual void Update(World* world, double dt) override; + +private: + IRenderer* m_Renderer; + World* m_World = nullptr; + Camera* m_Camera = nullptr; + + bool m_Enabled; + bool m_Visible; + boost::filesystem::path m_DefaultEntityDir; + boost::filesystem::path m_CurrentFile; + 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 = EntityID_Invalid; + EntityID m_WidgetX = EntityID_Invalid; + EntityID m_WidgetPlaneX = EntityID_Invalid; + EntityID m_WidgetY = EntityID_Invalid; + EntityID m_WidgetPlaneY = EntityID_Invalid; + EntityID m_WidgetZ = EntityID_Invalid; + EntityID m_WidgetPlaneZ = EntityID_Invalid; + EntityID m_WidgetOrigin = EntityID_Invalid; + glm::vec3 m_WidgetCurrentAxis; + float m_WidgetPickingDepth = 0.f; + glm::vec3 m_WidgetPickingPosition = glm::vec3(0); + + EntityID m_Selection = EntityID_Invalid; + EntityID m_LastSelection = EntityID_Invalid; + EntityID m_UIDraggingEntity = EntityID_Invalid; + glm::vec3 m_Position; + std::string m_LastDroppedFile; + + static boost::filesystem::path openDialog(boost::filesystem::path defaultPath); + static boost::filesystem::path saveDialog(boost::filesystem::path defaultPath); + + 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_EFileDropped; + bool OnFileDropped(const Events::FileDropped& e); + + void Picking(); + void createWidget(); + void updateWidget(); + void setWidgetMode(WidgetMode newMode); + void setWidgetSpace(WidgetSpace space); + void drawUI(World* world, double dt); + bool createDeleteButton(std::string componentType); + bool createEntityNode(World* world, EntityID entity); + void changeParent(EntityID entity, EntityID newParent); + void fileImport(World* world); + void fileSave(World* world); + void fileSaveAs(World* world); +}; \ No newline at end of file diff --git a/include/Engine/Editor/EditorUI.h b/include/Engine/Editor/EditorUI.h new file mode 100644 index 00000000..18299865 --- /dev/null +++ b/include/Engine/Editor/EditorUI.h @@ -0,0 +1,8 @@ +#include +#include + +class EditorUI +{ +public: + EditorUI(); +}; \ No newline at end of file diff --git a/include/Engine/Rendering/DebugCameraInputController.h b/include/Engine/Rendering/DebugCameraInputController.h index 4d74e288..1a43820c 100644 --- a/include/Engine/Rendering/DebugCameraInputController.h +++ b/include/Engine/Rendering/DebugCameraInputController.h @@ -1,3 +1,6 @@ +#ifndef DebugCameraInputController_h__ +#define DebugCameraInputController_h__ + #include #include "../Input/FirstPersonInputController.h" @@ -63,4 +66,6 @@ protected: glm::vec3 m_Velocity = glm::vec3(0, 0, 0); float m_BaseSpeed = 2.0f; float m_Speed = m_BaseSpeed; -}; \ No newline at end of file +}; + +#endif \ No newline at end of file diff --git a/include/Engine/Rendering/DrawFinalPass.h b/include/Engine/Rendering/DrawFinalPass.h index 52876592..20c7249d 100644 --- a/include/Engine/Rendering/DrawFinalPass.h +++ b/include/Engine/Rendering/DrawFinalPass.h @@ -32,7 +32,6 @@ private: const LightCullingPass* m_LightCullingPass; ShaderProgram* m_ForwardPlusProgram; - }; #endif \ No newline at end of file diff --git a/include/Engine/Rendering/ESetCamera.h b/include/Engine/Rendering/ESetCamera.h index 650f3b12..1b39e890 100644 --- a/include/Engine/Rendering/ESetCamera.h +++ b/include/Engine/Rendering/ESetCamera.h @@ -2,20 +2,14 @@ #define Events_SetCamera_h__ #include "../Core/EventBroker.h" -#include "../Core/Entity.h" -#include +#include "../Core/EntityWrapper.h" namespace Events { struct SetCamera : Event { -public: - SetCamera() { }; - std::string Name; - -private: - + EntityWrapper CameraEntity; }; } diff --git a/include/Engine/Rendering/IRenderer.h b/include/Engine/Rendering/IRenderer.h index 95053a85..6ef189f4 100644 --- a/include/Engine/Rendering/IRenderer.h +++ b/include/Engine/Rendering/IRenderer.h @@ -31,15 +31,6 @@ public: void SetFullscreen(bool fullscreen) { m_Fullscreen = fullscreen; } bool VSYNC() const { return m_VSYNC; } void SetVSYNC(bool vsync) { m_VSYNC = vsync; } - ::Camera* Camera() const { return m_Camera; } - void SetCamera(::Camera* camera) - { - if (camera == nullptr) { - m_Camera = m_DefaultCamera; - } else { - m_Camera = camera; - } - } virtual void Initialize() = 0; virtual void Update(double dt) = 0; virtual void Draw(RenderFrame& rq) = 0; @@ -54,8 +45,6 @@ protected: int m_GLVersion[2]; std::string m_GLVendor; GLFWwindow* m_Window = nullptr; - ::Camera* m_DefaultCamera; - ::Camera* m_Camera = nullptr; }; #endif // Renderer_h__ diff --git a/include/Engine/Rendering/RenderJob.h b/include/Engine/Rendering/RenderJob.h index 4afe0386..bcffc4a5 100644 --- a/include/Engine/Rendering/RenderJob.h +++ b/include/Engine/Rendering/RenderJob.h @@ -14,7 +14,6 @@ struct RenderJob friend class RenderQueue; public: - float Depth; protected: diff --git a/include/Engine/Rendering/RenderQueue.h b/include/Engine/Rendering/RenderQueue.h index 119ea57f..701d08b9 100644 --- a/include/Engine/Rendering/RenderQueue.h +++ b/include/Engine/Rendering/RenderQueue.h @@ -50,10 +50,11 @@ struct PointLightJob : RenderJob struct RenderScene { - ::Camera* Camera; + ::Camera* Camera = nullptr; std::list> ForwardJobs; std::list> PointLightJobs; Rectangle Viewport; + bool ClearDepth = false; void Clear() { diff --git a/include/Engine/Rendering/RenderState.h b/include/Engine/Rendering/RenderState.h index c6eb8775..688ef520 100644 --- a/include/Engine/Rendering/RenderState.h +++ b/include/Engine/Rendering/RenderState.h @@ -16,10 +16,10 @@ public: bool Disable(GLenum cap); bool CullFace(GLenum mode); bool ClearColor(glm::vec4 color); - bool Clear(GLbitfield mask); bool BindFramebuffer(GLint framebuffer); bool BlendEquation(GLenum mode); bool BlendFunc(GLenum sfactor, GLenum dfactor); + bool DepthMask(GLboolean flag); private: std::vector> m_ResetFunctions; diff --git a/include/Engine/Rendering/RenderSystem.h b/include/Engine/Rendering/RenderSystem.h index fe110276..39b35108 100644 --- a/include/Engine/Rendering/RenderSystem.h +++ b/include/Engine/Rendering/RenderSystem.h @@ -28,28 +28,17 @@ public: private: World* m_World = nullptr; const IRenderer* m_Renderer; - RenderFrame* m_RenderFrame; - bool m_SwitchCamera = false; Camera* m_Camera; - DebugCameraInputController* m_DebugCameraInputController; - - std::list m_CameraComponents; + EntityWrapper m_CurrentCamera = EntityWrapper::Invalid; EventRelay m_ESetCamera; - bool OnSetCamera(const Events::SetCamera &event); - EntityID m_CurrentCamera = EntityID_Invalid; - - void switchCamera(EntityID entity); - - void updateCamera(World* world, double dt); - void updateProjectionMatrix(ComponentWrapper& cameraComponent); - - void fillModels(std::list>& jobs, World* world); - void fillLight(std::list>& jobs, World* world); - + bool OnSetCamera(Events::SetCamera &event); EventRelay m_EInputCommand; bool OnInputCommand(const Events::InputCommand& e); + + void fillModels(std::list>& jobs, World* world); + void fillLight(std::list>& jobs, World* world); }; #endif \ No newline at end of file diff --git a/resources/Schema/Components/Camera.xml b/resources/Schema/Components/Camera.xml index ccb12f01..b9c28d53 100644 --- a/resources/Schema/Components/Camera.xml +++ b/resources/Schema/Components/Camera.xml @@ -1,6 +1,5 @@ - cam 45 0.01 5000 diff --git a/resources/Schema/Components/Camera.xsd b/resources/Schema/Components/Camera.xsd index 2b896c74..1bde2333 100644 --- a/resources/Schema/Components/Camera.xsd +++ b/resources/Schema/Components/Camera.xsd @@ -9,7 +9,6 @@ - Vertical Field of View in degrees diff --git a/resources/Schema/Components/PointLight.xsd b/resources/Schema/Components/PointLight.xsd index 9b802d8c..25d0aa07 100644 --- a/resources/Schema/Components/PointLight.xsd +++ b/resources/Schema/Components/PointLight.xsd @@ -12,7 +12,7 @@ - + diff --git a/resources/Schema/Entities/EditorWidget.xml b/resources/Schema/Entities/EditorWidget.xml new file mode 100755 index 00000000..e729af02 --- /dev/null +++ b/resources/Schema/Entities/EditorWidget.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + Models/TranslationWidgetOrigin.obj + + + + + + + + Models/TranslationWidgetX.obj + + + + + + + + Models/TranslationWidgetY.obj + + + + + + + + Models/TranslationWidgetZ.obj + + + + + + + + Models/WidgetPlaneX.obj + + + + + + + + Models/WidgetPlaneY.obj + + + + + + + + Models/WidgetPlaneZ.obj + + + + + + diff --git a/resources/Schema/Entities/Test.xml b/resources/Schema/Entities/Test.xml index d2838ae9..5f57dbb7 100644 --- a/resources/Schema/Entities/Test.xml +++ b/resources/Schema/Entities/Test.xml @@ -9,7 +9,6 @@ Models/DummyScene.obj - @@ -25,3 +24,4 @@ + diff --git a/src/Engine/Editor/EditorRenderSystem.cpp b/src/Engine/Editor/EditorRenderSystem.cpp new file mode 100644 index 00000000..2d25338d --- /dev/null +++ b/src/Engine/Editor/EditorRenderSystem.cpp @@ -0,0 +1,87 @@ +#include "Editor/EditorRenderSystem.h" + +EditorRenderSystem::EditorRenderSystem(EventBroker* eventBroker, IRenderer* renderer, RenderFrame* renderFrame) + : System(eventBroker) + , m_Renderer(renderer) + , m_RenderFrame(renderFrame) +{ + EVENT_SUBSCRIBE_MEMBER(m_ESetCamera, &EditorRenderSystem::OnSetCamera); + auto resolution = Rectangle::Rectangle(1280, 720); + m_EditorCamera = new Camera((float)resolution.Width / resolution.Height, glm::radians(45.f), 0.01f, 5000.f); +} + +void EditorRenderSystem::Update(World* world, double dt) +{ + if (m_CurrentCamera) { + ComponentWrapper cameraTransform = m_CurrentCamera["Transform"]; + m_EditorCamera->SetPosition(cameraTransform["Position"]); + m_EditorCamera->SetOrientation(glm::quat((const glm::vec3&)cameraTransform["Orientation"])); + } + + RenderScene scene; + scene.ClearDepth = true; + scene.Camera = m_EditorCamera; + scene.Viewport = Rectangle(1920, 1080); + + auto models = world->GetComponents("Model"); + if (models != nullptr) { + for (auto& cModel : *models) { + if (!(bool)cModel["Visible"]) { + continue; + } + + const std::string& resource = cModel["Resource"]; + + Model* model; + try { + model = ResourceManager::Load<::Model, true>(resource); + } catch (const Resource::StillLoadingException&) { + continue; + } catch (const std::exception&) { + try { + model = ResourceManager::Load<::Model>("Models/Core/Error.obj"); + } catch (const std::exception&) { + continue; + } + } + + EntityWrapper entity(world, cModel.EntityID); + glm::mat4 modelMatrix = Transform::ModelMatrix(entity.ID, entity.World); + for (auto matGroup : model->MaterialGroups()) { + std::shared_ptr modelJob = std::make_shared(model, nullptr, modelMatrix, matGroup, cModel, entity.World); + scene.ForwardJobs.push_back(modelJob); + } + } + } + + auto pointLights = world->GetComponents("PointLight"); + if (pointLights != nullptr) { + for (auto& cPointLight : *pointLights) { + bool visible = cPointLight["Visible"]; + if (!visible) { + continue; + } + + EntityWrapper entity(world, cPointLight.EntityID); + ComponentWrapper& cTransform = entity["Transform"]; + std::shared_ptr pointLightJob = std::make_shared(cTransform, cPointLight, entity.World); + scene.PointLightJobs.push_back(pointLightJob); + } + } + + m_RenderFrame->Add(scene); +} + +bool EditorRenderSystem::OnSetCamera(Events::SetCamera& e) +{ + ComponentWrapper cTransform = e.CameraEntity["Transform"]; + ComponentWrapper cCamera = e.CameraEntity["Camera"]; + m_EditorCamera->SetFOV((double)cCamera["FOV"]); + m_EditorCamera->SetNearClip((double)cCamera["NearClip"]); + m_EditorCamera->SetFarClip((double)cCamera["FarClip"]); + m_EditorCamera->SetPosition(cTransform["Position"]); + m_EditorCamera->SetOrientation(glm::quat((const glm::vec3&)cTransform["Orientation"])); + m_CurrentCamera = e.CameraEntity; + return true; +} + diff --git a/src/Engine/Editor/EditorSystem.cpp b/src/Engine/Editor/EditorSystem.cpp index d5863814..ec385e9b 100644 --- a/src/Engine/Editor/EditorSystem.cpp +++ b/src/Engine/Editor/EditorSystem.cpp @@ -1,738 +1,46 @@ #include "Editor/EditorSystem.h" -#define IMGUI_DEFINE_MATH_OPERATORS -#include +#include "Core/UniformScaleSystem.h" +#include "Editor/EditorRenderSystem.h" -EditorSystem::EditorSystem(EventBroker* eventBroker, IRenderer* renderer) +EditorSystem::EditorSystem(EventBroker* eventBroker, IRenderer* renderer, RenderFrame* renderFrame) : System(eventBroker) - , ImpureSystem() , m_Renderer(renderer) + , m_RenderFrame(renderFrame) { - auto config = ResourceManager::Load("Config.ini"); - m_Enabled = config->Get("Debug.EditorEnabled", false); - m_Visible = m_Enabled; - m_DefaultEntityDir = boost::filesystem::path("Schema") / boost::filesystem::path("Entities"); + m_EditorWorld = new World(); + m_EditorWorldSystemPipeline = new SystemPipeline(eventBroker); + m_EditorWorldSystemPipeline->AddSystem(0); + m_EditorWorldSystemPipeline->AddSystem(1, m_Renderer, m_RenderFrame); + + auto widgetEntityFile = ResourceManager::Load("Schema/Entities/EditorWidget.xml"); + EntityFilePreprocessor fpp(widgetEntityFile); + fpp.RegisterComponents(m_EditorWorld); + EntityFileParser fp(widgetEntityFile); + EntityID widgetID = fp.MergeEntities(m_EditorWorld); + m_Widget = EntityWrapper(m_EditorWorld, widgetID); - if (!m_Enabled) { - return; - } + m_Camera = EntityWrapper(m_EditorWorld, m_EditorWorld->CreateEntity()); + m_EditorWorld->AttachComponent(m_Camera.ID, "Transform"); + m_EditorWorld->AttachComponent(m_Camera.ID, "Camera"); + m_DebugCameraInputController = new DebugCameraInputController(m_EventBroker, -1); - 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_EFileDropped, &EditorSystem::OnFileDropped); + Events::SetCamera e; + e.CameraEntity = m_Camera; + m_EventBroker->Publish(e); +} + +EditorSystem::~EditorSystem() +{ + delete m_DebugCameraInputController; + delete m_EditorWorldSystemPipeline; + delete m_EditorWorld; } void EditorSystem::Update(World* world, double dt) { - m_World = world; + m_EditorWorldSystemPipeline->Update(m_EditorWorld, dt); - if (!m_Enabled) { - return; - } - - if (!m_Visible) { - return; - } - Picking(); - updateWidget(); - - drawUI(world, dt); - - // Clear drop queue if it wasn't handled by any UI element - if (!m_LastDroppedFile.empty()) { - m_LastDroppedFile = ""; - } -} - - -boost::filesystem::path EditorSystem::openDialog(boost::filesystem::path defaultPath) -{ - namespace bfs = boost::filesystem; - auto absolutePath = bfs::absolute(defaultPath); - nfdchar_t* outPath = nullptr; - nfdresult_t result = NFD_OpenDialog(NULL, absolutePath.string().c_str(), &outPath); - if (result == NFD_ERROR) { - LOG_ERROR("NFD Error: %s", NFD_GetError()); - return bfs::path(); - } - - return bfs::absolute(outPath); -} - -boost::filesystem::path EditorSystem::saveDialog(boost::filesystem::path defaultPath) -{ - namespace bfs = boost::filesystem; - auto absolutePath = bfs::absolute(defaultPath); - nfdchar_t* outPath = nullptr; - nfdresult_t result = NFD_SaveDialog(NULL, absolutePath.string().c_str(), &outPath); - if (result == NFD_ERROR) { - LOG_ERROR("NFD Error: %s", NFD_GetError()); - return bfs::path(); - } - - return bfs::absolute(outPath); -} - -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; -} - -bool EditorSystem::OnMousePress(const Events::MousePress& e) -{ - if (e.Button == GLFW_MOUSE_BUTTON_RIGHT) { - m_PickingQueue.push_back(glm::vec2((int)e.X, (int)e.Y)); - } - return true; -} - -bool EditorSystem::OnMouseMove(const Events::MouseMove& e) -{ - if (m_Widget == EntityID_Invalid) { - return false; - } - if (m_Selection == EntityID_Invalid) { - return false; - } - if (m_Selection == m_Widget) { - return false; - } - // TODO: No widgets for root entity until widgets reside in thier own world, - // or the widgets will move relative to the root entity being moved, which is WEEEIRD. - if (m_Selection == 0) { - return false; - } - if (m_Camera == nullptr) { - return false; - } - - auto widgetTransform = m_World->GetComponent(m_Widget, "Transform"); - glm::vec3 widgetOrientation = widgetTransform["Orientation"]; - glm::quat totalOrientation = m_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_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_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) { - EntityID parent = m_World->GetParent(m_Selection); - glm::quat inverseParentOrientation; - //if (parent != 0) { - inverseParentOrientation = glm::inverse(Transform::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; - } - } 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; - if (m_WidgetSpace == WidgetSpace::Global) { - EntityID parent = m_World->GetParent(m_Selection); - glm::quat parentOrientation; - //if (parent != 0) { - // parentOrientation = RenderSystem::AbsoluteOrientation(m_World, parent); - //} - glm::vec3& selectionOrientation = m_World->GetComponent(m_Selection, "Transform")["Orientation"]; - glm::quat currentOrientation = Transform::AbsoluteOrientation(m_World, m_Selection); - //glm::quat currentOrientation = parentOrientation * glm::quat(selectionOrientation); - glm::quat deltaOrientation(finalMovement); - 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); - } - } 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 && 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; - } - if (m_WidgetCurrentAxis.y > 0) { - scaleY.y += movement.y; - } - if (m_WidgetCurrentAxis.z > 0) { - scaleZ.z += movement.z; - } - (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; -} - -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; -} - -void EditorSystem::Picking() -{ - for (auto& pos : m_PickingQueue) { - auto result = m_Renderer->Pick(pos); - EntityID entity = result.Entity; - if (glm::length2(m_WidgetCurrentAxis) > 0.f) { - // ??? - } else { - LOG_INFO("Selected %i", entity); - if (entity != EntityID_Invalid) { - EntityID parent = m_World->GetParent(entity); - m_Camera = result.Camera; - if (parent == m_Widget) { - m_WidgetCurrentAxis = glm::vec3( - (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; - //auto widgetTransform = m_World->GetComponent(m_Widget, "Transform"); - //auto selectionTransform = m_World->GetComponent(m_Selection, "Transform"); - //widgetTransform["Position"] = (glm::vec3)selectionTransform["Position"]; - } else { - ImGui::SetActiveID(0, nullptr); - if (m_WidgetMode == WidgetMode::None) { - m_WidgetMode = WidgetMode::Translate; - } - setWidgetMode(m_WidgetMode); - m_Selection = entity; - } - } - } - } - m_PickingQueue.clear(); -}; - -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::createWidget() -{ - if (m_Widget == EntityID_Invalid) { - 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_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"); - setWidgetMode(WidgetMode::None); - } -} - -void EditorSystem::updateWidget() -{ - if (m_Widget == EntityID_Invalid) { - return; - } - if (m_Selection == m_Widget) { - return; - } - - if (m_Selection != EntityID_Invalid) { - auto widgetTransform = m_World->GetComponent(m_Widget, "Transform"); - glm::vec3 selectionPosition = Transform::AbsolutePosition(m_World, m_Selection); - widgetTransform["Position"] = selectionPosition; - if (m_WidgetSpace == WidgetSpace::Local) { - widgetTransform["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(m_World, m_Selection)); - } - } -} - -void EditorSystem::setWidgetMode(WidgetMode newMode) -{ - if (m_Widget == EntityID_Invalid) { - 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_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"; - // 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 != EntityID_Invalid) { - if (m_WidgetSpace == WidgetSpace::Local) { - auto selectionTransform = m_World->GetComponent(m_Selection, "Transform"); - widgetTransform["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(m_World, m_Selection)); - } - } - } 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 != EntityID_Invalid) { - auto selectionTransform = m_World->GetComponent(m_Selection, "Transform"); - widgetTransform["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(m_World, m_Selection)); - } - } 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"; - if (m_Selection != EntityID_Invalid) { - auto selectionTransform = m_World->GetComponent(m_Selection, "Transform"); - if (m_WidgetSpace == WidgetSpace::Local) { - widgetTransform["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(m_World, m_Selection)); - } - } - } - m_WidgetMode = newMode; -} - -void EditorSystem::setWidgetSpace(WidgetSpace space) -{ - m_WidgetSpace = space; - setWidgetMode(m_WidgetMode); -} - -void EditorSystem::drawUI(World* world, double dt) -{ - namespace bfs = boost::filesystem; - - ImGui::ShowTestWindow(); - //ImGui::ShowStyleEditor(); - - if (ImGui::BeginMainMenuBar()) { - if (ImGui::BeginMenu("File")) { - //if (ImGui::MenuItem("New")) { } - if (ImGui::MenuItem("Import", "Ctrl+O")) { - fileImport(world); - } - if (ImGui::MenuItem("Save", "Ctrl+S")) { - fileSave(world); - } - if (ImGui::MenuItem("Save As...", "Ctrl+Shift+S")) { - fileSaveAs(world); - } - ImGui::Separator(); - if (ImGui::MenuItem("Close Editor", "F1")) { } - - ImGui::EndMenu(); - } - - ImGui::SameLine(); - if (ImGui::Button("Move")) { - setWidgetMode(WidgetMode::Translate); - } - ImGui::SameLine(); - if (ImGui::Button("Rotate")) { - setWidgetMode(WidgetMode::Rotate); - } - ImGui::SameLine(); - if (ImGui::Button("Scale")) { - 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(); - } - - std::string title = std::string("Components #") + std::to_string(m_Selection) + std::string("###Components"); - if (ImGui::Begin(title.c_str())) { - if (m_Selection != EntityID_Invalid) { - auto& pools = world->GetComponentPools(); - - std::vector componentTypes; - for (auto& pair : pools) { - // Only add components the entity doesn't already have - if (!pair.second->KnowsEntity(m_Selection)) { - componentTypes.push_back(pair.first.c_str()); - } - } - int item = -1; - ImGui::PushItemWidth(ImGui::GetWindowContentRegionWidth() - 5.f); - if (ImGui::Combo("", &item, componentTypes.data(), componentTypes.size())) { - if (item != -1) { - std::string chosenType = std::string(componentTypes.at(item)); - world->AttachComponent(m_Selection, chosenType); - } - } - ImGui::PopItemWidth(); - - for (auto& pair : pools) { - const std::string& componentType = pair.first; - auto pool = pair.second; - if (!pool->KnowsEntity(m_Selection)) { - continue; - } - auto& ci = pool->ComponentInfo(); - - bool deletePressed = createDeleteButton(componentType); - if (deletePressed) { - world->DeleteComponent(m_Selection, componentType); - continue; - } - - if (ImGui::CollapsingHeader(componentType.c_str())) { - if (!ci.Meta->Annotation.empty()) { - ImGui::Text(ci.Meta->Annotation.c_str()); - } - - auto& component = world->GetComponent(m_Selection, componentType); - for (auto& kv : ci.Fields) { - const std::string& fieldName = kv.first; - auto& field = kv.second; - - std::string uniqueID = componentType + fieldName; - ImGui::PushID(uniqueID.c_str()); - if (field.Type == "Vector") { - auto& val = component.Field(fieldName); - if (fieldName == "Scale") { - ImGui::DragFloat3("", glm::value_ptr(val), 0.1f, 0.f, std::numeric_limits::max()); - } else if (fieldName == "Orientation") { - glm::vec3 tempVal = glm::fmod(val, glm::vec3(glm::two_pi())); - if (ImGui::SliderFloat3("", glm::value_ptr(tempVal), 0.f, glm::two_pi())) { - val = tempVal; - } - } else { - ImGui::DragFloat3("", glm::value_ptr(val), 0.1f, std::numeric_limits::lowest(), std::numeric_limits::max()); - } - } else if (field.Type == "Color") { - auto& val = component.Field(fieldName); - ImGui::ColorEdit4("", glm::value_ptr(val), true); - } else if (field.Type == "string") { - std::string& val = component.Field(fieldName); - char tempString[1024]; - memcpy(tempString, val.c_str(), std::min(val.length() + 1, sizeof(tempString))); - if (ImGui::InputText("", tempString, sizeof(tempString))) { - val = std::string(tempString); - LOG_DEBUG("%s::%s changed!", componentType.c_str(), fieldName.c_str()); - } - // DROP STUFF - if (ImGui::IsItemHovered() && !m_LastDroppedFile.empty()) { - val = m_LastDroppedFile; - m_LastDroppedFile = ""; - } - - } else if (field.Type == "double") { - float tempVal = static_cast(component.Field(fieldName)); - if (ImGui::InputFloat("", &tempVal, 0.01f, 1.f)) { - component.SetField(fieldName, static_cast(tempVal)); - } - } else if (field.Type == "int") { - int val = component.Field(fieldName); - ImGui::InputInt("", &val); - } else if (field.Type == "enum") { - int currentValue = component.Field(fieldName); - int item = -1; - std::stringstream enumKeys; - std::vector enumValues; - int i = 0; - for (auto& kv : ci.Meta->FieldEnumDefinitions.at(fieldName)) { - enumKeys << kv.first << " (" << kv.second << ")" << '\0'; - enumValues.push_back(kv.second); - if (currentValue == kv.second) { - item = i; - } - i++; - } - if (ImGui::Combo("", &item, enumKeys.str().c_str())) { - component.SetField(fieldName, enumValues.at(item)); - } - } else if (field.Type == "bool") { - auto& val = component.Field(fieldName); - ImGui::Checkbox("", &val); - } else { - ImGui::TextDisabled(field.Type.c_str()); - } - ImGui::PopID(); - - ImGui::SameLine(); - ImGui::Text(fieldName.c_str()); - if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("field annotation goes here"); - } - } - } - } - } - - } - ImGui::End(); - - if (ImGui::Begin("Entities")) { - auto entityChildren = world->GetEntityChildren(); - std::function recurse = [&](EntityID parent) { - auto range = entityChildren.equal_range(parent); - for (auto it = range.first; it != range.second; it++) { - if (createEntityNode(world, it->second)) { - recurse(it->second); - ImGui::TreePop(); - } - } - }; - recurse(EntityID_Invalid); - } - ImGui::End(); -} - -bool EditorSystem::createEntityNode(World* world, EntityID entity) -{ - // HACK: Don't show the widget entities in the entity tree - if (entity == m_Widget) { - return false; - } - - 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 == 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)) { - m_Selection = 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 = world->GetName(entity); - if (!entityName.empty()) { - nodeTitle = entityName; - } else { - nodeTitle = std::string("#") + std::to_string(entity); - } - 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")) { - EntityID newEntity = world->CreateEntity(entity); - world->AttachComponent(newEntity, "Transform"); - } - ImGui::SameLine(); - if (ImGui::Button("Delete")) { - world->DeleteEntity(entity); - ImGui::CloseCurrentPopup(); - if (!world->ValidEntity(m_Selection)) { - m_Selection = EntityID_Invalid; - } - } - ImGui::EndPopup(); - } - return true; - } else { - return false; - } -} - -bool EditorSystem::createDeleteButton(std::string componentType) -{ - float width = ImGui::GetContentRegionAvailWidth(); - ImGuiWindow* window = ImGui::GetCurrentWindow(); - auto pos = ImGui::GetCursorScreenPos() + ImVec2(width - 14.f, 1); - ImRect bb = ImRect(pos, pos + ImVec2(14.f, 14.f)); - std::string idString = "#DELETE"; - idString += componentType; - ImGuiID id = window->GetID(idString.c_str()); - bool hovered; - bool held; - bool pressed = ImGui::ButtonBehavior(bb, id, &hovered, &held); - //ImU32 col = window->Color((held && hovered) ? ImGuiCol_CloseButtonActive : hovered ? ImGuiCol_CloseButtonHovered : ImGuiCol_CloseButton); - ImU32 col = window->Color((held && hovered) ? ImGuiCol_CloseButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); - 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); -} - -void EditorSystem::fileImport(World* world) -{ - m_CurrentFile = openDialog(m_DefaultEntityDir); - auto file = ResourceManager::Load(m_CurrentFile.string()); - EntityFilePreprocessor fpp(file); - fpp.RegisterComponents(world); - EntityFileParser fp(file); - fp.MergeEntities(world); - createWidget(); - updateWidget(); -} - -void EditorSystem::fileSave(World* world) -{ - if (boost::filesystem::exists(m_CurrentFile)) { - // HACK: Delete the widgets so they don't appear in the saved file - world->DeleteEntity(m_Widget); - m_Widget = EntityID_Invalid; - - EntityFileWriter writer(m_CurrentFile.string()); - writer.WriteWorld(world); - - createWidget(); - } else { - fileSaveAs(world); - } -} - -void EditorSystem::fileSaveAs(World* world) -{ - auto filePath = saveDialog(m_DefaultEntityDir); - if (filePath.empty()) { - return; - } - - // HACK: Delete the widgets so they don't appear in the saved file - world->DeleteEntity(m_Widget); - m_Widget = EntityID_Invalid; - - EntityFileWriter writer(filePath.string()); - writer.WriteWorld(world); - - createWidget(); -} + 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 diff --git a/src/Engine/Editor/EditorSystemOld.cpp b/src/Engine/Editor/EditorSystemOld.cpp new file mode 100644 index 00000000..675ea80b --- /dev/null +++ b/src/Engine/Editor/EditorSystemOld.cpp @@ -0,0 +1,738 @@ +#include "Editor/EditorSystemOld.h" +#define IMGUI_DEFINE_MATH_OPERATORS +#include + +EditorSystemOld::EditorSystemOld(EventBroker* eventBroker, IRenderer* renderer) + : System(eventBroker) + , ImpureSystem() + , m_Renderer(renderer) +{ + auto config = ResourceManager::Load("Config.ini"); + m_Enabled = config->Get("Debug.EditorEnabled", false); + m_Visible = m_Enabled; + m_DefaultEntityDir = boost::filesystem::path("Schema") / boost::filesystem::path("Entities"); + + if (!m_Enabled) { + return; + } + + EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &EditorSystemOld::OnInputCommand); + EVENT_SUBSCRIBE_MEMBER(m_EMousePress, &EditorSystemOld::OnMousePress); + EVENT_SUBSCRIBE_MEMBER(m_EMouseRelease, &EditorSystemOld::OnMouseRelease); + EVENT_SUBSCRIBE_MEMBER(m_EMouseMove, &EditorSystemOld::OnMouseMove); + EVENT_SUBSCRIBE_MEMBER(m_EFileDropped, &EditorSystemOld::OnFileDropped); +} + +void EditorSystemOld::Update(World* world, double dt) +{ + m_World = world; + + if (!m_Enabled) { + return; + } + + if (!m_Visible) { + return; + } + Picking(); + updateWidget(); + + drawUI(world, dt); + + // Clear drop queue if it wasn't handled by any UI element + if (!m_LastDroppedFile.empty()) { + m_LastDroppedFile = ""; + } +} + + +boost::filesystem::path EditorSystemOld::openDialog(boost::filesystem::path defaultPath) +{ + namespace bfs = boost::filesystem; + auto absolutePath = bfs::absolute(defaultPath); + nfdchar_t* outPath = nullptr; + nfdresult_t result = NFD_OpenDialog(NULL, absolutePath.string().c_str(), &outPath); + if (result == NFD_ERROR) { + LOG_ERROR("NFD Error: %s", NFD_GetError()); + return bfs::path(); + } + + return bfs::absolute(outPath); +} + +boost::filesystem::path EditorSystemOld::saveDialog(boost::filesystem::path defaultPath) +{ + namespace bfs = boost::filesystem; + auto absolutePath = bfs::absolute(defaultPath); + nfdchar_t* outPath = nullptr; + nfdresult_t result = NFD_SaveDialog(NULL, absolutePath.string().c_str(), &outPath); + if (result == NFD_ERROR) { + LOG_ERROR("NFD Error: %s", NFD_GetError()); + return bfs::path(); + } + + return bfs::absolute(outPath); +} + +bool EditorSystemOld::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; +} + +bool EditorSystemOld::OnMousePress(const Events::MousePress& e) +{ + if (e.Button == GLFW_MOUSE_BUTTON_RIGHT) { + m_PickingQueue.push_back(glm::vec2((int)e.X, (int)e.Y)); + } + return true; +} + +bool EditorSystemOld::OnMouseMove(const Events::MouseMove& e) +{ + if (m_Widget == EntityID_Invalid) { + return false; + } + if (m_Selection == EntityID_Invalid) { + return false; + } + if (m_Selection == m_Widget) { + return false; + } + // TODO: No widgets for root entity until widgets reside in thier own world, + // or the widgets will move relative to the root entity being moved, which is WEEEIRD. + if (m_Selection == 0) { + return false; + } + if (m_Camera == nullptr) { + return false; + } + + auto widgetTransform = m_World->GetComponent(m_Widget, "Transform"); + glm::vec3 widgetOrientation = widgetTransform["Orientation"]; + glm::quat totalOrientation = m_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_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_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) { + EntityID parent = m_World->GetParent(m_Selection); + glm::quat inverseParentOrientation; + //if (parent != 0) { + inverseParentOrientation = glm::inverse(Transform::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; + } + } 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; + if (m_WidgetSpace == WidgetSpace::Global) { + EntityID parent = m_World->GetParent(m_Selection); + glm::quat parentOrientation; + //if (parent != 0) { + // parentOrientation = RenderSystem::AbsoluteOrientation(m_World, parent); + //} + glm::vec3& selectionOrientation = m_World->GetComponent(m_Selection, "Transform")["Orientation"]; + glm::quat currentOrientation = Transform::AbsoluteOrientation(m_World, m_Selection); + //glm::quat currentOrientation = parentOrientation * glm::quat(selectionOrientation); + glm::quat deltaOrientation(finalMovement); + 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); + } + } 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 && 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; + } + if (m_WidgetCurrentAxis.y > 0) { + scaleY.y += movement.y; + } + if (m_WidgetCurrentAxis.z > 0) { + scaleZ.z += movement.z; + } + (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; +} + +bool EditorSystemOld::OnMouseRelease(const Events::MouseRelease& e) +{ + if (glm::length2(m_WidgetCurrentAxis) > 0.f) { + m_WidgetCurrentAxis = glm::vec3(0.f); + //setWidgetMode(m_WidgetMode); + } + + return true; +} + +void EditorSystemOld::Picking() +{ + for (auto& pos : m_PickingQueue) { + auto result = m_Renderer->Pick(pos); + EntityID entity = result.Entity; + if (glm::length2(m_WidgetCurrentAxis) > 0.f) { + // ??? + } else { + LOG_INFO("Selected %i", entity); + if (entity != EntityID_Invalid) { + EntityID parent = m_World->GetParent(entity); + m_Camera = result.Camera; + if (parent == m_Widget) { + m_WidgetCurrentAxis = glm::vec3( + (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; + //auto widgetTransform = m_World->GetComponent(m_Widget, "Transform"); + //auto selectionTransform = m_World->GetComponent(m_Selection, "Transform"); + //widgetTransform["Position"] = (glm::vec3)selectionTransform["Position"]; + } else { + ImGui::SetActiveID(0, nullptr); + if (m_WidgetMode == WidgetMode::None) { + m_WidgetMode = WidgetMode::Translate; + } + setWidgetMode(m_WidgetMode); + m_Selection = entity; + } + } + } + } + m_PickingQueue.clear(); +}; + +bool EditorSystemOld::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 EditorSystemOld::createWidget() +{ + if (m_Widget == EntityID_Invalid) { + 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_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"); + setWidgetMode(WidgetMode::None); + } +} + +void EditorSystemOld::updateWidget() +{ + if (m_Widget == EntityID_Invalid) { + return; + } + if (m_Selection == m_Widget) { + return; + } + + if (m_Selection != EntityID_Invalid) { + auto widgetTransform = m_World->GetComponent(m_Widget, "Transform"); + glm::vec3 selectionPosition = Transform::AbsolutePosition(m_World, m_Selection); + widgetTransform["Position"] = selectionPosition; + if (m_WidgetSpace == WidgetSpace::Local) { + widgetTransform["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(m_World, m_Selection)); + } + } +} + +void EditorSystemOld::setWidgetMode(WidgetMode newMode) +{ + if (m_Widget == EntityID_Invalid) { + 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_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"; + // 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 != EntityID_Invalid) { + if (m_WidgetSpace == WidgetSpace::Local) { + auto selectionTransform = m_World->GetComponent(m_Selection, "Transform"); + widgetTransform["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(m_World, m_Selection)); + } + } + } 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 != EntityID_Invalid) { + auto selectionTransform = m_World->GetComponent(m_Selection, "Transform"); + widgetTransform["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(m_World, m_Selection)); + } + } 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"; + if (m_Selection != EntityID_Invalid) { + auto selectionTransform = m_World->GetComponent(m_Selection, "Transform"); + if (m_WidgetSpace == WidgetSpace::Local) { + widgetTransform["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(m_World, m_Selection)); + } + } + } + m_WidgetMode = newMode; +} + +void EditorSystemOld::setWidgetSpace(WidgetSpace space) +{ + m_WidgetSpace = space; + setWidgetMode(m_WidgetMode); +} + +void EditorSystemOld::drawUI(World* world, double dt) +{ + namespace bfs = boost::filesystem; + + ImGui::ShowTestWindow(); + //ImGui::ShowStyleEditor(); + + if (ImGui::BeginMainMenuBar()) { + if (ImGui::BeginMenu("File")) { + //if (ImGui::MenuItem("New")) { } + if (ImGui::MenuItem("Import", "Ctrl+O")) { + fileImport(world); + } + if (ImGui::MenuItem("Save", "Ctrl+S")) { + fileSave(world); + } + if (ImGui::MenuItem("Save As...", "Ctrl+Shift+S")) { + fileSaveAs(world); + } + ImGui::Separator(); + if (ImGui::MenuItem("Close Editor", "F1")) { } + + ImGui::EndMenu(); + } + + ImGui::SameLine(); + if (ImGui::Button("Move")) { + setWidgetMode(WidgetMode::Translate); + } + ImGui::SameLine(); + if (ImGui::Button("Rotate")) { + setWidgetMode(WidgetMode::Rotate); + } + ImGui::SameLine(); + if (ImGui::Button("Scale")) { + 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(); + } + + std::string title = std::string("Components #") + std::to_string(m_Selection) + std::string("###Components"); + if (ImGui::Begin(title.c_str())) { + if (m_Selection != EntityID_Invalid) { + auto& pools = world->GetComponentPools(); + + std::vector componentTypes; + for (auto& pair : pools) { + // Only add components the entity doesn't already have + if (!pair.second->KnowsEntity(m_Selection)) { + componentTypes.push_back(pair.first.c_str()); + } + } + int item = -1; + ImGui::PushItemWidth(ImGui::GetWindowContentRegionWidth() - 5.f); + if (ImGui::Combo("", &item, componentTypes.data(), componentTypes.size())) { + if (item != -1) { + std::string chosenType = std::string(componentTypes.at(item)); + world->AttachComponent(m_Selection, chosenType); + } + } + ImGui::PopItemWidth(); + + for (auto& pair : pools) { + const std::string& componentType = pair.first; + auto pool = pair.second; + if (!pool->KnowsEntity(m_Selection)) { + continue; + } + auto& ci = pool->ComponentInfo(); + + bool deletePressed = createDeleteButton(componentType); + if (deletePressed) { + world->DeleteComponent(m_Selection, componentType); + continue; + } + + if (ImGui::CollapsingHeader(componentType.c_str())) { + if (!ci.Meta->Annotation.empty()) { + ImGui::Text(ci.Meta->Annotation.c_str()); + } + + auto& component = world->GetComponent(m_Selection, componentType); + for (auto& kv : ci.Fields) { + const std::string& fieldName = kv.first; + auto& field = kv.second; + + std::string uniqueID = componentType + fieldName; + ImGui::PushID(uniqueID.c_str()); + if (field.Type == "Vector") { + auto& val = component.Field(fieldName); + if (fieldName == "Scale") { + ImGui::DragFloat3("", glm::value_ptr(val), 0.1f, 0.f, std::numeric_limits::max()); + } else if (fieldName == "Orientation") { + glm::vec3 tempVal = glm::fmod(val, glm::vec3(glm::two_pi())); + if (ImGui::SliderFloat3("", glm::value_ptr(tempVal), 0.f, glm::two_pi())) { + val = tempVal; + } + } else { + ImGui::DragFloat3("", glm::value_ptr(val), 0.1f, std::numeric_limits::lowest(), std::numeric_limits::max()); + } + } else if (field.Type == "Color") { + auto& val = component.Field(fieldName); + ImGui::ColorEdit4("", glm::value_ptr(val), true); + } else if (field.Type == "string") { + std::string& val = component.Field(fieldName); + char tempString[1024]; + memcpy(tempString, val.c_str(), std::min(val.length() + 1, sizeof(tempString))); + if (ImGui::InputText("", tempString, sizeof(tempString))) { + val = std::string(tempString); + LOG_DEBUG("%s::%s changed!", componentType.c_str(), fieldName.c_str()); + } + // DROP STUFF + if (ImGui::IsItemHovered() && !m_LastDroppedFile.empty()) { + val = m_LastDroppedFile; + m_LastDroppedFile = ""; + } + + } else if (field.Type == "double") { + float tempVal = static_cast(component.Field(fieldName)); + if (ImGui::InputFloat("", &tempVal, 0.01f, 1.f)) { + component.SetField(fieldName, static_cast(tempVal)); + } + } else if (field.Type == "int") { + int val = component.Field(fieldName); + ImGui::InputInt("", &val); + } else if (field.Type == "enum") { + int currentValue = component.Field(fieldName); + int item = -1; + std::stringstream enumKeys; + std::vector enumValues; + int i = 0; + for (auto& kv : ci.Meta->FieldEnumDefinitions.at(fieldName)) { + enumKeys << kv.first << " (" << kv.second << ")" << '\0'; + enumValues.push_back(kv.second); + if (currentValue == kv.second) { + item = i; + } + i++; + } + if (ImGui::Combo("", &item, enumKeys.str().c_str())) { + component.SetField(fieldName, enumValues.at(item)); + } + } else if (field.Type == "bool") { + auto& val = component.Field(fieldName); + ImGui::Checkbox("", &val); + } else { + ImGui::TextDisabled(field.Type.c_str()); + } + ImGui::PopID(); + + ImGui::SameLine(); + ImGui::Text(fieldName.c_str()); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("field annotation goes here"); + } + } + } + } + } + + } + ImGui::End(); + + if (ImGui::Begin("Entities")) { + auto entityChildren = world->GetEntityChildren(); + std::function recurse = [&](EntityID parent) { + auto range = entityChildren.equal_range(parent); + for (auto it = range.first; it != range.second; it++) { + if (createEntityNode(world, it->second)) { + recurse(it->second); + ImGui::TreePop(); + } + } + }; + recurse(EntityID_Invalid); + } + ImGui::End(); +} + +bool EditorSystemOld::createEntityNode(World* world, EntityID entity) +{ + // HACK: Don't show the widget entities in the entity tree + if (entity == m_Widget) { + return false; + } + + 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 == 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)) { + m_Selection = 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 = world->GetName(entity); + if (!entityName.empty()) { + nodeTitle = entityName; + } else { + nodeTitle = std::string("#") + std::to_string(entity); + } + 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")) { + EntityID newEntity = world->CreateEntity(entity); + world->AttachComponent(newEntity, "Transform"); + } + ImGui::SameLine(); + if (ImGui::Button("Delete")) { + world->DeleteEntity(entity); + ImGui::CloseCurrentPopup(); + if (!world->ValidEntity(m_Selection)) { + m_Selection = EntityID_Invalid; + } + } + ImGui::EndPopup(); + } + return true; + } else { + return false; + } +} + +bool EditorSystemOld::createDeleteButton(std::string componentType) +{ + float width = ImGui::GetContentRegionAvailWidth(); + ImGuiWindow* window = ImGui::GetCurrentWindow(); + auto pos = ImGui::GetCursorScreenPos() + ImVec2(width - 14.f, 1); + ImRect bb = ImRect(pos, pos + ImVec2(14.f, 14.f)); + std::string idString = "#DELETE"; + idString += componentType; + ImGuiID id = window->GetID(idString.c_str()); + bool hovered; + bool held; + bool pressed = ImGui::ButtonBehavior(bb, id, &hovered, &held); + //ImU32 col = window->Color((held && hovered) ? ImGuiCol_CloseButtonActive : hovered ? ImGuiCol_CloseButtonHovered : ImGuiCol_CloseButton); + ImU32 col = window->Color((held && hovered) ? ImGuiCol_CloseButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); + window->DrawList->AddCircleFilled(bb.GetCenter(), 7.f, col, 16); + return pressed; +} + +void EditorSystemOld::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); +} + +void EditorSystemOld::fileImport(World* world) +{ + m_CurrentFile = openDialog(m_DefaultEntityDir); + auto file = ResourceManager::Load(m_CurrentFile.string()); + EntityFilePreprocessor fpp(file); + fpp.RegisterComponents(world); + EntityFileParser fp(file); + fp.MergeEntities(world); + createWidget(); + updateWidget(); +} + +void EditorSystemOld::fileSave(World* world) +{ + if (boost::filesystem::exists(m_CurrentFile)) { + // HACK: Delete the widgets so they don't appear in the saved file + world->DeleteEntity(m_Widget); + m_Widget = EntityID_Invalid; + + EntityFileWriter writer(m_CurrentFile.string()); + writer.WriteWorld(world); + + createWidget(); + } else { + fileSaveAs(world); + } +} + +void EditorSystemOld::fileSaveAs(World* world) +{ + auto filePath = saveDialog(m_DefaultEntityDir); + if (filePath.empty()) { + return; + } + + // HACK: Delete the widgets so they don't appear in the saved file + world->DeleteEntity(m_Widget); + m_Widget = EntityID_Invalid; + + EntityFileWriter writer(filePath.string()); + writer.WriteWorld(world); + + createWidget(); +} diff --git a/src/Engine/Editor/EditorUI.cpp b/src/Engine/Editor/EditorUI.cpp new file mode 100644 index 00000000..e69de29b diff --git a/src/Engine/Rendering/DrawFinalPass.cpp b/src/Engine/Rendering/DrawFinalPass.cpp index b0ca4afe..45dafa71 100644 --- a/src/Engine/Rendering/DrawFinalPass.cpp +++ b/src/Engine/Rendering/DrawFinalPass.cpp @@ -27,6 +27,7 @@ void DrawFinalPass::Draw(RenderScene& scene) GLERROR("DrawFinalPass::Draw: Pre"); DrawFinalPassState state; + m_ForwardPlusProgram->Bind(); GLuint shaderHandle = m_ForwardPlusProgram->GetHandle(); @@ -34,8 +35,8 @@ void DrawFinalPass::Draw(RenderScene& scene) glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightCullingPass->LightGridSSBO()); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightCullingPass->LightIndexSSBO()); - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(m_Renderer->Camera()->ViewMatrix())); - glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(m_Renderer->Camera()->ProjectionMatrix())); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "V"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ViewMatrix())); + glUniformMatrix4fv(glGetUniformLocation(shaderHandle, "P"), 1, GL_FALSE, glm::value_ptr(scene.Camera->ProjectionMatrix())); glUniform2f(glGetUniformLocation(shaderHandle, "ScreenDimensions"), m_Renderer->Resolution().Width, m_Renderer->Resolution().Height); //TODO: Render: Add code for more jobs than modeljobs. diff --git a/src/Engine/Rendering/DrawFinalPassState.cpp b/src/Engine/Rendering/DrawFinalPassState.cpp index 1cb9d7da..2cda4069 100644 --- a/src/Engine/Rendering/DrawFinalPassState.cpp +++ b/src/Engine/Rendering/DrawFinalPassState.cpp @@ -9,7 +9,6 @@ DrawFinalPassState::DrawFinalPassState() Enable(GL_DEPTH_TEST); Enable(GL_CULL_FACE); ClearColor(glm::vec4(200.f / 255, 0.f / 255, 200.f / 255, 0.f)); - Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } DrawFinalPassState::~DrawFinalPassState() diff --git a/src/Engine/Rendering/RenderState.cpp b/src/Engine/Rendering/RenderState.cpp index 4c47a8a2..1da2f0b1 100644 --- a/src/Engine/Rendering/RenderState.cpp +++ b/src/Engine/Rendering/RenderState.cpp @@ -44,12 +44,6 @@ bool RenderState::ClearColor(glm::vec4 color) return !GLERROR("RenderState::ClearColor"); } -bool RenderState::Clear(GLbitfield mask) -{ - glClear(mask); - return !GLERROR("RenderState::Clear"); -} - bool RenderState::BindFramebuffer(GLint framebuffer) { GLint originalRead; @@ -91,6 +85,15 @@ bool RenderState::BlendFunc(GLenum sfactor, GLenum dfactor) return !GLERROR("RenderState::BlendFunc"); } +bool RenderState::DepthMask(GLboolean flag) +{ + GLboolean original; + glGetBooleanv(GL_DEPTH_WRITEMASK, &original); + m_ResetFunctions.push_back(std::bind(glDepthMask, original)); + glDepthMask(flag); + return !GLERROR("RenderState::DepthMask"); +} + RenderState::~RenderState() { for (auto& f : m_ResetFunctions) { diff --git a/src/Engine/Rendering/RenderSystem.cpp b/src/Engine/Rendering/RenderSystem.cpp index 38b80ea2..2af782e3 100644 --- a/src/Engine/Rendering/RenderSystem.cpp +++ b/src/Engine/Rendering/RenderSystem.cpp @@ -9,71 +9,26 @@ RenderSystem::RenderSystem(EventBroker* eventBroker, const IRenderer* renderer, EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &RenderSystem::OnInputCommand); m_Camera = new Camera((float)m_Renderer->Resolution().Width / m_Renderer->Resolution().Height, glm::radians(45.f), 0.01f, 5000.f); - m_DebugCameraInputController = new DebugCameraInputController(eventBroker, -1); } RenderSystem::~RenderSystem() { delete m_Camera; - delete m_DebugCameraInputController; } -bool RenderSystem::OnSetCamera(const Events::SetCamera &event) +bool RenderSystem::OnSetCamera(Events::SetCamera& e) { - auto cameras = m_World->GetComponents("Camera"); - - if (cameras != nullptr) { - for (auto it = cameras->begin(); it != cameras->end(); it++) { - if ((std::string)(*it)["Name"] == event.Name) { - switchCamera((*it).EntityID); - } - } - } + ComponentWrapper cTransform = e.CameraEntity["Transform"]; + ComponentWrapper cCamera = e.CameraEntity["Camera"]; + m_Camera->SetFOV((double)cCamera["FOV"]); + m_Camera->SetNearClip((double)cCamera["NearClip"]); + m_Camera->SetFarClip((double)cCamera["FarClip"]); + m_Camera->SetPosition(cTransform["Position"]); + m_Camera->SetOrientation(glm::quat((const glm::vec3&)cTransform["Orientation"])); + m_CurrentCamera = e.CameraEntity; return true; } -void RenderSystem::switchCamera(EntityID entity) -{ - if(m_World->HasComponent(entity, "Camera")) { - - if (m_CurrentCamera != EntityID_Invalid) { - if (m_World->HasComponent(m_CurrentCamera, "Model")) { - m_World->GetComponent(m_CurrentCamera, "Model")["Visible"] = true; - } - if (m_World->HasComponent(m_CurrentCamera, "Listener")) { - m_World->DeleteComponent(m_CurrentCamera, "Listener"); - } - } - - if (m_World->HasComponent(entity, "Model")) { - m_World->GetComponent(entity, "Model")["Visible"] = false; - } - if (!m_World->HasComponent(entity, "Listener")) { - m_World->AttachComponent(entity, "Listener"); - } - m_CurrentCamera = entity; - m_SwitchCamera = false; - - } else { - LOG_ERROR("Entity %i does not have a CameraComponent", entity); - m_SwitchCamera = false; - } -} - -void RenderSystem::updateProjectionMatrix(ComponentWrapper& cameraComponent) -{ - double fov = cameraComponent["FOV"]; - double aspectRatio = (float)m_Renderer->Resolution().Width / m_Renderer->Resolution().Height; - double nearClip = cameraComponent["NearClip"]; - double farClip = cameraComponent["FarClip"]; - - m_Camera->SetFOV(glm::radians(fov)); - m_Camera->SetAspectRatio(aspectRatio); - m_Camera->SetNearClip(nearClip); - m_Camera->SetFarClip(farClip); - m_Camera->UpdateProjectionMatrix(); -} - void RenderSystem::fillModels(std::list>& jobs, World* world) { auto models = world->GetComponents("Model"); @@ -113,7 +68,6 @@ void RenderSystem::fillModels(std::list>& jobs, World } } - void RenderSystem::fillLight(std::list>& jobs, World* world) { auto pointLights = world->GetComponents("PointLight"); @@ -138,12 +92,7 @@ void RenderSystem::fillLight(std::list>& jobs, World* bool RenderSystem::OnInputCommand(const Events::InputCommand& e) { - if (e.Command == "SwitchCamera" && e.Value > 0) { - m_SwitchCamera = true; - return true; - } else { - return false; - } + return false; } void RenderSystem::Update(World* world, double dt) @@ -151,10 +100,12 @@ void RenderSystem::Update(World* world, double dt) m_World = world; m_EventBroker->Process(); - updateCamera(world, dt); - + if (m_CurrentCamera) { + ComponentWrapper cameraTransform = m_CurrentCamera["Transform"]; + m_Camera->SetPosition(cameraTransform["Position"]); + m_Camera->SetOrientation(glm::quat((const glm::vec3&)cameraTransform["Orientation"])); + } //Only supports opaque geometry atm - m_RenderFrame->Clear(); RenderScene scene; scene.Camera = m_Camera; @@ -163,70 +114,4 @@ void RenderSystem::Update(World* world, double dt) fillLight(scene.PointLightJobs, world); m_RenderFrame->Add(scene); -} - -void RenderSystem::updateCamera(World* world, double dt) -{ - if (m_SwitchCamera) { - auto cameras = world->GetComponents("Camera"); - if (cameras == nullptr) { - return; - } - for (auto it = cameras->begin(); it != cameras->end(); it++) { - if ((*it).EntityID == m_CurrentCamera) { - it++; - if (it != cameras->end()) { - switchCamera((*it).EntityID); - } else { - switchCamera((*cameras->begin()).EntityID); - } - break; - } - } - if (m_World->HasComponent(m_CurrentCamera, "Camera")) { - ComponentWrapper& cameraComponent = world->GetComponent(m_CurrentCamera, "Camera"); - ComponentWrapper& cameraTransform = world->GetComponent(m_CurrentCamera, "Transform"); - - m_DebugCameraInputController->SetOrientation(glm::quat((glm::vec3)cameraTransform["Orientation"])); - m_DebugCameraInputController->SetPosition(cameraTransform["Position"]); - } - } - - if (m_World->ValidEntity(m_CurrentCamera)) { - if (world->HasComponent(m_CurrentCamera, "Camera") && world->HasComponent(m_CurrentCamera, "Transform")) { - ComponentWrapper& cameraComponent = world->GetComponent(m_CurrentCamera, "Camera"); - ComponentWrapper& cameraTransform = world->GetComponent(m_CurrentCamera, "Transform"); - - m_DebugCameraInputController->Update(dt); - (glm::vec3&)cameraTransform["Orientation"] = glm::eulerAngles(m_DebugCameraInputController->Orientation()); - (glm::vec3&)cameraTransform["Position"] = m_DebugCameraInputController->Position(); - - glm::vec3 position = Transform::AbsolutePosition(world, m_CurrentCamera); - glm::quat orientation = Transform::AbsoluteOrientation(world, m_CurrentCamera); - - m_Camera->SetPosition(position); - m_Camera->SetOrientation(orientation); - - updateProjectionMatrix(cameraComponent); - - } - } else { - m_Camera = m_Camera; - - auto cameras = world->GetComponents("Camera"); - if (cameras != nullptr) { - if (cameras->begin() != cameras->end()) { - ComponentWrapper& cameraC = *cameras->begin(); - switchCamera(cameraC.EntityID); - - ComponentWrapper& cameraComponent = world->GetComponent(m_CurrentCamera, "Camera"); - ComponentWrapper& cameraTransform = world->GetComponent(m_CurrentCamera, "Transform"); - - m_DebugCameraInputController->SetOrientation(glm::quat((glm::vec3)cameraTransform["Orientation"])); - m_DebugCameraInputController->SetPosition(cameraTransform["Position"]); - } - } - } - - m_Camera->UpdateViewMatrix(); } \ No newline at end of file diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index 2f4c0ba2..e8ed1d9a 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -15,15 +15,6 @@ void Renderer::Initialize() m_UnitSphere = ResourceManager::Load("Models/Core/UnitSphere.obj"); m_ImGuiRenderPass = new ImGuiRenderPass(this, m_EventBroker); - - - // Create default camera - m_DefaultCamera = new ::Camera((float)m_Resolution.Width / m_Resolution.Height, glm::radians(45.f), 0.01f, 5000.f); - m_DefaultCamera->SetPosition(glm::vec3(0, 0, 10)); - if (m_Camera == nullptr) { - m_Camera = m_DefaultCamera; - } - } void Renderer::InitializeWindow() @@ -92,14 +83,14 @@ void Renderer::Update(double dt) void Renderer::Draw(RenderFrame& frame) { glClearColor(255.f / 255, 163.f / 255, 176.f / 255, 0.f); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - m_PickingPass->ClearPicking(); for (auto scene : frame.RenderScenes){ + if (scene->ClearDepth) { + glClear(GL_DEPTH_BUFFER_BIT); + } - m_Camera = scene->Camera; // remove renderer camera when Editor uses the render scene cameras. FillDepth(*scene); m_PickingPass->Draw(*scene); m_LightCullingPass->GenerateNewFrustum(*scene); diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index ff1e28fd..5be95802 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -77,7 +77,6 @@ Game::Game(int argc, char* argv[]) unsigned int updateOrderLevel = 0; m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel); - m_SystemPipeline->AddSystem(updateOrderLevel, m_Renderer); m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel); m_SystemPipeline->AddSystem(updateOrderLevel); @@ -91,6 +90,8 @@ Game::Game(int argc, char* argv[]) m_SystemPipeline->AddSystem(updateOrderLevel, m_OctreeCollision); ++updateOrderLevel; m_SystemPipeline->AddSystem(updateOrderLevel, m_Renderer, m_RenderFrame); + ++updateOrderLevel; + m_SystemPipeline->AddSystem(updateOrderLevel, m_Renderer, m_RenderFrame); // Invoke network if (m_Config->Get("Networking.StartNetwork", false)) { @@ -149,6 +150,7 @@ void Game::Tick() m_SoundSystem->Update(dt); GLERROR("Game::Tick m_RenderQueueFactory->Update"); m_Renderer->Draw(*m_RenderFrame); + m_RenderFrame->Clear(); GLERROR("Game::Tick m_Renderer->Draw"); m_EventBroker->Swap(); m_EventBroker->Clear(); From 0d50ede6f56208140caf73ce7f7c71e512dcc988 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Sun, 17 Jan 2016 07:34:20 +0100 Subject: [PATCH 06/38] 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 From e39e4064f2c89dd0fb70f1d006dc6d7a6aabcf21 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Sun, 17 Jan 2016 23:06:32 +0100 Subject: [PATCH 07/38] Entity tree button mockup --- src/Engine/Editor/EditorGUI.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/Engine/Editor/EditorGUI.cpp b/src/Engine/Editor/EditorGUI.cpp index 66896474..408a3cbf 100644 --- a/src/Engine/Editor/EditorGUI.cpp +++ b/src/Engine/Editor/EditorGUI.cpp @@ -2,6 +2,7 @@ void EditorGUI::Draw(World* world) { + ImGui::ShowTestWindow(); drawMenu(); drawEntities(world); } @@ -25,6 +26,15 @@ void EditorGUI::drawEntities(World* world) return; } + float buttonWidth = (ImGui::GetContentRegionAvailWidth() - 10.f) / 3.f ; + ImGui::Button("Create", ImVec2(buttonWidth, 0)); + ImGui::SameLine(0.f, 5.f); + ImGui::Button("Import", ImVec2(buttonWidth, 0)); + ImGui::SameLine(0.f, 5.f); + ImGui::Button("Reference", ImVec2(buttonWidth, 0)); + + ImGui::ItemSize(ImVec2(0, 3)); + drawEntitiesRecursive(world, EntityID_Invalid); ImGui::End(); @@ -46,13 +56,13 @@ bool EditorGUI::drawEntityNode(EntityWrapper entity) { ImVec2 pos = ImGui::GetCursorScreenPos(); float width = ImGui::GetContentRegionAvailWidth(); - ImRect bb(pos + ImVec2(20, 0), pos + ImVec2(width, 13)); + ImRect bb(pos + ImVec2(20, 0), pos + ImVec2(width, 14)); 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()); + ImGuiID id = window->GetID((std::string("#SelectButton") + std::to_string(entity.ID)).c_str()); bool hovered = false; bool held = false; if (ImGui::ButtonBehavior(bb, id, &hovered, &held)) { From 504f301e4d8f483092ec9b5d27bd38dfa08463f0 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Mon, 18 Jan 2016 13:46:42 +0100 Subject: [PATCH 08/38] Added refactored property sheet for components --- include/Engine/Editor/EditorGUI.h | 18 +++ src/Engine/Editor/EditorGUI.cpp | 208 ++++++++++++++++++++++++++++++ 2 files changed, 226 insertions(+) diff --git a/include/Engine/Editor/EditorGUI.h b/include/Engine/Editor/EditorGUI.h index 6c8b3499..77218e9d 100644 --- a/include/Engine/Editor/EditorGUI.h +++ b/include/Engine/Editor/EditorGUI.h @@ -7,6 +7,8 @@ #include #include #include "../Common.h" +#include "../GLM.h" +#include #include "../Core/EventBroker.h" #include "../Core/World.h" @@ -42,6 +44,10 @@ public: // Called when the user means to delete an entity. typedef std::function OnEntityDelete_t; void SetEntityCreateCallback(OnEntityDelete_t f) { m_OnEntityDelete = f; } + // Called when the user means to attach a new component to an entity. + typedef std::function OnComponentAttach_t; + void SetComponentAttachCallback(OnComponentAttach_t f) { m_OnComponentAttach = f; } + private: EventBroker* m_EventBroker; @@ -55,11 +61,23 @@ private: OnEntitySave_t m_OnEntitySave = nullptr; OnEntityCreate_t m_OnEntityCreate = nullptr; OnEntityDelete_t m_OnEntityDelete = nullptr; + OnComponentAttach_t m_OnComponentAttach = nullptr; void drawMenu(); void drawEntities(World* world); void drawEntitiesRecursive(World* world, EntityID parent); bool drawEntityNode(EntityWrapper entity); + void drawComponents(EntityWrapper entity); + bool drawComponentNode(EntityWrapper entity, const ComponentInfo& componentType); + void drawComponentField(ComponentWrapper& c, const ComponentInfo::Field_t& field); + void drawComponentField_Vector(ComponentWrapper &c, const ComponentInfo::Field_t &field); + void drawComponentField_Color(ComponentWrapper &c, const ComponentInfo::Field_t &field); + void drawComponentField_int(ComponentWrapper &c, const ComponentInfo::Field_t &field); + void drawComponentField_enum(ComponentWrapper &c, const ComponentInfo::Field_t &field); + void drawComponentField_float(ComponentWrapper &c, const ComponentInfo::Field_t &field); + void drawComponentField_double(ComponentWrapper &c, const ComponentInfo::Field_t &field); + void drawComponentField_bool(ComponentWrapper &c, const ComponentInfo::Field_t &field); + void drawComponentField_string(ComponentWrapper &c, const ComponentInfo::Field_t &field); }; #endif \ No newline at end of file diff --git a/src/Engine/Editor/EditorGUI.cpp b/src/Engine/Editor/EditorGUI.cpp index 408a3cbf..388016a6 100644 --- a/src/Engine/Editor/EditorGUI.cpp +++ b/src/Engine/Editor/EditorGUI.cpp @@ -5,6 +5,7 @@ void EditorGUI::Draw(World* world) ImGui::ShowTestWindow(); drawMenu(); drawEntities(world); + drawComponents(m_CurrentSelection); } void EditorGUI::SelectEntity(EntityWrapper entity) @@ -122,3 +123,210 @@ bool EditorGUI::drawEntityNode(EntityWrapper entity) return false; } } + +void EditorGUI::drawComponents(EntityWrapper entity) +{ + std::stringstream title; + title << "Components"; + if (entity.Valid()) { + title << " #" << entity.ID << "###Components"; + } + if (!ImGui::Begin(title.str().c_str())) { + ImGui::End(); + return; + } + + if (!entity.Valid()) { + ImGui::End(); + return; + } + + auto& pools = entity.World->GetComponentPools(); + // Create list of component types available to be added + std::vector componentTypes; + for (auto& pair : pools) { + // Don't list components the entity already has attached + if (!entity.HasComponent(pair.first)) { + componentTypes.push_back(pair.first.c_str()); + } + } + // Draw combo box + ImGui::PushItemWidth(ImGui::GetContentRegionAvailWidth() - 10.f); + int selectedItem = -1; + if (ImGui::Combo("", &selectedItem, componentTypes.data(), componentTypes.size())) { + if (selectedItem != -1) { + if (m_OnComponentAttach != nullptr) { + std::string chosenComponentType(componentTypes.at(selectedItem)); + m_OnComponentAttach(entity, chosenComponentType); + } + } + } + ImGui::PopItemWidth(); + + for (auto& pair : pools) { + const std::string& componentType = pair.first; + auto pool = pair.second; + // Don't show components the entity doesn't have attached + if (!entity.HasComponent(componentType)) { + continue; + } + // TODO: Add delete button here + drawComponent(entity, pool->ComponentInfo()); + } + + ImGui::End(); +} + +bool EditorGUI::drawComponent(EntityWrapper entity, const ComponentInfo& ci) +{ + if (!ImGui::CollapsingHeader(ci.Name.c_str(), nullptr, true, true)) { + return false; + } + + // Show component annotation + const std::string annotation = ci.Meta->Annotation; + if (!annotation.empty()) { + ImGui::TextWrapped(annotation.c_str()); + } + + // Draw component fields + ComponentWrapper& component = entity.World->GetComponent(entity.ID, ci.Name); + for (auto& kv : ci.Fields) { + const std::string& fieldName = kv.first; + const ComponentInfo::Field_t& field = kv.second; + + // Draw the field widget based on its type + drawComponentField(component, field); + ImGui::SameLine(); + // Draw field name + ImGui::Text(fieldName.c_str()); + // Draw potential field annotation + auto fieldAnnotationIt = ci.Meta->FieldAnnotations.find(fieldName); + if (fieldAnnotationIt != ci.Meta->FieldAnnotations.end()) { + ImGui::SameLine(); + ImGui::TextDisabled("(?)"); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip(fieldAnnotationIt->second.c_str()); + } + } + } + + return true; +} + +void EditorGUI::drawComponentField(ComponentWrapper& c, const ComponentInfo::Field_t& field) +{ + // Push an unique widget id so different components with fields with equal names are still counted as different + ImGui::PushID((c.Info.Name + field.Name).c_str()); + + if (field.Type == "Vector") { + drawComponentField_Vector(c, field); + } else if (field.Type == "Color") { + drawComponentField_Color(c, field); + //} else if (field.Type == "Quaternion") { + } else if (field.Type == "int") { + drawComponentField_int(c, field); + } else if (field.Type == "enum") { + drawComponentField_enum(c, field); + } else if (field.Type == "float") { + drawComponentField_float(c, field); + } else if (field.Type == "double") { + drawComponentField_double(c, field); + } else if (field.Type == "bool") { + drawComponentField_bool(c, field); + } else if (field.Type == "string") { + drawComponentField_string(c, field); + } else { + ImGui::TextDisabled(field.Type.c_str()); + } + + ImGui::PopID(); +} + +void EditorGUI::drawComponentField_Vector(ComponentWrapper &c, const ComponentInfo::Field_t &field) +{ + auto& val = c.Field(field.Name); + if (field.Name == "Scale") { + // Limit scale values to a minimum of 0 + ImGui::DragFloat3("", glm::value_ptr(val), 0.1f, 0.f, std::numeric_limits::max()); + } else if (field.Name == "Orientation") { + // Make orentations have a period of 2*Pi + glm::vec3 tempVal = glm::fmod(val, glm::vec3(glm::two_pi())); + if (ImGui::SliderFloat3("", glm::value_ptr(tempVal), 0.f, glm::two_pi())) { + val = tempVal; + } + } else { + ImGui::DragFloat3("", glm::value_ptr(val), 0.1f, std::numeric_limits::lowest(), std::numeric_limits::max()); + } +} + +void EditorGUI::drawComponentField_Color(ComponentWrapper &c, const ComponentInfo::Field_t &field) +{ + auto& val = c.Field(field.Name); + ImGui::ColorEdit4("", glm::value_ptr(val), true); +} + +void EditorGUI::drawComponentField_int(ComponentWrapper &c, const ComponentInfo::Field_t &field) +{ + auto& val = c.Field(field.Name); + ImGui::InputInt("", &val); +} + +void EditorGUI::drawComponentField_enum(ComponentWrapper &c, const ComponentInfo::Field_t &field) +{ + auto fieldEnumDefIt = c.Info.Meta->FieldEnumDefinitions.find(field.Name); + if (fieldEnumDefIt == c.Info.Meta->FieldEnumDefinitions.end()) { + drawComponentField_int(c, field); + return; + } + + auto& val = c.Field(field.Name); + int selectedItem = -1; + std::stringstream enumKeys; + std::vector enumValues; + int i = 0; + for (auto& kv : fieldEnumDefIt->second) { + enumKeys << kv.first << " (" << kv.second << ")" << '\0'; + enumValues.push_back(kv.second); + if (val == kv.second) { + selectedItem = i; + } + } + if (ImGui::Combo("", &selectedItem, enumKeys.str().c_str())) { + val = enumValues.at(selectedItem); + } +} + +void EditorGUI::drawComponentField_float(ComponentWrapper &c, const ComponentInfo::Field_t &field) +{ + auto& val = c.Field(field.Name); + ImGui::InputFloat("", &val, 0.01f, 1.f); +} + +void EditorGUI::drawComponentField_double(ComponentWrapper &c, const ComponentInfo::Field_t &field) +{ + float tempVal = static_cast(c.Field(field.Name)); + if (ImGui::InputFloat("", &tempVal, 0.01f, 1.f)) { + c.SetField(field.Name, static_cast(tempVal)); + } +} + +void EditorGUI::drawComponentField_bool(ComponentWrapper &c, const ComponentInfo::Field_t &field) +{ + auto& val = c.Field(field.Name); + ImGui::Checkbox("", &val); +} + +void EditorGUI::drawComponentField_string(ComponentWrapper &c, const ComponentInfo::Field_t &field) +{ + auto& val = c.Field(field.Name); + char tempString[1024]; // Let's just hope this is an sufficiently large buffer for strings :) + tempString[1023] = '\0'; // Null terminator just in case the string is larger than the buffer + // Copy the string into the buffer, taking the null terminator into account + memcpy(tempString, val.c_str(), std::min(val.length() + 1, sizeof(tempString) - 1)); + if (ImGui::InputText("", tempString, sizeof(tempString))) { + val = std::string(tempString); + } + // TODO: Handle drag and drop of files +} + From 3bc7dceca5dbd5d3e97262b006e3f655b8a0189b Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Mon, 18 Jan 2016 14:55:49 +0100 Subject: [PATCH 09/38] Made EntityWrapper hashable --- include/Engine/Core/EntityWrapper.h | 17 ++++++++++++++++- src/Engine/Core/EntityWrapper.cpp | 2 +- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/include/Engine/Core/EntityWrapper.h b/include/Engine/Core/EntityWrapper.h index e4be8d78..79f90f33 100644 --- a/include/Engine/Core/EntityWrapper.h +++ b/include/Engine/Core/EntityWrapper.h @@ -2,6 +2,7 @@ #define EntityWrapper_h__ #include +#include #include "ComponentWrapper.h" class World; @@ -26,9 +27,23 @@ struct EntityWrapper bool Valid(); ComponentWrapper operator[](const char* componentName); - bool operator==(const EntityWrapper& e); + bool operator==(const EntityWrapper& e) const; explicit operator EntityID() const; operator bool(); }; +namespace std +{ + template<> struct hash + { + std::size_t operator()(const EntityWrapper& e) const + { + std::size_t seed = 0; + boost::hash_combine(seed, e.World); + boost::hash_combine(seed, e.ID); + return seed; + } + }; +} + #endif diff --git a/src/Engine/Core/EntityWrapper.cpp b/src/Engine/Core/EntityWrapper.cpp index c3c5cf27..8c1ab10d 100644 --- a/src/Engine/Core/EntityWrapper.cpp +++ b/src/Engine/Core/EntityWrapper.cpp @@ -3,7 +3,7 @@ const EntityWrapper EntityWrapper::Invalid = EntityWrapper(nullptr, EntityID_Invalid); -bool EntityWrapper::operator==(const EntityWrapper& e) +bool EntityWrapper::operator==(const EntityWrapper& e) const { return (this->World == e.World) && (this->ID == e.ID); } From 9cb5f4bd2f6721704e9466e3ac651a9467afa9d5 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Mon, 18 Jan 2016 18:03:45 +0100 Subject: [PATCH 10/38] Added a stats window --- include/Engine/Common.h | 1 + include/Engine/Editor/EditorStats.h | 29 +++++++ include/Engine/Editor/EditorSystem.h | 2 + src/Engine/Editor/EditorStats.cpp | 115 +++++++++++++++++++++++++++ src/Engine/Editor/EditorSystem.cpp | 4 + 5 files changed, 151 insertions(+) create mode 100644 include/Engine/Editor/EditorStats.h create mode 100644 src/Engine/Editor/EditorStats.cpp diff --git a/include/Engine/Common.h b/include/Engine/Common.h index 7d6f520d..8038b8af 100644 --- a/include/Engine/Common.h +++ b/include/Engine/Common.h @@ -4,6 +4,7 @@ #include #include #include +#include #include "Core/Util/Logging.h" #include "Core/Util/IfDebug.h" \ No newline at end of file diff --git a/include/Engine/Editor/EditorStats.h b/include/Engine/Editor/EditorStats.h new file mode 100644 index 00000000..5dfa5378 --- /dev/null +++ b/include/Engine/Editor/EditorStats.h @@ -0,0 +1,29 @@ +#include +#include +#include +#include "../Common.h" +#include "../GLM.h" +#include "../OpenGL.h" + +class EditorStats +{ +public: + EditorStats(); + void Draw(double dt); + +private: + // FPS graph + const unsigned int m_SampleSize = 100; + unsigned int m_FrameCount = 0; + std::vector m_FrameTimes; + double m_TimeAccumulator = 0.0; + double m_AveragedSamplesPerSecond = 10.0; + const unsigned int m_AveragedSampleSize = 100; + unsigned int m_CurrentAveragedSampleIndex = 0; + std::vector m_AveragedSamples; + void drawFPSGraph(double dt); + + void drawRAMUsage(double dt); + + void drawVRAMStats(double dt); +}; diff --git a/include/Engine/Editor/EditorSystem.h b/include/Engine/Editor/EditorSystem.h index 7b908872..ae3502c3 100644 --- a/include/Engine/Editor/EditorSystem.h +++ b/include/Engine/Editor/EditorSystem.h @@ -9,6 +9,7 @@ #include "../Core/EntityFilePreprocessor.h" #include "../Core/EntityFileParser.h" #include "EditorGUI.h" +#include "EditorStats.h" class EditorSystem : public ImpureSystem { @@ -28,6 +29,7 @@ private: EntityWrapper m_Camera = EntityWrapper::Invalid; DebugCameraInputController* m_DebugCameraInputController; EditorGUI* m_EditorGUI; + EditorStats* m_EditorStats; void OnEntitySelected(EntityWrapper entity); }; \ No newline at end of file diff --git a/src/Engine/Editor/EditorStats.cpp b/src/Engine/Editor/EditorStats.cpp new file mode 100644 index 00000000..a626c442 --- /dev/null +++ b/src/Engine/Editor/EditorStats.cpp @@ -0,0 +1,115 @@ +#include "Editor/EditorStats.h" +#ifdef WIN32 +#define WIN32_LEAN_AND_MEAN +#define NOMINMAX +#include +#include +#endif +#include + +EditorStats::EditorStats() +{ + m_AveragedSamples.push_back(0.0); + m_CurrentAveragedSampleIndex = 1; +} + +void EditorStats::Draw(double dt) +{ + if (ImGui::Begin("Stats")) { + drawFPSGraph(dt); + drawRAMUsage(dt); + drawVRAMStats(dt); + } + ImGui::End(); +} + +void EditorStats::drawFPSGraph(double dt) +{ + if (m_FrameCount < m_SampleSize) { + m_FrameTimes.push_back(dt); + } else { + m_FrameTimes[m_FrameCount % m_SampleSize] = dt; + } + m_FrameCount++; + + double average = 0.0; + double max = 0.0; + for (double t : m_FrameTimes) { + average += t; + max = std::max(max, t); + } + average /= m_FrameTimes.size(); + + m_TimeAccumulator += dt; + if (m_TimeAccumulator >= 1.0/m_AveragedSamplesPerSecond) { + if (m_CurrentAveragedSampleIndex < m_AveragedSampleSize) { + m_AveragedSamples.push_back(1.0/average); + } else { + m_AveragedSamples[m_CurrentAveragedSampleIndex % m_AveragedSampleSize] = 1.0/average; + } + m_CurrentAveragedSampleIndex++; + m_TimeAccumulator = 0.0; + } + + float maxFPS = 0.f; + ImVector values; + int values_offset = m_CurrentAveragedSampleIndex % m_AveragedSampleSize; + for (double d : m_AveragedSamples) { + values.push_back(static_cast(d)); + maxFPS = std::max(maxFPS, static_cast(d)); + } + std::stringstream header; + header << std::round(1.0/average) << " FPS (" << std::setprecision(5) << average << " ms)"; + ImGui::PlotLines("##FPSGraph", values.Data, values.Size, values_offset, header.str().c_str(), 0.f, maxFPS + maxFPS/5.f, ImVec2(0, 100)); +} + +void EditorStats::drawRAMUsage(double dt) +{ +#ifdef WIN32 + PROCESS_MEMORY_COUNTERS_EX ppm; + GetProcessMemoryInfo(GetCurrentProcess(), (PPROCESS_MEMORY_COUNTERS)&ppm, sizeof(ppm)); + float megabytes = ppm.WorkingSetSize / (float)std::pow(1024, 2); + ImGui::Text("Memory: ~%f MiB", megabytes); +#endif +} + +void EditorStats::drawVRAMStats(double dt) +{ + //const unsigned int GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX = 0x9049; + //const unsigned int GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX = 0x9048; + //glm::ivec4 total; + //glGetIntegerv(GPU_MEMORY_INFO_TOTAL_AVAILABLE_MEMORY_NVX, glm::value_ptr(total)); + //if (glGetError() == GL_NO_ERROR) { + // glm::ivec4 available; + // glGetIntegerv(GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX, glm::value_ptr(available)); + // float megabytes = (total.x - available.x) / 1024.f; // NVidia returns in KiB + // ImGui::Text("VRAM: %f", megabytes); + //} + + //GLuint uNoOfGPUs = wglGetGPUIDsAMD(0, 0); + //if (!GLERROR("")) { + // GLuint* uGPUIDs = new GLuint[uNoOfGPUs]; + // wglGetGPUIDsAMD(uNoOfGPUs, uGPUIDs); + // GLuint uTotalMemoryInMB = 0; + // wglGetGPUInfoAMD(uGPUIDs[0], + // WGL_GPU_RAM_AMD, + // GL_UNSIGNED_INT, + // sizeof(GLuint), + // &uTotalMemoryInMB); + // GLint nCurAvailMemoryInKB[4]; + // glGetIntegerv(GL_TEXTURE_FREE_MEMORY_ATI, + // &nCurAvailMemoryInKB[0]); + // float usedTexture = (nCurAvailMemoryInKB[0] / 1024.f); + // glGetIntegerv(GL_VBO_FREE_MEMORY_ATI, + // &nCurAvailMemoryInKB[0]); + // float usedVBO = (nCurAvailMemoryInKB[0] / 1024.f); + // glGetIntegerv(GL_RENDERBUFFER_FREE_MEMORY_ATI, + // &nCurAvailMemoryInKB[0]); + // float usedFB = (nCurAvailMemoryInKB[0] / 1024.f); + // ImGui::Text("VRAM: %f MiB ", (float)uTotalMemoryInMB - usedTexture - usedVBO - usedFB); + // ImGui::Text(" Texture: %f MiB", usedTexture); + // ImGui::Text(" VBO: %f MiB", usedVBO); + // ImGui::Text(" Framebuffer: %f MiB", usedFB); + // delete[] uGPUIDs; + //} +} diff --git a/src/Engine/Editor/EditorSystem.cpp b/src/Engine/Editor/EditorSystem.cpp index 2d0a4b55..0a96ab9b 100644 --- a/src/Engine/Editor/EditorSystem.cpp +++ b/src/Engine/Editor/EditorSystem.cpp @@ -27,6 +27,8 @@ EditorSystem::EditorSystem(EventBroker* eventBroker, IRenderer* renderer, Render m_EditorGUI = new EditorGUI(m_EventBroker); m_EditorGUI->SetEntitySelectedCallback(std::bind(&EditorSystem::OnEntitySelected, this, std::placeholders::_1)); + m_EditorStats = new EditorStats(); + Events::SetCamera e; e.CameraEntity = m_Camera; m_EventBroker->Publish(e); @@ -34,6 +36,7 @@ EditorSystem::EditorSystem(EventBroker* eventBroker, IRenderer* renderer, Render EditorSystem::~EditorSystem() { + delete m_EditorStats; delete m_EditorGUI; delete m_DebugCameraInputController; delete m_EditorWorldSystemPipeline; @@ -45,6 +48,7 @@ void EditorSystem::Update(World* world, double dt) m_EditorWorldSystemPipeline->Update(m_EditorWorld, dt); m_EditorGUI->Draw(world); + m_EditorStats->Draw(dt); m_DebugCameraInputController->Update(dt); m_Camera["Transform"]["Position"] = m_DebugCameraInputController->Position(); From 631dd57eeb7d9f9e3763d62c5fcf7c60445c33c5 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Mon, 18 Jan 2016 18:55:19 +0100 Subject: [PATCH 11/38] Editor entity import, save, delete, component attach, component delete. --- include/Engine/Editor/EditorGUI.h | 33 +++++- include/Engine/Editor/EditorSystem.h | 8 ++ src/Engine/Editor/EditorGUI.cpp | 160 ++++++++++++++++++++++++--- src/Engine/Editor/EditorSystem.cpp | 46 +++++++- 4 files changed, 219 insertions(+), 28 deletions(-) diff --git a/include/Engine/Editor/EditorGUI.h b/include/Engine/Editor/EditorGUI.h index 77218e9d..20946e36 100644 --- a/include/Engine/Editor/EditorGUI.h +++ b/include/Engine/Editor/EditorGUI.h @@ -29,12 +29,14 @@ public: 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; + // @param EntityWrapper The entity to parent the imported entity to. The entity will be imported into the world of this entity. + // @param boost::filesystem::path The path to the entity to import + // @return EntityWrapper The newly created entity + 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; + // Permitted to throw exceptions on save failure. + 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 @@ -47,13 +49,20 @@ public: // Called when the user means to attach a new component to an entity. typedef std::function OnComponentAttach_t; void SetComponentAttachCallback(OnComponentAttach_t f) { m_OnComponentAttach = f; } - + // Called when the user means to delete a component off an entity. + typedef std::function OnComponentDelete_t; + void SetComponentDeleteCallback(OnComponentDelete_t f) { m_OnComponentDelete = f; } private: EventBroker* m_EventBroker; + // Config variables + const boost::filesystem::path m_DefaultEntityPath = boost::filesystem::path("Schema") / boost::filesystem::path("Entities"); + // State variables EntityWrapper m_CurrentSelection = EntityWrapper::Invalid; + std::unordered_map m_EntityFiles; + std::string m_LastErrorMessage; // Callbacks OnEntitySelectedCallback_t m_OnEntitySelected = nullptr; @@ -62,7 +71,17 @@ private: OnEntityCreate_t m_OnEntityCreate = nullptr; OnEntityDelete_t m_OnEntityDelete = nullptr; OnComponentAttach_t m_OnComponentAttach = nullptr; + OnComponentDelete_t m_OnComponentDelete = nullptr; + + // Utility functions + boost::filesystem::path fileOpenDialog(); + boost::filesystem::path fileSaveDialog(); + + // Entity file handling methods + void entityImport(World* world); + void entitySave(EntityWrapper entity); + // UI drawing methods void drawMenu(); void drawEntities(World* world); void drawEntitiesRecursive(World* world, EntityID parent); @@ -78,6 +97,10 @@ private: void drawComponentField_double(ComponentWrapper &c, const ComponentInfo::Field_t &field); void drawComponentField_bool(ComponentWrapper &c, const ComponentInfo::Field_t &field); void drawComponentField_string(ComponentWrapper &c, const ComponentInfo::Field_t &field); + void drawModals(); + + // Custom UI elements + bool createDeleteButton(const std::string& componentType); }; #endif \ No newline at end of file diff --git a/include/Engine/Editor/EditorSystem.h b/include/Engine/Editor/EditorSystem.h index ae3502c3..7998a26d 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 "../Core/EntityFileWriter.h" #include "EditorGUI.h" #include "EditorStats.h" @@ -31,5 +32,12 @@ private: EditorGUI* m_EditorGUI; EditorStats* m_EditorStats; + // Utility functions + EntityWrapper importEntity(EntityWrapper parent, boost::filesystem::path filePath); + + // GUI callbacks void OnEntitySelected(EntityWrapper entity); + void OnEntitySave(EntityWrapper entity, boost::filesystem::path filePath); + void OnComponentAttach(EntityWrapper entity, const std::string& componentType); + void OnComponentDelete(EntityWrapper entity, const std::string& componentType); }; \ No newline at end of file diff --git a/src/Engine/Editor/EditorGUI.cpp b/src/Engine/Editor/EditorGUI.cpp index 388016a6..00c8b07c 100644 --- a/src/Engine/Editor/EditorGUI.cpp +++ b/src/Engine/Editor/EditorGUI.cpp @@ -28,9 +28,16 @@ void EditorGUI::drawEntities(World* world) } float buttonWidth = (ImGui::GetContentRegionAvailWidth() - 10.f) / 3.f ; - ImGui::Button("Create", ImVec2(buttonWidth, 0)); + if (ImGui::Button("Create", ImVec2(buttonWidth, 0))) { + if (m_OnEntityCreate != nullptr) { + EntityWrapper newEntity = m_OnEntityCreate(EntityWrapper(world, EntityID_Invalid)); + SelectEntity(newEntity); + } + } ImGui::SameLine(0.f, 5.f); - ImGui::Button("Import", ImVec2(buttonWidth, 0)); + if (ImGui::Button("Import", ImVec2(buttonWidth, 0))) { + entityImport(world); + } ImGui::SameLine(0.f, 5.f); ImGui::Button("Reference", ImVec2(buttonWidth, 0)); @@ -38,6 +45,8 @@ void EditorGUI::drawEntities(World* world) drawEntitiesRecursive(world, EntityID_Invalid); + // Draw any potential modals before ending this scope + drawModals(); ImGui::End(); } @@ -83,28 +92,29 @@ bool EditorGUI::drawEntityNode(EntityWrapper entity) // } //} - ImGui::SetNextTreeNodeOpened(true, ImGuiSetCond_Once); - std::string nodeTitle; + // Compose title + std::stringstream nodeTitle; const std::string& entityName = entity.World->GetName(entity); if (!entityName.empty()) { - nodeTitle = entityName; + nodeTitle << entityName; } else { - nodeTitle = std::string("#") + std::to_string(entity.ID); + nodeTitle << "#" << entity.ID; } - if (ImGui::TreeNode(nodeTitle.c_str())) { + if (m_EntityFiles.count(entity) == 1) { + nodeTitle << " (" << m_EntityFiles.at(entity).filename().string() << ")"; + } + + ImGui::SetNextTreeNodeOpened(true, ImGuiSetCond_Once); + if (ImGui::TreeNode(nodeTitle.str().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); - } + if (ImGui::BeginPopupContextItem("entity context menu")) { + if (ImGui::Button("Save")) { + entitySave(entity); } ImGui::SameLine(); if (ImGui::Button("Delete")) { @@ -116,6 +126,7 @@ bool EditorGUI::drawEntityNode(EntityWrapper entity) SelectEntity(EntityWrapper::Invalid); } } + drawModals(); ImGui::EndPopup(); } return true; @@ -170,14 +181,21 @@ void EditorGUI::drawComponents(EntityWrapper entity) if (!entity.HasComponent(componentType)) { continue; } - // TODO: Add delete button here - drawComponent(entity, pool->ComponentInfo()); + // Handle deletion with early out + if (createDeleteButton(componentType)) { + if (m_OnComponentDelete != nullptr) { + m_OnComponentDelete(entity, componentType); + continue; + } + } + // Draw the actual component node + drawComponentNode(entity, pool->ComponentInfo()); } ImGui::End(); } -bool EditorGUI::drawComponent(EntityWrapper entity, const ComponentInfo& ci) +bool EditorGUI::drawComponentNode(EntityWrapper entity, const ComponentInfo& ci) { if (!ImGui::CollapsingHeader(ci.Name.c_str(), nullptr, true, true)) { return false; @@ -330,3 +348,111 @@ void EditorGUI::drawComponentField_string(ComponentWrapper &c, const ComponentIn // TODO: Handle drag and drop of files } +void EditorGUI::drawModals() +{ + if (ImGui::BeginPopupModal("Import failed", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) { + ImGui::Text("Entity import failed. Check console for more information.\n\n"); + ImGui::SetCursorPosX(ImGui::GetContentRegionAvailWidth() - 120); + if (ImGui::Button("OK", ImVec2(120, 0))) { + ImGui::CloseCurrentPopup(); + } + ImGui::EndPopup(); + } + + if (ImGui::BeginPopupModal("Save failed", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) { + ImGui::Text("Entity save failed on an exception.\nMessage: %s\n\n", m_LastErrorMessage.c_str()); + ImGui::SetCursorPosX(ImGui::GetContentRegionAvailWidth() - 120); + if (ImGui::Button("OK", ImVec2(120, 0))) { + ImGui::CloseCurrentPopup(); + } + ImGui::EndPopup(); + } +} + +bool EditorGUI::createDeleteButton(const std::string& componentType) +{ + float width = ImGui::GetContentRegionAvailWidth(); + ImGuiWindow* window = ImGui::GetCurrentWindow(); + auto pos = ImGui::GetCursorScreenPos() + ImVec2(width - 14.f, 1); + ImRect bb = ImRect(pos, pos + ImVec2(14.f, 14.f)); + std::string idString = "#DELETE"; + idString += componentType; + ImGuiID id = window->GetID(idString.c_str()); + bool hovered; + bool held; + bool pressed = ImGui::ButtonBehavior(bb, id, &hovered, &held); + //ImU32 col = window->Color((held && hovered) ? ImGuiCol_CloseButtonActive : hovered ? ImGuiCol_CloseButtonHovered : ImGuiCol_CloseButton); + ImU32 col = window->Color((held && hovered) ? ImGuiCol_CloseButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); + window->DrawList->AddCircleFilled(bb.GetCenter(), 7.f, col, 16); + return pressed; +} + +boost::filesystem::path EditorGUI::fileOpenDialog() +{ + namespace bfs = boost::filesystem; + nfdchar_t* outPath = nullptr; + nfdresult_t result = NFD_OpenDialog("xml", bfs::absolute(m_DefaultEntityPath).string().c_str(), &outPath); + + if (result == NFD_ERROR) { + LOG_ERROR("NFD Error: %s", NFD_GetError()); + return bfs::path(); + } else if (result == NFD_CANCEL) { + return bfs::path(); + } else { + return bfs::absolute(outPath); + } +} + +boost::filesystem::path EditorGUI::fileSaveDialog() +{ + namespace bfs = boost::filesystem; + nfdchar_t* outPath = nullptr; + nfdresult_t result = NFD_SaveDialog("xml", bfs::absolute(m_DefaultEntityPath).string().c_str(), &outPath); + + if (result == NFD_ERROR) { + LOG_ERROR("NFD Error: %s", NFD_GetError()); + return bfs::path(); + } else if (result == NFD_CANCEL) { + return bfs::path(); + } else { + return bfs::absolute(outPath); + } +} + +void EditorGUI::entityImport(World* world) +{ + boost::filesystem::path filePath = fileOpenDialog(); + if (filePath.empty()) { + return; + } + + EntityWrapper entity = m_OnEntityImport(EntityWrapper(world, EntityID_Invalid), filePath); + if (entity.Valid()) { + m_EntityFiles[entity] = filePath; + SelectEntity(entity); + } else { + ImGui::OpenPopup("Import failed"); + } +} + +void EditorGUI::entitySave(EntityWrapper entity) +{ + boost::filesystem::path filePath; + if (m_EntityFiles.count(entity) == 1) { + filePath = m_EntityFiles.at(entity); + } else { + filePath = fileSaveDialog(); + } + + if (filePath.empty()) { + return; + } + + try { + m_OnEntitySave(entity, filePath); + m_EntityFiles[entity] = filePath; + } catch (const std::exception& e) { + m_LastErrorMessage = e.what(); + ImGui::OpenPopup("Save failed"); + } +} diff --git a/src/Engine/Editor/EditorSystem.cpp b/src/Engine/Editor/EditorSystem.cpp index 0a96ab9b..09cc52de 100644 --- a/src/Engine/Editor/EditorSystem.cpp +++ b/src/Engine/Editor/EditorSystem.cpp @@ -12,12 +12,7 @@ EditorSystem::EditorSystem(EventBroker* eventBroker, IRenderer* renderer, Render m_EditorWorldSystemPipeline->AddSystem(0); m_EditorWorldSystemPipeline->AddSystem(1, m_Renderer, m_RenderFrame); - auto widgetEntityFile = ResourceManager::Load("Schema/Entities/EditorWidget.xml"); - EntityFilePreprocessor fpp(widgetEntityFile); - fpp.RegisterComponents(m_EditorWorld); - EntityFileParser fp(widgetEntityFile); - EntityID widgetID = fp.MergeEntities(m_EditorWorld); - m_Widget = EntityWrapper(m_EditorWorld, widgetID); + m_Widget = importEntity(EntityWrapper(m_EditorWorld, EntityID_Invalid), "Schema/Entities/EditorWidget.xml"); m_Camera = EntityWrapper(m_EditorWorld, m_EditorWorld->CreateEntity()); m_EditorWorld->AttachComponent(m_Camera.ID, "Transform"); @@ -26,6 +21,10 @@ EditorSystem::EditorSystem(EventBroker* eventBroker, IRenderer* renderer, Render m_EditorGUI = new EditorGUI(m_EventBroker); m_EditorGUI->SetEntitySelectedCallback(std::bind(&EditorSystem::OnEntitySelected, this, std::placeholders::_1)); + m_EditorGUI->SetEntityImportCallback(std::bind(&EditorSystem::importEntity, this, std::placeholders::_1, std::placeholders::_2)); + m_EditorGUI->SetEntitySaveCallback(std::bind(&EditorSystem::OnEntitySave, this, std::placeholders::_1, std::placeholders::_2)); + m_EditorGUI->SetComponentAttachCallback(std::bind(&EditorSystem::OnComponentAttach, this, std::placeholders::_1, std::placeholders::_2)); + m_EditorGUI->SetComponentDeleteCallback(std::bind(&EditorSystem::OnComponentDelete, this, std::placeholders::_1, std::placeholders::_2)); m_EditorStats = new EditorStats(); @@ -59,3 +58,38 @@ void EditorSystem::OnEntitySelected(EntityWrapper entity) { m_Widget["Transform"]["Position"] = Transform::AbsolutePosition(entity.World, entity.ID); } + +void EditorSystem::OnEntitySave(EntityWrapper entity, boost::filesystem::path filePath) +{ + EntityFileWriter writer(filePath); + writer.WriteEntity(entity.World, entity.ID); +} + +void EditorSystem::OnComponentAttach(EntityWrapper entity, const std::string& componentType) +{ + entity.World->AttachComponent(entity.ID, componentType); +} + +void EditorSystem::OnComponentDelete(EntityWrapper entity, const std::string& componentType) +{ + entity.World->DeleteComponent(entity.ID, componentType); +} + +EntityWrapper EditorSystem::importEntity(EntityWrapper parent, boost::filesystem::path filePath) +{ + if (parent.World == nullptr) { + LOG_ERROR("Tried to import entity \"%s\" into null world!", filePath.string().c_str()); + return EntityWrapper::Invalid; + } + + try { + auto entityFile = ResourceManager::Load(filePath.string()); + EntityFilePreprocessor fpp(entityFile); + fpp.RegisterComponents(parent.World); + EntityFileParser fp(entityFile); + EntityID newEntity = fp.MergeEntities(parent.World, parent.ID); + return EntityWrapper(parent.World, newEntity); + } catch (const std::exception&) { + return EntityWrapper::Invalid; + } +} \ No newline at end of file From d4242bbead6ba9793274c7cd428e7a887711e7f9 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Mon, 18 Jan 2016 19:26:00 +0100 Subject: [PATCH 12/38] Editor entity create and delete. --- include/Engine/Editor/EditorGUI.h | 4 ++- include/Engine/Editor/EditorSystem.h | 2 ++ src/Engine/Editor/EditorGUI.cpp | 38 ++++++++++++++++++++-------- src/Engine/Editor/EditorSystem.cpp | 14 ++++++++++ src/Engine/Rendering/Renderer.cpp | 5 ++-- 5 files changed, 49 insertions(+), 14 deletions(-) diff --git a/include/Engine/Editor/EditorGUI.h b/include/Engine/Editor/EditorGUI.h index 20946e36..d37d4c83 100644 --- a/include/Engine/Editor/EditorGUI.h +++ b/include/Engine/Editor/EditorGUI.h @@ -45,7 +45,7 @@ public: 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; } + void SetEntityDeleteCallback(OnEntityDelete_t f) { m_OnEntityDelete = f; } // Called when the user means to attach a new component to an entity. typedef std::function OnComponentAttach_t; void SetComponentAttachCallback(OnComponentAttach_t f) { m_OnComponentAttach = f; } @@ -80,6 +80,8 @@ private: // Entity file handling methods void entityImport(World* world); void entitySave(EntityWrapper entity); + void entityCreate(World* world, EntityWrapper parent); + void entityDelete(EntityWrapper entity); // UI drawing methods void drawMenu(); diff --git a/include/Engine/Editor/EditorSystem.h b/include/Engine/Editor/EditorSystem.h index 7998a26d..fe8ef6ff 100644 --- a/include/Engine/Editor/EditorSystem.h +++ b/include/Engine/Editor/EditorSystem.h @@ -38,6 +38,8 @@ private: // GUI callbacks void OnEntitySelected(EntityWrapper entity); void OnEntitySave(EntityWrapper entity, boost::filesystem::path filePath); + EntityWrapper OnEntityCreate(EntityWrapper parent); + void OnEntityDelete(EntityWrapper entity); void OnComponentAttach(EntityWrapper entity, const std::string& componentType); void OnComponentDelete(EntityWrapper entity, const std::string& componentType); }; \ No newline at end of file diff --git a/src/Engine/Editor/EditorGUI.cpp b/src/Engine/Editor/EditorGUI.cpp index 00c8b07c..3cff403d 100644 --- a/src/Engine/Editor/EditorGUI.cpp +++ b/src/Engine/Editor/EditorGUI.cpp @@ -29,10 +29,7 @@ void EditorGUI::drawEntities(World* world) float buttonWidth = (ImGui::GetContentRegionAvailWidth() - 10.f) / 3.f ; if (ImGui::Button("Create", ImVec2(buttonWidth, 0))) { - if (m_OnEntityCreate != nullptr) { - EntityWrapper newEntity = m_OnEntityCreate(EntityWrapper(world, EntityID_Invalid)); - SelectEntity(newEntity); - } + entityCreate(world, m_CurrentSelection); } ImGui::SameLine(0.f, 5.f); if (ImGui::Button("Import", ImVec2(buttonWidth, 0))) { @@ -115,16 +112,12 @@ bool EditorGUI::drawEntityNode(EntityWrapper entity) if (ImGui::BeginPopupContextItem("entity context menu")) { if (ImGui::Button("Save")) { entitySave(entity); + ImGui::CloseCurrentPopup(); } ImGui::SameLine(); if (ImGui::Button("Delete")) { - if (m_OnEntityDelete != nullptr) { - m_OnEntityDelete(entity); - ImGui::CloseCurrentPopup(); - } - if (!m_CurrentSelection.Valid()) { - SelectEntity(EntityWrapper::Invalid); - } + entityDelete(entity); + ImGui::CloseCurrentPopup(); } drawModals(); ImGui::EndPopup(); @@ -456,3 +449,26 @@ void EditorGUI::entitySave(EntityWrapper entity) ImGui::OpenPopup("Save failed"); } } + +void EditorGUI::entityCreate(World* world, EntityWrapper parent) +{ + if (m_OnEntityCreate != nullptr) { + // Create the new entity in the world we're drawing for + if (parent.World == nullptr) { + parent.World = world; + } + EntityWrapper newEntity = m_OnEntityCreate(parent); + SelectEntity(newEntity); + } +} + +void EditorGUI::entityDelete(EntityWrapper entity) +{ + if (m_OnEntityDelete != nullptr) { + m_OnEntityDelete(entity); + m_EntityFiles.erase(entity); + } + if (!m_CurrentSelection.Valid()) { + SelectEntity(EntityWrapper::Invalid); + } +} diff --git a/src/Engine/Editor/EditorSystem.cpp b/src/Engine/Editor/EditorSystem.cpp index 09cc52de..51ab2f1f 100644 --- a/src/Engine/Editor/EditorSystem.cpp +++ b/src/Engine/Editor/EditorSystem.cpp @@ -23,6 +23,8 @@ EditorSystem::EditorSystem(EventBroker* eventBroker, IRenderer* renderer, Render m_EditorGUI->SetEntitySelectedCallback(std::bind(&EditorSystem::OnEntitySelected, this, std::placeholders::_1)); m_EditorGUI->SetEntityImportCallback(std::bind(&EditorSystem::importEntity, this, std::placeholders::_1, std::placeholders::_2)); m_EditorGUI->SetEntitySaveCallback(std::bind(&EditorSystem::OnEntitySave, this, std::placeholders::_1, std::placeholders::_2)); + m_EditorGUI->SetEntityCreateCallback(std::bind(&EditorSystem::OnEntityCreate, this, std::placeholders::_1)); + m_EditorGUI->SetEntityDeleteCallback(std::bind(&EditorSystem::OnEntityDelete, this, std::placeholders::_1)); m_EditorGUI->SetComponentAttachCallback(std::bind(&EditorSystem::OnComponentAttach, this, std::placeholders::_1, std::placeholders::_2)); m_EditorGUI->SetComponentDeleteCallback(std::bind(&EditorSystem::OnComponentDelete, this, std::placeholders::_1, std::placeholders::_2)); @@ -65,6 +67,18 @@ void EditorSystem::OnEntitySave(EntityWrapper entity, boost::filesystem::path fi writer.WriteEntity(entity.World, entity.ID); } +EntityWrapper EditorSystem::OnEntityCreate(EntityWrapper parent) +{ + EntityID entity = parent.World->CreateEntity(parent.ID); + parent.World->AttachComponent(entity, "Transform"); + return EntityWrapper(parent.World, entity); +} + +void EditorSystem::OnEntityDelete(EntityWrapper entity) +{ + entity.World->DeleteEntity(entity.ID); +} + void EditorSystem::OnComponentAttach(EntityWrapper entity, const std::string& componentType) { entity.World->AttachComponent(entity.ID, componentType); diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index e8ed1d9a..5989543e 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -160,7 +160,8 @@ void Renderer::InitializeRenderPasses() //Temp func void Renderer::FillDepth(RenderScene& scene) { - for (auto job : scene.ForwardJobs) { + // HACK: FIX ME TOBIAS + /*for (auto job : scene.ForwardJobs) { auto modelJob = std::dynamic_pointer_cast(job); if(! modelJob) { return; @@ -171,5 +172,5 @@ void Renderer::FillDepth(RenderScene& scene) glm::vec3 worldpos = glm::vec3(scene.Camera->ViewMatrix() * glm::vec4(abspos, 1)); modelJob->Depth = worldpos.z; } - scene.ForwardJobs.sort(Renderer::DepthSort); + scene.ForwardJobs.sort(Renderer::DepthSort);*/ } \ No newline at end of file From 1760f9dfb17a39d1db34bc67c1c4d789450c4773 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Mon, 18 Jan 2016 21:17:24 +0100 Subject: [PATCH 13/38] Added inequality operator to EntityWrapper --- include/Engine/Core/EntityWrapper.h | 1 + src/Engine/Core/EntityWrapper.cpp | 15 ++++++++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/include/Engine/Core/EntityWrapper.h b/include/Engine/Core/EntityWrapper.h index 79f90f33..74b5fc56 100644 --- a/include/Engine/Core/EntityWrapper.h +++ b/include/Engine/Core/EntityWrapper.h @@ -28,6 +28,7 @@ struct EntityWrapper ComponentWrapper operator[](const char* componentName); bool operator==(const EntityWrapper& e) const; + bool operator!=(const EntityWrapper& e) const; explicit operator EntityID() const; operator bool(); }; diff --git a/src/Engine/Core/EntityWrapper.cpp b/src/Engine/Core/EntityWrapper.cpp index 8c1ab10d..5dc493ff 100644 --- a/src/Engine/Core/EntityWrapper.cpp +++ b/src/Engine/Core/EntityWrapper.cpp @@ -3,11 +3,6 @@ const EntityWrapper EntityWrapper::Invalid = EntityWrapper(nullptr, EntityID_Invalid); -bool EntityWrapper::operator==(const EntityWrapper& e) const -{ - return (this->World == e.World) && (this->ID == e.ID); -} - bool EntityWrapper::HasComponent(const std::string& componentName) { return World->HasComponent(ID, componentName); @@ -41,6 +36,16 @@ ComponentWrapper EntityWrapper::operator[](const char* componentName) } } +bool EntityWrapper::operator==(const EntityWrapper& e) const +{ + return (this->World == e.World) && (this->ID == e.ID); +} + +bool EntityWrapper::operator!=(const EntityWrapper& e) const +{ + return !this->operator==(e); +} + EntityWrapper::operator EntityID() const { return this->ID; From 3fc44e944caad07007e69a299f705a05a8eb6b82 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Mon, 18 Jan 2016 21:18:23 +0100 Subject: [PATCH 14/38] Editor entity reparenting. --- assets | 2 +- include/Engine/Editor/EditorGUI.h | 16 ++- include/Engine/Editor/EditorSystem.h | 1 + src/Engine/Core/ComponentPool.cpp | 1 - src/Engine/Editor/EditorGUI.cpp | 161 ++++++++++++++++------- src/Engine/Editor/EditorSystem.cpp | 6 + src/Engine/Rendering/ImGuiRenderPass.cpp | 8 +- 7 files changed, 140 insertions(+), 55 deletions(-) diff --git a/assets b/assets index a3c92ac8..a1bb17db 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit a3c92ac876dd061776c36d1594bd82264372f028 +Subproject commit a1bb17dbe0da3d55932c2e187da50bc0257691f4 diff --git a/include/Engine/Editor/EditorGUI.h b/include/Engine/Editor/EditorGUI.h index d37d4c83..917d216f 100644 --- a/include/Engine/Editor/EditorGUI.h +++ b/include/Engine/Editor/EditorGUI.h @@ -13,13 +13,13 @@ #include "../Core/EventBroker.h" #include "../Core/World.h" #include "../Core/EntityWrapper.h" +#include "../Core/ResourceManager.h" +#include "../Rendering/Texture.h" class EditorGUI { public: - EditorGUI(EventBroker* eventBroker) - : m_EventBroker(eventBroker) - { } + EditorGUI(EventBroker* eventBroker); void Draw(World* world); @@ -46,6 +46,9 @@ public: // Called when the user means to delete an entity. typedef std::function OnEntityDelete_t; void SetEntityDeleteCallback(OnEntityDelete_t f) { m_OnEntityDelete = f; } + // Called when the user means to change the parent of an entity. + typedef std::function OnEntityChangeParent_t; + void SetEntityChangeParentCallback(OnEntityChangeParent_t f) { m_OnEntityChangeParent = f; } // Called when the user means to attach a new component to an entity. typedef std::function OnComponentAttach_t; void SetComponentAttachCallback(OnComponentAttach_t f) { m_OnComponentAttach = f; } @@ -62,6 +65,7 @@ private: // State variables EntityWrapper m_CurrentSelection = EntityWrapper::Invalid; std::unordered_map m_EntityFiles; + EntityWrapper m_CurrentlyDragging = EntityWrapper::Invalid; std::string m_LastErrorMessage; // Callbacks @@ -70,21 +74,25 @@ private: OnEntitySave_t m_OnEntitySave = nullptr; OnEntityCreate_t m_OnEntityCreate = nullptr; OnEntityDelete_t m_OnEntityDelete = nullptr; + OnEntityChangeParent_t m_OnEntityChangeParent = nullptr; OnComponentAttach_t m_OnComponentAttach = nullptr; OnComponentDelete_t m_OnComponentDelete = nullptr; // Utility functions boost::filesystem::path fileOpenDialog(); boost::filesystem::path fileSaveDialog(); + const std::string formatEntityName(EntityWrapper entity); // Entity file handling methods void entityImport(World* world); - void entitySave(EntityWrapper entity); + void entitySave(EntityWrapper entity, bool saveAs = false); void entityCreate(World* world, EntityWrapper parent); void entityDelete(EntityWrapper entity); + void entityChangeParent(EntityWrapper entity, EntityWrapper parent); // UI drawing methods void drawMenu(); + void drawTools(); void drawEntities(World* world); void drawEntitiesRecursive(World* world, EntityID parent); bool drawEntityNode(EntityWrapper entity); diff --git a/include/Engine/Editor/EditorSystem.h b/include/Engine/Editor/EditorSystem.h index fe8ef6ff..70ab2f15 100644 --- a/include/Engine/Editor/EditorSystem.h +++ b/include/Engine/Editor/EditorSystem.h @@ -40,6 +40,7 @@ private: void OnEntitySave(EntityWrapper entity, boost::filesystem::path filePath); EntityWrapper OnEntityCreate(EntityWrapper parent); void OnEntityDelete(EntityWrapper entity); + void OnEntityChangeParent(EntityWrapper entity, EntityWrapper parent); void OnComponentAttach(EntityWrapper entity, const std::string& componentType); void OnComponentDelete(EntityWrapper entity, const std::string& componentType); }; \ No newline at end of file diff --git a/src/Engine/Core/ComponentPool.cpp b/src/Engine/Core/ComponentPool.cpp index ce24c1f7..2ef64d71 100644 --- a/src/Engine/Core/ComponentPool.cpp +++ b/src/Engine/Core/ComponentPool.cpp @@ -50,7 +50,6 @@ ComponentWrapper ComponentPool::GetByEntity(EntityID ent) return ComponentWrapper(m_ComponentInfo, m_EntityToComponent.at(ent)); } - bool ComponentPool::KnowsEntity(EntityID ent) { return m_EntityToComponent.find(ent) != m_EntityToComponent.end(); diff --git a/src/Engine/Editor/EditorGUI.cpp b/src/Engine/Editor/EditorGUI.cpp index 3cff403d..94aaceb4 100644 --- a/src/Engine/Editor/EditorGUI.cpp +++ b/src/Engine/Editor/EditorGUI.cpp @@ -1,9 +1,16 @@ #include "Editor/EditorGUI.h" +EditorGUI::EditorGUI(EventBroker* eventBroker) + : m_EventBroker(eventBroker) +{ + +} + void EditorGUI::Draw(World* world) { ImGui::ShowTestWindow(); drawMenu(); + drawTools(); drawEntities(world); drawComponents(m_CurrentSelection); } @@ -21,6 +28,34 @@ void EditorGUI::drawMenu() } +void EditorGUI::drawTools() +{ + if (!ImGui::Begin("Tools", nullptr, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_AlwaysAutoResize)) { + return; + } + + GLuint translateIcon = 0; + try { + translateIcon = ResourceManager::Load("Textures/Icons/shaft.png")->m_Texture; + } catch (const std::exception&) { } + GLuint rotateIcon = 0; + try { + rotateIcon = ResourceManager::Load("Textures/Icons/circulararrows3.png")->m_Texture; + } catch (const std::exception&) { } + GLuint scaleIcon = 0; + try { + scaleIcon = ResourceManager::Load("Textures/Icons/increase10.png")->m_Texture; + } catch (const std::exception&) { } + + ImGui::ImageButton((void*)translateIcon, ImVec2(24, 24)); + ImGui::SameLine(); + ImGui::ImageButton((void*)rotateIcon, ImVec2(24, 24)); + ImGui::SameLine(); + ImGui::ImageButton((void*)scaleIcon, ImVec2(24, 24)); + + ImGui::End(); +} + void EditorGUI::drawEntities(World* world) { if (!ImGui::Begin("Entities")) { @@ -61,6 +96,7 @@ void EditorGUI::drawEntitiesRecursive(World* world, EntityID parent) bool EditorGUI::drawEntityNode(EntityWrapper entity) { + // Custom button hitbox to select entities on top of tree node ImVec2 pos = ImGui::GetCursorScreenPos(); float width = ImGui::GetContentRegionAvailWidth(); ImRect bb(pos + ImVec2(20, 0), pos + ImVec2(width, 14)); @@ -75,52 +111,52 @@ bool EditorGUI::drawEntityNode(EntityWrapper entity) 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(); - // } - //} - - // Compose title - std::stringstream nodeTitle; - const std::string& entityName = entity.World->GetName(entity); - if (!entityName.empty()) { - nodeTitle << entityName; - } else { - nodeTitle << "#" << entity.ID; + // Handle entity dragging + if (held) { + ImVec2 entityDragDelta = ImGui::GetMouseDragDelta(0); + if (std::abs(entityDragDelta.x) > 0 && std::abs(entityDragDelta.y) > 0) { + if (m_CurrentlyDragging == EntityWrapper::Invalid) { + m_CurrentlyDragging = entity; + LOG_DEBUG("Started dragging %i", entity.ID); + } + 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(formatEntityName(entity).c_str()); + ImGui::End(); + } + } else if (m_CurrentlyDragging == entity) { + LOG_DEBUG("Stopped dragging %i", entity.ID); + m_CurrentlyDragging = EntityWrapper::Invalid; } - if (m_EntityFiles.count(entity) == 1) { - nodeTitle << " (" << m_EntityFiles.at(entity).filename().string() << ")"; + // Entity context menu + std::string contextMenuUniqueID = std::string("EntityContextMenu") + std::to_string(entity.ID); + if (hovered && ImGui::IsMouseClicked(1)) { + ImGui::OpenPopup(contextMenuUniqueID.c_str()); + } + if (ImGui::BeginPopup(contextMenuUniqueID.c_str())) { + ImGui::TextDisabled(formatEntityName(entity).c_str()); + if (ImGui::MenuItem("Save", "Ctrl+S")) { + entitySave(entity); + } else + if (ImGui::MenuItem("Save As...", "Ctrl+Shift+S")) { + entitySave(entity, true); + } else + if (ImGui::MenuItem("Delete", "Del")) { + entityDelete(entity); + } else + if (ImGui::MenuItem("Move to root")) { + entityChangeParent(entity, EntityWrapper::Invalid); + } + drawModals(); + ImGui::EndPopup(); } ImGui::SetNextTreeNodeOpened(true, ImGuiSetCond_Once); - if (ImGui::TreeNode(nodeTitle.str().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("entity context menu")) { - if (ImGui::Button("Save")) { - entitySave(entity); - ImGui::CloseCurrentPopup(); - } - ImGui::SameLine(); - if (ImGui::Button("Delete")) { - entityDelete(entity); - ImGui::CloseCurrentPopup(); - } - drawModals(); - ImGui::EndPopup(); + if (ImGui::TreeNode(formatEntityName(entity).c_str())) { + // Handle drop events for reparenting + if (m_CurrentlyDragging != EntityWrapper::Invalid && ImGui::IsItemHoveredRect() && ImGui::IsMouseReleased(0)) { + entityChangeParent(m_CurrentlyDragging, entity); + m_CurrentlyDragging = EntityWrapper::Invalid; } return true; } else { @@ -133,7 +169,7 @@ void EditorGUI::drawComponents(EntityWrapper entity) std::stringstream title; title << "Components"; if (entity.Valid()) { - title << " #" << entity.ID << "###Components"; + title << formatEntityName(entity) << "###Components"; } if (!ImGui::Begin(title.str().c_str())) { ImGui::End(); @@ -380,6 +416,7 @@ bool EditorGUI::createDeleteButton(const std::string& componentType) return pressed; } + boost::filesystem::path EditorGUI::fileOpenDialog() { namespace bfs = boost::filesystem; @@ -412,6 +449,28 @@ boost::filesystem::path EditorGUI::fileSaveDialog() } } +const std::string EditorGUI::formatEntityName(EntityWrapper entity) +{ + if (!entity.Valid()) { + return "EntityID_Invalid"; + } + + std::stringstream name; + + const std::string& entityName = entity.World->GetName(entity); + if (!entityName.empty()) { + name << entityName; + } else { + name << "#" << entity.ID; + } + + if (m_EntityFiles.count(entity) == 1) { + name << " (" << m_EntityFiles.at(entity).filename().string() << ")"; + } + + return name.str(); +} + void EditorGUI::entityImport(World* world) { boost::filesystem::path filePath = fileOpenDialog(); @@ -428,10 +487,10 @@ void EditorGUI::entityImport(World* world) } } -void EditorGUI::entitySave(EntityWrapper entity) +void EditorGUI::entitySave(EntityWrapper entity, bool saveAs /* = false */) { boost::filesystem::path filePath; - if (m_EntityFiles.count(entity) == 1) { + if (!saveAs && m_EntityFiles.count(entity) == 1) { filePath = m_EntityFiles.at(entity); } else { filePath = fileSaveDialog(); @@ -472,3 +531,15 @@ void EditorGUI::entityDelete(EntityWrapper entity) SelectEntity(EntityWrapper::Invalid); } } + +void EditorGUI::entityChangeParent(EntityWrapper entity, EntityWrapper parent) +{ + if (entity == parent) { + return; + } + + if (m_OnEntityChangeParent != nullptr) { + m_OnEntityChangeParent(entity, parent); + LOG_DEBUG("Changed parent of %i to %i", entity.ID, parent.ID); + } +} diff --git a/src/Engine/Editor/EditorSystem.cpp b/src/Engine/Editor/EditorSystem.cpp index 51ab2f1f..b1e09422 100644 --- a/src/Engine/Editor/EditorSystem.cpp +++ b/src/Engine/Editor/EditorSystem.cpp @@ -25,6 +25,7 @@ EditorSystem::EditorSystem(EventBroker* eventBroker, IRenderer* renderer, Render m_EditorGUI->SetEntitySaveCallback(std::bind(&EditorSystem::OnEntitySave, this, std::placeholders::_1, std::placeholders::_2)); m_EditorGUI->SetEntityCreateCallback(std::bind(&EditorSystem::OnEntityCreate, this, std::placeholders::_1)); m_EditorGUI->SetEntityDeleteCallback(std::bind(&EditorSystem::OnEntityDelete, this, std::placeholders::_1)); + m_EditorGUI->SetEntityChangeParentCallback(std::bind(&EditorSystem::OnEntityChangeParent, this, std::placeholders::_1, std::placeholders::_2)); m_EditorGUI->SetComponentAttachCallback(std::bind(&EditorSystem::OnComponentAttach, this, std::placeholders::_1, std::placeholders::_2)); m_EditorGUI->SetComponentDeleteCallback(std::bind(&EditorSystem::OnComponentDelete, this, std::placeholders::_1, std::placeholders::_2)); @@ -79,6 +80,11 @@ void EditorSystem::OnEntityDelete(EntityWrapper entity) entity.World->DeleteEntity(entity.ID); } +void EditorSystem::OnEntityChangeParent(EntityWrapper entity, EntityWrapper parent) +{ + entity.World->SetParent(entity.ID, parent.ID); +} + void EditorSystem::OnComponentAttach(EntityWrapper entity, const std::string& componentType) { entity.World->AttachComponent(entity.ID, componentType); diff --git a/src/Engine/Rendering/ImGuiRenderPass.cpp b/src/Engine/Rendering/ImGuiRenderPass.cpp index 96f987d9..e67eea71 100644 --- a/src/Engine/Rendering/ImGuiRenderPass.cpp +++ b/src/Engine/Rendering/ImGuiRenderPass.cpp @@ -105,7 +105,7 @@ void ImGuiRenderPass::Draw() if (pcmd->UserCallback) { pcmd->UserCallback(cmd_list, pcmd); } else { - glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); + glBindTexture(GL_TEXTURE_2D, (GLuint)pcmd->TextureId); glScissor((int)pcmd->ClipRect.x, (int)(fb_height - pcmd->ClipRect.w), (int)(pcmd->ClipRect.z - pcmd->ClipRect.x), (int)(pcmd->ClipRect.w - pcmd->ClipRect.y)); glDrawElements(GL_TRIANGLES, (GLsizei)pcmd->ElemCount, sizeof(ImDrawIdx) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, idx_buffer_offset); } @@ -190,7 +190,7 @@ bool ImGuiRenderPass::createDeviceObjects() "{\n" " Frag_UV = UV;\n" " Frag_Color = Color;\n" - " gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" + " gl_Position = ProjMtx * vec4(Position.xy, 0, 1);\n" "}\n"; const GLchar* fragment_shader = @@ -201,7 +201,7 @@ bool ImGuiRenderPass::createDeviceObjects() "out vec4 Out_Color;\n" "void main()\n" "{\n" - " Out_Color = Frag_Color * texture( Texture, Frag_UV.st);\n" + " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n" "}\n"; g_ShaderHandle = glCreateProgram(); @@ -271,7 +271,7 @@ bool ImGuiRenderPass::createFontsTexture() glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); // Store our identifier - io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; + io.Fonts->TexID = (void*)g_FontTexture; // Restore state glBindTexture(GL_TEXTURE_2D, last_texture); From 51979d7f0ca38f4b4ec8d75f970198715caccaf0 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Mon, 18 Jan 2016 23:59:33 +0100 Subject: [PATCH 15/38] Changed System to take World through constructor and store it instead, cause it makes more sense. --- .../Engine/Collision/CollidableOctreeSystem.h | 8 +++--- include/Engine/Collision/CollisionSystem.h | 6 ++--- include/Engine/Collision/TriggerSystem.h | 6 ++--- include/Engine/Core/System.h | 14 +++++------ include/Engine/Core/SystemPipeline.h | 18 +++++++------ include/Engine/Core/UniformScaleSystem.h | 4 +-- include/Engine/Editor/EditorRenderSystem.h | 4 +-- include/Engine/Editor/EditorSystem.h | 4 +-- include/Engine/Editor/EditorSystemOld.h | 5 ++-- include/Engine/Rendering/RenderSystem.h | 9 +++---- include/Game/Systems/HealthSystem.h | 4 +-- include/Game/Systems/PlayerMovementSystem.h | 6 ++--- include/Game/Systems/PlayerSpawnSystem.h | 4 +-- include/Game/Systems/PlayerSystem.h | 6 ++--- include/Game/Systems/RaptorCopterSystem.h | 8 +++--- include/Game/Systems/SpawnerSystem.h | 2 +- .../Collision/CollidableOctreeSystem.cpp | 4 +-- src/Engine/Collision/CollisionSystem.cpp | 2 +- src/Engine/Collision/TriggerSystem.cpp | 6 ++--- src/Engine/Core/UniformScaleSystem.cpp | 6 ++--- src/Engine/Editor/EditorRenderSystem.cpp | 14 +++++------ src/Engine/Editor/EditorSystem.cpp | 12 ++++----- src/Engine/Editor/EditorSystemOld.cpp | 10 +++----- src/Engine/Rendering/RenderSystem.cpp | 25 +++++++++---------- src/Game/Game.cpp | 4 +-- src/Game/Systems/HealthSystem.cpp | 8 +++--- src/Game/Systems/PlayerMovementSystem.cpp | 2 +- src/Game/Systems/PlayerSpawnSystem.cpp | 10 ++++---- src/Game/Systems/PlayerSystem.cpp | 4 +-- src/Game/Systems/SpawnerSystem.cpp | 3 ++- src/Tests/HealthSystemTest.cpp | 2 +- src/Tests/OctTreeTestGameClass.cpp | 2 +- 32 files changed, 111 insertions(+), 111 deletions(-) diff --git a/include/Engine/Collision/CollidableOctreeSystem.h b/include/Engine/Collision/CollidableOctreeSystem.h index 8fa1f0a4..5b677186 100644 --- a/include/Engine/Collision/CollidableOctreeSystem.h +++ b/include/Engine/Collision/CollidableOctreeSystem.h @@ -8,14 +8,14 @@ class CollidableOctreeSystem : public ImpureSystem, public PureSystem { public: - CollidableOctreeSystem(EventBroker* eventBroker, Octree* octree) - : System(eventBroker) + CollidableOctreeSystem(World* world, EventBroker* eventBroker, Octree* octree) + : System(world, eventBroker) , PureSystem("Collidable") , m_Octree(octree) { } - virtual void Update(World* world, double dt) override; - virtual void UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& component, double dt) override; + virtual void Update(double dt) override; + virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override; private: Octree* m_Octree; diff --git a/include/Engine/Collision/CollisionSystem.h b/include/Engine/Collision/CollisionSystem.h index ea6004d9..6abbf802 100644 --- a/include/Engine/Collision/CollisionSystem.h +++ b/include/Engine/Collision/CollisionSystem.h @@ -13,8 +13,8 @@ class CollisionSystem : public PureSystem { public: - CollisionSystem(EventBroker* eventBroker, Octree* octree) - : System(eventBroker) + CollisionSystem(World* world, EventBroker* eventBroker, Octree* octree) + : System(world, eventBroker) , PureSystem("AABB") , m_Octree(octree) , zPress(false) @@ -23,7 +23,7 @@ public: EVENT_SUBSCRIBE_MEMBER(m_EKeyUp, &CollisionSystem::OnKeyUp); } - virtual void UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& component, double dt) override; + virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override; private: Octree* m_Octree; diff --git a/include/Engine/Collision/TriggerSystem.h b/include/Engine/Collision/TriggerSystem.h index ee53ad9b..23de924f 100644 --- a/include/Engine/Collision/TriggerSystem.h +++ b/include/Engine/Collision/TriggerSystem.h @@ -14,13 +14,13 @@ class AABB; class TriggerSystem : public PureSystem { public: - TriggerSystem(EventBroker* eventBroker, Octree* octree) - : System(eventBroker) + TriggerSystem(World* world, EventBroker* eventBroker, Octree* octree) + : System(world, eventBroker) , PureSystem("Trigger") , m_Octree(octree) { } - virtual void UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& component, double dt) override; + virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override; private: Octree* m_Octree; diff --git a/include/Engine/Core/System.h b/include/Engine/Core/System.h index b7de9dc2..dc7c879a 100644 --- a/include/Engine/Core/System.h +++ b/include/Engine/Core/System.h @@ -11,14 +11,14 @@ class System friend class SystemPipeline; protected: - System() - : m_EventBroker(nullptr) - { } - System(EventBroker* eventBroker) - : m_EventBroker(eventBroker) + System(World* world, EventBroker) { } + System(World* world, EventBroker* eventBroker) + : m_World(world) + , m_EventBroker(eventBroker) { } virtual ~System() = default; + World* m_World; EventBroker* m_EventBroker; }; @@ -34,7 +34,7 @@ protected: const std::string m_ComponentType; - virtual void UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& component, double dt) = 0; + virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cUniformScale, double dt) = 0; }; class ImpureSystem : public virtual System @@ -45,7 +45,7 @@ protected: ImpureSystem() = default; virtual ~ImpureSystem() = default; - virtual void Update(World* world, double dt) = 0; + virtual void Update(double dt) = 0; }; #endif \ No newline at end of file diff --git a/include/Engine/Core/SystemPipeline.h b/include/Engine/Core/SystemPipeline.h index c0cd8ed6..cc3c98e9 100644 --- a/include/Engine/Core/SystemPipeline.h +++ b/include/Engine/Core/SystemPipeline.h @@ -9,9 +9,11 @@ class SystemPipeline { public: - SystemPipeline(EventBroker* eventBroker) - : m_EventBroker(eventBroker) + SystemPipeline(World* world, EventBroker* eventBroker) + : m_World(world) + , m_EventBroker(eventBroker) { } + ~SystemPipeline() { for (UnorderedSystems& group : m_OrderedSystemGroups) { @@ -29,7 +31,7 @@ public: m_OrderedSystemGroups.resize(updateOrderLevel + 1); } UnorderedSystems& group = m_OrderedSystemGroups[updateOrderLevel]; - System* system = new T(m_EventBroker, args...); + System* system = new T(m_World, m_EventBroker, args...); group.Systems[typeid(T).name()] = system; PureSystem* pureSystem = dynamic_cast(system); @@ -47,7 +49,7 @@ public: } } - void Update(World* world, double dt) + void Update(double dt) { for (UnorderedSystems& group : m_OrderedSystemGroups) { // Process events @@ -57,18 +59,18 @@ public: // Update for (auto& system : group.ImpureSystems) { - system->Update(world, dt); + system->Update(dt); } for (auto& pair : group.PureSystems) { const std::string& componentName = pair.first; auto& systems = pair.second; - const ComponentPool* pool = world->GetComponents(componentName); + const ComponentPool* pool = m_World->GetComponents(componentName); if (pool == nullptr) { continue; } for (auto& component : *pool) { for (auto& system : systems) { - system->UpdateComponent(world, EntityWrapper(world, component.EntityID), component, dt); + system->UpdateComponent(EntityWrapper(m_World, component.EntityID), component, dt); } } } @@ -76,7 +78,9 @@ public: } private: + World* m_World; EventBroker* m_EventBroker; + struct UnorderedSystems { std::map Systems; diff --git a/include/Engine/Core/UniformScaleSystem.h b/include/Engine/Core/UniformScaleSystem.h index f44409f0..0ebc0672 100644 --- a/include/Engine/Core/UniformScaleSystem.h +++ b/include/Engine/Core/UniformScaleSystem.h @@ -8,9 +8,9 @@ class UniformScaleSystem : public PureSystem { public: - UniformScaleSystem(EventBroker* eventBroker); + UniformScaleSystem(World* world, EventBroker* eventBroker); - virtual void UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& cUniformScale, double dt) override; + virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cUniformScale, double dt) override; private: EntityWrapper m_Camera = EntityWrapper::Invalid; diff --git a/include/Engine/Editor/EditorRenderSystem.h b/include/Engine/Editor/EditorRenderSystem.h index c593e29a..361669ba 100644 --- a/include/Engine/Editor/EditorRenderSystem.h +++ b/include/Engine/Editor/EditorRenderSystem.h @@ -10,9 +10,9 @@ class EditorRenderSystem : public ImpureSystem { public: - EditorRenderSystem(EventBroker* eventBroker, IRenderer* renderer, RenderFrame* renderFrame); + EditorRenderSystem(World* world, EventBroker* eventBroker, IRenderer* renderer, RenderFrame* renderFrame); - virtual void Update(World* world, double dt) override; + virtual void Update(double dt) override; private: IRenderer* m_Renderer; diff --git a/include/Engine/Editor/EditorSystem.h b/include/Engine/Editor/EditorSystem.h index 70ab2f15..8ae3ac2e 100644 --- a/include/Engine/Editor/EditorSystem.h +++ b/include/Engine/Editor/EditorSystem.h @@ -15,10 +15,10 @@ class EditorSystem : public ImpureSystem { public: - EditorSystem(EventBroker* eventBroker, IRenderer* renderer, RenderFrame* renderFrame); + EditorSystem(World* world, EventBroker* eventBroker, IRenderer* renderer, RenderFrame* renderFrame); ~EditorSystem(); - void Update(World* world, double dt); + void Update(double dt); private: IRenderer* m_Renderer; diff --git a/include/Engine/Editor/EditorSystemOld.h b/include/Engine/Editor/EditorSystemOld.h index b2d7df0c..d49c3542 100644 --- a/include/Engine/Editor/EditorSystemOld.h +++ b/include/Engine/Editor/EditorSystemOld.h @@ -18,13 +18,12 @@ class EditorSystemOld : public ImpureSystem { public: - EditorSystemOld(EventBroker* eventBroker, IRenderer* renderer); + EditorSystemOld(World* world, EventBroker* eventBroker, IRenderer* renderer); - virtual void Update(World* world, double dt) override; + virtual void Update(double dt) override; private: IRenderer* m_Renderer; - World* m_World = nullptr; Camera* m_Camera = nullptr; bool m_Enabled; diff --git a/include/Engine/Rendering/RenderSystem.h b/include/Engine/Rendering/RenderSystem.h index 39b35108..198e22ee 100644 --- a/include/Engine/Rendering/RenderSystem.h +++ b/include/Engine/Rendering/RenderSystem.h @@ -20,13 +20,12 @@ class RenderSystem : public ImpureSystem { public: - RenderSystem(EventBroker* eventBrokerer, const IRenderer* renderer, RenderFrame* renderFrame); + RenderSystem(World* world, EventBroker* eventBrokerer, const IRenderer* renderer, RenderFrame* renderFrame); ~RenderSystem(); - virtual void Update(World* world, double dt) override; + virtual void Update(double dt) override; private: - World* m_World = nullptr; const IRenderer* m_Renderer; RenderFrame* m_RenderFrame; Camera* m_Camera; @@ -37,8 +36,8 @@ private: EventRelay m_EInputCommand; bool OnInputCommand(const Events::InputCommand& e); - void fillModels(std::list>& jobs, World* world); - void fillLight(std::list>& jobs, World* world); + void fillModels(std::list>& jobs); + void fillLight(std::list>& jobs); }; #endif \ No newline at end of file diff --git a/include/Game/Systems/HealthSystem.h b/include/Game/Systems/HealthSystem.h index 0db3ec41..f9843f11 100644 --- a/include/Game/Systems/HealthSystem.h +++ b/include/Game/Systems/HealthSystem.h @@ -16,10 +16,10 @@ class HealthSystem : public PureSystem { public: - HealthSystem(EventBroker* eventBroker); + HealthSystem(World* world, EventBroker* eventBroker); //updatecomponent - virtual void UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& component, double dt) override; + virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override; private: //methods which will take care of specific events diff --git a/include/Game/Systems/PlayerMovementSystem.h b/include/Game/Systems/PlayerMovementSystem.h index 6dc2dc31..1be61bdd 100644 --- a/include/Game/Systems/PlayerMovementSystem.h +++ b/include/Game/Systems/PlayerMovementSystem.h @@ -5,10 +5,10 @@ class PlayerMovementSystem : public PureSystem { public: - PlayerMovementSystem(EventBroker* eventBroker) - : System(eventBroker) + PlayerMovementSystem(World* world, EventBroker* eventBroker) + : System(world, eventBroker) , PureSystem("Player") { } - virtual void UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& component, double dt); + virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt); }; \ No newline at end of file diff --git a/include/Game/Systems/PlayerSpawnSystem.h b/include/Game/Systems/PlayerSpawnSystem.h index f0e10949..8ade03a6 100644 --- a/include/Game/Systems/PlayerSpawnSystem.h +++ b/include/Game/Systems/PlayerSpawnSystem.h @@ -6,9 +6,9 @@ class PlayerSpawnSystem : public ImpureSystem { public: - PlayerSpawnSystem(EventBroker* eventBroker); + PlayerSpawnSystem(World* world, EventBroker* eventBroker); - virtual void Update(World* world, double dt) override; + virtual void Update(double dt) override; private: EventRelay m_OnInputCommand; diff --git a/include/Game/Systems/PlayerSystem.h b/include/Game/Systems/PlayerSystem.h index a74cbb9f..fdf1132b 100644 --- a/include/Game/Systems/PlayerSystem.h +++ b/include/Game/Systems/PlayerSystem.h @@ -11,8 +11,8 @@ class PlayerSystem : public PureSystem { public: - PlayerSystem(EventBroker* eventBroker) - : System(eventBroker) + PlayerSystem(World* world, EventBroker* eventBroker) + : System(world, eventBroker) , PureSystem("Player") { EVENT_SUBSCRIBE_MEMBER(m_ETouch, &PlayerSystem::OnTouch); @@ -20,7 +20,7 @@ public: EVENT_SUBSCRIBE_MEMBER(m_ELeave, &PlayerSystem::OnLeave); } - virtual void UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& component, double dt) override; + virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override; private: float m_Speed = 5; EventRelay m_EEnter; diff --git a/include/Game/Systems/RaptorCopterSystem.h b/include/Game/Systems/RaptorCopterSystem.h index 57a8de86..8bb18de6 100644 --- a/include/Game/Systems/RaptorCopterSystem.h +++ b/include/Game/Systems/RaptorCopterSystem.h @@ -4,14 +4,14 @@ class RaptorCopterSystem : public PureSystem { public: - RaptorCopterSystem(EventBroker* eventBroker) - : System(eventBroker) + RaptorCopterSystem(World* world, EventBroker* eventBroker) + : System(world, eventBroker) , PureSystem("RaptorCopter") { } - virtual void UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& component, double dt) override + virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) override { - ComponentWrapper& transform = world->GetComponent(component.EntityID, "Transform"); + ComponentWrapper& transform = m_World->GetComponent(component.EntityID, "Transform"); (glm::vec3&)transform["Orientation"] += (float)(double)component["Speed"] * (float)dt * (glm::vec3)component["Axis"]; } }; \ No newline at end of file diff --git a/include/Game/Systems/SpawnerSystem.h b/include/Game/Systems/SpawnerSystem.h index 2c094528..62f6b09a 100644 --- a/include/Game/Systems/SpawnerSystem.h +++ b/include/Game/Systems/SpawnerSystem.h @@ -13,7 +13,7 @@ class SpawnerSystem : public System { public: - SpawnerSystem(EventBroker* eventBroker); + SpawnerSystem(World* world, EventBroker* eventBroker); static EntityWrapper Spawn(EntityWrapper spawner, EntityWrapper parent = EntityWrapper::Invalid); diff --git a/src/Engine/Collision/CollidableOctreeSystem.cpp b/src/Engine/Collision/CollidableOctreeSystem.cpp index 62d742f5..e5da7910 100644 --- a/src/Engine/Collision/CollidableOctreeSystem.cpp +++ b/src/Engine/Collision/CollidableOctreeSystem.cpp @@ -1,11 +1,11 @@ #include "Collision/CollidableOctreeSystem.h" -void CollidableOctreeSystem::Update(World* world, double dt) +void CollidableOctreeSystem::Update(double dt) { m_Octree->ClearDynamicObjects(); } -void CollidableOctreeSystem::UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& component, double dt) +void CollidableOctreeSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) { if (entity.HasComponent("AABB")) { boost::optional absoluteAABB = Collision::EntityAbsoluteAABB(entity); diff --git a/src/Engine/Collision/CollisionSystem.cpp b/src/Engine/Collision/CollisionSystem.cpp index 96e49153..d4903c5e 100644 --- a/src/Engine/Collision/CollisionSystem.cpp +++ b/src/Engine/Collision/CollisionSystem.cpp @@ -2,7 +2,7 @@ #include "Collision/CollisionSystem.h" #include "Core/AABB.h" -void CollisionSystem::UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& component, double dt) +void CollisionSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) { if (!entity.HasComponent("Physics")) { return; diff --git a/src/Engine/Collision/TriggerSystem.cpp b/src/Engine/Collision/TriggerSystem.cpp index 58d1e332..20d30ae1 100644 --- a/src/Engine/Collision/TriggerSystem.cpp +++ b/src/Engine/Collision/TriggerSystem.cpp @@ -3,10 +3,10 @@ #include "Core/AABB.h" #include "Rendering/Model.h" -void TriggerSystem::UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& component, double dt) +void TriggerSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) { //Currently only players can trigger things. - auto players = world->GetComponents("Player"); + auto players = m_World->GetComponents("Player"); if (players == nullptr) { return; } @@ -18,7 +18,7 @@ void TriggerSystem::UpdateComponent(World* world, EntityWrapper& entity, Compone } for (auto& pc : *players) { EntityID pId = pc.EntityID; - boost::optional playerBox = Collision::EntityAbsoluteAABB(EntityWrapper(world, pId)); + boost::optional playerBox = Collision::EntityAbsoluteAABB(EntityWrapper(m_World, pId)); //The player can't trigger anything without an AABB. if (!playerBox) { continue; diff --git a/src/Engine/Core/UniformScaleSystem.cpp b/src/Engine/Core/UniformScaleSystem.cpp index 8cf670fc..ab954a05 100644 --- a/src/Engine/Core/UniformScaleSystem.cpp +++ b/src/Engine/Core/UniformScaleSystem.cpp @@ -1,13 +1,13 @@ #include "Core/UniformScaleSystem.h" -UniformScaleSystem::UniformScaleSystem(EventBroker* eventBroker) - : System(eventBroker) +UniformScaleSystem::UniformScaleSystem(World* world, EventBroker* eventBroker) + : System(world, eventBroker) , PureSystem("UniformScale") { EVENT_SUBSCRIBE_MEMBER(m_ESetCamera, &UniformScaleSystem::OnSetCamera); } -void UniformScaleSystem::UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& cUniformScale, double dt) +void UniformScaleSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cUniformScale, double dt) { if (!m_Camera.Valid()) { return; diff --git a/src/Engine/Editor/EditorRenderSystem.cpp b/src/Engine/Editor/EditorRenderSystem.cpp index 2d25338d..d320a198 100644 --- a/src/Engine/Editor/EditorRenderSystem.cpp +++ b/src/Engine/Editor/EditorRenderSystem.cpp @@ -1,7 +1,7 @@ #include "Editor/EditorRenderSystem.h" -EditorRenderSystem::EditorRenderSystem(EventBroker* eventBroker, IRenderer* renderer, RenderFrame* renderFrame) - : System(eventBroker) +EditorRenderSystem::EditorRenderSystem(World* m_World, EventBroker* eventBroker, IRenderer* renderer, RenderFrame* renderFrame) + : System(m_World, eventBroker) , m_Renderer(renderer) , m_RenderFrame(renderFrame) { @@ -10,7 +10,7 @@ EditorRenderSystem::EditorRenderSystem(EventBroker* eventBroker, IRenderer* rend m_EditorCamera = new Camera((float)resolution.Width / resolution.Height, glm::radians(45.f), 0.01f, 5000.f); } -void EditorRenderSystem::Update(World* world, double dt) +void EditorRenderSystem::Update(double dt) { if (m_CurrentCamera) { ComponentWrapper cameraTransform = m_CurrentCamera["Transform"]; @@ -23,7 +23,7 @@ void EditorRenderSystem::Update(World* world, double dt) scene.Camera = m_EditorCamera; scene.Viewport = Rectangle(1920, 1080); - auto models = world->GetComponents("Model"); + auto models = m_World->GetComponents("Model"); if (models != nullptr) { for (auto& cModel : *models) { if (!(bool)cModel["Visible"]) { @@ -45,7 +45,7 @@ void EditorRenderSystem::Update(World* world, double dt) } } - EntityWrapper entity(world, cModel.EntityID); + EntityWrapper entity(m_World, cModel.EntityID); glm::mat4 modelMatrix = Transform::ModelMatrix(entity.ID, entity.World); for (auto matGroup : model->MaterialGroups()) { std::shared_ptr modelJob = std::make_shared(model, nullptr, modelMatrix, matGroup, cModel, entity.World); @@ -54,7 +54,7 @@ void EditorRenderSystem::Update(World* world, double dt) } } - auto pointLights = world->GetComponents("PointLight"); + auto pointLights = m_World->GetComponents("PointLight"); if (pointLights != nullptr) { for (auto& cPointLight : *pointLights) { bool visible = cPointLight["Visible"]; @@ -62,7 +62,7 @@ void EditorRenderSystem::Update(World* world, double dt) continue; } - EntityWrapper entity(world, cPointLight.EntityID); + EntityWrapper entity(m_World, cPointLight.EntityID); ComponentWrapper& cTransform = entity["Transform"]; std::shared_ptr pointLightJob = std::make_shared(cTransform, cPointLight, entity.World); scene.PointLightJobs.push_back(pointLightJob); diff --git a/src/Engine/Editor/EditorSystem.cpp b/src/Engine/Editor/EditorSystem.cpp index b1e09422..64f16cc6 100644 --- a/src/Engine/Editor/EditorSystem.cpp +++ b/src/Engine/Editor/EditorSystem.cpp @@ -2,13 +2,13 @@ #include "Core/UniformScaleSystem.h" #include "Editor/EditorRenderSystem.h" -EditorSystem::EditorSystem(EventBroker* eventBroker, IRenderer* renderer, RenderFrame* renderFrame) - : System(eventBroker) +EditorSystem::EditorSystem(World* world, EventBroker* eventBroker, IRenderer* renderer, RenderFrame* renderFrame) + : System(world, eventBroker) , m_Renderer(renderer) , m_RenderFrame(renderFrame) { m_EditorWorld = new World(); - m_EditorWorldSystemPipeline = new SystemPipeline(eventBroker); + m_EditorWorldSystemPipeline = new SystemPipeline(m_EditorWorld, eventBroker); m_EditorWorldSystemPipeline->AddSystem(0); m_EditorWorldSystemPipeline->AddSystem(1, m_Renderer, m_RenderFrame); @@ -45,11 +45,11 @@ EditorSystem::~EditorSystem() delete m_EditorWorld; } -void EditorSystem::Update(World* world, double dt) +void EditorSystem::Update(double dt) { - m_EditorWorldSystemPipeline->Update(m_EditorWorld, dt); + m_EditorWorldSystemPipeline->Update(dt); - m_EditorGUI->Draw(world); + m_EditorGUI->Draw(m_World); m_EditorStats->Draw(dt); m_DebugCameraInputController->Update(dt); diff --git a/src/Engine/Editor/EditorSystemOld.cpp b/src/Engine/Editor/EditorSystemOld.cpp index 675ea80b..332bef05 100644 --- a/src/Engine/Editor/EditorSystemOld.cpp +++ b/src/Engine/Editor/EditorSystemOld.cpp @@ -2,8 +2,8 @@ #define IMGUI_DEFINE_MATH_OPERATORS #include -EditorSystemOld::EditorSystemOld(EventBroker* eventBroker, IRenderer* renderer) - : System(eventBroker) +EditorSystemOld::EditorSystemOld(World* world, EventBroker* eventBroker, IRenderer* renderer) + : System(world, eventBroker) , ImpureSystem() , m_Renderer(renderer) { @@ -23,10 +23,8 @@ EditorSystemOld::EditorSystemOld(EventBroker* eventBroker, IRenderer* renderer) EVENT_SUBSCRIBE_MEMBER(m_EFileDropped, &EditorSystemOld::OnFileDropped); } -void EditorSystemOld::Update(World* world, double dt) +void EditorSystemOld::Update(double dt) { - m_World = world; - if (!m_Enabled) { return; } @@ -37,7 +35,7 @@ void EditorSystemOld::Update(World* world, double dt) Picking(); updateWidget(); - drawUI(world, dt); + drawUI(m_World, dt); // Clear drop queue if it wasn't handled by any UI element if (!m_LastDroppedFile.empty()) { diff --git a/src/Engine/Rendering/RenderSystem.cpp b/src/Engine/Rendering/RenderSystem.cpp index 2af782e3..7b26bdad 100644 --- a/src/Engine/Rendering/RenderSystem.cpp +++ b/src/Engine/Rendering/RenderSystem.cpp @@ -1,7 +1,7 @@ #include "Rendering/RenderSystem.h" -RenderSystem::RenderSystem(EventBroker* eventBroker, const IRenderer* renderer, RenderFrame* renderFrame) - : System(eventBroker) +RenderSystem::RenderSystem(World* world, EventBroker* eventBroker, const IRenderer* renderer, RenderFrame* renderFrame) + : System(world, eventBroker) , m_Renderer(renderer) , m_RenderFrame(renderFrame) { @@ -29,9 +29,9 @@ bool RenderSystem::OnSetCamera(Events::SetCamera& e) return true; } -void RenderSystem::fillModels(std::list>& jobs, World* world) +void RenderSystem::fillModels(std::list>& jobs) { - auto models = world->GetComponents("Model"); + auto models = m_World->GetComponents("Model"); if (models == nullptr) { return; } @@ -60,17 +60,17 @@ void RenderSystem::fillModels(std::list>& jobs, World } } - glm::mat4 modelMatrix = Transform::ModelMatrix(modelComponent.EntityID, world); + glm::mat4 modelMatrix = Transform::ModelMatrix(modelComponent.EntityID, m_World); for (auto matGroup : model->MaterialGroups()) { - std::shared_ptr modelJob = std::shared_ptr(new ModelJob(model, m_Camera, modelMatrix, matGroup, modelComponent, world)); + std::shared_ptr modelJob = std::shared_ptr(new ModelJob(model, m_Camera, modelMatrix, matGroup, modelComponent, m_World)); jobs.push_back(modelJob); } } } -void RenderSystem::fillLight(std::list>& jobs, World* world) +void RenderSystem::fillLight(std::list>& jobs) { - auto pointLights = world->GetComponents("PointLight"); + auto pointLights = m_World->GetComponents("PointLight"); if (pointLights == nullptr) { return; } @@ -80,7 +80,7 @@ void RenderSystem::fillLight(std::list>& jobs, World* if (!visible) { continue; } - auto transformC = world->GetComponent(pointlightC.EntityID, "Transform"); + auto transformC = m_World->GetComponent(pointlightC.EntityID, "Transform"); if (&transformC == nullptr) { return; } @@ -95,9 +95,8 @@ bool RenderSystem::OnInputCommand(const Events::InputCommand& e) return false; } -void RenderSystem::Update(World* world, double dt) +void RenderSystem::Update(double dt) { - m_World = world; m_EventBroker->Process(); if (m_CurrentCamera) { @@ -110,8 +109,8 @@ void RenderSystem::Update(World* world, double dt) RenderScene scene; scene.Camera = m_Camera; scene.Viewport = Rectangle(1280, 720); - fillModels(scene.ForwardJobs, world); - fillLight(scene.PointLightJobs, world); + fillModels(scene.ForwardJobs); + fillLight(scene.PointLightJobs); m_RenderFrame->Add(scene); } \ No newline at end of file diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index 5be95802..d60863bb 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -71,7 +71,7 @@ Game::Game(int argc, char* argv[]) m_OctreeCollision = new Octree(AABB(glm::vec3(-100), glm::vec3(100)), 4); m_OctreeFrustrumCulling = new Octree(AABB(glm::vec3(-100), glm::vec3(100)), 4); // Create system pipeline - m_SystemPipeline = new SystemPipeline(m_EventBroker); + m_SystemPipeline = new SystemPipeline(m_World, m_EventBroker); // All systems with orderlevel 0 will be updated first. unsigned int updateOrderLevel = 0; @@ -143,7 +143,7 @@ void Game::Tick() m_ClientOrServer->Update(); } // Iterate through systems and update world! - m_SystemPipeline->Update(m_World, dt); + m_SystemPipeline->Update(dt); debugTick(dt); m_Renderer->Update(dt); m_EventBroker->Process(); diff --git a/src/Game/Systems/HealthSystem.cpp b/src/Game/Systems/HealthSystem.cpp index b6d46dc9..e1cb9175 100644 --- a/src/Game/Systems/HealthSystem.cpp +++ b/src/Game/Systems/HealthSystem.cpp @@ -1,7 +1,7 @@ #include "Systems/HealthSystem.h" -HealthSystem::HealthSystem(EventBroker* eventBroker) - : System(eventBroker) +HealthSystem::HealthSystem(World* m_World, EventBroker* eventBroker) + : System(m_World, eventBroker) , PureSystem("Health") { //subscribe/listenTo playerdamage,healthpickup events (using the eventBroker) @@ -9,10 +9,10 @@ HealthSystem::HealthSystem(EventBroker* eventBroker) EVENT_SUBSCRIBE_MEMBER(m_EPlayerHealthPickup, &HealthSystem::OnPlayerHealthPickup); } -void HealthSystem::UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& component, double dt) +void HealthSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) { //if entityID of health is 9 then the players ID is also 9 (player,health are connected to the same entity) - ComponentWrapper player = world->GetComponent(component.EntityID, "Player"); + ComponentWrapper player = m_World->GetComponent(component.EntityID, "Player"); double maxHealth = (double)component["MaxHealth"]; //process the DeltaHealthVector and change the entitys health accordingly diff --git a/src/Game/Systems/PlayerMovementSystem.cpp b/src/Game/Systems/PlayerMovementSystem.cpp index 536624b3..6f419b46 100644 --- a/src/Game/Systems/PlayerMovementSystem.cpp +++ b/src/Game/Systems/PlayerMovementSystem.cpp @@ -1,6 +1,6 @@ #include "Systems/PlayerMovementSystem.h" -void PlayerMovementSystem::UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& component, double dt) +void PlayerMovementSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) { ComponentWrapper& cTransform = entity["Transform"]; if (!entity.HasComponent("Physics")) { diff --git a/src/Game/Systems/PlayerSpawnSystem.cpp b/src/Game/Systems/PlayerSpawnSystem.cpp index 0bf5bdea..4224d46c 100644 --- a/src/Game/Systems/PlayerSpawnSystem.cpp +++ b/src/Game/Systems/PlayerSpawnSystem.cpp @@ -1,21 +1,21 @@ #include "Systems/PlayerSpawnSystem.h" -PlayerSpawnSystem::PlayerSpawnSystem(EventBroker* eventBroker) - : System(eventBroker) +PlayerSpawnSystem::PlayerSpawnSystem(World* m_World, EventBroker* eventBroker) + : System(m_World, eventBroker) { EVENT_SUBSCRIBE_MEMBER(m_OnInputCommand, &PlayerSpawnSystem::OnInputCommand); } -void PlayerSpawnSystem::Update(World* world, double dt) +void PlayerSpawnSystem::Update(double dt) { - auto playerSpawns = world->GetComponents("PlayerSpawn"); + auto playerSpawns = m_World->GetComponents("PlayerSpawn"); if (playerSpawns == nullptr) { return; } for (auto& team : m_SpawnRequests) { for (auto& cPlayerSpawn : *playerSpawns) { - EntityWrapper spawner(world, cPlayerSpawn.EntityID); + EntityWrapper spawner(m_World, cPlayerSpawn.EntityID); if (!spawner.HasComponent("Spawner")) { continue; } diff --git a/src/Game/Systems/PlayerSystem.cpp b/src/Game/Systems/PlayerSystem.cpp index 8cdddf84..a4970ba9 100644 --- a/src/Game/Systems/PlayerSystem.cpp +++ b/src/Game/Systems/PlayerSystem.cpp @@ -1,6 +1,6 @@ #include "Systems/PlayerSystem.h" -void PlayerSystem::UpdateComponent(World* world, EntityWrapper& entity, ComponentWrapper& component, double dt) +void PlayerSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& component, double dt) { component["Velocity"] = glm::vec3(0.f, 0.f, 0.f); if ((bool&)component["Forward"] == true) { @@ -18,7 +18,7 @@ void PlayerSystem::UpdateComponent(World* world, EntityWrapper& entity, Componen } if ((glm::vec3)component["Velocity"] != glm::vec3(0.f)) { - ComponentWrapper& transform = world->GetComponent(component.EntityID, "Transform"); + ComponentWrapper& transform = m_World->GetComponent(component.EntityID, "Transform"); (glm::vec3&)transform["Position"] += (glm::vec3)component["Velocity"]; } } diff --git a/src/Game/Systems/SpawnerSystem.cpp b/src/Game/Systems/SpawnerSystem.cpp index 3454c58b..8cb5b99d 100644 --- a/src/Game/Systems/SpawnerSystem.cpp +++ b/src/Game/Systems/SpawnerSystem.cpp @@ -1,6 +1,7 @@ #include "Systems/SpawnerSystem.h" -SpawnerSystem::SpawnerSystem(EventBroker* eventBroker) : System(eventBroker) +SpawnerSystem::SpawnerSystem(World* world, EventBroker* eventBroker) + : System(world, eventBroker) { EVENT_SUBSCRIBE_MEMBER(m_OnSpawnerSpawn, &SpawnerSystem::OnSpawnerSpawn); } diff --git a/src/Tests/HealthSystemTest.cpp b/src/Tests/HealthSystemTest.cpp index 84d6199d..347d8071 100644 --- a/src/Tests/HealthSystemTest.cpp +++ b/src/Tests/HealthSystemTest.cpp @@ -102,7 +102,7 @@ void GameHealthSystemTest::Tick() m_LastTime = currentTime; // Iterate through systems and update world! - m_SystemPipeline->Update(m_World, dt); + m_SystemPipeline->Update(dt); m_EventBroker->Swap(); m_EventBroker->Clear(); diff --git a/src/Tests/OctTreeTestGameClass.cpp b/src/Tests/OctTreeTestGameClass.cpp index 2c45d897..f125f425 100644 --- a/src/Tests/OctTreeTestGameClass.cpp +++ b/src/Tests/OctTreeTestGameClass.cpp @@ -179,7 +179,7 @@ void Game::Tick() #endif // Iterate through systems and update world! - m_SystemPipeline->Update(m_World, dt); + m_SystemPipeline->Update(dt); m_Renderer->Update(dt); m_RenderQueueFactory->Update(m_World); From 79eaa7364c9ae5ca72cce9b9bfa28215a081e2e3 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Mon, 18 Jan 2016 23:59:46 +0100 Subject: [PATCH 16/38] Editor toolbox buttons --- assets | 2 +- src/Engine/Editor/EditorGUI.cpp | 32 +++++++++++++++++++++++++------- 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/assets b/assets index a1bb17db..e794bef3 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit a1bb17dbe0da3d55932c2e187da50bc0257691f4 +Subproject commit e794bef3a75ddcfb9bd87c1bd0f439c72e81036f diff --git a/src/Engine/Editor/EditorGUI.cpp b/src/Engine/Editor/EditorGUI.cpp index 94aaceb4..b7a7fbb9 100644 --- a/src/Engine/Editor/EditorGUI.cpp +++ b/src/Engine/Editor/EditorGUI.cpp @@ -36,22 +36,39 @@ void EditorGUI::drawTools() GLuint translateIcon = 0; try { - translateIcon = ResourceManager::Load("Textures/Icons/shaft.png")->m_Texture; + translateIcon = ResourceManager::Load("Textures/Icons/Translate.png")->m_Texture; } catch (const std::exception&) { } GLuint rotateIcon = 0; try { - rotateIcon = ResourceManager::Load("Textures/Icons/circulararrows3.png")->m_Texture; + rotateIcon = ResourceManager::Load("Textures/Icons/Rotate.png")->m_Texture; } catch (const std::exception&) { } GLuint scaleIcon = 0; try { - scaleIcon = ResourceManager::Load("Textures/Icons/increase10.png")->m_Texture; + scaleIcon = ResourceManager::Load("Textures/Icons/Scale.png")->m_Texture; } catch (const std::exception&) { } - ImGui::ImageButton((void*)translateIcon, ImVec2(24, 24)); + ImGui::ImageButton((void*)translateIcon, ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0)); ImGui::SameLine(); - ImGui::ImageButton((void*)rotateIcon, ImVec2(24, 24)); + ImGui::ImageButton((void*)rotateIcon, ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0)); ImGui::SameLine(); - ImGui::ImageButton((void*)scaleIcon, ImVec2(24, 24)); + ImGui::ImageButton((void*)scaleIcon, ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0)); + ImGui::SameLine(); + ImGui::ItemSize(ImVec2(5, 0)); + ImGui::SameLine(); + + GLuint playIcon = 0; + try { + playIcon = ResourceManager::Load("Textures/Icons/Play.png")->m_Texture; + } catch (const std::exception&) { } + GLuint pauseIcon = 0; + try { + pauseIcon = ResourceManager::Load("Textures/Icons/Pause.png")->m_Texture; + } catch (const std::exception&) { } + + + ImGui::ImageButton((void*)playIcon, ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0), -1, ImVec4(0, 0, 0, 0), ImVec4(0, 1, 0, 1)); + ImGui::SameLine(); + ImGui::ImageButton((void*)pauseIcon, ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0)); ImGui::End(); } @@ -169,8 +186,9 @@ void EditorGUI::drawComponents(EntityWrapper entity) std::stringstream title; title << "Components"; if (entity.Valid()) { - title << formatEntityName(entity) << "###Components"; + title << " " << formatEntityName(entity); } + title << "###Components"; if (!ImGui::Begin(title.str().c_str())) { ImGui::End(); return; From 9e3dfff7b6c86a2d5b3e205d43661187ff6cd45d Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Tue, 19 Jan 2016 00:52:17 +0100 Subject: [PATCH 17/38] WIP world pausing --- include/Engine/Core/EPause.h | 22 ++++++++++++++++++++++ include/Engine/Core/SystemPipeline.h | 26 +++++++++++++++++++++++++- include/Engine/Editor/EditorGUI.h | 6 ++++-- src/Engine/Editor/EditorGUI.cpp | 25 ++++++++++++++++++------- src/Engine/Editor/EditorSystem.cpp | 4 ++-- src/Game/Game.cpp | 2 +- 6 files changed, 72 insertions(+), 13 deletions(-) create mode 100644 include/Engine/Core/EPause.h diff --git a/include/Engine/Core/EPause.h b/include/Engine/Core/EPause.h new file mode 100644 index 00000000..5aca36d8 --- /dev/null +++ b/include/Engine/Core/EPause.h @@ -0,0 +1,22 @@ +#ifndef EPause_h__ +#define EPause_h__ + +#include "EventBroker.h" +#include "World.h" + +namespace Events +{ + +struct Pause : Event +{ + ::World* World; +}; + +struct Resume : Event +{ + ::World* World; +}; + +} + +#endif \ No newline at end of file diff --git a/include/Engine/Core/SystemPipeline.h b/include/Engine/Core/SystemPipeline.h index cc3c98e9..90303f12 100644 --- a/include/Engine/Core/SystemPipeline.h +++ b/include/Engine/Core/SystemPipeline.h @@ -5,6 +5,7 @@ #include "EventBroker.h" #include "System.h" #include "World.h" +#include "EPause.h" class SystemPipeline { @@ -12,7 +13,10 @@ public: SystemPipeline(World* world, EventBroker* eventBroker) : m_World(world) , m_EventBroker(eventBroker) - { } + { + EVENT_SUBSCRIBE_MEMBER(m_EPause, &SystemPipeline::OnPause); + EVENT_SUBSCRIBE_MEMBER(m_EResume, &SystemPipeline::OnResume); + } ~SystemPipeline() { @@ -51,6 +55,10 @@ public: void Update(double dt) { + if (m_Paused) { + dt = 0.0; + } + for (UnorderedSystems& group : m_OrderedSystemGroups) { // Process events for (auto& pair : group.Systems) { @@ -80,6 +88,7 @@ public: private: World* m_World; EventBroker* m_EventBroker; + bool m_Paused = false; struct UnorderedSystems { @@ -88,6 +97,21 @@ private: std::vector ImpureSystems; }; std::vector m_OrderedSystemGroups; + + EventRelay m_EPause; + bool OnPause(const Events::Pause& e) { + if (e.World == m_World) { + m_Paused = true; + } + return true; + } + EventRelay m_EResume; + bool OnResume(const Events::Resume& e) { + if (e.World == m_World) { + m_Paused = false; + } + return true; + } }; #endif \ No newline at end of file diff --git a/include/Engine/Editor/EditorGUI.h b/include/Engine/Editor/EditorGUI.h index 917d216f..7e36f211 100644 --- a/include/Engine/Editor/EditorGUI.h +++ b/include/Engine/Editor/EditorGUI.h @@ -14,14 +14,15 @@ #include "../Core/World.h" #include "../Core/EntityWrapper.h" #include "../Core/ResourceManager.h" +#include "../Core/EPause.h" #include "../Rendering/Texture.h" class EditorGUI { public: - EditorGUI(EventBroker* eventBroker); + EditorGUI(World* world, EventBroker* eventBroker); - void Draw(World* world); + void Draw(); void SelectEntity(EntityWrapper entity); @@ -57,6 +58,7 @@ public: void SetComponentDeleteCallback(OnComponentDelete_t f) { m_OnComponentDelete = f; } private: + World* m_World; EventBroker* m_EventBroker; // Config variables diff --git a/src/Engine/Editor/EditorGUI.cpp b/src/Engine/Editor/EditorGUI.cpp index b7a7fbb9..e3c714bd 100644 --- a/src/Engine/Editor/EditorGUI.cpp +++ b/src/Engine/Editor/EditorGUI.cpp @@ -1,17 +1,18 @@ #include "Editor/EditorGUI.h" -EditorGUI::EditorGUI(EventBroker* eventBroker) - : m_EventBroker(eventBroker) +EditorGUI::EditorGUI(World* world, EventBroker* eventBroker) + : m_World(world) + , m_EventBroker(eventBroker) { } -void EditorGUI::Draw(World* world) +void EditorGUI::Draw() { ImGui::ShowTestWindow(); drawMenu(); drawTools(); - drawEntities(world); + drawEntities(m_World); drawComponents(m_CurrentSelection); } @@ -65,10 +66,20 @@ void EditorGUI::drawTools() pauseIcon = ResourceManager::Load("Textures/Icons/Pause.png")->m_Texture; } catch (const std::exception&) { } - - ImGui::ImageButton((void*)playIcon, ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0), -1, ImVec4(0, 0, 0, 0), ImVec4(0, 1, 0, 1)); + static bool paused = false; + if (ImGui::ImageButton((void*)playIcon, ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0), -1, ImVec4(0, 0, 0, 0), (!paused) ? ImVec4(0, 1, 0, 1) : ImVec4(1, 1, 1, 1))) { + Events::Resume e; + e.World = m_World; + m_EventBroker->Publish(e); + paused = false; + } ImGui::SameLine(); - ImGui::ImageButton((void*)pauseIcon, ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0)); + if (ImGui::ImageButton((void*)pauseIcon, ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0), -1, ImVec4(0, 0, 0, 0), (paused) ? ImVec4(0, 1, 0, 1) : ImVec4(1, 1, 1, 1))) { + Events::Pause e; + e.World = m_World; + m_EventBroker->Publish(e); + paused = true; + } ImGui::End(); } diff --git a/src/Engine/Editor/EditorSystem.cpp b/src/Engine/Editor/EditorSystem.cpp index 64f16cc6..05e9974b 100644 --- a/src/Engine/Editor/EditorSystem.cpp +++ b/src/Engine/Editor/EditorSystem.cpp @@ -19,7 +19,7 @@ EditorSystem::EditorSystem(World* world, EventBroker* eventBroker, IRenderer* re m_EditorWorld->AttachComponent(m_Camera.ID, "Camera"); m_DebugCameraInputController = new DebugCameraInputController(m_EventBroker, -1); - m_EditorGUI = new EditorGUI(m_EventBroker); + m_EditorGUI = new EditorGUI(m_World, m_EventBroker); m_EditorGUI->SetEntitySelectedCallback(std::bind(&EditorSystem::OnEntitySelected, this, std::placeholders::_1)); m_EditorGUI->SetEntityImportCallback(std::bind(&EditorSystem::importEntity, this, std::placeholders::_1, std::placeholders::_2)); m_EditorGUI->SetEntitySaveCallback(std::bind(&EditorSystem::OnEntitySave, this, std::placeholders::_1, std::placeholders::_2)); @@ -49,7 +49,7 @@ void EditorSystem::Update(double dt) { m_EditorWorldSystemPipeline->Update(dt); - m_EditorGUI->Draw(m_World); + m_EditorGUI->Draw(); m_EditorStats->Draw(dt); m_DebugCameraInputController->Update(dt); diff --git a/src/Game/Game.cpp b/src/Game/Game.cpp index d60863bb..0f6d3dc5 100644 --- a/src/Game/Game.cpp +++ b/src/Game/Game.cpp @@ -27,7 +27,6 @@ Game::Game(int argc, char* argv[]) // Create the core event broker m_EventBroker = new EventBroker(); - // Create the renderer m_Renderer = new Renderer(m_EventBroker, m_World); m_Renderer->SetFullscreen(m_Config->Get("Video.Fullscreen", false)); @@ -143,6 +142,7 @@ void Game::Tick() m_ClientOrServer->Update(); } // Iterate through systems and update world! + m_EventBroker->Process(); m_SystemPipeline->Update(dt); debugTick(dt); m_Renderer->Update(dt); From b62e42567cd35ed23dbfdee59114b3f3d9151a7f Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Tue, 19 Jan 2016 11:35:31 +0100 Subject: [PATCH 18/38] Fixed editor enum selection --- src/Engine/Editor/EditorGUI.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Engine/Editor/EditorGUI.cpp b/src/Engine/Editor/EditorGUI.cpp index e3c714bd..d0a6fd05 100644 --- a/src/Engine/Editor/EditorGUI.cpp +++ b/src/Engine/Editor/EditorGUI.cpp @@ -367,6 +367,7 @@ void EditorGUI::drawComponentField_enum(ComponentWrapper &c, const ComponentInfo if (val == kv.second) { selectedItem = i; } + i++; } if (ImGui::Combo("", &selectedItem, enumKeys.str().c_str())) { val = enumValues.at(selectedItem); From 68af853a03a3d31550156e6cbfdeba47c911dccf Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Tue, 19 Jan 2016 11:42:26 +0100 Subject: [PATCH 19/38] Editor entity naming --- include/Engine/Editor/EditorGUI.h | 4 ++++ include/Engine/Editor/EditorSystem.h | 1 + src/Engine/Editor/EditorGUI.cpp | 27 ++++++++++++++++++++++++++- src/Engine/Editor/EditorSystem.cpp | 6 ++++++ 4 files changed, 37 insertions(+), 1 deletion(-) diff --git a/include/Engine/Editor/EditorGUI.h b/include/Engine/Editor/EditorGUI.h index 7e36f211..f28b95cf 100644 --- a/include/Engine/Editor/EditorGUI.h +++ b/include/Engine/Editor/EditorGUI.h @@ -50,6 +50,9 @@ public: // Called when the user means to change the parent of an entity. typedef std::function OnEntityChangeParent_t; void SetEntityChangeParentCallback(OnEntityChangeParent_t f) { m_OnEntityChangeParent = f; } + // Called when the user means to rename an entity. + typedef std::function OnEntityChangeName_t; + void SetEntityChangeNameCallback(OnEntityChangeName_t f) { m_OnEntityChangeName = f; } // Called when the user means to attach a new component to an entity. typedef std::function OnComponentAttach_t; void SetComponentAttachCallback(OnComponentAttach_t f) { m_OnComponentAttach = f; } @@ -77,6 +80,7 @@ private: OnEntityCreate_t m_OnEntityCreate = nullptr; OnEntityDelete_t m_OnEntityDelete = nullptr; OnEntityChangeParent_t m_OnEntityChangeParent = nullptr; + OnEntityChangeName_t m_OnEntityChangeName = nullptr; OnComponentAttach_t m_OnComponentAttach = nullptr; OnComponentDelete_t m_OnComponentDelete = nullptr; diff --git a/include/Engine/Editor/EditorSystem.h b/include/Engine/Editor/EditorSystem.h index 8ae3ac2e..c0db917d 100644 --- a/include/Engine/Editor/EditorSystem.h +++ b/include/Engine/Editor/EditorSystem.h @@ -41,6 +41,7 @@ private: EntityWrapper OnEntityCreate(EntityWrapper parent); void OnEntityDelete(EntityWrapper entity); void OnEntityChangeParent(EntityWrapper entity, EntityWrapper parent); + void OnEntityChangeName(EntityWrapper entity, const std::string& name); void OnComponentAttach(EntityWrapper entity, const std::string& componentType); void OnComponentDelete(EntityWrapper entity, const std::string& componentType); }; \ No newline at end of file diff --git a/src/Engine/Editor/EditorGUI.cpp b/src/Engine/Editor/EditorGUI.cpp index d0a6fd05..68a136c3 100644 --- a/src/Engine/Editor/EditorGUI.cpp +++ b/src/Engine/Editor/EditorGUI.cpp @@ -101,6 +101,31 @@ void EditorGUI::drawEntities(World* world) ImGui::SameLine(0.f, 5.f); ImGui::Button("Reference", ImVec2(buttonWidth, 0)); + // Naming + char buffer[256]; + buffer[0] = '\0'; + buffer[255] = '\0'; + std::size_t nameLength = 0; + ImGuiInputTextFlags flags = ImGuiInputTextFlags_CharsNoBlank | ImGuiInputTextFlags_AutoSelectAll; + if (m_CurrentSelection.Valid()) { + std::string name = world->GetName(m_CurrentSelection.ID); + nameLength = name.length(); + if (!name.empty()) { + memcpy(buffer, name.c_str(), std::min(sizeof(buffer) - 1, name.length() + 1)); + } + } else { + flags |= ImGuiInputTextFlags_ReadOnly; + } + ImGui::PushItemWidth(ImGui::GetContentRegionAvailWidth() - 7.f); + if (ImGui::InputText("", &buffer[0], sizeof(buffer), flags)) { + if (m_CurrentSelection.Valid()) { + if (m_OnEntityChangeName != nullptr) { + m_OnEntityChangeName(m_CurrentSelection, std::string(buffer)); + } + } + } + ImGui::PopItemWidth(); + ImGui::ItemSize(ImVec2(0, 3)); drawEntitiesRecursive(world, EntityID_Invalid); @@ -487,7 +512,7 @@ const std::string EditorGUI::formatEntityName(EntityWrapper entity) std::stringstream name; - const std::string& entityName = entity.World->GetName(entity); + std::string entityName = entity.World->GetName(entity.ID); if (!entityName.empty()) { name << entityName; } else { diff --git a/src/Engine/Editor/EditorSystem.cpp b/src/Engine/Editor/EditorSystem.cpp index 05e9974b..36f2baa4 100644 --- a/src/Engine/Editor/EditorSystem.cpp +++ b/src/Engine/Editor/EditorSystem.cpp @@ -26,6 +26,7 @@ EditorSystem::EditorSystem(World* world, EventBroker* eventBroker, IRenderer* re m_EditorGUI->SetEntityCreateCallback(std::bind(&EditorSystem::OnEntityCreate, this, std::placeholders::_1)); m_EditorGUI->SetEntityDeleteCallback(std::bind(&EditorSystem::OnEntityDelete, this, std::placeholders::_1)); m_EditorGUI->SetEntityChangeParentCallback(std::bind(&EditorSystem::OnEntityChangeParent, this, std::placeholders::_1, std::placeholders::_2)); + m_EditorGUI->SetEntityChangeNameCallback(std::bind(&EditorSystem::OnEntityChangeName, this, std::placeholders::_1, std::placeholders::_2)); m_EditorGUI->SetComponentAttachCallback(std::bind(&EditorSystem::OnComponentAttach, this, std::placeholders::_1, std::placeholders::_2)); m_EditorGUI->SetComponentDeleteCallback(std::bind(&EditorSystem::OnComponentDelete, this, std::placeholders::_1, std::placeholders::_2)); @@ -85,6 +86,11 @@ void EditorSystem::OnEntityChangeParent(EntityWrapper entity, EntityWrapper pare entity.World->SetParent(entity.ID, parent.ID); } +void EditorSystem::OnEntityChangeName(EntityWrapper entity, const std::string& name) +{ + entity.World->SetName(entity.ID, name); +} + void EditorSystem::OnComponentAttach(EntityWrapper entity, const std::string& componentType) { entity.World->AttachComponent(entity.ID, componentType); From 267a60ef305cf411f42866e2d4d0a13b5754f21a Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Tue, 19 Jan 2016 11:43:38 +0100 Subject: [PATCH 20/38] Better loading of editor toolbox icons --- include/Engine/Editor/EditorGUI.h | 1 + src/Engine/Editor/EditorGUI.cpp | 51 +++++++++++++------------------ 2 files changed, 23 insertions(+), 29 deletions(-) diff --git a/include/Engine/Editor/EditorGUI.h b/include/Engine/Editor/EditorGUI.h index f28b95cf..9d2712e1 100644 --- a/include/Engine/Editor/EditorGUI.h +++ b/include/Engine/Editor/EditorGUI.h @@ -88,6 +88,7 @@ private: boost::filesystem::path fileOpenDialog(); boost::filesystem::path fileSaveDialog(); const std::string formatEntityName(EntityWrapper entity); + GLuint tryLoadTexture(std::string filePath); // Entity file handling methods void entityImport(World* world); diff --git a/src/Engine/Editor/EditorGUI.cpp b/src/Engine/Editor/EditorGUI.cpp index 68a136c3..1bf0f9e9 100644 --- a/src/Engine/Editor/EditorGUI.cpp +++ b/src/Engine/Editor/EditorGUI.cpp @@ -35,46 +35,30 @@ void EditorGUI::drawTools() return; } - GLuint translateIcon = 0; - try { - translateIcon = ResourceManager::Load("Textures/Icons/Translate.png")->m_Texture; - } catch (const std::exception&) { } - GLuint rotateIcon = 0; - try { - rotateIcon = ResourceManager::Load("Textures/Icons/Rotate.png")->m_Texture; - } catch (const std::exception&) { } - GLuint scaleIcon = 0; - try { - scaleIcon = ResourceManager::Load("Textures/Icons/Scale.png")->m_Texture; - } catch (const std::exception&) { } + // Translate widget button + ImGui::ImageButton((void*)tryLoadTexture("Textures/Icons/Translate.png"), ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0)); + // Rotate widget button + ImGui::SameLine(); + ImGui::ImageButton((void*)tryLoadTexture("Textures/Icons/Rotate.png"), ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0)); + // Scale widget button + ImGui::SameLine(); + ImGui::ImageButton((void*)tryLoadTexture("Textures/Icons/Scale.png"), ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0)); - ImGui::ImageButton((void*)translateIcon, ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0)); - ImGui::SameLine(); - ImGui::ImageButton((void*)rotateIcon, ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0)); - ImGui::SameLine(); - ImGui::ImageButton((void*)scaleIcon, ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0)); ImGui::SameLine(); ImGui::ItemSize(ImVec2(5, 0)); + + // Play button ImGui::SameLine(); - - GLuint playIcon = 0; - try { - playIcon = ResourceManager::Load("Textures/Icons/Play.png")->m_Texture; - } catch (const std::exception&) { } - GLuint pauseIcon = 0; - try { - pauseIcon = ResourceManager::Load("Textures/Icons/Pause.png")->m_Texture; - } catch (const std::exception&) { } - static bool paused = false; - if (ImGui::ImageButton((void*)playIcon, ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0), -1, ImVec4(0, 0, 0, 0), (!paused) ? ImVec4(0, 1, 0, 1) : ImVec4(1, 1, 1, 1))) { + if (ImGui::ImageButton((void*)tryLoadTexture("Textures/Icons/Play.png"), ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0), -1, ImVec4(0, 0, 0, 0), (!paused) ? ImVec4(0, 1, 0, 1) : ImVec4(1, 1, 1, 1))) { Events::Resume e; e.World = m_World; m_EventBroker->Publish(e); paused = false; } + // Pause button ImGui::SameLine(); - if (ImGui::ImageButton((void*)pauseIcon, ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0), -1, ImVec4(0, 0, 0, 0), (paused) ? ImVec4(0, 1, 0, 1) : ImVec4(1, 1, 1, 1))) { + if (ImGui::ImageButton((void*)tryLoadTexture("Textures/Icons/Pause.png"), ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0), -1, ImVec4(0, 0, 0, 0), (paused) ? ImVec4(0, 1, 0, 1) : ImVec4(1, 1, 1, 1))) { Events::Pause e; e.World = m_World; m_EventBroker->Publish(e); @@ -526,6 +510,15 @@ const std::string EditorGUI::formatEntityName(EntityWrapper entity) return name.str(); } +GLuint EditorGUI::tryLoadTexture(std::string filePath) +{ + GLuint texture = 0; + try { + texture = ResourceManager::Load(filePath)->m_Texture; + } catch (const std::exception&) { } + return texture; +} + void EditorGUI::entityImport(World* world) { boost::filesystem::path filePath = fileOpenDialog(); From 3fb975a8d968da9c70d6ae0d79d75b352dced998 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Tue, 19 Jan 2016 11:44:03 +0100 Subject: [PATCH 21/38] Editor widget entities --- resources/Schema/Components.xsd | 1 + resources/Schema/Components/EditorWidget.xml | 5 + resources/Schema/Components/EditorWidget.xsd | 27 +++++ .../Schema/Entities/EditorWidgetRotate.xml | 57 ++++++++++ .../Schema/Entities/EditorWidgetScale.xml | 62 +++++++++++ .../Schema/Entities/EditorWidgetTranslate.xml | 101 ++++++++++++++++++ resources/Schema/Types/Entity.xsd | 1 + 7 files changed, 254 insertions(+) create mode 100644 resources/Schema/Components/EditorWidget.xml create mode 100644 resources/Schema/Components/EditorWidget.xsd create mode 100644 resources/Schema/Entities/EditorWidgetRotate.xml create mode 100644 resources/Schema/Entities/EditorWidgetScale.xml create mode 100644 resources/Schema/Entities/EditorWidgetTranslate.xml diff --git a/resources/Schema/Components.xsd b/resources/Schema/Components.xsd index b9c8647c..f129b9f3 100644 --- a/resources/Schema/Components.xsd +++ b/resources/Schema/Components.xsd @@ -19,4 +19,5 @@ + \ No newline at end of file diff --git a/resources/Schema/Components/EditorWidget.xml b/resources/Schema/Components/EditorWidget.xml new file mode 100644 index 00000000..6a94d2f6 --- /dev/null +++ b/resources/Schema/Components/EditorWidget.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/resources/Schema/Components/EditorWidget.xsd b/resources/Schema/Components/EditorWidget.xsd new file mode 100644 index 00000000..e4c4ff71 --- /dev/null +++ b/resources/Schema/Components/EditorWidget.xsd @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/EditorWidgetRotate.xml b/resources/Schema/Entities/EditorWidgetRotate.xml new file mode 100644 index 00000000..fc41b596 --- /dev/null +++ b/resources/Schema/Entities/EditorWidgetRotate.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + 2 + + + + Models/RotationWidgetX.obj + + + + + + + + + 2 + + + + Models/RotationWidgetY.obj + + + + + + + + + 2 + + + + Models/RotationWidgetZ.obj + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/EditorWidgetScale.xml b/resources/Schema/Entities/EditorWidgetScale.xml new file mode 100644 index 00000000..f4c44d66 --- /dev/null +++ b/resources/Schema/Entities/EditorWidgetScale.xml @@ -0,0 +1,62 @@ + + + + + + Models/ScaleWidgetOrigin.obj + + + + + + + + + 3 + + + + Models/ScaleWidgetX.obj + + + + + + + + + 3 + + + + Models/ScaleWidgetY.obj + + + + + + + + + 3 + + + + Models/ScaleWidgetZ.obj + + + + + + + + + + + + + + + + + diff --git a/resources/Schema/Entities/EditorWidgetTranslate.xml b/resources/Schema/Entities/EditorWidgetTranslate.xml new file mode 100644 index 00000000..bc43538d --- /dev/null +++ b/resources/Schema/Entities/EditorWidgetTranslate.xml @@ -0,0 +1,101 @@ + + + + + + Models/TranslationWidgetOrigin.obj + + + + + + + + + 1 + + + + Models/TranslationWidgetX.obj + + + + + + + + + 1 + + + + Models/TranslationWidgetY.obj + + + + + + + + + 1 + + + + Models/TranslationWidgetZ.obj + + + + + + + + + 1 + + + + Models/WidgetPlaneX.obj + + + + + + + + + 1 + + + + Models/WidgetPlaneY.obj + + + + + + + + + 1 + + + + Models/WidgetPlaneZ.obj + + + + + + + + + + + + + + + + + diff --git a/resources/Schema/Types/Entity.xsd b/resources/Schema/Types/Entity.xsd index 3b0a1c88..e44b1d72 100644 --- a/resources/Schema/Types/Entity.xsd +++ b/resources/Schema/Types/Entity.xsd @@ -28,6 +28,7 @@ + From 162523d3ca5381c4d53ae9719dca84e15c6da108 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Tue, 19 Jan 2016 11:55:27 +0100 Subject: [PATCH 22/38] Made EntityFileWriter store enums as strings instead of integer values to be resistant to enum value changes! --- src/Engine/Core/EntityFileWriter.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Engine/Core/EntityFileWriter.cpp b/src/Engine/Core/EntityFileWriter.cpp index 4d46be06..3efc9253 100644 --- a/src/Engine/Core/EntityFileWriter.cpp +++ b/src/Engine/Core/EntityFileWriter.cpp @@ -114,9 +114,18 @@ void EntityFileWriter::appentEntityComponents(xercesc::DOMElement* parentElement fieldElement->setAttribute(X("Y"), X(boost::lexical_cast(q.y))); fieldElement->setAttribute(X("Z"), X(boost::lexical_cast(q.z))); fieldElement->setAttribute(X("W"), X(boost::lexical_cast(q.w))); - } else if (field.Type == "int" || field.Type == "enum") { + } else if (field.Type == "int") { const int& value = c[fieldName]; fieldElement->appendChild(doc->createTextNode(X(boost::lexical_cast(value)))); + } else if (field.Type == "enum") { + const int& value = c[fieldName]; + auto& enumDef = c.Info.Meta->FieldEnumDefinitions.at(fieldName); + for (auto& kv : enumDef) { + if (kv.second == value) { + fieldElement->appendChild(doc->createElement(X(kv.first))); + break; + } + } } else if (field.Type == "float") { const float& value = c[fieldName]; fieldElement->appendChild(doc->createTextNode(X(boost::lexical_cast(value)))); From a6445c65aa005bba03645ea50e8206fca222ce3a Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Tue, 19 Jan 2016 12:15:20 +0100 Subject: [PATCH 23/38] Fixed EntityParser to handle string enums properly. --- .../Schema/Entities/EditorWidgetRotate.xml | 12 ++++-- .../Schema/Entities/EditorWidgetScale.xml | 12 ++++-- .../Schema/Entities/EditorWidgetTranslate.xml | 24 +++++++++--- src/Engine/Core/EntityFile.cpp | 37 ++++++++++--------- 4 files changed, 56 insertions(+), 29 deletions(-) diff --git a/resources/Schema/Entities/EditorWidgetRotate.xml b/resources/Schema/Entities/EditorWidgetRotate.xml index fc41b596..55dd9af4 100644 --- a/resources/Schema/Entities/EditorWidgetRotate.xml +++ b/resources/Schema/Entities/EditorWidgetRotate.xml @@ -9,7 +9,9 @@ - 2 + + + @@ -22,7 +24,9 @@ - 2 + + + @@ -35,7 +39,9 @@ - 2 + + + diff --git a/resources/Schema/Entities/EditorWidgetScale.xml b/resources/Schema/Entities/EditorWidgetScale.xml index f4c44d66..b317b1cc 100644 --- a/resources/Schema/Entities/EditorWidgetScale.xml +++ b/resources/Schema/Entities/EditorWidgetScale.xml @@ -12,7 +12,9 @@ - 3 + + + @@ -25,7 +27,9 @@ - 3 + + + @@ -38,7 +42,9 @@ - 3 + + + diff --git a/resources/Schema/Entities/EditorWidgetTranslate.xml b/resources/Schema/Entities/EditorWidgetTranslate.xml index bc43538d..56943adc 100644 --- a/resources/Schema/Entities/EditorWidgetTranslate.xml +++ b/resources/Schema/Entities/EditorWidgetTranslate.xml @@ -12,7 +12,9 @@ - 1 + + + @@ -25,7 +27,9 @@ - 1 + + + @@ -38,7 +42,9 @@ - 1 + + + @@ -51,7 +57,9 @@ - 1 + + + @@ -64,7 +72,9 @@ - 1 + + + @@ -77,7 +87,9 @@ - 1 + + + diff --git a/src/Engine/Core/EntityFile.cpp b/src/Engine/Core/EntityFile.cpp index c1125e10..d5fb4c12 100644 --- a/src/Engine/Core/EntityFile.cpp +++ b/src/Engine/Core/EntityFile.cpp @@ -86,23 +86,26 @@ void EntityFile::WriteAttributeData(char* outData, const ComponentInfo::Field_t& void EntityFile::WriteValueData(char* outData, const ComponentInfo::Field_t& field, const char* valueData) { - if (field.Type == "int" || field.Type == "enum") { - int value = boost::lexical_cast(valueData); - memcpy(outData, reinterpret_cast(&value), field.Stride); - } else if (field.Type == "float") { - float value = boost::lexical_cast(valueData); - memcpy(outData, reinterpret_cast(&value), field.Stride); - } else if (field.Type == "double") { - double value = boost::lexical_cast(valueData); - memcpy(outData, reinterpret_cast(&value), field.Stride); - } else if (field.Type == "bool") { - bool value = (valueData[0] == 't'); // Lazy bool evaluation - memcpy(outData, reinterpret_cast(&value), field.Stride); - } else if (field.Type == "string") { - new (outData) std::string(valueData); - } else { - LOG_WARNING("Unknown value data type: %s", field.Type.c_str()); - } + // Catch and ignore casting errors so whitespace around string enums won't mess anything up + try { + if (field.Type == "int" || field.Type == "enum") { + int value = boost::lexical_cast(valueData); + memcpy(outData, reinterpret_cast(&value), field.Stride); + } else if (field.Type == "float") { + float value = boost::lexical_cast(valueData); + memcpy(outData, reinterpret_cast(&value), field.Stride); + } else if (field.Type == "double") { + double value = boost::lexical_cast(valueData); + memcpy(outData, reinterpret_cast(&value), field.Stride); + } else if (field.Type == "bool") { + bool value = (valueData[0] == 't'); // Lazy bool evaluation + memcpy(outData, reinterpret_cast(&value), field.Stride); + } else if (field.Type == "string") { + new (outData) std::string(valueData); + } else { + LOG_WARNING("Unknown value data type: %s", field.Type.c_str()); + } + } catch (const boost::bad_lexical_cast&) { } } EntityFileSAXHandler::EntityFileSAXHandler(const EntityFileHandler* handler, xercesc::SAX2XMLReader* reader) : m_Handler(handler) From cfe023cc1de3d0f688d6e1acec634e093e5a1e5c Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Tue, 19 Jan 2016 12:33:53 +0100 Subject: [PATCH 24/38] Created ComponentInfo::EnumType which defines which native type to use for enums. --- include/Engine/Core/ComponentInfo.h | 4 +++- include/Engine/Core/ComponentWrapper.h | 4 ++-- src/Engine/Core/EntityFile.cpp | 7 +++++-- src/Engine/Core/EntityFilePreprocessor.cpp | 2 +- src/Engine/Core/EntityFileWriter.cpp | 2 +- 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/include/Engine/Core/ComponentInfo.h b/include/Engine/Core/ComponentInfo.h index def2a323..49ed2a3f 100644 --- a/include/Engine/Core/ComponentInfo.h +++ b/include/Engine/Core/ComponentInfo.h @@ -5,12 +5,14 @@ struct ComponentInfo { + typedef int EnumType; + struct Meta_t { std::string Annotation; unsigned int Allocation = 0; std::map FieldAnnotations; - std::map> FieldEnumDefinitions; + std::map> FieldEnumDefinitions; }; struct Field_t diff --git a/include/Engine/Core/ComponentWrapper.h b/include/Engine/Core/ComponentWrapper.h index f124d3d5..c7a32370 100644 --- a/include/Engine/Core/ComponentWrapper.h +++ b/include/Engine/Core/ComponentWrapper.h @@ -18,7 +18,7 @@ struct ComponentWrapper const ::EntityID EntityID; char* Data; - int Enum(const char* fieldName, const char* enumKey) + ComponentInfo::EnumType Enum(const char* fieldName, const char* enumKey) { return Info.Meta->FieldEnumDefinitions.at(fieldName).at(enumKey); } @@ -58,7 +58,7 @@ struct ComponentWrapper public: // Return the integer value of an enum type key for this field - int Enum(const char* enumKey) { return m_Component->Enum(m_PropertyName.c_str(), enumKey); } + ComponentInfo::EnumType Enum(const char* enumKey) { return m_Component->Enum(m_PropertyName.c_str(), enumKey); } template operator T&() { return m_Component->Field(m_PropertyName); } diff --git a/src/Engine/Core/EntityFile.cpp b/src/Engine/Core/EntityFile.cpp index d5fb4c12..7609db2b 100644 --- a/src/Engine/Core/EntityFile.cpp +++ b/src/Engine/Core/EntityFile.cpp @@ -47,7 +47,7 @@ std::size_t EntityFile::GetTypeStride(std::string typeName) { "float", sizeof(float) }, { "double", sizeof(double) }, { "string", sizeof(std::string) }, - { "enum", sizeof(int) }, + { "enum", sizeof(ComponentInfo::EnumType) }, { "Vector", sizeof(glm::vec3) }, { "Quaternion", sizeof(glm::quat) }, { "Color", sizeof(glm::vec4) } @@ -88,9 +88,12 @@ void EntityFile::WriteValueData(char* outData, const ComponentInfo::Field_t& fie { // Catch and ignore casting errors so whitespace around string enums won't mess anything up try { - if (field.Type == "int" || field.Type == "enum") { + if (field.Type == "int") { int value = boost::lexical_cast(valueData); memcpy(outData, reinterpret_cast(&value), field.Stride); + } else if (field.Type == "enum") { + ComponentInfo::EnumType value = boost::lexical_cast(valueData); + memcpy(outData, reinterpret_cast(&value), field.Stride); } else if (field.Type == "float") { float value = boost::lexical_cast(valueData); memcpy(outData, reinterpret_cast(&value), field.Stride); diff --git a/src/Engine/Core/EntityFilePreprocessor.cpp b/src/Engine/Core/EntityFilePreprocessor.cpp index 90151941..5cd56cd0 100644 --- a/src/Engine/Core/EntityFilePreprocessor.cpp +++ b/src/Engine/Core/EntityFilePreprocessor.cpp @@ -146,7 +146,7 @@ void EntityFilePreprocessor::parseComponentInfo() auto enumElement = xsChoiceParticles->elementAt(i)->getElementTerm(); std::string enumName = XS::ToString(enumElement->getName()); std::string enumValue = XS::ToString(enumElement->getConstraintValue()); - compInfo.Meta->FieldEnumDefinitions[name][enumName] = boost::lexical_cast(enumValue); + compInfo.Meta->FieldEnumDefinitions[name][enumName] = boost::lexical_cast(enumValue); LOG_DEBUG("ENUM %s = %s", enumName.c_str(), enumValue.c_str()); } } diff --git a/src/Engine/Core/EntityFileWriter.cpp b/src/Engine/Core/EntityFileWriter.cpp index 3efc9253..06a3c4ca 100644 --- a/src/Engine/Core/EntityFileWriter.cpp +++ b/src/Engine/Core/EntityFileWriter.cpp @@ -118,7 +118,7 @@ void EntityFileWriter::appentEntityComponents(xercesc::DOMElement* parentElement const int& value = c[fieldName]; fieldElement->appendChild(doc->createTextNode(X(boost::lexical_cast(value)))); } else if (field.Type == "enum") { - const int& value = c[fieldName]; + const ComponentInfo::EnumType& value = c[fieldName]; auto& enumDef = c.Info.Meta->FieldEnumDefinitions.at(fieldName); for (auto& kv : enumDef) { if (kv.second == value) { From 61984d2c4a81135ce2323e0339fa3f19c9c90603 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Tue, 19 Jan 2016 13:27:29 +0100 Subject: [PATCH 25/38] Removed lots of slowing debug output from entity parsing pipeline --- src/Engine/Core/EntityFileParser.cpp | 14 ++++---- src/Engine/Core/EntityFilePreprocessor.cpp | 41 +++++++++++----------- 2 files changed, 27 insertions(+), 28 deletions(-) diff --git a/src/Engine/Core/EntityFileParser.cpp b/src/Engine/Core/EntityFileParser.cpp index 1633bbc7..23c0c4c4 100644 --- a/src/Engine/Core/EntityFileParser.cpp +++ b/src/Engine/Core/EntityFileParser.cpp @@ -28,14 +28,14 @@ void EntityFileParser::onStartEntity(EntityID entity, EntityID parent, const std m_World->SetName(realEntity, name); } m_EntityIDMapper[entity] = realEntity; - LOG_DEBUG("Created entity #%i (%i) with parent %i (%i)", entity, realEntity, parent, realParent); + //LOG_DEBUG("Created entity #%i (%i) with parent %i (%i)", entity, realEntity, parent, realParent); } void EntityFileParser::onStartComponent(EntityID entity, const std::string& component) { EntityID realEntity = m_EntityIDMapper.at(entity); m_World->AttachComponent(realEntity, component); - LOG_DEBUG("Attached component of type \"%s\" to entity #%i (%i)", component.c_str(), entity, realEntity); + //LOG_DEBUG("Attached component of type \"%s\" to entity #%i (%i)", component.c_str(), entity, realEntity); } void EntityFileParser::onStartComponentField(EntityID entity, const std::string& componentType, const std::string& fieldName, const std::map& attributes) @@ -49,11 +49,11 @@ void EntityFileParser::onStartComponentField(EntityID entity, const std::string& } auto& field = fieldIt->second; - LOG_DEBUG("Field \"%s\" type \"%s\"", fieldName.c_str(), field.Type.c_str()); - LOG_DEBUG("Attributes:"); - for (auto& kv : attributes) { - LOG_DEBUG("\t%s = %s", kv.first.c_str(), kv.second.c_str()); - } + //LOG_DEBUG("Field \"%s\" type \"%s\"", fieldName.c_str(), field.Type.c_str()); + //LOG_DEBUG("Attributes:"); + //for (auto& kv : attributes) { + // LOG_DEBUG("\t%s = %s", kv.first.c_str(), kv.second.c_str()); + //} char* data = component.Data + field.Offset; EntityFile::WriteAttributeData(data, field, attributes); diff --git a/src/Engine/Core/EntityFilePreprocessor.cpp b/src/Engine/Core/EntityFilePreprocessor.cpp index 5cd56cd0..7b4b2bb7 100644 --- a/src/Engine/Core/EntityFilePreprocessor.cpp +++ b/src/Engine/Core/EntityFilePreprocessor.cpp @@ -7,23 +7,23 @@ EntityFilePreprocessor::EntityFilePreprocessor(const EntityFile* entityFile) handler.SetStartComponentCallback(std::bind(&EntityFilePreprocessor::onStartComponent, this, std::placeholders::_1, std::placeholders::_2)); m_EntityFile->Parse(&handler); - LOG_DEBUG("___ COMPONENT DEFINITIONS ___"); - for (auto& kv : m_ComponentCounts) { - LOG_DEBUG("%s: %i", kv.first.c_str(), kv.second); - } + //LOG_DEBUG("___ COMPONENT DEFINITIONS ___"); + //for (auto& kv : m_ComponentCounts) { + // LOG_DEBUG("%s: %i", kv.first.c_str(), kv.second); + //} parseComponentInfo(); - for (auto& kv : m_ComponentInfo) { - auto& info = kv.second; - LOG_DEBUG("Component: %s (%s)", info.Name.c_str(), info.Meta->Annotation.c_str()); - LOG_DEBUG("Stride: %i", info.Stride); - LOG_DEBUG("Allocation: %i", info.Meta->Allocation); - for (auto& kv : info.Fields) { - auto& field = kv.second; - LOG_DEBUG("\t%i\t%s %s", field.Offset, field.Type.c_str(), kv.first.c_str()); - } - } + //for (auto& kv : m_ComponentInfo) { + // auto& info = kv.second; + // LOG_DEBUG("Component: %s (%s)", info.Name.c_str(), info.Meta->Annotation.c_str()); + // LOG_DEBUG("Stride: %i", info.Stride); + // LOG_DEBUG("Allocation: %i", info.Meta->Allocation); + // for (auto& kv : info.Fields) { + // auto& field = kv.second; + // LOG_DEBUG("\t%i\t%s %s", field.Offset, field.Type.c_str(), kv.first.c_str()); + // } + //} parseDefaults(); } @@ -50,7 +50,6 @@ void EntityFilePreprocessor::parseComponentInfo() auto xsModel = grammarPool->getXSModel(whateverTheFuckThisIs); // Find component xsd element declarations - std::cout << "Enumerating components..." << std::endl; // auto topLevelElements = xsModel->getComponents(XSConstants::ELEMENT_DECLARATION); for (unsigned int i = 0; i < topLevelElements->getLength(); ++i) { @@ -73,7 +72,7 @@ void EntityFilePreprocessor::parseComponentInfo() if (componentAnnotation != nullptr) { compInfo.Meta->Annotation = parseAnnotationXML(componentAnnotation->getAnnotationString()); } else { - LOG_WARNING("Component \"%s\" is missing an annotation!", compInfo.Name.c_str()); + //LOG_WARNING("Component \"%s\" is missing an annotation!", compInfo.Name.c_str()); } // @@ -91,7 +90,7 @@ void EntityFilePreprocessor::parseComponentInfo() // auto modelGroupParticle = complexTypeDefinition->getParticle(); if (modelGroupParticle == nullptr || modelGroupParticle->getTermType() != XSParticle::TERM_MODELGROUP) { - LOG_ERROR("Failed to parse component definition for \"%s\": Model group particle was null or wasn't TERM_MODELGROUP!", compInfo.Name.c_str()); + //LOG_ERROR("Failed to parse component definition for \"%s\": Model group particle was null or wasn't TERM_MODELGROUP!", compInfo.Name.c_str()); continue; } auto modelGroup = modelGroupParticle->getModelGroupTerm(); @@ -103,7 +102,7 @@ void EntityFilePreprocessor::parseComponentInfo() for (unsigned int i = 0; i < particles->size(); ++i) { auto particle = particles->elementAt(i); if (particle->getTermType() != XSParticle::TERM_ELEMENT) { - LOG_ERROR("Failed to parse a field definition in component \"%s\": Particle wasn't TERM_ELEMENT! Skipping.", compInfo.Name.c_str()); + //LOG_ERROR("Failed to parse a field definition in component \"%s\": Particle wasn't TERM_ELEMENT! Skipping.", compInfo.Name.c_str()); continue; } auto elementDeclaration = particle->getElementTerm(); @@ -129,7 +128,7 @@ void EntityFilePreprocessor::parseComponentInfo() if (fieldAnnotation != nullptr) { compInfo.Meta->FieldAnnotations[name] = parseAnnotationXML(fieldAnnotation->getAnnotationString()); } else { - LOG_WARNING("Component field \"%s.%s\" is missing an annotation!", compInfo.Name.c_str(), name.c_str()); + //LOG_WARNING("Component field \"%s.%s\" is missing an annotation!", compInfo.Name.c_str(), name.c_str()); } if (effectiveType == "enum") { @@ -147,7 +146,7 @@ void EntityFilePreprocessor::parseComponentInfo() std::string enumName = XS::ToString(enumElement->getName()); std::string enumValue = XS::ToString(enumElement->getConstraintValue()); compInfo.Meta->FieldEnumDefinitions[name][enumName] = boost::lexical_cast(enumValue); - LOG_DEBUG("ENUM %s = %s", enumName.c_str(), enumValue.c_str()); + //LOG_DEBUG("ENUM %s = %s", enumName.c_str(), enumValue.c_str()); } } } @@ -190,7 +189,7 @@ void EntityFilePreprocessor::parseDefaults() //std::string namespaceSchema = schemaLocation.string(); //parser.setExternalNoNamespaceSchemaLocation("Teamasdasdasdasd.xsd"); - LOG_DEBUG("Parsing defaults for component %s", componentName.c_str()); + //LOG_DEBUG("Parsing defaults for component %s", componentName.c_str()); boost::filesystem::path defaultsFile = "Schema/Components/" + componentName + ".xml"; parser.parse(defaultsFile.string().c_str()); From d030e8f6990fefeb97440efcfec6f33a64e43b93 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Tue, 19 Jan 2016 13:28:02 +0100 Subject: [PATCH 26/38] Editor widget selection and creation --- include/Engine/Editor/EditorGUI.h | 13 +++++ include/Engine/Editor/EditorSystem.h | 7 ++- include/Engine/Editor/EditorWidgetSystem.h | 6 +++ resources/Schema/Components/EditorWidget.xml | 2 +- resources/Schema/Components/EditorWidget.xsd | 7 ++- src/Engine/Editor/EditorGUI.cpp | 50 ++++++++++++++++++-- src/Engine/Editor/EditorSystem.cpp | 42 ++++++++++++++-- 7 files changed, 112 insertions(+), 15 deletions(-) create mode 100644 include/Engine/Editor/EditorWidgetSystem.h diff --git a/include/Engine/Editor/EditorGUI.h b/include/Engine/Editor/EditorGUI.h index 9d2712e1..104c6787 100644 --- a/include/Engine/Editor/EditorGUI.h +++ b/include/Engine/Editor/EditorGUI.h @@ -10,6 +10,7 @@ #include "../GLM.h" #include +#include "EditorWidgetSystem.h" #include "../Core/EventBroker.h" #include "../Core/World.h" #include "../Core/EntityWrapper.h" @@ -22,6 +23,13 @@ class EditorGUI public: EditorGUI(World* world, EventBroker* eventBroker); + enum class WidgetMode + { + Translate, + Rotate, + Scale + }; + void Draw(); void SelectEntity(EntityWrapper entity); @@ -59,6 +67,9 @@ public: // Called when the user means to delete a component off an entity. typedef std::function OnComponentDelete_t; void SetComponentDeleteCallback(OnComponentDelete_t f) { m_OnComponentDelete = f; } + // Called when the user selects a widget mode. + typedef std::function OnWidgetMode_t; + void SetWidgetModeCallback(OnWidgetMode_t f) { m_OnWidgetMode = f; } private: World* m_World; @@ -72,6 +83,7 @@ private: std::unordered_map m_EntityFiles; EntityWrapper m_CurrentlyDragging = EntityWrapper::Invalid; std::string m_LastErrorMessage; + WidgetMode m_CurrentWidgetMode = WidgetMode::Translate; // Callbacks OnEntitySelectedCallback_t m_OnEntitySelected = nullptr; @@ -83,6 +95,7 @@ private: OnEntityChangeName_t m_OnEntityChangeName = nullptr; OnComponentAttach_t m_OnComponentAttach = nullptr; OnComponentDelete_t m_OnComponentDelete = nullptr; + OnWidgetMode_t m_OnWidgetMode = nullptr; // Utility functions boost::filesystem::path fileOpenDialog(); diff --git a/include/Engine/Editor/EditorSystem.h b/include/Engine/Editor/EditorSystem.h index c0db917d..31d5064c 100644 --- a/include/Engine/Editor/EditorSystem.h +++ b/include/Engine/Editor/EditorSystem.h @@ -26,14 +26,19 @@ 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; EditorStats* m_EditorStats; + // State + EditorGUI::WidgetMode m_WidgetMode = EditorGUI::WidgetMode::Translate; + EntityWrapper m_Widget = EntityWrapper::Invalid; + EntityWrapper m_CurrentSelection = EntityWrapper::Invalid; + // Utility functions EntityWrapper importEntity(EntityWrapper parent, boost::filesystem::path filePath); + void setWidgetMode(EditorGUI::WidgetMode mode); // GUI callbacks void OnEntitySelected(EntityWrapper entity); diff --git a/include/Engine/Editor/EditorWidgetSystem.h b/include/Engine/Editor/EditorWidgetSystem.h new file mode 100644 index 00000000..2350d24b --- /dev/null +++ b/include/Engine/Editor/EditorWidgetSystem.h @@ -0,0 +1,6 @@ +#ifndef EditorWidgetSystem_h__ +#define EditorWidgetSystem_h__ + + + +#endif diff --git a/resources/Schema/Components/EditorWidget.xml b/resources/Schema/Components/EditorWidget.xml index 6a94d2f6..fed2f809 100644 --- a/resources/Schema/Components/EditorWidget.xml +++ b/resources/Schema/Components/EditorWidget.xml @@ -1,5 +1,5 @@ - + \ No newline at end of file diff --git a/resources/Schema/Components/EditorWidget.xsd b/resources/Schema/Components/EditorWidget.xsd index e4c4ff71..3d08e82e 100644 --- a/resources/Schema/Components/EditorWidget.xsd +++ b/resources/Schema/Components/EditorWidget.xsd @@ -7,10 +7,9 @@ - - - - + + + diff --git a/src/Engine/Editor/EditorGUI.cpp b/src/Engine/Editor/EditorGUI.cpp index 1bf0f9e9..318e3199 100644 --- a/src/Engine/Editor/EditorGUI.cpp +++ b/src/Engine/Editor/EditorGUI.cpp @@ -36,13 +36,55 @@ void EditorGUI::drawTools() } // Translate widget button - ImGui::ImageButton((void*)tryLoadTexture("Textures/Icons/Translate.png"), ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0)); + if (ImGui::ImageButton( + (void*)tryLoadTexture("Textures/Icons/Translate.png"), + ImVec2(24, 24), + ImVec2(0, 1), + ImVec2(1, 0), + -1, + ImVec4(0, 0, 0, 0), + (m_CurrentWidgetMode == WidgetMode::Translate) ? ImVec4(0, 1, 0, 1) : ImVec4(1, 1, 1, 1) + ) + ) { + m_CurrentWidgetMode = WidgetMode::Translate; + if (m_OnWidgetMode != nullptr) { + m_OnWidgetMode(m_CurrentWidgetMode); + } + } // Rotate widget button ImGui::SameLine(); - ImGui::ImageButton((void*)tryLoadTexture("Textures/Icons/Rotate.png"), ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0)); + if (ImGui::ImageButton( + (void*)tryLoadTexture("Textures/Icons/Rotate.png"), + ImVec2(24, 24), + ImVec2(0, 1), + ImVec2(1, 0), + -1, + ImVec4(0, 0, 0, 0), + (m_CurrentWidgetMode == WidgetMode::Rotate) ? ImVec4(0, 1, 0, 1) : ImVec4(1, 1, 1, 1) + ) + ) { + m_CurrentWidgetMode = WidgetMode::Rotate; + if (m_OnWidgetMode != nullptr) { + m_OnWidgetMode(m_CurrentWidgetMode); + } + } // Scale widget button ImGui::SameLine(); - ImGui::ImageButton((void*)tryLoadTexture("Textures/Icons/Scale.png"), ImVec2(24, 24), ImVec2(0, 1), ImVec2(1, 0)); + if (ImGui::ImageButton( + (void*)tryLoadTexture("Textures/Icons/Scale.png"), + ImVec2(24, 24), + ImVec2(0, 1), + ImVec2(1, 0), + -1, + ImVec4(0, 0, 0, 0), + (m_CurrentWidgetMode == WidgetMode::Scale) ? ImVec4(0, 1, 0, 1) : ImVec4(1, 1, 1, 1) + ) + ) { + m_CurrentWidgetMode = WidgetMode::Scale; + if (m_OnWidgetMode != nullptr) { + m_OnWidgetMode(m_CurrentWidgetMode); + } + } ImGui::SameLine(); ImGui::ItemSize(ImVec2(5, 0)); @@ -83,7 +125,7 @@ void EditorGUI::drawEntities(World* world) entityImport(world); } ImGui::SameLine(0.f, 5.f); - ImGui::Button("Reference", ImVec2(buttonWidth, 0)); + ImGui::ButtonEx("Reference", ImVec2(buttonWidth, 0), ImGuiButtonFlags_Disabled); // Naming char buffer[256]; diff --git a/src/Engine/Editor/EditorSystem.cpp b/src/Engine/Editor/EditorSystem.cpp index 36f2baa4..03b90a37 100644 --- a/src/Engine/Editor/EditorSystem.cpp +++ b/src/Engine/Editor/EditorSystem.cpp @@ -12,9 +12,7 @@ EditorSystem::EditorSystem(World* world, EventBroker* eventBroker, IRenderer* re m_EditorWorldSystemPipeline->AddSystem(0); m_EditorWorldSystemPipeline->AddSystem(1, m_Renderer, m_RenderFrame); - m_Widget = importEntity(EntityWrapper(m_EditorWorld, EntityID_Invalid), "Schema/Entities/EditorWidget.xml"); - - m_Camera = EntityWrapper(m_EditorWorld, m_EditorWorld->CreateEntity()); + m_Camera = importEntity(EntityWrapper(m_EditorWorld, EntityID_Invalid), "Schema/Entities/Empty.xml"); m_EditorWorld->AttachComponent(m_Camera.ID, "Transform"); m_EditorWorld->AttachComponent(m_Camera.ID, "Camera"); m_DebugCameraInputController = new DebugCameraInputController(m_EventBroker, -1); @@ -29,6 +27,7 @@ EditorSystem::EditorSystem(World* world, EventBroker* eventBroker, IRenderer* re m_EditorGUI->SetEntityChangeNameCallback(std::bind(&EditorSystem::OnEntityChangeName, this, std::placeholders::_1, std::placeholders::_2)); m_EditorGUI->SetComponentAttachCallback(std::bind(&EditorSystem::OnComponentAttach, this, std::placeholders::_1, std::placeholders::_2)); m_EditorGUI->SetComponentDeleteCallback(std::bind(&EditorSystem::OnComponentDelete, this, std::placeholders::_1, std::placeholders::_2)); + m_EditorGUI->SetWidgetModeCallback(std::bind(&EditorSystem::setWidgetMode, this, std::placeholders::_1)); m_EditorStats = new EditorStats(); @@ -60,7 +59,8 @@ void EditorSystem::Update(double dt) void EditorSystem::OnEntitySelected(EntityWrapper entity) { - m_Widget["Transform"]["Position"] = Transform::AbsolutePosition(entity.World, entity.ID); + m_CurrentSelection = entity; + setWidgetMode(m_WidgetMode); } void EditorSystem::OnEntitySave(EntityWrapper entity, boost::filesystem::path filePath) @@ -118,4 +118,36 @@ EntityWrapper EditorSystem::importEntity(EntityWrapper parent, boost::filesystem } catch (const std::exception&) { return EntityWrapper::Invalid; } -} \ No newline at end of file +} + +void EditorSystem::setWidgetMode(EditorGUI::WidgetMode mode) +{ + if (mode == m_WidgetMode && m_Widget.Valid() && m_CurrentSelection.Valid()) { + return; + } + + if (m_Widget.Valid()) { + m_Widget.World->DeleteEntity(m_Widget.ID); + m_Widget = EntityWrapper::Invalid; + } + + if (!m_CurrentSelection.Valid()) { + return; + } + + switch (mode) { + case EditorGUI::WidgetMode::Translate: + m_Widget = importEntity(EntityWrapper(m_World, EntityID_Invalid), "Schema/Entities/EditorWidgetTranslate.xml"); + break; + case EditorGUI::WidgetMode::Rotate: + m_Widget = importEntity(EntityWrapper(m_World, EntityID_Invalid), "Schema/Entities/EditorWidgetRotate.xml"); + break; + case EditorGUI::WidgetMode::Scale: + m_Widget = importEntity(EntityWrapper(m_World, EntityID_Invalid), "Schema/Entities/EditorWidgetScale.xml"); + break; + } + + m_Widget["Transform"]["Position"] = Transform::AbsolutePosition(m_CurrentSelection.World, m_CurrentSelection.ID); + + m_WidgetMode = mode; +} From 260203fa4d7657a787e43a2edc42130ea5d03869 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Tue, 19 Jan 2016 13:28:16 +0100 Subject: [PATCH 27/38] Annotation on physics component --- resources/Schema/Components/Physics.xsd | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/resources/Schema/Components/Physics.xsd b/resources/Schema/Components/Physics.xsd index 001dd2c8..554f76fd 100644 --- a/resources/Schema/Components/Physics.xsd +++ b/resources/Schema/Components/Physics.xsd @@ -9,7 +9,9 @@ - + + m/s^2 + From 8854794cbcf997b00df81242c086c41d0d9dae46 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Tue, 19 Jan 2016 13:32:32 +0100 Subject: [PATCH 28/38] fixup! Editor widget selection and creation --- include/Engine/Editor/EditorGUI.h | 1 + .../Schema/Entities/EditorWidgetRotate.xml | 11 ++- .../Schema/Entities/EditorWidgetScale.xml | 6 +- .../Schema/Entities/EditorWidgetTranslate.xml | 45 ++-------- src/Engine/Editor/EditorGUI.cpp | 85 +++++++++---------- src/Engine/Editor/EditorSystem.cpp | 10 +-- 6 files changed, 64 insertions(+), 94 deletions(-) diff --git a/include/Engine/Editor/EditorGUI.h b/include/Engine/Editor/EditorGUI.h index 104c6787..49e0f8ab 100644 --- a/include/Engine/Editor/EditorGUI.h +++ b/include/Engine/Editor/EditorGUI.h @@ -131,6 +131,7 @@ private: // Custom UI elements bool createDeleteButton(const std::string& componentType); + void createWidgetToolButton(WidgetMode mode); }; #endif \ No newline at end of file diff --git a/resources/Schema/Entities/EditorWidgetRotate.xml b/resources/Schema/Entities/EditorWidgetRotate.xml index 55dd9af4..8c454f0c 100644 --- a/resources/Schema/Entities/EditorWidgetRotate.xml +++ b/resources/Schema/Entities/EditorWidgetRotate.xml @@ -3,6 +3,9 @@ + + + @@ -12,7 +15,6 @@ - Models/RotationWidgetX.obj @@ -27,7 +29,6 @@ - Models/RotationWidgetY.obj @@ -42,7 +43,6 @@ - Models/RotationWidgetZ.obj @@ -53,7 +53,10 @@ - + + -1 + 0 + diff --git a/resources/Schema/Entities/EditorWidgetScale.xml b/resources/Schema/Entities/EditorWidgetScale.xml index b317b1cc..15bcb38b 100644 --- a/resources/Schema/Entities/EditorWidgetScale.xml +++ b/resources/Schema/Entities/EditorWidgetScale.xml @@ -6,6 +6,9 @@ Models/ScaleWidgetOrigin.obj + + + @@ -15,7 +18,6 @@ - Models/ScaleWidgetX.obj @@ -30,7 +32,6 @@ - Models/ScaleWidgetY.obj @@ -45,7 +46,6 @@ - Models/ScaleWidgetZ.obj diff --git a/resources/Schema/Entities/EditorWidgetTranslate.xml b/resources/Schema/Entities/EditorWidgetTranslate.xml index 56943adc..e2cfd69a 100644 --- a/resources/Schema/Entities/EditorWidgetTranslate.xml +++ b/resources/Schema/Entities/EditorWidgetTranslate.xml @@ -6,17 +6,15 @@ Models/TranslationWidgetOrigin.obj + + + - - - - - - + Models/TranslationWidgetX.obj @@ -26,12 +24,7 @@ - - - - - - + Models/TranslationWidgetY.obj @@ -41,12 +34,7 @@ - - - - - - + Models/TranslationWidgetZ.obj @@ -56,12 +44,7 @@ - - - - - - + Models/WidgetPlaneX.obj @@ -71,12 +54,7 @@ - - - - - - + Models/WidgetPlaneY.obj @@ -86,12 +64,7 @@ - - - - - - + Models/WidgetPlaneZ.obj diff --git a/src/Engine/Editor/EditorGUI.cpp b/src/Engine/Editor/EditorGUI.cpp index 318e3199..f65386aa 100644 --- a/src/Engine/Editor/EditorGUI.cpp +++ b/src/Engine/Editor/EditorGUI.cpp @@ -35,57 +35,20 @@ void EditorGUI::drawTools() return; } - // Translate widget button - if (ImGui::ImageButton( - (void*)tryLoadTexture("Textures/Icons/Translate.png"), - ImVec2(24, 24), - ImVec2(0, 1), - ImVec2(1, 0), - -1, - ImVec4(0, 0, 0, 0), - (m_CurrentWidgetMode == WidgetMode::Translate) ? ImVec4(0, 1, 0, 1) : ImVec4(1, 1, 1, 1) - ) - ) { - m_CurrentWidgetMode = WidgetMode::Translate; - if (m_OnWidgetMode != nullptr) { - m_OnWidgetMode(m_CurrentWidgetMode); - } + createWidgetToolButton(WidgetMode::Translate); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Translate"); } - // Rotate widget button ImGui::SameLine(); - if (ImGui::ImageButton( - (void*)tryLoadTexture("Textures/Icons/Rotate.png"), - ImVec2(24, 24), - ImVec2(0, 1), - ImVec2(1, 0), - -1, - ImVec4(0, 0, 0, 0), - (m_CurrentWidgetMode == WidgetMode::Rotate) ? ImVec4(0, 1, 0, 1) : ImVec4(1, 1, 1, 1) - ) - ) { - m_CurrentWidgetMode = WidgetMode::Rotate; - if (m_OnWidgetMode != nullptr) { - m_OnWidgetMode(m_CurrentWidgetMode); - } + createWidgetToolButton(WidgetMode::Rotate); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Rotate"); } - // Scale widget button ImGui::SameLine(); - if (ImGui::ImageButton( - (void*)tryLoadTexture("Textures/Icons/Scale.png"), - ImVec2(24, 24), - ImVec2(0, 1), - ImVec2(1, 0), - -1, - ImVec4(0, 0, 0, 0), - (m_CurrentWidgetMode == WidgetMode::Scale) ? ImVec4(0, 1, 0, 1) : ImVec4(1, 1, 1, 1) - ) - ) { - m_CurrentWidgetMode = WidgetMode::Scale; - if (m_OnWidgetMode != nullptr) { - m_OnWidgetMode(m_CurrentWidgetMode); - } + createWidgetToolButton(WidgetMode::Scale); + if (ImGui::IsItemHovered()) { + ImGui::SetTooltip("Scale"); } - ImGui::SameLine(); ImGui::ItemSize(ImVec2(5, 0)); @@ -497,6 +460,36 @@ bool EditorGUI::createDeleteButton(const std::string& componentType) return pressed; } +void EditorGUI::createWidgetToolButton(WidgetMode mode) +{ + GLuint texture = 0; + switch (mode) { + case WidgetMode::Translate: + texture = tryLoadTexture("Textures/Icons/Translate.png"); + break; + case WidgetMode::Rotate: + texture = tryLoadTexture("Textures/Icons/Rotate.png"); + break; + case WidgetMode::Scale: + texture = tryLoadTexture("Textures/Icons/Scale.png"); + break; + } + if (ImGui::ImageButton( + (void*)texture, + ImVec2(24, 24), + ImVec2(0, 1), + ImVec2(1, 0), + -1, + ImVec4(0, 0, 0, 0), + (m_CurrentWidgetMode == mode) ? ImVec4(0, 1, 0, 1) : ImVec4(1, 1, 1, 1) + ) + ) { + if (m_OnWidgetMode != nullptr) { + m_OnWidgetMode(mode); + } + m_CurrentWidgetMode = mode; + } +} boost::filesystem::path EditorGUI::fileOpenDialog() { diff --git a/src/Engine/Editor/EditorSystem.cpp b/src/Engine/Editor/EditorSystem.cpp index 03b90a37..596f8154 100644 --- a/src/Engine/Editor/EditorSystem.cpp +++ b/src/Engine/Editor/EditorSystem.cpp @@ -126,6 +126,8 @@ void EditorSystem::setWidgetMode(EditorGUI::WidgetMode mode) return; } + m_WidgetMode = mode; + if (m_Widget.Valid()) { m_Widget.World->DeleteEntity(m_Widget.ID); m_Widget = EntityWrapper::Invalid; @@ -137,17 +139,15 @@ void EditorSystem::setWidgetMode(EditorGUI::WidgetMode mode) switch (mode) { case EditorGUI::WidgetMode::Translate: - m_Widget = importEntity(EntityWrapper(m_World, EntityID_Invalid), "Schema/Entities/EditorWidgetTranslate.xml"); + m_Widget = importEntity(EntityWrapper(m_EditorWorld, EntityID_Invalid), "Schema/Entities/EditorWidgetTranslate.xml"); break; case EditorGUI::WidgetMode::Rotate: - m_Widget = importEntity(EntityWrapper(m_World, EntityID_Invalid), "Schema/Entities/EditorWidgetRotate.xml"); + m_Widget = importEntity(EntityWrapper(m_EditorWorld, EntityID_Invalid), "Schema/Entities/EditorWidgetRotate.xml"); break; case EditorGUI::WidgetMode::Scale: - m_Widget = importEntity(EntityWrapper(m_World, EntityID_Invalid), "Schema/Entities/EditorWidgetScale.xml"); + m_Widget = importEntity(EntityWrapper(m_EditorWorld, EntityID_Invalid), "Schema/Entities/EditorWidgetScale.xml"); break; } m_Widget["Transform"]["Position"] = Transform::AbsolutePosition(m_CurrentSelection.World, m_CurrentSelection.ID); - - m_WidgetMode = mode; } From 4aa9100c69619c21edb9d14f1c2d25d1b36a6532 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Thu, 21 Jan 2016 10:29:36 +0100 Subject: [PATCH 29/38] Camera::WorldToScreen helper function --- include/Engine/Rendering/Camera.h | 4 +++- src/Engine/Rendering/Camera.cpp | 13 +++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/include/Engine/Rendering/Camera.h b/include/Engine/Rendering/Camera.h index 2b863448..29dd4626 100644 --- a/include/Engine/Rendering/Camera.h +++ b/include/Engine/Rendering/Camera.h @@ -2,6 +2,7 @@ #define Camera_h__ #include "../GLM.h" +#include "../Core/Util/Rectangle.h" class Camera { @@ -32,7 +33,6 @@ public: glm::mat4 ViewMatrix() const { return m_ViewMatrix; } void SetViewMatrix(glm::mat4 val); - float AspectRatio() const { return m_AspectRatio; } void SetAspectRatio(float val); @@ -48,6 +48,8 @@ public: void UpdateViewMatrix(); void UpdateProjectionMatrix(); + glm::vec2 WorldToScreen(glm::vec3 worldCoord, Rectangle resolution); + private: glm::vec3 m_Position; diff --git a/src/Engine/Rendering/Camera.cpp b/src/Engine/Rendering/Camera.cpp index 5a774c34..f6b2e5ef 100644 --- a/src/Engine/Rendering/Camera.cpp +++ b/src/Engine/Rendering/Camera.cpp @@ -79,6 +79,19 @@ void Camera::UpdateProjectionMatrix() m_ProjectionMatrix = glm::perspective(m_FOV, m_AspectRatio, m_NearClip, m_FarClip); } +glm::vec2 Camera::WorldToScreen(glm::vec3 worldCoord, Rectangle resolution) +{ + glm::vec4 screenCoord = m_ProjectionMatrix * m_ViewMatrix * glm::vec4(worldCoord, 1.f); + if (screenCoord.w != 0) { + screenCoord.x /= screenCoord.w; + screenCoord.y /= screenCoord.w; + screenCoord.z /= screenCoord.w; + } + screenCoord.x = screenCoord.x * (resolution.Width / 2.f); + screenCoord.y = screenCoord.y * (resolution.Height / 2.f); + return glm::vec2(screenCoord); +} + void Camera::UpdateViewMatrix() { m_ViewMatrix = glm::toMat4(glm::inverse(m_Orientation)) From 5e70d6eef6e10676582228d59e3c40fe3883d412 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Thu, 21 Jan 2016 10:29:48 +0100 Subject: [PATCH 30/38] EntityWrapper::Parent helper function --- include/Engine/Core/EntityWrapper.h | 1 + src/Engine/Core/EntityWrapper.cpp | 7 ++++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/include/Engine/Core/EntityWrapper.h b/include/Engine/Core/EntityWrapper.h index 74b5fc56..3ba4e087 100644 --- a/include/Engine/Core/EntityWrapper.h +++ b/include/Engine/Core/EntityWrapper.h @@ -24,6 +24,7 @@ struct EntityWrapper static const EntityWrapper Invalid; bool HasComponent(const std::string& componentName); + EntityWrapper Parent(); bool Valid(); ComponentWrapper operator[](const char* componentName); diff --git a/src/Engine/Core/EntityWrapper.cpp b/src/Engine/Core/EntityWrapper.cpp index 5dc493ff..58dd1ee6 100644 --- a/src/Engine/Core/EntityWrapper.cpp +++ b/src/Engine/Core/EntityWrapper.cpp @@ -8,6 +8,11 @@ bool EntityWrapper::HasComponent(const std::string& componentName) return World->HasComponent(ID, componentName); } +EntityWrapper EntityWrapper::Parent() +{ + return EntityWrapper(World, World->GetParent(ID)); +} + bool EntityWrapper::Valid() { if (this->World == nullptr) { @@ -38,7 +43,7 @@ ComponentWrapper EntityWrapper::operator[](const char* componentName) bool EntityWrapper::operator==(const EntityWrapper& e) const { - return (this->World == e.World) && (this->ID == e.ID); + return (this->ID == e.ID) && (this->World == e.World); } bool EntityWrapper::operator!=(const EntityWrapper& e) const From f1345419b654cae8eeff662268562890bc773ee5 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Thu, 21 Jan 2016 10:30:19 +0100 Subject: [PATCH 31/38] EditorWidgetSystem that takes care of moving widgets around --- include/Engine/Core/System.h | 2 +- include/Engine/Editor/EditorWidgetSystem.h | 35 +++++++++ include/Engine/GLM.h | 3 +- .../Schema/Entities/EditorWidgetTranslate.xml | 27 ++++--- src/Engine/Editor/EditorGUI.cpp | 1 + src/Engine/Editor/EditorSystem.cpp | 2 + src/Engine/Editor/EditorWidgetSystem.cpp | 76 +++++++++++++++++++ 7 files changed, 135 insertions(+), 11 deletions(-) create mode 100644 src/Engine/Editor/EditorWidgetSystem.cpp diff --git a/include/Engine/Core/System.h b/include/Engine/Core/System.h index dc7c879a..ec57f5fc 100644 --- a/include/Engine/Core/System.h +++ b/include/Engine/Core/System.h @@ -34,7 +34,7 @@ protected: const std::string m_ComponentType; - virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cUniformScale, double dt) = 0; + virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cComponent, double dt) = 0; }; class ImpureSystem : public virtual System diff --git a/include/Engine/Editor/EditorWidgetSystem.h b/include/Engine/Editor/EditorWidgetSystem.h index 2350d24b..f3e4e4db 100644 --- a/include/Engine/Editor/EditorWidgetSystem.h +++ b/include/Engine/Editor/EditorWidgetSystem.h @@ -1,6 +1,41 @@ #ifndef EditorWidgetSystem_h__ #define EditorWidgetSystem_h__ +#include +#include "../GLM.h" +#include "../Core/System.h" +#include "../Rendering/IRenderer.h" +#include "../Rendering/Util/ScreenCoords.h" +#include "../Core/EMouseMove.h" +#include "../Core/EMousePress.h" +#include "../Core/EMouseRelease.h" +class EditorWidgetSystem : public ImpureSystem, PureSystem +{ +public: + EditorWidgetSystem(World* world, EventBroker* eventBroker, IRenderer* renderer); + + virtual void Update(double dt) override; + virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cEditorWidget, double dt) override; + + void debugPrintVector(const char* name, glm::vec3 axisNDC); + + void debugPrintVector(const char* name, glm::vec4 axisNDC); + void debugPrintVector(const char* name, glm::vec2 axisNDC); +private: + IRenderer* m_Renderer; + + // State + EntityWrapper m_PickEntity = EntityWrapper::Invalid; + PickData m_PickData; + glm::vec2 m_MouseDelta; + + EventRelay m_EMouseMove; + bool OnMouseMove(const Events::MouseMove& e); + EventRelay m_EMousePress; + bool OnMousePress(const Events::MousePress& e); + EventRelay m_EMouseRelease; + bool OnMouseRelease(const Events::MouseRelease& e); +}; #endif diff --git a/include/Engine/GLM.h b/include/Engine/GLM.h index 32729845..3143c905 100644 --- a/include/Engine/GLM.h +++ b/include/Engine/GLM.h @@ -7,4 +7,5 @@ #include #include #include -#include \ No newline at end of file +#include +#include \ No newline at end of file diff --git a/resources/Schema/Entities/EditorWidgetTranslate.xml b/resources/Schema/Entities/EditorWidgetTranslate.xml index e2cfd69a..75d96a51 100644 --- a/resources/Schema/Entities/EditorWidgetTranslate.xml +++ b/resources/Schema/Entities/EditorWidgetTranslate.xml @@ -6,15 +6,14 @@ Models/TranslationWidgetOrigin.obj - - - - + + + Models/TranslationWidgetX.obj @@ -24,7 +23,9 @@ - + + + Models/TranslationWidgetY.obj @@ -34,7 +35,9 @@ - + + + Models/TranslationWidgetZ.obj @@ -44,7 +47,9 @@ - + + + Models/WidgetPlaneX.obj @@ -54,7 +59,9 @@ - + + + Models/WidgetPlaneY.obj @@ -64,7 +71,9 @@ - + + + Models/WidgetPlaneZ.obj diff --git a/src/Engine/Editor/EditorGUI.cpp b/src/Engine/Editor/EditorGUI.cpp index f65386aa..d5638d31 100644 --- a/src/Engine/Editor/EditorGUI.cpp +++ b/src/Engine/Editor/EditorGUI.cpp @@ -76,6 +76,7 @@ void EditorGUI::drawTools() void EditorGUI::drawEntities(World* world) { if (!ImGui::Begin("Entities")) { + ImGui::End(); return; } diff --git a/src/Engine/Editor/EditorSystem.cpp b/src/Engine/Editor/EditorSystem.cpp index 596f8154..613f0edb 100644 --- a/src/Engine/Editor/EditorSystem.cpp +++ b/src/Engine/Editor/EditorSystem.cpp @@ -1,6 +1,7 @@ #include "Editor/EditorSystem.h" #include "Core/UniformScaleSystem.h" #include "Editor/EditorRenderSystem.h" +#include "Editor/EditorWidgetSystem.h" EditorSystem::EditorSystem(World* world, EventBroker* eventBroker, IRenderer* renderer, RenderFrame* renderFrame) : System(world, eventBroker) @@ -10,6 +11,7 @@ EditorSystem::EditorSystem(World* world, EventBroker* eventBroker, IRenderer* re m_EditorWorld = new World(); m_EditorWorldSystemPipeline = new SystemPipeline(m_EditorWorld, eventBroker); m_EditorWorldSystemPipeline->AddSystem(0); + m_EditorWorldSystemPipeline->AddSystem(0, m_Renderer); m_EditorWorldSystemPipeline->AddSystem(1, m_Renderer, m_RenderFrame); m_Camera = importEntity(EntityWrapper(m_EditorWorld, EntityID_Invalid), "Schema/Entities/Empty.xml"); diff --git a/src/Engine/Editor/EditorWidgetSystem.cpp b/src/Engine/Editor/EditorWidgetSystem.cpp new file mode 100644 index 00000000..3a200e0f --- /dev/null +++ b/src/Engine/Editor/EditorWidgetSystem.cpp @@ -0,0 +1,76 @@ +#include "Editor/EditorWidgetSystem.h" + +EditorWidgetSystem::EditorWidgetSystem(World* world, EventBroker* eventBroker, IRenderer* renderer) + : System(world, eventBroker) + , PureSystem("EditorWidget") + , m_Renderer(renderer) +{ + EVENT_SUBSCRIBE_MEMBER(m_EMouseMove, &EditorWidgetSystem::OnMouseMove); + EVENT_SUBSCRIBE_MEMBER(m_EMousePress, &EditorWidgetSystem::OnMousePress); + EVENT_SUBSCRIBE_MEMBER(m_EMouseRelease, &EditorWidgetSystem::OnMouseRelease); +} + +void EditorWidgetSystem::Update(double dt) +{ + // Pick at current mouse position +} + +void EditorWidgetSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper& cEditorWidget, double dt) +{ + if (!m_PickEntity.Valid() || m_PickEntity != entity) { + return; + } + + EntityWrapper moveEntity = entity.Parent(); + if (!moveEntity.Valid()) { + moveEntity = entity; + } + + ComponentWrapper::SubscriptProxy& type = cEditorWidget["Type"]; + if ((ComponentInfo::EnumType)type == type.Enum("Translate")) { + auto camera = m_PickData.Camera; + glm::vec3 axis = cEditorWidget["Axis"]; + glm::vec2 axisScreen = camera->WorldToScreen(axis, m_Renderer->Resolution()) - camera->WorldToScreen(glm::vec3(0, 0, 0), m_Renderer->Resolution()); + float dot = glm::dot(m_MouseDelta, glm::normalize(axisScreen)) / glm::length(axisScreen); + glm::vec3 worldMovement = dot * axis; + (glm::vec3&)moveEntity["Transform"]["Position"] += worldMovement; + } + + m_MouseDelta = glm::vec2(0); +} + +void EditorWidgetSystem::debugPrintVector(const char* name, glm::vec2 axisNDC) +{ + ImGui::Text("%s: (%f, %f)", name, axisNDC.x, axisNDC.y); +} +void EditorWidgetSystem::debugPrintVector(const char* name, glm::vec4 axisNDC) +{ + ImGui::Text("%s: (%f, %f, %f, %f)", name, axisNDC.x, axisNDC.y, axisNDC.z, axisNDC.w); +} +void EditorWidgetSystem::debugPrintVector(const char* name, glm::vec3 axisNDC) +{ + ImGui::Text("%s: (%f, %f, %f)", name, axisNDC.x, axisNDC.y, axisNDC.z); +} + +bool EditorWidgetSystem::OnMouseMove(const Events::MouseMove& e) +{ + m_MouseDelta = glm::vec2((float)e.DeltaX, (float)-e.DeltaY); + return false; +} + +bool EditorWidgetSystem::OnMousePress(const Events::MousePress & e) +{ + if (e.Button == GLFW_MOUSE_BUTTON_2) { + m_PickData = m_Renderer->Pick(glm::vec2(e.X, e.Y)); + if (m_PickData.Entity != EntityID_Invalid && m_PickData.World == m_World) { + m_PickEntity = EntityWrapper(m_World, m_PickData.Entity); + } + } + return true; +} + +bool EditorWidgetSystem::OnMouseRelease(const Events::MouseRelease& e) +{ + m_PickEntity = EntityWrapper::Invalid; + return true; +} \ No newline at end of file From 0183e1bdb7390299cddeb977b03a473d5a90ede2 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Thu, 21 Jan 2016 12:24:08 +0100 Subject: [PATCH 32/38] Fixed enum string parsing bug that would ignore parsing additional fields in a component after it encountered the first enum. --- resources/Schema/Entities/EditorWidgetRotate.xml | 6 +++--- src/Engine/Core/EntityFile.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/resources/Schema/Entities/EditorWidgetRotate.xml b/resources/Schema/Entities/EditorWidgetRotate.xml index 8c454f0c..6a5f72ea 100644 --- a/resources/Schema/Entities/EditorWidgetRotate.xml +++ b/resources/Schema/Entities/EditorWidgetRotate.xml @@ -3,9 +3,6 @@ - - - @@ -15,6 +12,7 @@ + Models/RotationWidgetX.obj @@ -29,6 +27,7 @@ + Models/RotationWidgetY.obj @@ -43,6 +42,7 @@ + Models/RotationWidgetZ.obj diff --git a/src/Engine/Core/EntityFile.cpp b/src/Engine/Core/EntityFile.cpp index 7609db2b..a8e93e49 100644 --- a/src/Engine/Core/EntityFile.cpp +++ b/src/Engine/Core/EntityFile.cpp @@ -171,7 +171,7 @@ void EntityFileSAXHandler::endElement(const XMLCh* const _uri, const XMLCh* cons //} } - if (m_StateStack.top() == State::ComponentField) { + if (m_StateStack.top() == State::ComponentField && name == m_CurrentField) { m_StateStack.pop(); onEndComponentField(name); return; From b9147344e199f4f88fbd846e81d555a76859215f Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Thu, 21 Jan 2016 14:14:22 +0100 Subject: [PATCH 33/38] Semi-working translation widget --- include/Engine/Editor/EditorSystem.h | 7 +++++ include/Engine/Editor/EditorWidgetSystem.h | 12 +++++++ .../Schema/Entities/EditorWidgetRotate.xml | 3 ++ .../Schema/Entities/EditorWidgetTranslate.xml | 3 ++ src/Engine/Core/Transform.cpp | 2 +- src/Engine/Editor/EditorSystem.cpp | 31 +++++++++++++++++-- src/Engine/Editor/EditorWidgetSystem.cpp | 23 ++++++++++---- 7 files changed, 72 insertions(+), 9 deletions(-) diff --git a/include/Engine/Editor/EditorSystem.h b/include/Engine/Editor/EditorSystem.h index 31d5064c..befa46b6 100644 --- a/include/Engine/Editor/EditorSystem.h +++ b/include/Engine/Editor/EditorSystem.h @@ -9,6 +9,7 @@ #include "../Core/EntityFilePreprocessor.h" #include "../Core/EntityFileParser.h" #include "../Core/EntityFileWriter.h" +#include "../Core/EMouseRelease.h" #include "EditorGUI.h" #include "EditorStats.h" @@ -49,4 +50,10 @@ private: void OnEntityChangeName(EntityWrapper entity, const std::string& name); void OnComponentAttach(EntityWrapper entity, const std::string& componentType); void OnComponentDelete(EntityWrapper entity, const std::string& componentType); + + // Events + EventRelay m_EMouseRelease; + bool OnMouseRelease(const Events::MouseRelease& e); + EventRelay m_EWidgetDelta; + bool OnWidgetDelta(const Events::WidgetDelta& e); }; \ No newline at end of file diff --git a/include/Engine/Editor/EditorWidgetSystem.h b/include/Engine/Editor/EditorWidgetSystem.h index f3e4e4db..a2329342 100644 --- a/include/Engine/Editor/EditorWidgetSystem.h +++ b/include/Engine/Editor/EditorWidgetSystem.h @@ -10,6 +10,18 @@ #include "../Core/EMousePress.h" #include "../Core/EMouseRelease.h" +namespace Events +{ + +struct WidgetDelta : Event +{ + glm::vec3 Translation; + glm::vec3 Rotation; + glm::vec3 Scale; +}; + +} + class EditorWidgetSystem : public ImpureSystem, PureSystem { public: diff --git a/resources/Schema/Entities/EditorWidgetRotate.xml b/resources/Schema/Entities/EditorWidgetRotate.xml index 6a5f72ea..0a8f06b8 100644 --- a/resources/Schema/Entities/EditorWidgetRotate.xml +++ b/resources/Schema/Entities/EditorWidgetRotate.xml @@ -9,6 +9,7 @@ + @@ -24,6 +25,7 @@ + @@ -39,6 +41,7 @@ + diff --git a/resources/Schema/Entities/EditorWidgetTranslate.xml b/resources/Schema/Entities/EditorWidgetTranslate.xml index 75d96a51..70ca09a8 100644 --- a/resources/Schema/Entities/EditorWidgetTranslate.xml +++ b/resources/Schema/Entities/EditorWidgetTranslate.xml @@ -12,6 +12,7 @@ + @@ -24,6 +25,7 @@ + @@ -36,6 +38,7 @@ + diff --git a/src/Engine/Core/Transform.cpp b/src/Engine/Core/Transform.cpp index 8acac937..cbc405a3 100644 --- a/src/Engine/Core/Transform.cpp +++ b/src/Engine/Core/Transform.cpp @@ -7,7 +7,7 @@ glm::vec3 Transform::AbsolutePosition(World* world, EntityID entity) while (entity != EntityID_Invalid) { ComponentWrapper transform = world->GetComponent(entity, "Transform"); EntityID parent = world->GetParent(entity); - position += Transform::AbsoluteScale(world, parent) * Transform::AbsoluteOrientation(world, parent) * (glm::vec3)transform["Position"]; + position += Transform::AbsoluteOrientation(world, parent) * (glm::vec3)transform["Position"]; entity = parent; } diff --git a/src/Engine/Editor/EditorSystem.cpp b/src/Engine/Editor/EditorSystem.cpp index 613f0edb..13d74a65 100644 --- a/src/Engine/Editor/EditorSystem.cpp +++ b/src/Engine/Editor/EditorSystem.cpp @@ -31,6 +31,9 @@ EditorSystem::EditorSystem(World* world, EventBroker* eventBroker, IRenderer* re m_EditorGUI->SetComponentDeleteCallback(std::bind(&EditorSystem::OnComponentDelete, this, std::placeholders::_1, std::placeholders::_2)); m_EditorGUI->SetWidgetModeCallback(std::bind(&EditorSystem::setWidgetMode, this, std::placeholders::_1)); + EVENT_SUBSCRIBE_MEMBER(m_EMouseRelease, &EditorSystem::OnMouseRelease); + EVENT_SUBSCRIBE_MEMBER(m_EWidgetDelta, &EditorSystem::OnWidgetDelta); + m_EditorStats = new EditorStats(); Events::SetCamera e; @@ -49,11 +52,15 @@ EditorSystem::~EditorSystem() void EditorSystem::Update(double dt) { - m_EditorWorldSystemPipeline->Update(dt); - m_EditorGUI->Draw(); m_EditorStats->Draw(dt); + if (m_CurrentSelection.Valid() && m_Widget.Valid()) { + (glm::vec3&)m_Widget["Transform"]["Position"] = Transform::AbsolutePosition(m_CurrentSelection.World, m_CurrentSelection.ID); + } + + m_EditorWorldSystemPipeline->Update(dt); + m_DebugCameraInputController->Update(dt); m_Camera["Transform"]["Position"] = m_DebugCameraInputController->Position(); m_Camera["Transform"]["Orientation"] = glm::eulerAngles(m_DebugCameraInputController->Orientation()); @@ -103,6 +110,26 @@ void EditorSystem::OnComponentDelete(EntityWrapper entity, const std::string& co entity.World->DeleteComponent(entity.ID, componentType); } +bool EditorSystem::OnMouseRelease(const Events::MouseRelease& e) +{ + if (e.Button == GLFW_MOUSE_BUTTON_1) { + PickData pick = m_Renderer->Pick(glm::vec2(e.X, e.Y)); + if (pick.World == m_World) { + m_CurrentSelection = EntityWrapper(m_World, pick.Entity); + m_EditorGUI->SelectEntity(m_CurrentSelection); + } + } + return true; +} + +bool EditorSystem::OnWidgetDelta(const Events::WidgetDelta& e) +{ + if (m_CurrentSelection.Valid()) { + (glm::vec3&)m_CurrentSelection["Transform"]["Position"] += glm::inverse(Transform::AbsoluteOrientation(m_CurrentSelection.World, m_CurrentSelection.ID)) * e.Translation; + } + return true; +} + EntityWrapper EditorSystem::importEntity(EntityWrapper parent, boost::filesystem::path filePath) { if (parent.World == nullptr) { diff --git a/src/Engine/Editor/EditorWidgetSystem.cpp b/src/Engine/Editor/EditorWidgetSystem.cpp index 3a200e0f..1417f20e 100644 --- a/src/Engine/Editor/EditorWidgetSystem.cpp +++ b/src/Engine/Editor/EditorWidgetSystem.cpp @@ -21,19 +21,30 @@ void EditorWidgetSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper return; } + Events::WidgetDelta e; + EntityWrapper moveEntity = entity.Parent(); if (!moveEntity.Valid()) { moveEntity = entity; } + auto camera = m_PickData.Camera; + glm::vec3 axis = cEditorWidget["Axis"]; + glm::vec2 axisScreen = camera->WorldToScreen(axis, m_Renderer->Resolution()) - camera->WorldToScreen(glm::vec3(0, 0, 0), m_Renderer->Resolution()); + float dot = glm::dot(m_MouseDelta, glm::normalize(axisScreen)) / glm::length(axisScreen); + glm::vec3 worldMovement = dot * axis; + ComponentWrapper::SubscriptProxy& type = cEditorWidget["Type"]; if ((ComponentInfo::EnumType)type == type.Enum("Translate")) { - auto camera = m_PickData.Camera; - glm::vec3 axis = cEditorWidget["Axis"]; - glm::vec2 axisScreen = camera->WorldToScreen(axis, m_Renderer->Resolution()) - camera->WorldToScreen(glm::vec3(0, 0, 0), m_Renderer->Resolution()); - float dot = glm::dot(m_MouseDelta, glm::normalize(axisScreen)) / glm::length(axisScreen); - glm::vec3 worldMovement = dot * axis; - (glm::vec3&)moveEntity["Transform"]["Position"] += worldMovement; + e.Translation += worldMovement; + m_EventBroker->Publish(e); + } else if ((ComponentInfo::EnumType)type == type.Enum("Rotate")) { + //if (glm::length(worldMovement) > 0) { + // glm::vec3& orientation = moveEntity["Transform"]["Orientation"]; + // glm::quat q = glm::quat(orientation); + // q *= glm::quat(glm::vec3(worldMovement)); + // orientation = glm::eulerAngles(q); + //} } m_MouseDelta = glm::vec2(0); From fc06a4babcc75b6827c569fa59b71209997e67cc Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Thu, 21 Jan 2016 15:58:27 +0100 Subject: [PATCH 34/38] Editor keyboard shortcuts: Ctrl+S to save the currently selected entity file (iterates to the base parent) Ctrl+N to create a new empty entity under the selection Ctrl+O to import an entity file Del to delete an entity --- include/Engine/Core/EKeyDown.h | 3 + include/Engine/Core/EKeyUp.h | 3 + include/Engine/Editor/EditorGUI.h | 38 +++- .../Schema/Entities/EditorWidgetRotate.xml | 3 - .../Schema/Entities/EditorWidgetTranslate.xml | 3 - src/Engine/Core/EntityWrapper.cpp | 6 +- src/Engine/Core/InputManager.cpp | 6 + src/Engine/Editor/EditorGUI.cpp | 193 ++++++++++++++---- src/Engine/Editor/EditorSystem.cpp | 22 +- 9 files changed, 210 insertions(+), 67 deletions(-) diff --git a/include/Engine/Core/EKeyDown.h b/include/Engine/Core/EKeyDown.h index 3a506bf4..2745fdef 100644 --- a/include/Engine/Core/EKeyDown.h +++ b/include/Engine/Core/EKeyDown.h @@ -11,6 +11,9 @@ struct KeyDown : Event { /** GLFW key code */ int KeyCode; + bool ModCtrl; + bool ModAlt; + bool ModShift; }; } diff --git a/include/Engine/Core/EKeyUp.h b/include/Engine/Core/EKeyUp.h index c7531a01..2d34f04e 100644 --- a/include/Engine/Core/EKeyUp.h +++ b/include/Engine/Core/EKeyUp.h @@ -11,6 +11,9 @@ struct KeyUp : Event { /** GLFW key code */ int KeyCode; + bool ModCtrl; + bool ModAlt; + bool ModShift; }; } diff --git a/include/Engine/Editor/EditorGUI.h b/include/Engine/Editor/EditorGUI.h index 49e0f8ab..973f6a90 100644 --- a/include/Engine/Editor/EditorGUI.h +++ b/include/Engine/Editor/EditorGUI.h @@ -6,6 +6,7 @@ #include #include #include +#include #include "../Common.h" #include "../GLM.h" #include @@ -16,6 +17,7 @@ #include "../Core/EntityWrapper.h" #include "../Core/ResourceManager.h" #include "../Core/EPause.h" +#include "../Core/EKeyDown.h" #include "../Rendering/Texture.h" class EditorGUI @@ -33,6 +35,7 @@ public: void Draw(); void SelectEntity(EntityWrapper entity); + void SetDirty(EntityWrapper entity); // Called when an entity is selected in the entity tree typedef std::function OnEntitySelectedCallback_t; @@ -75,15 +78,23 @@ private: World* m_World; EventBroker* m_EventBroker; + struct EntityFileInfo + { + boost::filesystem::path Path; + bool Dirty = false; + }; + // Config variables const boost::filesystem::path m_DefaultEntityPath = boost::filesystem::path("Schema") / boost::filesystem::path("Entities"); - // State variables + // State EntityWrapper m_CurrentSelection = EntityWrapper::Invalid; - std::unordered_map m_EntityFiles; + std::unordered_map m_EntityFiles; EntityWrapper m_CurrentlyDragging = EntityWrapper::Invalid; std::string m_LastErrorMessage; WidgetMode m_CurrentWidgetMode = WidgetMode::Translate; + std::set m_ModalsToOpen; + std::map m_ModalData; // Callbacks OnEntitySelectedCallback_t m_OnEntitySelected = nullptr; @@ -97,11 +108,16 @@ private: OnComponentDelete_t m_OnComponentDelete = nullptr; OnWidgetMode_t m_OnWidgetMode = nullptr; + // Events + EventRelay m_EKeyDown; + bool OnKeyDown(const Events::KeyDown& e); + // Utility functions boost::filesystem::path fileOpenDialog(); boost::filesystem::path fileSaveDialog(); const std::string formatEntityName(EntityWrapper entity); GLuint tryLoadTexture(std::string filePath); + void openModal(const std::string& modal); // Entity file handling methods void entityImport(World* world); @@ -118,15 +134,15 @@ private: bool drawEntityNode(EntityWrapper entity); void drawComponents(EntityWrapper entity); bool drawComponentNode(EntityWrapper entity, const ComponentInfo& componentType); - void drawComponentField(ComponentWrapper& c, const ComponentInfo::Field_t& field); - void drawComponentField_Vector(ComponentWrapper &c, const ComponentInfo::Field_t &field); - void drawComponentField_Color(ComponentWrapper &c, const ComponentInfo::Field_t &field); - void drawComponentField_int(ComponentWrapper &c, const ComponentInfo::Field_t &field); - void drawComponentField_enum(ComponentWrapper &c, const ComponentInfo::Field_t &field); - void drawComponentField_float(ComponentWrapper &c, const ComponentInfo::Field_t &field); - void drawComponentField_double(ComponentWrapper &c, const ComponentInfo::Field_t &field); - void drawComponentField_bool(ComponentWrapper &c, const ComponentInfo::Field_t &field); - void drawComponentField_string(ComponentWrapper &c, const ComponentInfo::Field_t &field); + bool drawComponentField(ComponentWrapper& c, const ComponentInfo::Field_t& field); + bool drawComponentField_Vector(ComponentWrapper &c, const ComponentInfo::Field_t &field); + bool drawComponentField_Color(ComponentWrapper &c, const ComponentInfo::Field_t &field); + bool drawComponentField_int(ComponentWrapper &c, const ComponentInfo::Field_t &field); + bool drawComponentField_enum(ComponentWrapper &c, const ComponentInfo::Field_t &field); + bool drawComponentField_float(ComponentWrapper &c, const ComponentInfo::Field_t &field); + bool drawComponentField_double(ComponentWrapper &c, const ComponentInfo::Field_t &field); + bool drawComponentField_bool(ComponentWrapper &c, const ComponentInfo::Field_t &field); + bool drawComponentField_string(ComponentWrapper &c, const ComponentInfo::Field_t &field); void drawModals(); // Custom UI elements diff --git a/resources/Schema/Entities/EditorWidgetRotate.xml b/resources/Schema/Entities/EditorWidgetRotate.xml index 0a8f06b8..6a5f72ea 100644 --- a/resources/Schema/Entities/EditorWidgetRotate.xml +++ b/resources/Schema/Entities/EditorWidgetRotate.xml @@ -9,7 +9,6 @@ - @@ -25,7 +24,6 @@ - @@ -41,7 +39,6 @@ - diff --git a/resources/Schema/Entities/EditorWidgetTranslate.xml b/resources/Schema/Entities/EditorWidgetTranslate.xml index 70ca09a8..75d96a51 100644 --- a/resources/Schema/Entities/EditorWidgetTranslate.xml +++ b/resources/Schema/Entities/EditorWidgetTranslate.xml @@ -12,7 +12,6 @@ - @@ -25,7 +24,6 @@ - @@ -38,7 +36,6 @@ - diff --git a/src/Engine/Core/EntityWrapper.cpp b/src/Engine/Core/EntityWrapper.cpp index 58dd1ee6..98b9c7d4 100644 --- a/src/Engine/Core/EntityWrapper.cpp +++ b/src/Engine/Core/EntityWrapper.cpp @@ -10,7 +10,11 @@ bool EntityWrapper::HasComponent(const std::string& componentName) EntityWrapper EntityWrapper::Parent() { - return EntityWrapper(World, World->GetParent(ID)); + if (this->World == nullptr || this->ID == EntityID_Invalid) { + return EntityWrapper::Invalid; + } else { + return EntityWrapper(this->World, this->World->GetParent(this->ID)); + } } bool EntityWrapper::Valid() diff --git a/src/Engine/Core/InputManager.cpp b/src/Engine/Core/InputManager.cpp index 50dcac7c..941cc223 100644 --- a/src/Engine/Core/InputManager.cpp +++ b/src/Engine/Core/InputManager.cpp @@ -34,10 +34,16 @@ void InputManager::Update(double dt) if (m_CurrentKeyState[i]) { Events::KeyDown e; e.KeyCode = i; + e.ModCtrl = glfwGetKey(m_GLFWWindow, GLFW_KEY_LEFT_CONTROL) || glfwGetKey(m_GLFWWindow, GLFW_KEY_RIGHT_CONTROL); + e.ModAlt = glfwGetKey(m_GLFWWindow, GLFW_KEY_LEFT_ALT) || glfwGetKey(m_GLFWWindow, GLFW_KEY_RIGHT_ALT); + e.ModShift = glfwGetKey(m_GLFWWindow, GLFW_KEY_LEFT_SHIFT) || glfwGetKey(m_GLFWWindow, GLFW_KEY_RIGHT_SHIFT); m_EventBroker->Publish(e); } else { Events::KeyUp e; e.KeyCode = i; + e.ModCtrl = glfwGetKey(m_GLFWWindow, GLFW_KEY_LEFT_CONTROL) || glfwGetKey(m_GLFWWindow, GLFW_KEY_RIGHT_CONTROL); + e.ModAlt = glfwGetKey(m_GLFWWindow, GLFW_KEY_LEFT_ALT) || glfwGetKey(m_GLFWWindow, GLFW_KEY_RIGHT_ALT); + e.ModShift = glfwGetKey(m_GLFWWindow, GLFW_KEY_LEFT_SHIFT) || glfwGetKey(m_GLFWWindow, GLFW_KEY_RIGHT_SHIFT); m_EventBroker->Publish(e); } } diff --git a/src/Engine/Editor/EditorGUI.cpp b/src/Engine/Editor/EditorGUI.cpp index d5638d31..390e69a5 100644 --- a/src/Engine/Editor/EditorGUI.cpp +++ b/src/Engine/Editor/EditorGUI.cpp @@ -4,7 +4,7 @@ EditorGUI::EditorGUI(World* world, EventBroker* eventBroker) : m_World(world) , m_EventBroker(eventBroker) { - + EVENT_SUBSCRIBE_MEMBER(m_EKeyDown, &EditorGUI::OnKeyDown); } void EditorGUI::Draw() @@ -14,6 +14,7 @@ void EditorGUI::Draw() drawTools(); drawEntities(m_World); drawComponents(m_CurrentSelection); + drawModals(); } void EditorGUI::SelectEntity(EntityWrapper entity) @@ -111,6 +112,7 @@ void EditorGUI::drawEntities(World* world) if (m_CurrentSelection.Valid()) { if (m_OnEntityChangeName != nullptr) { m_OnEntityChangeName(m_CurrentSelection, std::string(buffer)); + SetDirty(m_CurrentSelection); } } } @@ -120,8 +122,6 @@ void EditorGUI::drawEntities(World* world) drawEntitiesRecursive(world, EntityID_Invalid); - // Draw any potential modals before ending this scope - drawModals(); ImGui::End(); } @@ -167,10 +167,10 @@ bool EditorGUI::drawEntityNode(EntityWrapper entity) ImGui::Text(formatEntityName(entity).c_str()); ImGui::End(); } - } else if (m_CurrentlyDragging == entity) { + }/* else if (m_CurrentlyDragging == entity) { LOG_DEBUG("Stopped dragging %i", entity.ID); m_CurrentlyDragging = EntityWrapper::Invalid; - } + }*/ // Entity context menu std::string contextMenuUniqueID = std::string("EntityContextMenu") + std::to_string(entity.ID); if (hovered && ImGui::IsMouseClicked(1)) { @@ -190,7 +190,6 @@ bool EditorGUI::drawEntityNode(EntityWrapper entity) if (ImGui::MenuItem("Move to root")) { entityChangeParent(entity, EntityWrapper::Invalid); } - drawModals(); ImGui::EndPopup(); } @@ -242,6 +241,7 @@ void EditorGUI::drawComponents(EntityWrapper entity) if (m_OnComponentAttach != nullptr) { std::string chosenComponentType(componentTypes.at(selectedItem)); m_OnComponentAttach(entity, chosenComponentType); + SetDirty(entity); } } } @@ -287,7 +287,10 @@ bool EditorGUI::drawComponentNode(EntityWrapper entity, const ComponentInfo& ci) const ComponentInfo::Field_t& field = kv.second; // Draw the field widget based on its type - drawComponentField(component, field); + bool dirty = drawComponentField(component, field); + if (dirty) { + SetDirty(entity); + } ImGui::SameLine(); // Draw field name ImGui::Text(fieldName.c_str()); @@ -305,70 +308,76 @@ bool EditorGUI::drawComponentNode(EntityWrapper entity, const ComponentInfo& ci) return true; } -void EditorGUI::drawComponentField(ComponentWrapper& c, const ComponentInfo::Field_t& field) +bool EditorGUI::drawComponentField(ComponentWrapper& c, const ComponentInfo::Field_t& field) { // Push an unique widget id so different components with fields with equal names are still counted as different ImGui::PushID((c.Info.Name + field.Name).c_str()); + bool dirty = false; + if (field.Type == "Vector") { - drawComponentField_Vector(c, field); + dirty = drawComponentField_Vector(c, field); } else if (field.Type == "Color") { - drawComponentField_Color(c, field); + dirty = drawComponentField_Color(c, field); //} else if (field.Type == "Quaternion") { } else if (field.Type == "int") { - drawComponentField_int(c, field); + dirty = drawComponentField_int(c, field); } else if (field.Type == "enum") { - drawComponentField_enum(c, field); + dirty = drawComponentField_enum(c, field); } else if (field.Type == "float") { - drawComponentField_float(c, field); + dirty = drawComponentField_float(c, field); } else if (field.Type == "double") { - drawComponentField_double(c, field); + dirty = drawComponentField_double(c, field); } else if (field.Type == "bool") { - drawComponentField_bool(c, field); + dirty = drawComponentField_bool(c, field); } else if (field.Type == "string") { - drawComponentField_string(c, field); + dirty = drawComponentField_string(c, field); } else { ImGui::TextDisabled(field.Type.c_str()); } ImGui::PopID(); + + return dirty; } -void EditorGUI::drawComponentField_Vector(ComponentWrapper &c, const ComponentInfo::Field_t &field) +bool EditorGUI::drawComponentField_Vector(ComponentWrapper &c, const ComponentInfo::Field_t &field) { auto& val = c.Field(field.Name); if (field.Name == "Scale") { // Limit scale values to a minimum of 0 - ImGui::DragFloat3("", glm::value_ptr(val), 0.1f, 0.f, std::numeric_limits::max()); + return ImGui::DragFloat3("", glm::value_ptr(val), 0.1f, 0.f, std::numeric_limits::max()); } else if (field.Name == "Orientation") { // Make orentations have a period of 2*Pi glm::vec3 tempVal = glm::fmod(val, glm::vec3(glm::two_pi())); if (ImGui::SliderFloat3("", glm::value_ptr(tempVal), 0.f, glm::two_pi())) { val = tempVal; + return true; + } else { + return false; } } else { - ImGui::DragFloat3("", glm::value_ptr(val), 0.1f, std::numeric_limits::lowest(), std::numeric_limits::max()); + return ImGui::DragFloat3("", glm::value_ptr(val), 0.1f, std::numeric_limits::lowest(), std::numeric_limits::max()); } } -void EditorGUI::drawComponentField_Color(ComponentWrapper &c, const ComponentInfo::Field_t &field) +bool EditorGUI::drawComponentField_Color(ComponentWrapper &c, const ComponentInfo::Field_t &field) { auto& val = c.Field(field.Name); - ImGui::ColorEdit4("", glm::value_ptr(val), true); + return ImGui::ColorEdit4("", glm::value_ptr(val), true); } -void EditorGUI::drawComponentField_int(ComponentWrapper &c, const ComponentInfo::Field_t &field) +bool EditorGUI::drawComponentField_int(ComponentWrapper &c, const ComponentInfo::Field_t &field) { auto& val = c.Field(field.Name); - ImGui::InputInt("", &val); + return ImGui::InputInt("", &val); } -void EditorGUI::drawComponentField_enum(ComponentWrapper &c, const ComponentInfo::Field_t &field) +bool EditorGUI::drawComponentField_enum(ComponentWrapper &c, const ComponentInfo::Field_t &field) { auto fieldEnumDefIt = c.Info.Meta->FieldEnumDefinitions.find(field.Name); if (fieldEnumDefIt == c.Info.Meta->FieldEnumDefinitions.end()) { - drawComponentField_int(c, field); - return; + return drawComponentField_int(c, field); } auto& val = c.Field(field.Name); @@ -386,30 +395,36 @@ void EditorGUI::drawComponentField_enum(ComponentWrapper &c, const ComponentInfo } if (ImGui::Combo("", &selectedItem, enumKeys.str().c_str())) { val = enumValues.at(selectedItem); + return true; + } else { + return false; } } -void EditorGUI::drawComponentField_float(ComponentWrapper &c, const ComponentInfo::Field_t &field) +bool EditorGUI::drawComponentField_float(ComponentWrapper &c, const ComponentInfo::Field_t &field) { auto& val = c.Field(field.Name); - ImGui::InputFloat("", &val, 0.01f, 1.f); + return ImGui::InputFloat("", &val, 0.01f, 1.f); } -void EditorGUI::drawComponentField_double(ComponentWrapper &c, const ComponentInfo::Field_t &field) +bool EditorGUI::drawComponentField_double(ComponentWrapper &c, const ComponentInfo::Field_t &field) { float tempVal = static_cast(c.Field(field.Name)); if (ImGui::InputFloat("", &tempVal, 0.01f, 1.f)) { c.SetField(field.Name, static_cast(tempVal)); + return true; + } else { + return false; } } -void EditorGUI::drawComponentField_bool(ComponentWrapper &c, const ComponentInfo::Field_t &field) +bool EditorGUI::drawComponentField_bool(ComponentWrapper &c, const ComponentInfo::Field_t &field) { auto& val = c.Field(field.Name); - ImGui::Checkbox("", &val); + return ImGui::Checkbox("", &val); } -void EditorGUI::drawComponentField_string(ComponentWrapper &c, const ComponentInfo::Field_t &field) +bool EditorGUI::drawComponentField_string(ComponentWrapper &c, const ComponentInfo::Field_t &field) { auto& val = c.Field(field.Name); char tempString[1024]; // Let's just hope this is an sufficiently large buffer for strings :) @@ -418,12 +433,20 @@ void EditorGUI::drawComponentField_string(ComponentWrapper &c, const ComponentIn memcpy(tempString, val.c_str(), std::min(val.length() + 1, sizeof(tempString) - 1)); if (ImGui::InputText("", tempString, sizeof(tempString))) { val = std::string(tempString); + return true; + } else { + return false; } // TODO: Handle drag and drop of files } void EditorGUI::drawModals() { + for (auto& modal : m_ModalsToOpen) { + ImGui::OpenPopup(modal.c_str()); + } + m_ModalsToOpen.clear(); + if (ImGui::BeginPopupModal("Import failed", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) { ImGui::Text("Entity import failed. Check console for more information.\n\n"); ImGui::SetCursorPosX(ImGui::GetContentRegionAvailWidth() - 120); @@ -441,6 +464,26 @@ void EditorGUI::drawModals() } ImGui::EndPopup(); } + + if (ImGui::BeginPopupModal("Confirm deletion", nullptr, ImGuiWindowFlags_AlwaysAutoResize)) { + if (m_ModalData.count("Confirm deletion") == 0) { + ImGui::CloseCurrentPopup(); + } + + ImGui::Text("Are you sure you want to delete entity \"%s\"?", formatEntityName(m_CurrentSelection).c_str()); + ImGui::ItemSize(ImVec2(5.f, 0.f)); + ImGui::SetCursorPosX(ImGui::GetContentRegionAvailWidth() - 2*60); + if (ImGui::Button("Delete (Del)", ImVec2(60, 0))) { + entityDelete(boost::any_cast(m_ModalData.at("Confirm deletion"))); + ImGui::CloseCurrentPopup(); + } + ImGui::SameLine(); + if (ImGui::Button("Cancel", ImVec2(60, 0))) { + m_ModalData.erase("Confirm deletion"); + ImGui::CloseCurrentPopup(); + } + ImGui::EndPopup(); + } } bool EditorGUI::createDeleteButton(const std::string& componentType) @@ -492,6 +535,35 @@ void EditorGUI::createWidgetToolButton(WidgetMode mode) } } +bool EditorGUI::OnKeyDown(const Events::KeyDown& e) +{ + if (e.ModCtrl && e.KeyCode == GLFW_KEY_S) { + if (m_CurrentSelection.Valid()) { + EntityWrapper baseParent = m_CurrentSelection; + while (baseParent.Parent().Valid()) { + baseParent = baseParent.Parent(); + } + entitySave(baseParent); + } + } + + if (e.ModCtrl && e.KeyCode == GLFW_KEY_N) { + entityCreate(m_World, m_CurrentSelection); + } + + if (e.ModCtrl && e.KeyCode == GLFW_KEY_O) { + entityImport(m_World); + } + + if (e.KeyCode == GLFW_KEY_DELETE) { + if (m_CurrentSelection.Valid()) { + entityDelete(m_CurrentSelection); + } + } + + return true; +} + boost::filesystem::path EditorGUI::fileOpenDialog() { namespace bfs = boost::filesystem; @@ -540,7 +612,10 @@ const std::string EditorGUI::formatEntityName(EntityWrapper entity) } if (m_EntityFiles.count(entity) == 1) { - name << " (" << m_EntityFiles.at(entity).filename().string() << ")"; + name << " (" << m_EntityFiles.at(entity).Path.filename().string() << ")"; + if (m_EntityFiles.at(entity).Dirty) { + name << "*"; + } } return name.str(); @@ -555,6 +630,22 @@ GLuint EditorGUI::tryLoadTexture(std::string filePath) return texture; } +void EditorGUI::openModal(const std::string& modal) +{ + m_ModalsToOpen.insert(modal); +} + +void EditorGUI::SetDirty(EntityWrapper entity) +{ + EntityWrapper baseParent = entity; + while (baseParent.Parent().Valid()) { + baseParent = baseParent.Parent(); + } + if (m_EntityFiles.find(baseParent) != m_EntityFiles.end()) { + m_EntityFiles.at(baseParent).Dirty = true; + } +} + void EditorGUI::entityImport(World* world) { boost::filesystem::path filePath = fileOpenDialog(); @@ -564,10 +655,10 @@ void EditorGUI::entityImport(World* world) EntityWrapper entity = m_OnEntityImport(EntityWrapper(world, EntityID_Invalid), filePath); if (entity.Valid()) { - m_EntityFiles[entity] = filePath; + m_EntityFiles[entity].Path = filePath; SelectEntity(entity); } else { - ImGui::OpenPopup("Import failed"); + openModal("Import failed"); } } @@ -575,7 +666,7 @@ void EditorGUI::entitySave(EntityWrapper entity, bool saveAs /* = false */) { boost::filesystem::path filePath; if (!saveAs && m_EntityFiles.count(entity) == 1) { - filePath = m_EntityFiles.at(entity); + filePath = m_EntityFiles.at(entity).Path; } else { filePath = fileSaveDialog(); } @@ -586,10 +677,11 @@ void EditorGUI::entitySave(EntityWrapper entity, bool saveAs /* = false */) try { m_OnEntitySave(entity, filePath); - m_EntityFiles[entity] = filePath; + m_EntityFiles[entity].Path = filePath; + m_EntityFiles[entity].Dirty = false; } catch (const std::exception& e) { m_LastErrorMessage = e.what(); - ImGui::OpenPopup("Save failed"); + openModal("Save failed"); } } @@ -607,12 +699,24 @@ void EditorGUI::entityCreate(World* world, EntityWrapper parent) void EditorGUI::entityDelete(EntityWrapper entity) { - if (m_OnEntityDelete != nullptr) { - m_OnEntityDelete(entity); - m_EntityFiles.erase(entity); - } - if (!m_CurrentSelection.Valid()) { - SelectEntity(EntityWrapper::Invalid); + std::string modalName = "Confirm deletion"; + + if (m_ModalData.count(modalName) == 0) { + m_ModalData[modalName] = entity; + openModal(modalName); + } else { + if (boost::any_cast(m_ModalData[modalName]) == entity) { + EntityWrapper parent = entity.Parent(); + if (m_OnEntityDelete != nullptr) { + SetDirty(entity); + m_OnEntityDelete(entity); + m_EntityFiles.erase(entity); + } + if (!m_CurrentSelection.Valid()) { + SelectEntity(parent); + } + } + m_ModalData.erase(modalName); } } @@ -623,6 +727,7 @@ void EditorGUI::entityChangeParent(EntityWrapper entity, EntityWrapper parent) } if (m_OnEntityChangeParent != nullptr) { + SetDirty(entity); m_OnEntityChangeParent(entity, parent); LOG_DEBUG("Changed parent of %i to %i", entity.ID, parent.ID); } diff --git a/src/Engine/Editor/EditorSystem.cpp b/src/Engine/Editor/EditorSystem.cpp index 13d74a65..116ad4cc 100644 --- a/src/Engine/Editor/EditorSystem.cpp +++ b/src/Engine/Editor/EditorSystem.cpp @@ -52,6 +52,7 @@ EditorSystem::~EditorSystem() void EditorSystem::Update(double dt) { + m_EventBroker->Process(); m_EditorGUI->Draw(); m_EditorStats->Draw(dt); @@ -87,27 +88,37 @@ EntityWrapper EditorSystem::OnEntityCreate(EntityWrapper parent) void EditorSystem::OnEntityDelete(EntityWrapper entity) { - entity.World->DeleteEntity(entity.ID); + if (entity.Valid()) { + entity.World->DeleteEntity(entity.ID); + } } void EditorSystem::OnEntityChangeParent(EntityWrapper entity, EntityWrapper parent) { - entity.World->SetParent(entity.ID, parent.ID); + if (entity.Valid()) { + entity.World->SetParent(entity.ID, parent.ID); + } } void EditorSystem::OnEntityChangeName(EntityWrapper entity, const std::string& name) { - entity.World->SetName(entity.ID, name); + if (entity.Valid()) { + entity.World->SetName(entity.ID, name); + } } void EditorSystem::OnComponentAttach(EntityWrapper entity, const std::string& componentType) { - entity.World->AttachComponent(entity.ID, componentType); + if (entity.Valid()) { + entity.World->AttachComponent(entity.ID, componentType); + } } void EditorSystem::OnComponentDelete(EntityWrapper entity, const std::string& componentType) { - entity.World->DeleteComponent(entity.ID, componentType); + if (entity.Valid()) { + entity.World->DeleteComponent(entity.ID, componentType); + } } bool EditorSystem::OnMouseRelease(const Events::MouseRelease& e) @@ -126,6 +137,7 @@ bool EditorSystem::OnWidgetDelta(const Events::WidgetDelta& e) { if (m_CurrentSelection.Valid()) { (glm::vec3&)m_CurrentSelection["Transform"]["Position"] += glm::inverse(Transform::AbsoluteOrientation(m_CurrentSelection.World, m_CurrentSelection.ID)) * e.Translation; + m_EditorGUI->SetDirty(m_CurrentSelection); } return true; } From 43b8fd29f62a52f4035eb24aa87df2d398ea7fea Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Thu, 21 Jan 2016 16:21:20 +0100 Subject: [PATCH 35/38] Fixed widget world movement --- src/Engine/Editor/EditorSystem.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Engine/Editor/EditorSystem.cpp b/src/Engine/Editor/EditorSystem.cpp index 116ad4cc..1ef8b02b 100644 --- a/src/Engine/Editor/EditorSystem.cpp +++ b/src/Engine/Editor/EditorSystem.cpp @@ -136,7 +136,12 @@ bool EditorSystem::OnMouseRelease(const Events::MouseRelease& e) bool EditorSystem::OnWidgetDelta(const Events::WidgetDelta& e) { if (m_CurrentSelection.Valid()) { - (glm::vec3&)m_CurrentSelection["Transform"]["Position"] += glm::inverse(Transform::AbsoluteOrientation(m_CurrentSelection.World, m_CurrentSelection.ID)) * e.Translation; + glm::quat parentOrientation; + EntityWrapper parent = m_CurrentSelection.Parent(); + if (parent.Valid()) { + parentOrientation = glm::inverse(Transform::AbsoluteOrientation(parent.World, parent.ID)); + } + (glm::vec3&)m_CurrentSelection["Transform"]["Position"] += parentOrientation * e.Translation; m_EditorGUI->SetDirty(m_CurrentSelection); } return true; From 1c6750f5b03bf711e6f428191e4f37208846a5f1 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Thu, 21 Jan 2016 16:37:35 +0100 Subject: [PATCH 36/38] Fixed uniform scale on editor widgets --- resources/Schema/Entities/EditorWidget.xml | 79 ------------------- .../Schema/Entities/EditorWidgetRotate.xml | 3 + .../Schema/Entities/EditorWidgetTranslate.xml | 3 + 3 files changed, 6 insertions(+), 79 deletions(-) delete mode 100755 resources/Schema/Entities/EditorWidget.xml diff --git a/resources/Schema/Entities/EditorWidget.xml b/resources/Schema/Entities/EditorWidget.xml deleted file mode 100755 index e729af02..00000000 --- a/resources/Schema/Entities/EditorWidget.xml +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - Models/TranslationWidgetOrigin.obj - - - - - - - - Models/TranslationWidgetX.obj - - - - - - - - Models/TranslationWidgetY.obj - - - - - - - - Models/TranslationWidgetZ.obj - - - - - - - - Models/WidgetPlaneX.obj - - - - - - - - Models/WidgetPlaneY.obj - - - - - - - - Models/WidgetPlaneZ.obj - - - - - - diff --git a/resources/Schema/Entities/EditorWidgetRotate.xml b/resources/Schema/Entities/EditorWidgetRotate.xml index 6a5f72ea..b918794e 100644 --- a/resources/Schema/Entities/EditorWidgetRotate.xml +++ b/resources/Schema/Entities/EditorWidgetRotate.xml @@ -3,6 +3,9 @@ + + + diff --git a/resources/Schema/Entities/EditorWidgetTranslate.xml b/resources/Schema/Entities/EditorWidgetTranslate.xml index 75d96a51..a9b7eaff 100644 --- a/resources/Schema/Entities/EditorWidgetTranslate.xml +++ b/resources/Schema/Entities/EditorWidgetTranslate.xml @@ -6,6 +6,9 @@ Models/TranslationWidgetOrigin.obj + + + From 254caf9e5dcc46dc11df9028b3283a84a932c9e9 Mon Sep 17 00:00:00 2001 From: viktorljung Date: Thu, 21 Jan 2016 16:49:20 +0100 Subject: [PATCH 37/38] Picking depthbuffer fix --- src/Engine/Rendering/DrawFinalPass.cpp | 4 ++++ src/Engine/Rendering/PickingPass.cpp | 4 +++- src/Engine/Rendering/Renderer.cpp | 4 +--- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Engine/Rendering/DrawFinalPass.cpp b/src/Engine/Rendering/DrawFinalPass.cpp index 45dafa71..eeaa7bb3 100644 --- a/src/Engine/Rendering/DrawFinalPass.cpp +++ b/src/Engine/Rendering/DrawFinalPass.cpp @@ -31,6 +31,10 @@ void DrawFinalPass::Draw(RenderScene& scene) m_ForwardPlusProgram->Bind(); GLuint shaderHandle = m_ForwardPlusProgram->GetHandle(); + if (scene.ClearDepth) { + glClear(GL_DEPTH_BUFFER_BIT); + } + glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, m_LightCullingPass->LightSSBO()); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 2, m_LightCullingPass->LightGridSSBO()); glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 4, m_LightCullingPass->LightIndexSSBO()); diff --git a/src/Engine/Rendering/PickingPass.cpp b/src/Engine/Rendering/PickingPass.cpp index 6800df1d..3b5ade59 100644 --- a/src/Engine/Rendering/PickingPass.cpp +++ b/src/Engine/Rendering/PickingPass.cpp @@ -53,7 +53,9 @@ void PickingPass::Draw(RenderScene& scene) GLuint ShaderHandle = m_PickingProgram->GetHandle(); m_PickingProgram->Bind(); - + if (scene.ClearDepth) { + glClear(GL_DEPTH_BUFFER_BIT); + } m_Camera = scene.Camera; diff --git a/src/Engine/Rendering/Renderer.cpp b/src/Engine/Rendering/Renderer.cpp index 858fb6dc..c0347612 100644 --- a/src/Engine/Rendering/Renderer.cpp +++ b/src/Engine/Rendering/Renderer.cpp @@ -87,9 +87,7 @@ void Renderer::Draw(RenderFrame& frame) m_PickingPass->ClearPicking(); for (auto scene : frame.RenderScenes){ - if (scene->ClearDepth) { - glClear(GL_DEPTH_BUFFER_BIT); - } + SortRenderJobsByDepth(*scene); m_PickingPass->Draw(*scene); m_LightCullingPass->GenerateNewFrustum(*scene); From 75dcdcec414b4f5632f5ade7a091d0754aeacdb4 Mon Sep 17 00:00:00 2001 From: sippeangelo Date: Thu, 21 Jan 2016 17:00:47 +0100 Subject: [PATCH 38/38] Fixed inconsistent editor input controls. Left mouse = select and move. Right mouse = camera. --- include/Engine/Editor/EditorSystemOld.h | 93 --- include/Engine/Editor/EditorWidgetSystem.h | 4 - .../Rendering/DebugCameraInputController.h | 37 +- src/Engine/Editor/EditorSystemOld.cpp | 736 ------------------ src/Engine/Editor/EditorWidgetSystem.cpp | 15 +- 5 files changed, 26 insertions(+), 859 deletions(-) delete mode 100644 include/Engine/Editor/EditorSystemOld.h delete mode 100644 src/Engine/Editor/EditorSystemOld.cpp diff --git a/include/Engine/Editor/EditorSystemOld.h b/include/Engine/Editor/EditorSystemOld.h deleted file mode 100644 index d49c3542..00000000 --- a/include/Engine/Editor/EditorSystemOld.h +++ /dev/null @@ -1,93 +0,0 @@ -#include -#include -#include -#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 "../Core/Transform.h" -#include "../Core/EFileDropped.h" -#include "../Core/EntityFilePreprocessor.h" -#include "../Core/EntityFileParser.h" -#include "../Core/EntityFileWriter.h" - -class EditorSystemOld : public ImpureSystem -{ -public: - EditorSystemOld(World* world, EventBroker* eventBroker, IRenderer* renderer); - - virtual void Update(double dt) override; - -private: - IRenderer* m_Renderer; - Camera* m_Camera = nullptr; - - bool m_Enabled; - bool m_Visible; - boost::filesystem::path m_DefaultEntityDir; - boost::filesystem::path m_CurrentFile; - 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 = EntityID_Invalid; - EntityID m_WidgetX = EntityID_Invalid; - EntityID m_WidgetPlaneX = EntityID_Invalid; - EntityID m_WidgetY = EntityID_Invalid; - EntityID m_WidgetPlaneY = EntityID_Invalid; - EntityID m_WidgetZ = EntityID_Invalid; - EntityID m_WidgetPlaneZ = EntityID_Invalid; - EntityID m_WidgetOrigin = EntityID_Invalid; - glm::vec3 m_WidgetCurrentAxis; - float m_WidgetPickingDepth = 0.f; - glm::vec3 m_WidgetPickingPosition = glm::vec3(0); - - EntityID m_Selection = EntityID_Invalid; - EntityID m_LastSelection = EntityID_Invalid; - EntityID m_UIDraggingEntity = EntityID_Invalid; - glm::vec3 m_Position; - std::string m_LastDroppedFile; - - static boost::filesystem::path openDialog(boost::filesystem::path defaultPath); - static boost::filesystem::path saveDialog(boost::filesystem::path defaultPath); - - 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_EFileDropped; - bool OnFileDropped(const Events::FileDropped& e); - - void Picking(); - void createWidget(); - void updateWidget(); - void setWidgetMode(WidgetMode newMode); - void setWidgetSpace(WidgetSpace space); - void drawUI(World* world, double dt); - bool createDeleteButton(std::string componentType); - bool createEntityNode(World* world, EntityID entity); - void changeParent(EntityID entity, EntityID newParent); - void fileImport(World* world); - void fileSave(World* world); - void fileSaveAs(World* world); -}; \ No newline at end of file diff --git a/include/Engine/Editor/EditorWidgetSystem.h b/include/Engine/Editor/EditorWidgetSystem.h index a2329342..a060bdd5 100644 --- a/include/Engine/Editor/EditorWidgetSystem.h +++ b/include/Engine/Editor/EditorWidgetSystem.h @@ -30,10 +30,6 @@ public: virtual void Update(double dt) override; virtual void UpdateComponent(EntityWrapper& entity, ComponentWrapper& cEditorWidget, double dt) override; - void debugPrintVector(const char* name, glm::vec3 axisNDC); - - void debugPrintVector(const char* name, glm::vec4 axisNDC); - void debugPrintVector(const char* name, glm::vec2 axisNDC); private: IRenderer* m_Renderer; diff --git a/include/Engine/Rendering/DebugCameraInputController.h b/include/Engine/Rendering/DebugCameraInputController.h index 1a43820c..5ce85b3f 100644 --- a/include/Engine/Rendering/DebugCameraInputController.h +++ b/include/Engine/Rendering/DebugCameraInputController.h @@ -3,6 +3,8 @@ #include #include "../Input/FirstPersonInputController.h" +#include "../Core/EMousePress.h" +#include "../Core/EMouseRelease.h" template class DebugCameraInputController : public FirstPersonInputController @@ -10,7 +12,10 @@ class DebugCameraInputController : public FirstPersonInputController 0) { - if (!io.WantCaptureMouse) { - LockMouse(); - } - } else { - UnlockMouse(); - } - return false; - } - if (!io.WantCaptureKeyboard) { if (e.Command == "Right") { float value = std::max(-1.f, std::min(e.Value, 1.f)); @@ -66,6 +60,25 @@ protected: glm::vec3 m_Velocity = glm::vec3(0, 0, 0); float m_BaseSpeed = 2.0f; float m_Speed = m_BaseSpeed; + EventRelay m_EMousePress; + bool OnMousePress(const Events::MousePress& e) + { + if (e.Button == GLFW_MOUSE_BUTTON_2) { + ImGuiIO& io = ImGui::GetIO(); + if (!io.WantCaptureMouse) { + LockMouse(); + } + } + return true; + } + EventRelay m_EMouseRelease; + bool OnMouseRelease(const Events::MouseRelease& e) + { + if (e.Button == GLFW_MOUSE_BUTTON_2) { + UnlockMouse(); + } + return true; + } }; #endif \ No newline at end of file diff --git a/src/Engine/Editor/EditorSystemOld.cpp b/src/Engine/Editor/EditorSystemOld.cpp deleted file mode 100644 index 332bef05..00000000 --- a/src/Engine/Editor/EditorSystemOld.cpp +++ /dev/null @@ -1,736 +0,0 @@ -#include "Editor/EditorSystemOld.h" -#define IMGUI_DEFINE_MATH_OPERATORS -#include - -EditorSystemOld::EditorSystemOld(World* world, EventBroker* eventBroker, IRenderer* renderer) - : System(world, eventBroker) - , ImpureSystem() - , m_Renderer(renderer) -{ - auto config = ResourceManager::Load("Config.ini"); - m_Enabled = config->Get("Debug.EditorEnabled", false); - m_Visible = m_Enabled; - m_DefaultEntityDir = boost::filesystem::path("Schema") / boost::filesystem::path("Entities"); - - if (!m_Enabled) { - return; - } - - EVENT_SUBSCRIBE_MEMBER(m_EInputCommand, &EditorSystemOld::OnInputCommand); - EVENT_SUBSCRIBE_MEMBER(m_EMousePress, &EditorSystemOld::OnMousePress); - EVENT_SUBSCRIBE_MEMBER(m_EMouseRelease, &EditorSystemOld::OnMouseRelease); - EVENT_SUBSCRIBE_MEMBER(m_EMouseMove, &EditorSystemOld::OnMouseMove); - EVENT_SUBSCRIBE_MEMBER(m_EFileDropped, &EditorSystemOld::OnFileDropped); -} - -void EditorSystemOld::Update(double dt) -{ - if (!m_Enabled) { - return; - } - - if (!m_Visible) { - return; - } - Picking(); - updateWidget(); - - drawUI(m_World, dt); - - // Clear drop queue if it wasn't handled by any UI element - if (!m_LastDroppedFile.empty()) { - m_LastDroppedFile = ""; - } -} - - -boost::filesystem::path EditorSystemOld::openDialog(boost::filesystem::path defaultPath) -{ - namespace bfs = boost::filesystem; - auto absolutePath = bfs::absolute(defaultPath); - nfdchar_t* outPath = nullptr; - nfdresult_t result = NFD_OpenDialog(NULL, absolutePath.string().c_str(), &outPath); - if (result == NFD_ERROR) { - LOG_ERROR("NFD Error: %s", NFD_GetError()); - return bfs::path(); - } - - return bfs::absolute(outPath); -} - -boost::filesystem::path EditorSystemOld::saveDialog(boost::filesystem::path defaultPath) -{ - namespace bfs = boost::filesystem; - auto absolutePath = bfs::absolute(defaultPath); - nfdchar_t* outPath = nullptr; - nfdresult_t result = NFD_SaveDialog(NULL, absolutePath.string().c_str(), &outPath); - if (result == NFD_ERROR) { - LOG_ERROR("NFD Error: %s", NFD_GetError()); - return bfs::path(); - } - - return bfs::absolute(outPath); -} - -bool EditorSystemOld::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; -} - -bool EditorSystemOld::OnMousePress(const Events::MousePress& e) -{ - if (e.Button == GLFW_MOUSE_BUTTON_RIGHT) { - m_PickingQueue.push_back(glm::vec2((int)e.X, (int)e.Y)); - } - return true; -} - -bool EditorSystemOld::OnMouseMove(const Events::MouseMove& e) -{ - if (m_Widget == EntityID_Invalid) { - return false; - } - if (m_Selection == EntityID_Invalid) { - return false; - } - if (m_Selection == m_Widget) { - return false; - } - // TODO: No widgets for root entity until widgets reside in thier own world, - // or the widgets will move relative to the root entity being moved, which is WEEEIRD. - if (m_Selection == 0) { - return false; - } - if (m_Camera == nullptr) { - return false; - } - - auto widgetTransform = m_World->GetComponent(m_Widget, "Transform"); - glm::vec3 widgetOrientation = widgetTransform["Orientation"]; - glm::quat totalOrientation = m_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_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_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) { - EntityID parent = m_World->GetParent(m_Selection); - glm::quat inverseParentOrientation; - //if (parent != 0) { - inverseParentOrientation = glm::inverse(Transform::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; - } - } 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; - if (m_WidgetSpace == WidgetSpace::Global) { - EntityID parent = m_World->GetParent(m_Selection); - glm::quat parentOrientation; - //if (parent != 0) { - // parentOrientation = RenderSystem::AbsoluteOrientation(m_World, parent); - //} - glm::vec3& selectionOrientation = m_World->GetComponent(m_Selection, "Transform")["Orientation"]; - glm::quat currentOrientation = Transform::AbsoluteOrientation(m_World, m_Selection); - //glm::quat currentOrientation = parentOrientation * glm::quat(selectionOrientation); - glm::quat deltaOrientation(finalMovement); - 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); - } - } 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 && 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; - } - if (m_WidgetCurrentAxis.y > 0) { - scaleY.y += movement.y; - } - if (m_WidgetCurrentAxis.z > 0) { - scaleZ.z += movement.z; - } - (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; -} - -bool EditorSystemOld::OnMouseRelease(const Events::MouseRelease& e) -{ - if (glm::length2(m_WidgetCurrentAxis) > 0.f) { - m_WidgetCurrentAxis = glm::vec3(0.f); - //setWidgetMode(m_WidgetMode); - } - - return true; -} - -void EditorSystemOld::Picking() -{ - for (auto& pos : m_PickingQueue) { - auto result = m_Renderer->Pick(pos); - EntityID entity = result.Entity; - if (glm::length2(m_WidgetCurrentAxis) > 0.f) { - // ??? - } else { - LOG_INFO("Selected %i", entity); - if (entity != EntityID_Invalid) { - EntityID parent = m_World->GetParent(entity); - m_Camera = result.Camera; - if (parent == m_Widget) { - m_WidgetCurrentAxis = glm::vec3( - (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; - //auto widgetTransform = m_World->GetComponent(m_Widget, "Transform"); - //auto selectionTransform = m_World->GetComponent(m_Selection, "Transform"); - //widgetTransform["Position"] = (glm::vec3)selectionTransform["Position"]; - } else { - ImGui::SetActiveID(0, nullptr); - if (m_WidgetMode == WidgetMode::None) { - m_WidgetMode = WidgetMode::Translate; - } - setWidgetMode(m_WidgetMode); - m_Selection = entity; - } - } - } - } - m_PickingQueue.clear(); -}; - -bool EditorSystemOld::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 EditorSystemOld::createWidget() -{ - if (m_Widget == EntityID_Invalid) { - 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_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"); - setWidgetMode(WidgetMode::None); - } -} - -void EditorSystemOld::updateWidget() -{ - if (m_Widget == EntityID_Invalid) { - return; - } - if (m_Selection == m_Widget) { - return; - } - - if (m_Selection != EntityID_Invalid) { - auto widgetTransform = m_World->GetComponent(m_Widget, "Transform"); - glm::vec3 selectionPosition = Transform::AbsolutePosition(m_World, m_Selection); - widgetTransform["Position"] = selectionPosition; - if (m_WidgetSpace == WidgetSpace::Local) { - widgetTransform["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(m_World, m_Selection)); - } - } -} - -void EditorSystemOld::setWidgetMode(WidgetMode newMode) -{ - if (m_Widget == EntityID_Invalid) { - 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_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"; - // 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 != EntityID_Invalid) { - if (m_WidgetSpace == WidgetSpace::Local) { - auto selectionTransform = m_World->GetComponent(m_Selection, "Transform"); - widgetTransform["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(m_World, m_Selection)); - } - } - } 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 != EntityID_Invalid) { - auto selectionTransform = m_World->GetComponent(m_Selection, "Transform"); - widgetTransform["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(m_World, m_Selection)); - } - } 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"; - if (m_Selection != EntityID_Invalid) { - auto selectionTransform = m_World->GetComponent(m_Selection, "Transform"); - if (m_WidgetSpace == WidgetSpace::Local) { - widgetTransform["Orientation"] = glm::eulerAngles(Transform::AbsoluteOrientation(m_World, m_Selection)); - } - } - } - m_WidgetMode = newMode; -} - -void EditorSystemOld::setWidgetSpace(WidgetSpace space) -{ - m_WidgetSpace = space; - setWidgetMode(m_WidgetMode); -} - -void EditorSystemOld::drawUI(World* world, double dt) -{ - namespace bfs = boost::filesystem; - - ImGui::ShowTestWindow(); - //ImGui::ShowStyleEditor(); - - if (ImGui::BeginMainMenuBar()) { - if (ImGui::BeginMenu("File")) { - //if (ImGui::MenuItem("New")) { } - if (ImGui::MenuItem("Import", "Ctrl+O")) { - fileImport(world); - } - if (ImGui::MenuItem("Save", "Ctrl+S")) { - fileSave(world); - } - if (ImGui::MenuItem("Save As...", "Ctrl+Shift+S")) { - fileSaveAs(world); - } - ImGui::Separator(); - if (ImGui::MenuItem("Close Editor", "F1")) { } - - ImGui::EndMenu(); - } - - ImGui::SameLine(); - if (ImGui::Button("Move")) { - setWidgetMode(WidgetMode::Translate); - } - ImGui::SameLine(); - if (ImGui::Button("Rotate")) { - setWidgetMode(WidgetMode::Rotate); - } - ImGui::SameLine(); - if (ImGui::Button("Scale")) { - 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(); - } - - std::string title = std::string("Components #") + std::to_string(m_Selection) + std::string("###Components"); - if (ImGui::Begin(title.c_str())) { - if (m_Selection != EntityID_Invalid) { - auto& pools = world->GetComponentPools(); - - std::vector componentTypes; - for (auto& pair : pools) { - // Only add components the entity doesn't already have - if (!pair.second->KnowsEntity(m_Selection)) { - componentTypes.push_back(pair.first.c_str()); - } - } - int item = -1; - ImGui::PushItemWidth(ImGui::GetWindowContentRegionWidth() - 5.f); - if (ImGui::Combo("", &item, componentTypes.data(), componentTypes.size())) { - if (item != -1) { - std::string chosenType = std::string(componentTypes.at(item)); - world->AttachComponent(m_Selection, chosenType); - } - } - ImGui::PopItemWidth(); - - for (auto& pair : pools) { - const std::string& componentType = pair.first; - auto pool = pair.second; - if (!pool->KnowsEntity(m_Selection)) { - continue; - } - auto& ci = pool->ComponentInfo(); - - bool deletePressed = createDeleteButton(componentType); - if (deletePressed) { - world->DeleteComponent(m_Selection, componentType); - continue; - } - - if (ImGui::CollapsingHeader(componentType.c_str())) { - if (!ci.Meta->Annotation.empty()) { - ImGui::Text(ci.Meta->Annotation.c_str()); - } - - auto& component = world->GetComponent(m_Selection, componentType); - for (auto& kv : ci.Fields) { - const std::string& fieldName = kv.first; - auto& field = kv.second; - - std::string uniqueID = componentType + fieldName; - ImGui::PushID(uniqueID.c_str()); - if (field.Type == "Vector") { - auto& val = component.Field(fieldName); - if (fieldName == "Scale") { - ImGui::DragFloat3("", glm::value_ptr(val), 0.1f, 0.f, std::numeric_limits::max()); - } else if (fieldName == "Orientation") { - glm::vec3 tempVal = glm::fmod(val, glm::vec3(glm::two_pi())); - if (ImGui::SliderFloat3("", glm::value_ptr(tempVal), 0.f, glm::two_pi())) { - val = tempVal; - } - } else { - ImGui::DragFloat3("", glm::value_ptr(val), 0.1f, std::numeric_limits::lowest(), std::numeric_limits::max()); - } - } else if (field.Type == "Color") { - auto& val = component.Field(fieldName); - ImGui::ColorEdit4("", glm::value_ptr(val), true); - } else if (field.Type == "string") { - std::string& val = component.Field(fieldName); - char tempString[1024]; - memcpy(tempString, val.c_str(), std::min(val.length() + 1, sizeof(tempString))); - if (ImGui::InputText("", tempString, sizeof(tempString))) { - val = std::string(tempString); - LOG_DEBUG("%s::%s changed!", componentType.c_str(), fieldName.c_str()); - } - // DROP STUFF - if (ImGui::IsItemHovered() && !m_LastDroppedFile.empty()) { - val = m_LastDroppedFile; - m_LastDroppedFile = ""; - } - - } else if (field.Type == "double") { - float tempVal = static_cast(component.Field(fieldName)); - if (ImGui::InputFloat("", &tempVal, 0.01f, 1.f)) { - component.SetField(fieldName, static_cast(tempVal)); - } - } else if (field.Type == "int") { - int val = component.Field(fieldName); - ImGui::InputInt("", &val); - } else if (field.Type == "enum") { - int currentValue = component.Field(fieldName); - int item = -1; - std::stringstream enumKeys; - std::vector enumValues; - int i = 0; - for (auto& kv : ci.Meta->FieldEnumDefinitions.at(fieldName)) { - enumKeys << kv.first << " (" << kv.second << ")" << '\0'; - enumValues.push_back(kv.second); - if (currentValue == kv.second) { - item = i; - } - i++; - } - if (ImGui::Combo("", &item, enumKeys.str().c_str())) { - component.SetField(fieldName, enumValues.at(item)); - } - } else if (field.Type == "bool") { - auto& val = component.Field(fieldName); - ImGui::Checkbox("", &val); - } else { - ImGui::TextDisabled(field.Type.c_str()); - } - ImGui::PopID(); - - ImGui::SameLine(); - ImGui::Text(fieldName.c_str()); - if (ImGui::IsItemHovered()) { - ImGui::SetTooltip("field annotation goes here"); - } - } - } - } - } - - } - ImGui::End(); - - if (ImGui::Begin("Entities")) { - auto entityChildren = world->GetEntityChildren(); - std::function recurse = [&](EntityID parent) { - auto range = entityChildren.equal_range(parent); - for (auto it = range.first; it != range.second; it++) { - if (createEntityNode(world, it->second)) { - recurse(it->second); - ImGui::TreePop(); - } - } - }; - recurse(EntityID_Invalid); - } - ImGui::End(); -} - -bool EditorSystemOld::createEntityNode(World* world, EntityID entity) -{ - // HACK: Don't show the widget entities in the entity tree - if (entity == m_Widget) { - return false; - } - - 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 == 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)) { - m_Selection = 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 = world->GetName(entity); - if (!entityName.empty()) { - nodeTitle = entityName; - } else { - nodeTitle = std::string("#") + std::to_string(entity); - } - 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")) { - EntityID newEntity = world->CreateEntity(entity); - world->AttachComponent(newEntity, "Transform"); - } - ImGui::SameLine(); - if (ImGui::Button("Delete")) { - world->DeleteEntity(entity); - ImGui::CloseCurrentPopup(); - if (!world->ValidEntity(m_Selection)) { - m_Selection = EntityID_Invalid; - } - } - ImGui::EndPopup(); - } - return true; - } else { - return false; - } -} - -bool EditorSystemOld::createDeleteButton(std::string componentType) -{ - float width = ImGui::GetContentRegionAvailWidth(); - ImGuiWindow* window = ImGui::GetCurrentWindow(); - auto pos = ImGui::GetCursorScreenPos() + ImVec2(width - 14.f, 1); - ImRect bb = ImRect(pos, pos + ImVec2(14.f, 14.f)); - std::string idString = "#DELETE"; - idString += componentType; - ImGuiID id = window->GetID(idString.c_str()); - bool hovered; - bool held; - bool pressed = ImGui::ButtonBehavior(bb, id, &hovered, &held); - //ImU32 col = window->Color((held && hovered) ? ImGuiCol_CloseButtonActive : hovered ? ImGuiCol_CloseButtonHovered : ImGuiCol_CloseButton); - ImU32 col = window->Color((held && hovered) ? ImGuiCol_CloseButtonActive : hovered ? ImGuiCol_ButtonHovered : ImGuiCol_Button); - window->DrawList->AddCircleFilled(bb.GetCenter(), 7.f, col, 16); - return pressed; -} - -void EditorSystemOld::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); -} - -void EditorSystemOld::fileImport(World* world) -{ - m_CurrentFile = openDialog(m_DefaultEntityDir); - auto file = ResourceManager::Load(m_CurrentFile.string()); - EntityFilePreprocessor fpp(file); - fpp.RegisterComponents(world); - EntityFileParser fp(file); - fp.MergeEntities(world); - createWidget(); - updateWidget(); -} - -void EditorSystemOld::fileSave(World* world) -{ - if (boost::filesystem::exists(m_CurrentFile)) { - // HACK: Delete the widgets so they don't appear in the saved file - world->DeleteEntity(m_Widget); - m_Widget = EntityID_Invalid; - - EntityFileWriter writer(m_CurrentFile.string()); - writer.WriteWorld(world); - - createWidget(); - } else { - fileSaveAs(world); - } -} - -void EditorSystemOld::fileSaveAs(World* world) -{ - auto filePath = saveDialog(m_DefaultEntityDir); - if (filePath.empty()) { - return; - } - - // HACK: Delete the widgets so they don't appear in the saved file - world->DeleteEntity(m_Widget); - m_Widget = EntityID_Invalid; - - EntityFileWriter writer(filePath.string()); - writer.WriteWorld(world); - - createWidget(); -} diff --git a/src/Engine/Editor/EditorWidgetSystem.cpp b/src/Engine/Editor/EditorWidgetSystem.cpp index 1417f20e..f0c72ab0 100644 --- a/src/Engine/Editor/EditorWidgetSystem.cpp +++ b/src/Engine/Editor/EditorWidgetSystem.cpp @@ -50,19 +50,6 @@ void EditorWidgetSystem::UpdateComponent(EntityWrapper& entity, ComponentWrapper m_MouseDelta = glm::vec2(0); } -void EditorWidgetSystem::debugPrintVector(const char* name, glm::vec2 axisNDC) -{ - ImGui::Text("%s: (%f, %f)", name, axisNDC.x, axisNDC.y); -} -void EditorWidgetSystem::debugPrintVector(const char* name, glm::vec4 axisNDC) -{ - ImGui::Text("%s: (%f, %f, %f, %f)", name, axisNDC.x, axisNDC.y, axisNDC.z, axisNDC.w); -} -void EditorWidgetSystem::debugPrintVector(const char* name, glm::vec3 axisNDC) -{ - ImGui::Text("%s: (%f, %f, %f)", name, axisNDC.x, axisNDC.y, axisNDC.z); -} - bool EditorWidgetSystem::OnMouseMove(const Events::MouseMove& e) { m_MouseDelta = glm::vec2((float)e.DeltaX, (float)-e.DeltaY); @@ -71,7 +58,7 @@ bool EditorWidgetSystem::OnMouseMove(const Events::MouseMove& e) bool EditorWidgetSystem::OnMousePress(const Events::MousePress & e) { - if (e.Button == GLFW_MOUSE_BUTTON_2) { + if (e.Button == GLFW_MOUSE_BUTTON_1) { m_PickData = m_Renderer->Pick(glm::vec2(e.X, e.Y)); if (m_PickData.Entity != EntityID_Invalid && m_PickData.World == m_World) { m_PickEntity = EntityWrapper(m_World, m_PickData.Entity);