[Bf-blender-cvs] [4b11312335b] soc-2021-knife-tools: Knife: Added orientation locking to knife tool

Cian Jinks noreply at git.blender.org
Fri Jun 11 14:07:04 CEST 2021


Commit: 4b11312335b53326c64bcd252c545f69435fe5d3
Author: Cian Jinks
Date:   Fri Jun 11 13:04:32 2021 +0100
Branches: soc-2021-knife-tools
https://developer.blender.org/rB4b11312335b53326c64bcd252c545f69435fe5d3

Knife: Added orientation locking to knife tool

- Pressing X, Y or Z will lock current cut to corresponding axis.
- Pressing the same key twice will lock to local object axis.
- Scene orientation setting takes priority over this when set to anything other than global. This provides support for custom orientations.

===================================================================

M	release/scripts/presets/keyconfig/keymap_data/blender_default.py
M	source/blender/editors/mesh/editmesh_knife.c

===================================================================

diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
index 3165a3aa980..712744b443a 100644
--- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py
+++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
@@ -5363,7 +5363,7 @@ def km_knife_tool_modal_map(_params):
         ("IGNORE_SNAP_ON", {"type": 'RIGHT_SHIFT', "value": 'PRESS', "any": True}, None),
         ("IGNORE_SNAP_OFF", {"type": 'RIGHT_SHIFT', "value": 'RELEASE', "any": True}, None),
         ("ANGLE_SNAP_TOGGLE", {"type": 'C', "value": 'PRESS'}, None),
-        ("CUT_THROUGH_TOGGLE", {"type": 'Z', "value": 'PRESS'}, None),
+        ("CUT_THROUGH_TOGGLE", {"type": 'T', "value": 'PRESS'}, None),
     ])
 
     return keymap
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c
index 4cce2e65c0b..4a26e4b7e42 100644
--- a/source/blender/editors/mesh/editmesh_knife.c
+++ b/source/blender/editors/mesh/editmesh_knife.c
@@ -45,6 +45,7 @@
 #include "BKE_editmesh.h"
 #include "BKE_editmesh_bvh.h"
 #include "BKE_report.h"
+#include "BKE_scene.h"
 #include "BKE_unit.h"
 
 #include "GPU_immediate.h"
@@ -55,6 +56,7 @@
 #include "ED_numinput.h"
 #include "ED_screen.h"
 #include "ED_space_api.h"
+#include "ED_transform.h"
 #include "ED_view3d.h"
 
 #include "WM_api.h"
@@ -255,6 +257,11 @@ typedef struct KnifeTool_OpData {
   float angle;
 
   const float (*cagecos)[3];
+
+  short constrain_axis;
+  short constrain_axis_mode;
+  bool axis_constrained;
+  float curr_cage_adjusted[3];
 } KnifeTool_OpData;
 
 enum {
@@ -272,13 +279,25 @@ enum {
   KNF_MODAL_ADD_CUT_CLOSED,
 };
 
+enum {
+  KNF_CONSTRAIN_AXIS_NONE = 0,
+  KNF_CONSTRAIN_AXIS_X = 1,
+  KNF_CONSTRAIN_AXIS_Y = 2,
+  KNF_CONSTRAIN_AXIS_Z = 3
+};
+
+enum {
+  KNF_CONSTRAIN_AXIS_MODE_NONE = 0,
+  KNF_CONSTRAIN_AXIS_MODE_GLOBAL = 1,
+  KNF_CONSTRAIN_AXIS_MODE_LOCAL = 2
+};
+
 /* -------------------------------------------------------------------- */
 /** \name Drawing
  * \{ */
 
-static void knifetool_draw_angle_snapping(const KnifeTool_OpData *kcd)
+static void knifetool_raycast_planes(const KnifeTool_OpData *kcd, float r_v1[3], float r_v2[3])
 {
-  float v1[3], v2[3];
   float planes[4][4];
 
   planes_from_projmat(
@@ -328,9 +347,16 @@ static void knifetool_draw_angle_snapping(const KnifeTool_OpData *kcd)
       }
     }
 
-    copy_v3_v3(v1, ray_hit_best[0]);
-    copy_v3_v3(v2, ray_hit_best[1]);
+    copy_v3_v3(r_v1, ray_hit_best[0]);
+    copy_v3_v3(r_v2, ray_hit_best[1]);
   }
+}
+
+static void knifetool_draw_angle_snapping(const KnifeTool_OpData *kcd)
+{
+  float v1[3], v2[3];
+
+  knifetool_raycast_planes(kcd, v1, v2);
 
   uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
 
@@ -346,6 +372,46 @@ static void knifetool_draw_angle_snapping(const KnifeTool_OpData *kcd)
   immUnbindProgram();
 }
 
