Knife: support vert/edge snapping when not directly over a face
Respect the distance argument to EDBM_face_find_nearest, when zero, sample a single pixel, otherwise sample a region. Knife uses the selection-buffer to pick a face when the ray-cast failed. This was meant to allow snapping to nearby faces however as the margin was ignored, it was only used in edge cases where the ray-cast missed but the pixel didn't. Now the face-picking threshold is working as expected. Note that other callers to EDBM_face_find_nearest have been updated so set their distance argument to zero so this only impacts the knife. Regular selection and path select could be modified separately if users prefer this behavior.
This commit is contained in:
parent
3659340571
commit
80cbbd2843
Notes:
blender-bot
2023-02-14 10:43:47 +01:00
Referenced by commit 14901e3774
, Fix T87080: Select shortest path fails in face mode
Referenced by issue #87080, Select shortest path in face selection mode doesnt work
Referenced by issue #87081, Face selection issue in X-ray mode
|
@ -646,6 +646,9 @@ static BMElem *edbm_elem_find_nearest(ViewContext *vc, const char htype)
|
|||
return (BMElem *)EDBM_edge_find_nearest(vc, &dist);
|
||||
}
|
||||
if ((em->selectmode & SCE_SELECT_FACE) && (htype == BM_FACE)) {
|
||||
/* Only pick faces directly under the cursor.
|
||||
* We could look into changing this, for now it matches regular face selection. */
|
||||
dist = 0.0f;
|
||||
return (BMElem *)EDBM_face_find_nearest(vc, &dist);
|
||||
}
|
||||
|
||||
|
|
|
@ -715,14 +715,27 @@ BMFace *EDBM_face_find_nearest_ex(ViewContext *vc,
|
|||
uint base_index = 0;
|
||||
|
||||
if (!XRAY_FLAG_ENABLED(vc->v3d)) {
|
||||
float dist_test = 0.0f;
|
||||
float dist_test;
|
||||
uint index;
|
||||
BMFace *efa;
|
||||
|
||||
{
|
||||
uint dist_px = 0;
|
||||
if (*r_dist != 0.0f) {
|
||||
dist_px = (uint)ED_view3d_backbuf_sample_size_clamp(vc->region, *r_dist);
|
||||
}
|
||||
|
||||
DRW_select_buffer_context_create(bases, bases_len, SCE_SELECT_FACE);
|
||||
|
||||
index = DRW_select_buffer_sample_point(vc->depsgraph, vc->region, vc->v3d, vc->mval);
|
||||
if (dist_px == 0) {
|
||||
index = DRW_select_buffer_sample_point(vc->depsgraph, vc->region, vc->v3d, vc->mval);
|
||||
dist_test = 0.0f;
|
||||
}
|
||||
else {
|
||||
index = DRW_select_buffer_find_nearest_to_point(
|
||||
vc->depsgraph, vc->region, vc->v3d, vc->mval, 1, UINT_MAX, &dist_px);
|
||||
dist_test = dist_px;
|
||||
}
|
||||
|
||||
if (index) {
|
||||
efa = (BMFace *)edbm_select_id_bm_elem_get(bases, index, &base_index);
|
||||
|
@ -875,6 +888,13 @@ static bool unified_findnearest(ViewContext *vc,
|
|||
/* no afterqueue (yet), so we check it now, otherwise the em_xxxofs indices are bad */
|
||||
|
||||
if ((dist > 0.0f) && (em->selectmode & SCE_SELECT_FACE)) {
|
||||
|
||||
/* Force zero distance, this is a historic exception for faces
|
||||
* as this function didn't originally support using a margin.
|
||||
* Only pick faces directly under the cursor to prevent unexpected changes in behavior.
|
||||
* While this could be changed, take care this isn't causing issues from a user perspective. */
|
||||
dist = 0.0f;
|
||||
|
||||
float dist_center = 0.0f;
|
||||
float *dist_center_p = (em->selectmode & (SCE_SELECT_EDGE | SCE_SELECT_VERTEX)) ?
|
||||
&dist_center :
|
||||
|
@ -885,6 +905,9 @@ static bool unified_findnearest(ViewContext *vc,
|
|||
BMFace *efa_test = EDBM_face_find_nearest_ex(
|
||||
vc, &dist, dist_center_p, true, use_cycle, &efa_zbuf, bases, bases_len, &base_index);
|
||||
|
||||
if (efa_test == NULL) {
|
||||
dist = dist_init;
|
||||
}
|
||||
if (efa_test && dist_center_p) {
|
||||
dist = min_ff(dist_margin, dist_center);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue