From 39646f68b23d2899bff7e6ee1ec56fedc649accf Mon Sep 17 00:00:00 2001
From: svsalem <54895424+svsalem@users.noreply.github.com>
Date: Mon, 26 Apr 2021 22:38:47 -0500
Subject: [PATCH] added univ scale

---
 src/gui/widgets.cpp | 78 +++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 71 insertions(+), 7 deletions(-)

diff --git a/src/gui/widgets.cpp b/src/gui/widgets.cpp
index 08844cf..9c6879a 100644
--- a/src/gui/widgets.cpp
+++ b/src/gui/widgets.cpp
@@ -41,6 +41,7 @@ Widgets::Widgets() : lines(1.0f) {
     y_scl = Scene_Object((Scene_ID)Widget_IDs::y_scl, {}, Util::scale_mesh());
     z_scl = Scene_Object((Scene_ID)Widget_IDs::z_scl, Pose::rotated(Vec3{90.0f, 0.0f, 0.0f}),
                          Util::scale_mesh());
+    xyz_scl = Scene_Object((Scene_ID)Widget_IDs::xyz_scl, Pose::moved(Vec3{1.0f}), Util::cube_mesh(0.15f));
 
 #define setcolor(o, c) o.material.opt.albedo = Spectrum((c).x, (c).y, (c).z);
     setcolor(x_mov, Color::red);
@@ -55,6 +56,7 @@ Widgets::Widgets() : lines(1.0f) {
     setcolor(x_scl, Color::red);
     setcolor(y_scl, Color::green);
     setcolor(z_scl, Color::blue);
+    setcolor(xyz_scl, Color::yellow);
 #undef setcolor
 }
 
@@ -70,6 +72,10 @@ void Widgets::generate_lines(Vec3 pos) {
     if(drag_plane) {
         add_axis(((int)axis + 1) % 3);
         add_axis(((int)axis + 2) % 3);
+    } else if(univ_scl) {
+        add_axis((int)axis);
+        add_axis(((int)axis)+1)%3);
+        add_axis(((int)axis)+2)%3);
     } else {
         add_axis((int)axis);
     }
@@ -151,6 +157,10 @@ void Widgets::render(const Mat4& view, Vec3 pos, float scl) {
         z_scl.pose.scale = scale;
         z_scl.pose.pos = pos + Vec3(0.0f, 0.0f, 0.15f * scl);
         z_scl.render(view, true);
+        
+        xyz_scl.pose.scale = scale;
+        xyz_scl.pose.pos = pos + Vec3(0.15f*scl, 0.15f*scl, 0.15f*scl);
+        xyz_scl.render(view, true);
     }
 }
 
