diff options
author | Campbell Barton <ideasman42@gmail.com> | 2021-03-29 05:14:23 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2021-03-29 05:29:14 +0300 |
commit | 27a7b2e27ae8088dccfa87e66c820dc2e37c113a (patch) | |
tree | f3885e9da14bbf9ebb76b18314073370ab57fd76 /source/blender/editors/mesh/editmesh_knife.c | |
parent | e47f5cf1979de2a00241619dc4544818837aae8e (diff) |
Fix T83391: Knife sometimes snaps to object center
Knife snapping logic assumed having a face under the cursor meant
the projected positions were set.
This is not always the case as failure to ray-cast uses the back-buffer
as a fallback.
Diffstat (limited to 'source/blender/editors/mesh/editmesh_knife.c')
-rw-r--r-- | source/blender/editors/mesh/editmesh_knife.c | 40 |
1 files changed, 30 insertions, 10 deletions
diff --git a/source/blender/editors/mesh/editmesh_knife.c b/source/blender/editors/mesh/editmesh_knife.c index c5bfeb57eb1..f8b4bf52920 100644 --- a/source/blender/editors/mesh/editmesh_knife.c +++ b/source/blender/editors/mesh/editmesh_knife.c @@ -146,6 +146,8 @@ typedef struct KnifePosData { KnifeVert *vert; KnifeEdge *edge; BMFace *bmface; + + /** When true, the cursor isn't over a face. */ bool is_space; float mval[2]; /* mouse screen position (may be non-integral if snapped to something) */ @@ -2218,7 +2220,15 @@ static bool knife_snap_angle(KnifeTool_OpData *kcd) return true; } -static void knife_snap_update_from_mval(KnifeTool_OpData *kcd, const float mval[2]) +/** + * \return true when `kcd->curr.co` & `kcd->curr.cage` are set. + * + * In this case `is_space` is nearly always false. + * There are some situations when vertex or edge can be snapped to, when `is_space` is true. + * In this case the selection-buffer is used to select the face, + * then the closest `vert` or `edge` is set, and those will enable `is_co_set`. + */ +static bool knife_snap_update_from_mval(KnifeTool_OpData *kcd, const float mval[2]) { knife_pos_data_clear(&kcd->curr); copy_v2_v2(kcd->curr.mval, mval); @@ -2236,29 +2246,39 @@ static void knife_snap_update_from_mval(KnifeTool_OpData *kcd, const float mval[ kcd->curr.bmface = knife_find_closest_face( kcd, kcd->curr.co, kcd->curr.cage, &kcd->curr.is_space); + bool is_co_set = false; + if (kcd->curr.bmface) { + if (kcd->curr.is_space == false) { + is_co_set = true; + } kcd->curr.vert = knife_find_closest_vert_of_face( kcd, kcd->curr.bmface, kcd->curr.co, kcd->curr.cage); - - if (!kcd->curr.vert && - /* no edge snapping while dragging (edges are too sticky when cuts are immediate) */ - !kcd->is_drag_hold) { - kcd->curr.edge = knife_find_closest_edge_of_face( - kcd, kcd->curr.bmface, kcd->curr.co, kcd->curr.cage); + if (kcd->curr.vert) { + is_co_set = true; + } + else { + /* No edge snapping while dragging (edges are too sticky when cuts are immediate). */ + if (!kcd->is_drag_hold) { + kcd->curr.edge = knife_find_closest_edge_of_face( + kcd, kcd->curr.bmface, kcd->curr.co, kcd->curr.cage); + if (kcd->curr.edge) { + is_co_set = true; + } + } } } + return is_co_set; } /* update active knife edge/vert pointers */ static int knife_update_active(KnifeTool_OpData *kcd) { - knife_snap_update_from_mval(kcd, kcd->mval); - /* if no hits are found this would normally default to (0, 0, 0) so instead * get a point at the mouse ray closest to the previous point. * Note that drawing lines in `free-space` isn't properly supported * but there's no guarantee (0, 0, 0) has any geometry either - campbell */ - if (kcd->curr.vert == NULL && kcd->curr.edge == NULL && kcd->curr.bmface == NULL) { + if (!knife_snap_update_from_mval(kcd, kcd->mval)) { float origin[3]; float origin_ofs[3]; |