[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