diff --git a/src/atta/graphics/interface.h b/src/atta/graphics/interface.h index ed584884..da2d8825 100644 --- a/src/atta/graphics/interface.h +++ b/src/atta/graphics/interface.h @@ -46,12 +46,12 @@ void setUiShutDownFunc(std::function uiShutDownFunc); void setUiStartUpFunc(std::function uiStartUpFunc); //----- Viewport -----// -std::vector> getViewports(); -void clearViewports(); -void addViewport(std::shared_ptr viewport); -void removeViewport(std::shared_ptr viewport); -void createDefaultViewports(); -component::EntityId viewportEntityClick(std::shared_ptr viewport, vec2i pos); +// std::vector> getViewports(); +// void clearViewports(); +// void addViewport(std::shared_ptr viewport); +// void removeViewport(std::shared_ptr viewport); +// void createDefaultViewports(); +// component::EntityId viewportEntityClick(std::shared_ptr viewport, vec2i pos); void* getImGuiImage(StringId sid); } // namespace atta::graphics diff --git a/src/atta/graphics/manager.h b/src/atta/graphics/manager.h index e2c2e80b..211632b9 100644 --- a/src/atta/graphics/manager.h +++ b/src/atta/graphics/manager.h @@ -47,12 +47,12 @@ class Manager final { friend std::shared_ptr getGraphicsAPI(); friend std::shared_ptr getWindow(); - friend std::vector> getViewports(); - friend void clearViewports(); - friend void addViewport(std::shared_ptr viewport); - friend void removeViewport(std::shared_ptr viewport); - friend void createDefaultViewports(); - friend component::EntityId viewportEntityClick(std::shared_ptr viewport, vec2i pos); + // friend std::vector> getViewports(); + // friend void clearViewports(); + // friend void addViewport(std::shared_ptr viewport); + // friend void removeViewport(std::shared_ptr viewport); + // friend void createDefaultViewports(); + // friend component::EntityId viewportEntityClick(std::shared_ptr viewport, vec2i pos); friend void* getImGuiImage(StringId sid); const std::unordered_map>& getMeshes() const; @@ -75,11 +75,11 @@ class Manager final { void recreateGraphicsAPI(); std::vector>& getViewportsImpl(); - void clearViewportsImpl(); - void addViewportImpl(std::shared_ptr viewport); - void removeViewportImpl(std::shared_ptr viewport); - void createDefaultViewportsImpl(); - component::EntityId viewportEntityClickImpl(std::shared_ptr viewport, vec2i pos); + // void clearViewportsImpl(); + // void addViewportImpl(std::shared_ptr viewport); + // void removeViewportImpl(std::shared_ptr viewport); + // void createDefaultViewportsImpl(); + // component::EntityId viewportEntityClickImpl(std::shared_ptr viewport, vec2i pos); void* getImGuiImageImpl(StringId sid); gfx::Image::Format convertFormat(res::Image::Format format) const; diff --git a/src/atta/ui/editor/widgets/gizmo.cpp b/src/atta/ui/editor/widgets/gizmo.cpp new file mode 100644 index 00000000..9a2998a6 --- /dev/null +++ b/src/atta/ui/editor/widgets/gizmo.cpp @@ -0,0 +1,120 @@ +//-------------------------------------------------- +// Atta UI Module +// guizmo.h +// Date: 2024-01-05 +// By Breno Cunha Queiroz +//-------------------------------------------------- +#include + +#include +#include + +#include +#include + +#include + +namespace atta::ui { + +Gizmo::Gizmo() : _operation(TRANSLATE), _mode(WORLD), _isOrthographic(false), _snap(false) {} + +void Gizmo::setOperation(Operation operation) { _operation = operation; } +void Gizmo::setMode(Mode mode) { _mode = mode; } +void Gizmo::setSnap(bool snap) { _snap = snap; } + +void Gizmo::setCamera(std::weak_ptr camera) { _camera = camera; } + +ImGuizmo::OPERATION convert(Operation operation) { + ImGuizmo::OPERATION result{}; + if (operation & TRANSLATE > 0) + result = result | ImGuizmo::OPERATION::TRANSLATE; + if (operation & ROTATE > 0) + result = result | ImGuizmo::OPERATION::ROTATE; + if (operation & SCALE > 0) + result = result | ImGuizmo::OPERATION::SCALE; + return result; +} + +ImGuizmo::MODE convert(Mode mode) { return mode == WORLD ? ImGuizmo::MODE::WORLD : ImGuizmo::MODE::LOCAL; } + +bool Gizmo::manipulate(component::EntityId entity) { + std::shared_ptr camera = _camera.lock(); + component::Transform* t = component::getComponent(entity); + if (t) { + mat4 transform = transpose(t->getWorldTransformMatrix(entity)); + + ImGuizmo::SetDrawlist(); + ImGuizmo::SetRect(ImGui::GetWindowPos().x + 5.0f, ImGui::GetWindowPos().y + 24.0f, 500, 500); + + ImGuizmo::OPERATION operation = convert(_operation); + ImGuizmo::MODE mode = convert(_mode); + + ImGuizmo::SetOrthographic(camera->getName() == "OrthographicCamera"); + mat4 view = transpose(camera->getView()); + mat4 proj = transpose(camera->getProj()); + proj.mat[1][1] *= -1; + + if (ImGuizmo::Manipulate(transpose(_view).data, _proj.data, operation, mode, transform.data, nullptr, snap ? snapValues : nullptr)) { + transform.transpose(); + + // Get changed + vec3 pos, scale; + quat newOri; + transform.getPosOriScale(pos, newOri, scale); + vec3 oriDelta = newOri.getEuler() - t->orientation.getEuler(); + quat ori; + ori.setEuler(t->orientation.getEuler() + oriDelta); + + // Delta world to local + component::Relationship* r = component::getComponent(entity); + if (r && r->getParent() != -1) { + // Get transform of the first entity that has transform when going up in the hierarchy + component::Transform* pt = nullptr; + component::EntityId parentId = -1; + while (pt == nullptr) { + parentId = r->getParent(); + pt = component::getComponent(parentId); + r = component::getComponent(parentId); + if (r->getParent() == -1) + break; + } + + // If found some entity with transform component, convert result to be relative to it + if (pt) { + component::Transform pTransform = pt->getWorldTransform(parentId); + vec3 pPos = pTransform.position; + vec3 pScale = pTransform.scale; + quat pOri = pTransform.orientation; + + // Calculate pos ori scale relative to parent + pos -= pPos; + scale /= pScale; + ori = ori * (-pOri); // Rotation from pOri to ori + } + } + + // Update entity transform + if (mouseOperation == ImGuizmo::OPERATION::TRANSLATE) + t->position = pos; + else if (mouseOperation == ImGuizmo::OPERATION::ROTATE) + t->orientation = ori; + else if (mouseOperation == ImGuizmo::OPERATION::SCALE) + t->scale = scale; + + // component::RigidBody2D* rb2d = component::getComponent(entity); + // if (rb2d) { + // if (mouseOperation == ImGuizmo::OPERATION::TRANSLATE || mouseOperation == ImGuizmo::OPERATION::ROTATE) { + // vec2 pos = vec2(t->position); + // float angle = -t->orientation.getEuler().z; + // rb2d->setTransform(pos, angle); + // } else if (mouseOperation == ImGuizmo::OPERATION::SCALE) { + // // TODO Recreate box2d rigid body + // } + // } + return true; + } + } + return false; +} + +} // namespace atta::ui diff --git a/src/atta/ui/editor/widgets/gizmo.h b/src/atta/ui/editor/widgets/gizmo.h new file mode 100644 index 00000000..8df3f717 --- /dev/null +++ b/src/atta/ui/editor/widgets/gizmo.h @@ -0,0 +1,38 @@ +//-------------------------------------------------- +// Atta UI Module +// guizmo.h +// Date: 2024-01-05 +// By Breno Cunha Queiroz +//-------------------------------------------------- +#include +#include + +namespace atta::ui { + +class Gizmo { + public: + enum Operation { + TRANSLATE = 1 << 0, + ROTATE = 1 << 1, + SCALE = 1 << 2, + }; + inline Operation operator|(OPERATION l, OPERATION r) { return Operation(int(l) | int(r)); } + enum Mode { WORLD = 0, LOCAL }; + + Gizmo(); + + void setOperation(Operation operation); + void setMode(Mode mode); + void setCamera(std::weak_ptr camera); + void setSnap(bool snap); + + bool manipulate(component::EntityId entity); + + private: + Operation _operation; + Mode _mode; + std::weak_ptr _camera; + bool _snap; +}; + +} // namespace atta::ui diff --git a/src/atta/ui/editor/windows/viewportWindows.cpp b/src/atta/ui/editor/windows/viewportWindows.cpp index 1fd864cc..20715075 100644 --- a/src/atta/ui/editor/windows/viewportWindows.cpp +++ b/src/atta/ui/editor/windows/viewportWindows.cpp @@ -19,8 +19,6 @@ #include #include -#include - namespace atta::ui { void ViewportWindows::render() { @@ -199,29 +197,6 @@ void ViewportWindows::render() { } } - //----- Overlay -----// - //{ - // ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoDocking | ImGuiWindowFlags_AlwaysAutoResize | - // ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav | - // ImGuiWindowFlags_NoMove; - // ImVec2 window = ImGui::GetWindowPos(); - // ImGui::SetNextWindowPos(ImVec2(window.x + 10, window.y + 30)); - // ImGui::SetNextWindowBgAlpha(0.35f); - // bool open = true; - // if (ImGui::Begin((viewport->getSID().getString() + "Overlay").c_str(), &open, window_flags)) { - // ImGui::Text("To move the camera"); - // ImGui::BulletText("Holding mouse middle button"); - // ImGui::BulletText("Rotate with mouse"); - // ImGui::BulletText("Move with ASWD QE"); - // ImGui::Text("To move objects"); - // ImGui::BulletText("Select some object"); - // ImGui::BulletText("Translate: SHIFT+t"); - // ImGui::BulletText("Scale: SHIFT+s"); - // ImGui::BulletText("Rotate: SHIFT+r"); - // } - // ImGui::End(); - //} - //----- Resize -----// ImVec2 windowSize = ImGui::GetWindowSize(); if (windowSize.x != size.x || windowSize.y != size.y)