Commit: 9cb397238d13e1362f0d94fd2b4e84a1fd1eb1b0
Author: Campbell Barton
Date:   Fri May 4 19:01:53 2018 +0200
Branches: blender2.8
https://developer.blender.org/rB9cb397238d13e1362f0d94fd2b4e84a1fd1eb1b0

Fix crash selecting edit-mesh

The base and the vert/edge/face could be out of sync.

===================================================================

M       source/blender/editors/mesh/editmesh_select.c

===================================================================

diff --git a/source/blender/editors/mesh/editmesh_select.c 
b/source/blender/editors/mesh/editmesh_select.c
index ac5999c97c4..b96fcd3b277 100644
--- a/source/blender/editors/mesh/editmesh_select.c
+++ b/source/blender/editors/mesh/editmesh_select.c
@@ -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);
+
+       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;
+       }
 
-       *r_eve = eve;
-       *r_eed = eed;
-       *r_efa = efa;
+       *r_eve = hit.v.ele;
+       *r_eed = hit.e.ele;
+       *r_efa = hit.f.ele;
 
-       return (eve || eed || efa);
+       return (hit.v.ele || hit.e.ele || hit.f.ele);
 }
 
 /** \} */

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to