Skip to content

Commit 5edf760

Browse files
committed
Feat: Show gizmo for selected entity
1 parent d74f3d8 commit 5edf760

File tree

5 files changed

+72
-149
lines changed

5 files changed

+72
-149
lines changed

src/atta/ui/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ set(ATTA_UI_MODULE_SOURCE
1111

1212
widgets/align.cpp
1313
widgets/button.cpp
14+
widgets/gizmo.cpp
1415
widgets/help.cpp
1516
widgets/image.cpp
1617

src/atta/ui/widgets/gizmo.cpp

+30-25
Original file line numberDiff line numberDiff line change
@@ -16,35 +16,35 @@
1616

1717
namespace atta::ui {
1818

19-
Gizmo::Gizmo() : _operation(TRANSLATE), _mode(WORLD), _isOrthographic(false), _snap(false) {}
19+
Gizmo::Gizmo() : _operation(TRANSLATE), _mode(WORLD), _snap(false) {}
2020

2121
void Gizmo::setOperation(Operation operation) { _operation = operation; }
2222
void Gizmo::setMode(Mode mode) { _mode = mode; }
23+
void Gizmo::setCamera(std::weak_ptr<gfx::Camera> camera) { _camera = camera; }
2324
void Gizmo::setSnap(bool snap) { _snap = snap; }
2425

25-
void Gizmo::setCamera(std::weak_ptr<Camera> camera) { _camera = camera; }
26-
27-
ImGuizmo::OPERATION convert(Operation operation) {
26+
ImGuizmo::OPERATION convert(Gizmo::Operation operation) {
2827
ImGuizmo::OPERATION result{};
29-
if (operation & TRANSLATE > 0)
28+
if ((operation & Gizmo::TRANSLATE) > 0)
3029
result = result | ImGuizmo::OPERATION::TRANSLATE;
31-
if (operation & ROTATE > 0)
30+
if ((operation & Gizmo::ROTATE) > 0)
3231
result = result | ImGuizmo::OPERATION::ROTATE;
33-
if (operation & SCALE > 0)
32+
if ((operation & Gizmo::SCALE) > 0)
3433
result = result | ImGuizmo::OPERATION::SCALE;
3534
return result;
3635
}
3736

38-
ImGuizmo::MODE convert(Mode mode) { return mode == WORLD ? ImGuizmo::MODE::WORLD : ImGuizmo::MODE::LOCAL; }
37+
ImGuizmo::MODE convert(Gizmo::Mode mode) { return mode == Gizmo::WORLD ? ImGuizmo::MODE::WORLD : ImGuizmo::MODE::LOCAL; }
3938

40-
bool Gizmo::manipulate(component::EntityId entity) {
41-
std::shared_ptr<Camera> camera = _camera.lock();
42-
component::Transform* t = component::getComponent<component::Transform>(entity);
43-
if (t) {
39+
bool Gizmo::manipulate(cmp::EntityId entity) {
40+
std::shared_ptr<gfx::Camera> camera = _camera.lock();
41+
cmp::Transform* t = cmp::getComponent<cmp::Transform>(entity);
42+
if (camera && t) {
4443
mat4 transform = transpose(t->getWorldTransformMatrix(entity));
4544

46-
ImGuizmo::SetDrawlist();
47-
ImGuizmo::SetRect(ImGui::GetWindowPos().x + 5.0f, ImGui::GetWindowPos().y + 24.0f, 500, 500);
45+
ImVec2 windowPos = ImGui::GetWindowPos();
46+
ImVec2 windowSize = ImGui::GetWindowSize();
47+
ImGuizmo::SetRect(windowPos.x, windowPos.y, windowSize.x - 10.0f, windowSize.y - 8.0f);
4848

4949
ImGuizmo::OPERATION operation = convert(_operation);
5050
ImGuizmo::MODE mode = convert(_mode);
@@ -54,7 +54,12 @@ bool Gizmo::manipulate(component::EntityId entity) {
5454
mat4 proj = transpose(camera->getProj());
5555
proj.mat[1][1] *= -1;
5656

57-
if (ImGuizmo::Manipulate(transpose(_view).data, _proj.data, operation, mode, transform.data, nullptr, snap ? snapValues : nullptr)) {
57+
float snapValue = 0.5f;
58+
if (operation == ImGuizmo::OPERATION::ROTATE)
59+
snapValue = 45.0f;
60+
float snapValues[3] = {snapValue, snapValue, snapValue};
61+
62+
if (ImGuizmo::Manipulate(view.data, proj.data, operation, mode, transform.data, nullptr, _snap ? snapValues : nullptr)) {
5863
transform.transpose();
5964

6065
// Get changed
@@ -66,22 +71,22 @@ bool Gizmo::manipulate(component::EntityId entity) {
6671
ori.setEuler(t->orientation.getEuler() + oriDelta);
6772

6873
// Delta world to local
69-
component::Relationship* r = component::getComponent<component::Relationship>(entity);
74+
cmp::Relationship* r = cmp::getComponent<cmp::Relationship>(entity);
7075
if (r && r->getParent() != -1) {
7176
// Get transform of the first entity that has transform when going up in the hierarchy
72-
component::Transform* pt = nullptr;
73-
component::EntityId parentId = -1;
77+
cmp::Transform* pt = nullptr;
78+
cmp::EntityId parentId = -1;
7479
while (pt == nullptr) {
7580
parentId = r->getParent();
76-
pt = component::getComponent<component::Transform>(parentId);
77-
r = component::getComponent<component::Relationship>(parentId);
81+
pt = cmp::getComponent<cmp::Transform>(parentId);
82+
r = cmp::getComponent<cmp::Relationship>(parentId);
7883
if (r->getParent() == -1)
7984
break;
8085
}
8186

8287
// If found some entity with transform component, convert result to be relative to it
8388
if (pt) {
84-
component::Transform pTransform = pt->getWorldTransform(parentId);
89+
cmp::Transform pTransform = pt->getWorldTransform(parentId);
8590
vec3 pPos = pTransform.position;
8691
vec3 pScale = pTransform.scale;
8792
quat pOri = pTransform.orientation;
@@ -94,14 +99,14 @@ bool Gizmo::manipulate(component::EntityId entity) {
9499
}
95100

96101
// Update entity transform
97-
if (mouseOperation == ImGuizmo::OPERATION::TRANSLATE)
102+
if (operation == ImGuizmo::OPERATION::TRANSLATE)
98103
t->position = pos;
99-
else if (mouseOperation == ImGuizmo::OPERATION::ROTATE)
104+
else if (operation == ImGuizmo::OPERATION::ROTATE)
100105
t->orientation = ori;
101-
else if (mouseOperation == ImGuizmo::OPERATION::SCALE)
106+
else if (operation == ImGuizmo::OPERATION::SCALE)
102107
t->scale = scale;
103108

104-
// component::RigidBody2D* rb2d = component::getComponent<component::RigidBody2D>(entity);
109+
// cmp::RigidBody2D* rb2d = cmp::getComponent<cmp::RigidBody2D>(entity);
105110
// if (rb2d) {
106111
// if (mouseOperation == ImGuizmo::OPERATION::TRANSLATE || mouseOperation == ImGuizmo::OPERATION::ROTATE) {
107112
// vec2 pos = vec2(t->position);

src/atta/ui/widgets/gizmo.h

+7-3
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,27 @@ class Gizmo {
1818
TRANSLATE = 1 << 0,
1919
ROTATE = 1 << 1,
2020
SCALE = 1 << 2,
21+
TRANSLATE_ROTATE = TRANSLATE | ROTATE,
22+
TRANSLATE_SCALE = TRANSLATE | SCALE,
23+
ROTATE_SCALE = ROTATE | SCALE,
24+
ALL = TRANSLATE | ROTATE | SCALE
2125
};
22-
inline Operation operator|(OPERATION l, OPERATION r) { return Operation(int(l) | int(r)); }
26+
friend inline Operation operator|(Operation l, Operation r) { return Operation(int(l) | int(r)); }
2327
enum Mode { WORLD = 0, LOCAL };
2428

2529
Gizmo();
2630

2731
void setOperation(Operation operation);
2832
void setMode(Mode mode);
29-
void setCamera(std::weak_ptr<Camera> camera);
33+
void setCamera(std::weak_ptr<gfx::Camera> camera);
3034
void setSnap(bool snap);
3135

3236
bool manipulate(component::EntityId entity);
3337

3438
private:
3539
Operation _operation;
3640
Mode _mode;
37-
std::weak_ptr<Camera> _camera;
41+
std::weak_ptr<gfx::Camera> _camera;
3842
bool _snap;
3943
};
4044

src/atta/ui/windows/viewport/viewportWindows.cpp

+28-121
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
// Date: 2021-12-28
55
// By Breno Cunha Queiroz
66
//--------------------------------------------------
7+
#include <atta/component/base.h>
78
#include <atta/component/components/material.h>
89
#include <atta/component/components/mesh.h>
910
#include <atta/component/components/name.h>
@@ -107,130 +108,36 @@ void ViewportWindows::renderUI() {
107108
ImGui::OpenPopup("Editor_AddBasicShape");
108109
addBasicShapePopup();
109110

110-
//----- Keyboard click -----//
111-
// static ImGuizmo::OPERATION mouseOperation = ImGuizmo::OPERATION::TRANSLATE;
112-
// static ImGuizmo::MODE mouseMode = ImGuizmo::MODE::LOCAL;
113-
// static bool snap = false;
114-
115-
// if (ImGui::IsWindowHovered()) {
116-
// snap = false;
117-
// ImGuiIO& io = ImGui::GetIO();
118-
// if (ImGui::IsKeyPressed(ImGuiKey_T) && io.KeyCtrl) {
119-
// mouseOperation = ImGuizmo::OPERATION::TRANSLATE;
120-
// mouseMode = ImGuizmo::MODE::LOCAL;
121-
// } else if (ImGui::IsKeyPressed(ImGuiKey_T) && io.KeyShift) {
122-
// mouseOperation = ImGuizmo::OPERATION::TRANSLATE;
123-
// mouseMode = ImGuizmo::MODE::WORLD;
124-
// } else if (ImGui::IsKeyPressed(ImGuiKey_S) && io.KeyCtrl) {
125-
// mouseOperation = ImGuizmo::OPERATION::SCALE;
126-
// mouseMode = ImGuizmo::MODE::LOCAL;
127-
// } else if (ImGui::IsKeyPressed(ImGuiKey_S) && io.KeyShift) {
128-
// mouseOperation = ImGuizmo::OPERATION::SCALE;
129-
// mouseMode = ImGuizmo::MODE::WORLD;
130-
// } else if (ImGui::IsKeyPressed(ImGuiKey_R) && io.KeyCtrl) {
131-
// mouseOperation = ImGuizmo::OPERATION::ROTATE;
132-
// mouseMode = ImGuizmo::MODE::LOCAL;
133-
// } else if (ImGui::IsKeyPressed(ImGuiKey_R) && io.KeyShift) {
134-
// mouseOperation = ImGuizmo::OPERATION::ROTATE;
135-
// mouseMode = ImGuizmo::MODE::WORLD;
136-
// } else if (io.KeyCtrl)
137-
// snap = true;
138-
// }
139-
140-
//----- Render to texture -----//
111+
//----- Operation selection -----//
112+
if (ImGui::IsWindowHovered()) {
113+
ImGuiIO& io = ImGui::GetIO();
114+
115+
if (io.KeyCtrl)
116+
_gizmo.setMode(Gizmo::LOCAL);
117+
if (io.KeyShift)
118+
_gizmo.setMode(Gizmo::WORLD);
119+
120+
if (ImGui::IsKeyPressed(ImGuiKey_T))
121+
_gizmo.setOperation(Gizmo::TRANSLATE);
122+
else if (ImGui::IsKeyPressed(ImGuiKey_S))
123+
_gizmo.setOperation(Gizmo::SCALE);
124+
else if (ImGui::IsKeyPressed(ImGuiKey_R))
125+
_gizmo.setOperation(Gizmo::ROTATE);
126+
}
127+
128+
//----- Render viewport to texture -----//
141129
ImVec2 size = ImVec2(viewport->getWidth(), viewport->getHeight());
142130
ImGui::Image((ImTextureID)(intptr_t)viewport->getImGuiTexture(), size, ImVec2(0, 0), ImVec2(1, 1));
143131

144-
//----- ImGuizmo -----//
145-
bool imGuizmoUsingMouse = false;
146-
// component::EntityId entity = component::getSelectedEntity();
147-
// if (entity >= 0) {
148-
// component::Transform* t = component::getComponent<component::Transform>(entity);
149-
150-
// if (t) {
151-
// ImGuizmo::SetOrthographic(viewport->getCamera()->getName() == "OrthographicCamera");
152-
// ImGuizmo::SetDrawlist();
153-
// ImGuizmo::SetRect(ImGui::GetWindowPos().x + 5.0f, ImGui::GetWindowPos().y + 24.0f, viewport->getWidth(),
154-
// viewport->getHeight());
155-
// mat4 view = transpose(viewport->getCamera()->getView());
156-
// mat4 proj = viewport->getCamera()->getProj();
157-
// proj.mat[1][1] *= -1;
158-
// proj.transpose();
159-
160-
// mat4 transform = transpose(t->getWorldTransformMatrix(entity));
161-
162-
// float snapValue = 0.5f;
163-
// if (mouseOperation == ImGuizmo::OPERATION::ROTATE)
164-
// snapValue = 45.0f;
165-
// float snapValues[3] = {snapValue, snapValue, snapValue};
166-
167-
// ImGuizmo::Manipulate(view.data, proj.data, mouseOperation, mouseMode, transform.data, nullptr, snap ? snapValues :
168-
// nullptr);
169-
170-
// if (ImGuizmo::IsUsing()) {
171-
// imGuizmoUsingMouse = true;
172-
// transform.transpose();
173-
174-
// // Get changed
175-
// vec3 pos, scale;
176-
// quat newOri;
177-
// transform.getPosOriScale(pos, newOri, scale);
178-
// vec3 oriDelta = newOri.getEuler() - t->orientation.getEuler();
179-
// quat ori;
180-
// ori.setEuler(t->orientation.getEuler() + oriDelta);
181-
182-
// // Delta world to local
183-
// component::Relationship* r = component::getComponent<component::Relationship>(entity);
184-
// if (r && r->getParent() != -1) {
185-
// // Get transform of the first entity that has transform when going up in the hierarchy
186-
// component::Transform* pt = nullptr;
187-
// component::EntityId parentId = -1;
188-
// while (pt == nullptr) {
189-
// parentId = r->getParent();
190-
// pt = component::getComponent<component::Transform>(parentId);
191-
// r = component::getComponent<component::Relationship>(parentId);
192-
// if (r->getParent() == -1)
193-
// break;
194-
// }
195-
196-
// // If found some entity with transform component, convert result to be relative to it
197-
// if (pt) {
198-
// component::Transform pTransform = pt->getWorldTransform(parentId);
199-
// vec3 pPos = pTransform.position;
200-
// vec3 pScale = pTransform.scale;
201-
// quat pOri = pTransform.orientation;
202-
203-
// // Calculate pos ori scale relative to parent
204-
// pos -= pPos;
205-
// scale /= pScale;
206-
// ori = ori * (-pOri); // Rotation from pOri to ori
207-
// }
208-
// }
209-
210-
// // Update entity transform
211-
// if (mouseOperation == ImGuizmo::OPERATION::TRANSLATE)
212-
// t->position = pos;
213-
// else if (mouseOperation == ImGuizmo::OPERATION::ROTATE)
214-
// t->orientation = ori;
215-
// else if (mouseOperation == ImGuizmo::OPERATION::SCALE)
216-
// t->scale = scale;
217-
218-
// // component::RigidBody2D* rb2d = component::getComponent<component::RigidBody2D>(entity);
219-
// // if (rb2d) {
220-
// // if (mouseOperation == ImGuizmo::OPERATION::TRANSLATE || mouseOperation == ImGuizmo::OPERATION::ROTATE) {
221-
// // vec2 pos = vec2(t->position);
222-
// // float angle = -t->orientation.getEuler().z;
223-
// // rb2d->setTransform(pos, angle);
224-
// // } else if (mouseOperation == ImGuizmo::OPERATION::SCALE) {
225-
// // // TODO Recreate box2d rigid body
226-
// // }
227-
// // }
228-
// }
229-
// }
230-
// }
231-
232-
// //----- Mouse click selection -----//
233-
if (!imGuizmoUsingMouse) {
132+
//----- Gizmo manipulation -----//
133+
bool gizmoUsingMouse = false;
134+
_gizmo.setCamera(viewport->getCamera());
135+
cmp::EntityId eid = component::getSelectedEntity();
136+
if (eid >= 0 && _gizmo.manipulate(eid))
137+
gizmoUsingMouse = true;
138+
139+
//----- Mouse click selection -----//
140+
if (!gizmoUsingMouse) {
234141
if (click.x >= 0 && click.y >= 0 && click.x < (int)viewport->getWidth() && click.y < (int)viewport->getHeight()) {
235142
cmp::EntityId eid = _computeEntityClick->click(viewport->getRenderer(), viewport->getCamera(), click);
236143
cmp::setSelectedEntity(eid);

src/atta/ui/windows/viewport/viewportWindows.h

+6
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
#include <atta/component/interface.h>
1111
#include <atta/graphics/compute/entityClick.h>
12+
#include <atta/ui/widgets/gizmo.h>
1213
#include <atta/ui/windows/viewport/viewport.h>
1314

1415
namespace atta::ui {
@@ -40,8 +41,13 @@ class ViewportWindows {
4041
float _viewportFPS = 30.0; ///< Desired viewport FPS (UI module handles the viewport rendering)
4142
bool _viewportRendering = true; ///< If should render the viewport
4243

44+
// Gizmo
45+
Gizmo _gizmo;
46+
4347
// Compute
4448
std::unique_ptr<gfx::EntityClick> _computeEntityClick;
49+
50+
// Modals
4551
std::map<StringId, bool> _openModals; ///< Open modals for each viewport
4652
};
4753

0 commit comments

Comments
 (0)