+static void knifetool_draw_orientation_locking(const KnifeTool_OpData *kcd)
+{
+  if (!compare_v3v3(kcd->prev.cage, kcd->curr.cage, KNIFE_FLT_EPSBIG)) {
+    float v1[3], v2[3];
+
+    knifetool_raycast_planes(kcd, v1, v2);
+
+    uint pos = GPU_vertformat_attr_add(immVertexFormat(), "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
+    immBindBuiltinProgram(GPU_SHADER_3D_UNIFORM_COLOR);
+
+    switch (kcd->constrain_axis) {
+      case KNF_CONSTRAIN_AXIS_X: {
+        immUniformThemeColor3(TH_AXIS_X);
+        break;
+      }
+      case KNF_CONSTRAIN_AXIS_Y: {
+        immUniformThemeColor3(TH_AXIS_Y);
+        break;
+      }
+      case KNF_CONSTRAIN_AXIS_Z: {
+        immUniformThemeColor3(TH_AXIS_Z);
+        break;
+      }
+      default: {
+        immUniformThemeColor3(TH_TRANSFORM);
+        break;
+      }
+    }
+
+    GPU_line_width(2.0);
+
+    immBegin(GPU_PRIM_LINES, 2);
+    immVertex3fv(pos, v1);
+    immVertex3fv(pos, v2);
+    immEnd();
+
+    immUnbindProgram();
+  }
+}
+
 /* modal loop selection drawing callback */
 static void knifetool_draw(const bContext *UNUSED(C), ARegion *UNUSED(region), void *arg)
 {
@@ -358,8 +424,13 @@ static void knifetool_draw(const bContext *UNUSED(C), ARegion *UNUSED(region), v
   GPU_matrix_push();
   GPU_matrix_mul(kcd->ob->obmat);
 
-  if (kcd->mode == MODE_DRAGGING && kcd->is_angle_snapping) {
-    knifetool_draw_angle_snapping(kcd);
+  if (kcd->mode == MODE_DRAGGING) {
+    if (kcd->is_angle_snapping) {
+      knifetool_draw_angle_snapping(kcd);
+    }
+    else if (kcd->axis_constrained) {
+      knifetool_draw_orientation_locking(kcd);
+    }
   }
 
   GPUVertFormat *format = immVertexFormat();
@@ -548,7 +619,7 @@ static void knife_update_header(bContext *C, wmOperator *op, KnifeTool_OpData *k
                     "%s: start/define cut, %s: close cut, %s: new cut, "
                     "%s: midpoint snap (%s), %s: ignore snap (%s), "
                     "%s: angle constraint %.2f (%s), %s: cut through (%s), "
-                    "%s: panning"),
+                    "%s: panning, XYZ: orientation lock (%s)"),
                WM_MODALKEY(KNF_MODAL_CONFIRM),
                WM_MODALKEY(KNF_MODAL_CANCEL),
                WM_MODALKEY(KNF_MODAL_ADD_CUT),
@@ -566,7 +637,8 @@ static void knife_update_header(bContext *C, wmOperator *op, KnifeTool_OpData *k
                WM_bool_as_string(kcd->angle_snapping),
                WM_MODALKEY(KNF_MODAL_CUT_THROUGH_TOGGLE),
                WM_bool_as_string(kcd->cut_through),
-               WM_MODALKEY(KNF_MODAL_PANNING));
+               WM_MODALKEY(KNF_MODAL_PANNING),
+               WM_bool_as_string(kcd->axis_constrained));
 
 #undef WM_MODALKEY
 
@@ -1566,7 +1638,8 @@ static void set_lowest_face_tri(KnifeTool_OpData *kcd, BMFace *f, int index)
   BLI_ghash_insert(kcd->facetrimap, f, POINTER_FROM_INT(i + 1));
 }
 
-/* This should only be called for faces that have had a lowest face tri set by previous function */
+/* This should only be called for faces that have had a lowest face tri set by previous function
+ */
 static int get_lowest_face_tri(KnifeTool_OpData *kcd, BMFace *f)
 {
   int ans;
@@ -1835,7 +1908,8 @@ static void set_linehit_depth(KnifeTool_OpData *kcd, KnifeLineHit *lh)
   lh->m = dot_m4_v3_row_z(kcd->vc.rv3d->persmatob, lh->cagehit);
 }
 
-/* Finds visible (or all, if cutting through) edges that intersects the current screen drag line */
+/* Finds visible (or all, if cutting through) edges that intersects the current screen drag line
+ */
 static void knife_find_line_hits(KnifeTool_OpData *kcd)
 {
   SmallHash faces, kfes, kfvs;
@@ -2297,21 +2371,21 @@ static float knife_snap_size(KnifeTool_OpData *kcd, float maxsize)
   return density ? min_ff(maxsize / ((float)density * 0.5f), maxsize) : maxsize;
 }
 
-/* Snap to edge in a specified angle.
+/* Snap to edge when in a constrained mode
  * Returns 'lambda' calculated (in screen-space). */
-static bool knife_snap_edge_in_angle(KnifeTool_OpData *kcd,
-                                     const float sco[3],
-                                     const float kfv1_sco[2],
-                                     const float kfv2_sco[2],
-                                     float *r_dist_sq,
-                                     float *r_lambda)
+static bool knife_snap_edge_constrained(KnifeTool_OpData *kcd,
+                                        const float sco[3],
+                                        const float kfv1_sco[2],
+                                        const float kfv2_sco[2],
+                                        float *r_dist_sq,
+                                        float *r_lambda)
 {
   /* if snapping, check we're in bounds */
   float sco_snap[2];
   isect_line_line_v2_point(kfv1_sco, kfv2_sco, kcd->prev.mval, kcd->curr.mval, sco_snap);
   float lambda = line_point_factor_v2(sco_snap, kfv1_sco, kfv2_sco);
 
-  /* be strict about angle-snapping within edge */
+  /* be strict when constrained within edge */
   if ((lambda < 0.0f - KNIFE_FLT_EPSBIG) || (lambda > 1.0f + KNIFE_FLT_EPSBIG)) {
     return false;
   }
@@ -2389,9 +2463,9 @@ static KnifeEdge *knife_find_closest_edge_of_face(KnifeTool_OpData *kcd,
     knife_project_v2(kcd, kfe->v2->cageco, kfv2_sco);
 
     /* check if we're close enough and calculate 'lambda' */
-    if (kcd->is_angle_snapping) {
+    if (kcd->is_angle_snapping || kcd->axis_constrained) {
       dis_sq = curdis_sq;
-      if (!knife_snap_edge_in_angle(kcd, sco, kfv1_sco, kfv2_sco, &dis_sq, &lambda)) {
+      if (!knife_snap_edge_constrained(kcd, sco, kfv1_sco, kfv2_sco, &dis_sq, &lambda)) {
         continue;
       }
     }
@@ -2474,9 +2548,9 @@ static KnifeVert *knife_find_closest_vert_of_edge(KnifeTool_OpData *kcd,
 
     knife_project_v2(kcd, kfv->cageco, kfv_sco);
 
-    /* be strict about angle snapping, the vertex needs to be very close to the angle,
+    /* be strict when in a constrained mode, the vertex needs to be very close to the cut line,
      * or we ignore */
-    if (kcd->is_angle_snapping) {
+    if (kcd->is_angle_snapping || kcd->axis_constrained) {
       if (dist_squared_to_line_segment_v2(kfv_sco, kcd->prev.mval, kcd->curr.mval) >
           KNIFE_FLT_EPSBIG) {
         continue;
@@ -2565,6 +2639,69 @@ static void knife_reset_snap_angle_input(KnifeTool_OpData *kcd)
     kcd->num.str_cur--;
   }
 }
+/**
+ * Constrains the current cut to an axis.
+ * If scene orientation is set to anything other than global it takes priority.
+ * Otherwise kcd->constrain_axis_mode is used.
+ */
+static void knife_constrain_axis(bContext *C, KnifeTool_OpData *kcd)
+{
+  /* Obtain previous cage and current mouse position in world space */
+  float prev_cage_adjusted[3];
+  copy_v3_v3(prev_cage_adjusted, kcd->prev.cage);
+  mul_m4_v3(kcd->ob->obmat, prev_cage_adjusted);
+  ED_view3d_win_to_3d(
+      kcd->vc.v3d, kcd->region, prev_cage_adjusted, kcd->curr.mval, kcd->curr_cage_adjusted);
+
+  /* Constrain axes */
+  Scene *scene = kcd->scene;
+  ViewLayer *view_layer = CTX_data_view_layer(C);
+  Object *obedit = kcd->ob;
+  RegionView3D *rv3d = kcd->region->regiondata;
+  Object *ob = OBACT(view_layer);
+  const short scene_orientation = BKE_scene_orientation_get_index(scene, SCE_ORIENT_DEFAULT);
+  /* Scene orientation t

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list