@@ -170,12 +180,20 @@ Pose Widgets::apply_action(const Pose& pose) {
         result.euler = combined.to_euler();
     } break;
     case Widget_Type::scale: {
-        result.scale = Vec3{1.0f};
-        result.scale[(int)axis] = drag_end[(int)axis];
-        Mat4 rot = pose.rotation_mat();
-        Mat4 trans =
-            Mat4::transpose(rot) * Mat4::scale(result.scale) * rot * Mat4::scale(pose.scale);
-        result.scale = Vec3(trans[0][0], trans[1][1], trans[2][2]);
+        if(univ_scl) {
+            result.scale = drag_end;
+            Mat4 rot = pose.rotation_mat();
+            Mat4 trans = 
+                Mat4::transpose(rot) * Mat4::scale(result.scale) * rot * Mat4::scale(pose.scale);
+            result.scale = Vec3(trans[0][0], trans[1][1], trans[2][2]);
+        } else {
+            result.scale = Vec3{1.0f};
+            result.scale[(int)axis] = drag_end[(int)axis];
+            Mat4 rot = pose.rotation_mat();
+            Mat4 trans =
+                Mat4::transpose(rot) * Mat4::scale(result.scale) * rot * Mat4::scale(pose.scale);
+            result.scale = Vec3(trans[0][0], trans[1][1], trans[2][2]);
+        }
     } break;
     case Widget_Type::bevel: {
         Vec2 off = bevel_start - bevel_end;
@@ -217,6 +235,41 @@ bool Widgets::to_axis(Vec3 obj_pos, Vec3 cam_pos, Vec3 dir, Vec3& hit) {
     return hit.valid();
 }
 
+bool Widgets::to_axis3(Vec3 obj_pos, Vec3 cam_pos, Vec3 dir, Vec3& hit) {
+
+    Vec3 axis1;
+    axis1[(int)axis] = 1.0f;
+    Vec3 axis2;
+    axis2[((int)axis + 1) % 3] = 1.0f;
+    Vec3 axis3;
+    axis3[((int)axis + 2) % 3] = 1.0f;
+
+    Line select(cam_pos, dir);
+    Line target(obj_pos, axis1);
+    Plane l(obj_pos, axis2);
+    Plane r(obj_pos, axis3);
+    Plane k(obj_pos, axis);
+
+    Vec3 hit1, hit2, hit3;
+    bool hl = l.hit(select, hit1);
+    bool hr = r.hit(select, hit2);
+    bool hk = k.hit(select, hit3);
+    if(!hl && !hr && !hk)
+        return false;
+    else if(!hl && !hk)
+        hit = hit2;
+    else if(!hr && !hk)
+        hit = hit1;
+    else if(!hl && !hr)
+        hit = hit3;
+    else {
+        Vec3 temp = (hit1 - cam_pos).norm() > (hit2 - cam_pos).norm() ? hit2 : hit1;
+        hit = (temp - cam_pos).norm() > (hit3 - cam_pos).norm() ? hit3 : temp;
+    }
+    hit = target.closest(hit);
+    return hit.valid();
+}
+
 bool Widgets::to_plane(Vec3 obj_pos, Vec3 cam_pos, Vec3 dir, Vec3 norm, Vec3& hit) {
 
     Line look(cam_pos, dir);
@@ -254,6 +307,8 @@ void Widgets::start_drag(Vec3 pos, Vec3 cam, Vec2 spos, Vec3 dir) {
 
         if(drag_plane)
             good = to_plane(pos, cam, dir, norm, hit);
+        else if(univ_scl)
+            good = to_axis3(pos, cam, dir, hit);
         else
             good = to_axis(pos, cam, dir, hit);
 
@@ -279,6 +334,7 @@ void Widgets::end_drag() {
     bevel_start = bevel_end = {};
     dragging = false;
     drag_plane = false;
+    univ_scl = false;
 }
 
 void Widgets::drag_to(Vec3 pos, Vec3 cam, Vec2 spos, Vec3 dir, bool scale_invert) {
@@ -313,6 +369,8 @@ void Widgets::drag_to(Vec3 pos, Vec3 cam, Vec2 spos, Vec3 dir, bool scale_invert
 
         if(active == Widget_Type::move) {
             drag_end = hit;
+        } else if(univ_scl && active == Widget_Type::scale) {
+            drag_end = Vec3((hit - pos).norm());
         } else if(active == Widget_Type::scale) {
             drag_end = Vec3{1.0f};
             drag_end[(int)axis] = (hit - pos).norm() / (drag_start - pos).norm();
@@ -320,7 +378,7 @@ void Widgets::drag_to(Vec3 pos, Vec3 cam, Vec2 spos, Vec3 dir, bool scale_invert
             assert(false);
     }
 
-    if(scale_invert && active == Widget_Type::scale) {
+    if(scale_invert && active == Widget_Type::scale && !univ_scl) {
         drag_end[(int)axis] *= sign(dot(hit - pos, drag_start - pos));
     }
 }
@@ -329,6 +387,7 @@ void Widgets::select(Scene_ID id) {
 
     start_dragging = true;
     drag_plane = false;
+    univ_scl = false;
 
     switch(id) {
     case(Scene_ID)Widget_IDs::x_mov: {
@@ -382,6 +441,11 @@ void Widgets::select(Scene_ID id) {
         active = Widget_Type::scale;
         axis = Axis::Z;
     } break;
+    case(Scene_ID)Widget_IDs::xyz_scl: {
+        active = Widget_Type::scale;
+        axis = Axis::X;
+        univ_scl = true;
+    } break;
     default: {
         start_dragging = false;
     } break;
-- 
GitLab