summaryrefslogtreecommitdiff
path: root/editor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'editor.cpp')
-rw-r--r--editor.cpp111
1 files changed, 111 insertions, 0 deletions
diff --git a/editor.cpp b/editor.cpp
index 698b5ff..9cc4539 100644
--- a/editor.cpp
+++ b/editor.cpp
@@ -1,3 +1,4 @@
+#include "camera.hpp"
#include "debugdraw.hpp"
#include "editor.hpp"
#include "model.hpp"
@@ -7,6 +8,7 @@
extern "C" {
#include "memory.h"
+#include "plat.h"
}
static struct {
@@ -24,6 +26,10 @@ static struct {
Entity_Id selected;
Model_Instance* selected_inst;
int selected_mesh;
+ int hovered_axis;
+ int dragging_gizmo;
+ v3f drag_axis, drag_off;
+ v3f gf, gu, gr;
} editor;
static int mat_win_handler(UI::Element* e, const UI::Message& m) {
@@ -235,6 +241,7 @@ void init_editor(UI* ui, World* world) {
editor.ent_win = 0;
editor.phy_win = 0;
editor.world = world;
+ editor.dragging_gizmo = 0;
zero(&editor.settings, sizeof editor.settings);
}
@@ -267,6 +274,110 @@ void editor_draw(Line_Renderer& lr) {
editor.selected_inst->bounds[editor.selected_mesh]
);
}
+ if (editor.selected) {
+ Entity_Id e = editor.selected;
+ World& w = *editor.world;
+ if (w.has<Transform>(e)) {
+ Transform& t = w.get<Transform>(e);
+ m4f& m = t.mat;
+ v3f p = v3f(m.m[3][0], m.m[3][1], m.m[3][2]);
+ v3f& f = editor.gf;
+ v3f& u = editor.gu;
+ v3f& r = editor.gr;
+ if (editor.hovered_axis == 1)
+ lr.colour(v3f(1.0f, 1.0f, 1.0f));
+ else
+ lr.colour(v3f(1.0f, 0.0f, 0.0f));
+ lr.add_arrow(p, p + f);
+ if (editor.hovered_axis == 2)
+ lr.colour(v3f(1.0f, 1.0f, 1.0f));
+ else
+ lr.colour(v3f(0.0f, 1.0f, 0.0f));
+ lr.add_arrow(p, p + u);
+ if (editor.hovered_axis == 3)
+ lr.colour(v3f(1.0f, 1.0f, 1.0f));
+ else
+ lr.colour(v3f(0.0f, 0.0f, 1.0f));
+ lr.add_arrow(p, p + r);
+ }
+ }
+}
+
+v3f gizmo_pos(const v3f& p, const App& app, const Camera& cam) {
+ v2f uv = (2.0f * v2f(app.mx, app.my) - v2f(app.w, app.h)) / (float)app.h;
+ v4f e =
+ cam.get_proj().inverse() *
+ v4f(uv.x, uv.y, -1.0f, 1.0f);
+ e.z = -1.0f; e.w = 0.0f;
+ v4f d4 = cam.get_view().inverse() * e;
+ v3f d = v3f::normalised(v3f(d4.x, d4.y, d4.z));
+ v3f n = v3f::perp(editor.drag_axis);
+ float denom = v3f::dot(n, d);
+ v3f o = cam.position + cam.near * cam.forward;
+ float t = v3f::dot(p - o, n) / denom;
+ return (o + t * d) * editor.drag_axis;
+}
+
+void editor_update(const App& app, const Camera& cam) {
+ Entity_Id e = editor.selected;
+ World& w = *editor.world;
+ if (!e || !w.has<Transform>(e))
+ return;
+ Transform& t = w.get<Transform>(e);
+ m4f& m = t.mat;
+ v3f p = v3f(m.m[3][0], m.m[3][1], m.m[3][2]);
+ auto vp = cam.get_proj() * cam.get_view();
+ if (editor.dragging_gizmo) {
+ auto gp = gizmo_pos(p, app, cam) + editor.drag_off;
+ m.m[3][0] += (gp.x - m.m[3][0]) * editor.drag_axis.x;
+ m.m[3][1] += (gp.y - m.m[3][1]) * editor.drag_axis.y;
+ m.m[3][2] += (gp.z - m.m[3][2]) * editor.drag_axis.z;
+ if (app.mjr(mbtn_left))
+ editor.dragging_gizmo = 0;
+ return;
+ }
+ editor.hovered_axis = 0;
+ editor.gf = v3f::normalised((m * v4f(0.0f, 0.0f, 1.0f, 0.0f)).xyz());
+ editor.gu = v3f::normalised((m * v4f(0.0f, 1.0f, 0.0f, 0.0f)).xyz());
+ editor.gr = v3f::normalised((m * v4f(1.0f, 0.0f, 0.0f, 0.0f)).xyz());
+ auto do_axis = [&](const v3f& axis) {
+ v4f sss4 = vp * v4f(p, 1.0f);
+ v4f sse4 = vp * v4f(p + axis, 1.0f);
+ if (sss4.w < 0.0f || sse4.w < 0.0f) return false;
+ float mx = app.mx;
+ float my = app.my;
+ v3f sss = sss4.xyz() / sss4.w;
+ v3f sse = sse4.xyz() / sse4.w;
+ v3f s = v3f(app.w, app.h, 1.0f);
+ sss = (sss * 0.5f + 0.5f) * s;
+ sse = (sse * 0.5f + 0.5f) * s;
+ float d = fabsf((sse.y - sss.y) * mx - (sse.x - sss.x) * my + sse.x * sss.y - sse.y * sss.x);
+ d /= v2f::mag(sse.xy() - sss.xy());
+ if (d < 8.0f) {
+ v2f mini( INFINITY, INFINITY);
+ v2f maxi(-INFINITY, -INFINITY);
+ if (sss.x < mini.x) mini.x = sss.x;
+ if (sss.y < mini.y) mini.y = sss.y;
+ if (sse.x < mini.x) mini.x = sse.x;
+ if (sse.y < mini.y) mini.y = sse.y;
+ if (sss.x > maxi.x) maxi.x = sss.x;
+ if (sss.y > maxi.y) maxi.y = sss.y;
+ if (sse.x > maxi.x) maxi.x = sse.x;
+ if (sse.y > maxi.y) maxi.y = sse.y;
+ if (mx > mini.x && my > mini.y && mx < maxi.x && my < maxi.y) {
+ if (app.mjp(mbtn_left)) {
+ editor.drag_axis = axis;
+ editor.drag_off = p - gizmo_pos(p, app, cam);
+ editor.dragging_gizmo = 1;
+ }
+ return true;
+ }
+ }
+ return false;
+ };
+ if (do_axis(editor.gf)) { editor.hovered_axis = 1; return; }
+ if (do_axis(editor.gu)) { editor.hovered_axis = 2; return; }
+ if (do_axis(editor.gr)) { editor.hovered_axis = 3; return; }
}
Editor_Settings& editor_settings() {