Fix crash selecting edit-mesh
The base and the vert/edge/face could be out of sync.
This commit is contained in:
parent
d9c5a35587
commit
9cb397238d
|
@ -921,7 +921,7 @@ BMFace *EDBM_face_find_nearest(ViewContext *vc, float *r_dist)
|
|||
* selected vertices and edges get disadvantage
|
||||
* return 1 if found one
|
||||
*/
|
||||
static int unified_findnearest(
|
||||
static bool unified_findnearest(
|
||||
ViewContext *vc,
|
||||
Base **r_base, BMVert **r_eve, BMEdge **r_eed, BMFace **r_efa)
|
||||
{
|
||||
|
@ -933,12 +933,21 @@ static int unified_findnearest(
|
|||
/* since edges select lines, we give dots advantage of ~20 pix */
|
||||
const float dist_margin = (dist_init / 2);
|
||||
float dist = dist_init;
|
||||
BMFace *efa_zbuf = NULL;
|
||||
BMEdge *eed_zbuf = NULL;
|
||||
|
||||
BMVert *eve = NULL;
|
||||
BMEdge *eed = NULL;
|
||||
BMFace *efa = NULL;
|
||||
struct {
|
||||
struct {
|
||||
BMVert *ele;
|
||||
Base *base;
|
||||
} v;
|
||||
struct {
|
||||
BMEdge *ele;
|
||||
Base *base;
|
||||
} e, e_zbuf;
|
||||
struct {
|
||||
BMFace *ele;
|
||||
Base *base;
|
||||
} f, f_zbuf;
|
||||
} hit = {{NULL}};
|
||||
|
||||
/* TODO(campbell): perform selection as one pass
|
||||
* instead of many smaller passes (which doesn't work for zbuf occlusion). */
|
||||
|
@ -956,14 +965,18 @@ static int unified_findnearest(
|
|||
Object *obedit = base_iter->object;
|
||||
ED_view3d_viewcontext_init_object(vc, obedit);
|
||||
ED_view3d_backbuf_validate(vc);
|
||||
|
||||
BMFace *efa_zbuf = NULL;
|
||||
BMFace *efa_test = EDBM_face_find_nearest_ex(vc, &dist, dist_center_p, true, use_cycle, &efa_zbuf);
|
||||
if (efa && dist_center_p) {
|
||||
if (hit.f.ele && dist_center_p) {
|
||||
dist = min_ff(dist_margin, dist_center);
|
||||
}
|
||||
if (efa_test) {
|
||||
*r_base = base_iter;
|
||||
efa = efa_test;
|
||||
hit.f.base = base_iter;
|
||||
hit.f.ele = efa_test;
|
||||
}
|
||||
if (efa_zbuf) {
|
||||
hit.f_zbuf.base = base_iter;
|
||||
hit.f_zbuf.ele = efa_zbuf;
|
||||
}
|
||||
} /* bases */
|
||||
}
|
||||
|
@ -977,13 +990,18 @@ static int unified_findnearest(
|
|||
Object *obedit = base_iter->object;
|
||||
ED_view3d_viewcontext_init_object(vc, obedit);
|
||||
ED_view3d_backbuf_validate(vc);
|
||||
BMEdge *eed_zbuf = NULL;
|
||||
BMEdge *eed_test = EDBM_edge_find_nearest_ex(vc, &dist, dist_center_p, true, use_cycle, &eed_zbuf);
|
||||
if (eed && dist_center_p) {
|
||||
if (hit.e.ele && dist_center_p) {
|
||||
dist = min_ff(dist_margin, dist_center);
|
||||
}
|
||||
if (eed_test) {
|
||||
*r_base = base_iter;
|
||||
eed = eed_test;
|
||||
hit.e.base = base_iter;
|
||||
hit.e.ele = eed_test;
|
||||
}
|
||||
if (eed_zbuf) {
|
||||
hit.e_zbuf.base = base_iter;
|
||||
hit.e_zbuf.ele = eed_zbuf;
|
||||
}
|
||||
} /* bases */
|
||||
}
|
||||
|
@ -996,8 +1014,8 @@ static int unified_findnearest(
|
|||
ED_view3d_backbuf_validate(vc);
|
||||
BMVert *eve_test = EDBM_vert_find_nearest_ex(vc, &dist, true, use_cycle);
|
||||
if (eve_test) {
|
||||
*r_base = base_iter;
|
||||
eve = eve_test;
|
||||
hit.v.base = base_iter;
|
||||
hit.v.ele = eve_test;
|
||||
}
|
||||
} /* bases */
|
||||
}
|
||||
|
@ -1005,32 +1023,48 @@ static int unified_findnearest(
|
|||
MEM_SAFE_FREE(bases);
|
||||
|
||||
/* return only one of 3 pointers, for frontbuffer redraws */
|
||||
if (eve) {
|
||||
efa = NULL; eed = NULL;
|
||||
if (hit.v.ele) {
|
||||
hit.f.ele = NULL;
|
||||
hit.e.ele = NULL;
|
||||
}
|
||||
else if (eed) {
|
||||
efa = NULL;
|
||||
else if (hit.e.ele) {
|
||||
hit.f.ele = NULL;
|
||||
}
|
||||
|
||||
/* there may be a face under the cursor, who's center if too far away
|
||||
* use this if all else fails, it makes sense to select this */
|
||||
if ((eve || eed || efa) == 0) {
|
||||
if (eed_zbuf) {
|
||||
eed = eed_zbuf;
|
||||
if ((hit.v.ele || hit.e.ele || hit.f.ele) == 0) {
|
||||
if (hit.e_zbuf.ele) {
|
||||
hit.e.base = hit.e_zbuf.base;
|
||||
hit.e.ele = hit.e_zbuf.ele;
|
||||
}
|
||||
else if (efa_zbuf) {
|
||||
efa = efa_zbuf;
|
||||
else if (hit.f_zbuf.ele) {
|
||||
hit.f.base = hit.f_zbuf.base;
|
||||
hit.f.ele = hit.f_zbuf.ele;
|
||||
}
|
||||
}
|
||||
|
||||
mval_prev[0] = vc->mval[0];
|
||||
mval_prev[1] = vc->mval[1];
|
||||
|
||||
/* Only one element type will be non-null. */
|
||||
BLI_assert(((hit.v.ele != NULL) + (hit.e.ele != NULL) + (hit.f.ele != NULL)) <= 1);
|
||||
|
||||
*r_eve = eve;
|
||||
*r_eed = eed;
|
||||
*r_efa = efa;
|
||||
if (hit.v.ele) {
|
||||
*r_base = hit.v.base;
|
||||
}
|
||||
if (hit.e.ele) {
|
||||
*r_base = hit.e.base;
|
||||
}
|
||||
if (hit.f.ele) {
|
||||
*r_base = hit.f.base;
|
||||
}
|
||||
|
||||
return (eve || eed || efa);
|
||||
*r_eve = hit.v.ele;
|
||||
*r_eed = hit.e.ele;
|
||||
*r_efa = hit.f.ele;
|
||||
|
||||
return (hit.v.ele || hit.e.ele || hit.f.ele);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
|
Loading…
Reference in New Issue