Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCampbell Barton <ideasman42@gmail.com>2021-03-29 05:14:23 +0300
committerCampbell Barton <ideasman42@gmail.com>2021-03-29 05:29:14 +0300
commit27a7b2e27ae8088dccfa87e66c820dc2e37c113a (patch)
treef3885e9da14bbf9ebb76b18314073370ab57fd76 /source/blender/editors/mesh
parente47f5cf1979de2a00241619dc4544818837aae8e (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')
-rw-r--r--source/blender/editors/mesh/editmesh_knife.c40
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];