Commit: 488b342741ea96ef8e80dab7a7bcf3b9a0be5bcd
Author: Campbell Barton
Date:   Tue Feb 3 19:54:34 2015 +1100
Branches: master
https://developer.blender.org/rB488b342741ea96ef8e80dab7a7bcf3b9a0be5bcd

BMesh: optimize selection flushing

De-selecting a face would do flushing checks on each vertex 3 times, now only 
do once.

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

M       source/blender/bmesh/intern/bmesh_marking.c
M       source/blender/bmesh/intern/bmesh_marking.h

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

diff --git a/source/blender/bmesh/intern/bmesh_marking.c 
b/source/blender/bmesh/intern/bmesh_marking.c
index ffbd2bf..8aa6490 100644
--- a/source/blender/bmesh/intern/bmesh_marking.c
+++ b/source/blender/bmesh/intern/bmesh_marking.c
@@ -70,6 +70,69 @@ static void recount_totsels(BMesh *bm)
        }
 }
 
+/** \name BMesh helper functions for selection flushing.
+ * \{ */
+
+static bool bm_vert_is_edge_select_any_other(BMVert *v, BMEdge *e_first)
+{
+       BMEdge *e_iter = e_first;
+
+       /* start by stepping over the current edge */
+       while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first) {
+               if (BM_elem_flag_test(e_iter, BM_ELEM_SELECT)) {
+                       return true;
+               }
+       }
+       return false;
+}
+
+#if 0
+static bool bm_vert_is_edge_select_any(BMVert *v)
+{
+       if (v->e) {
+               BMEdge *e_iter, *e_first;
+               e_iter = e_first = v->e;
+               do {
+                       if (BM_elem_flag_test(e_iter, BM_ELEM_SELECT)) {
+                               return true;
+                       }
+               } while ((e_iter = bmesh_disk_edge_next(e_iter, v)) != e_first);
+       }
+       return false;
+}
+#endif
+
+static bool bm_edge_is_face_select_any_other(BMLoop *l_first)
+{
+       BMLoop *l_iter = l_first;
+
+       /* start by stepping over the current face */
+       while ((l_iter = l_iter->radial_next) != l_first) {
+               if (BM_elem_flag_test(l_iter->f, BM_ELEM_SELECT)) {
+                       return true;
+               }
+       }
+       return false;
+}
+
+#if 0
+static bool bm_edge_is_face_select_any(BMEdge *e)
+{
+       if (e->l) {
+               BMLoop *l_iter, *l_first;
+               l_iter = l_first = e->l;
+               do {
+                       if (BM_elem_flag_test(l_iter->f, BM_ELEM_SELECT)) {
+                               return true;
+                       }
+               } while ((l_iter = l_iter->radial_next) != l_first);
+       }
+       return false;
+}
+#endif
+
+/** \} */
+
 /**
  * \brief Select Mode Clean
  *
@@ -386,19 +449,8 @@ void BM_edge_select_set(BMesh *bm, BMEdge *e, const bool 
select)
 
                        /* check if the vert is used by a selected edge */
                        for (i = 0; i < 2; i++) {
-                               bool deselect = true;
                                BMVert *v = *((&e->v1) + i);
-                               BMEdge *e_other = e;
-
-                               /* start by stepping over the current edge */
-                               while ((e_other = bmesh_disk_edge_next(e_other, 
v)) != e) {
-                                       if (BM_elem_flag_test(e_other, 
BM_ELEM_SELECT)) {
-                                               deselect = false;
-                                               break;
-                                       }
-                               }
-
-                               if (deselect) {
+                               if (bm_vert_is_edge_select_any_other(v, e) == 
false) {
                                        BM_vert_select_set(bm, v, false);
                                }
                        }
@@ -441,8 +493,6 @@ void BM_face_select_set(BMesh *bm, BMFace *f, const bool 
select)
                } while ((l_iter = l_iter->next) != l_first);
        }
        else {
-               BMIter liter;
-               BMLoop *l;
 
                if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
                        BM_elem_flag_disable(f, BM_ELEM_SELECT);
@@ -450,35 +500,73 @@ void BM_face_select_set(BMesh *bm, BMFace *f, const bool 
select)
                }
 
                /* flush down to edges */
-               BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
-                       BMIter fiter;
-                       BMFace *f2;
-                       BM_ITER_ELEM (f2, &fiter, l->e, BM_FACES_OF_EDGE) {
-                               if (BM_elem_flag_test(f2, BM_ELEM_SELECT))
-                                       break;
+               l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+               do {
+                       /* vertex flushing is handled below */
+                       if (bm_edge_is_face_select_any_other(l_iter) == false) {
+                               BM_edge_select_set_noflush(bm, l_iter->e, 
false);
                        }
+               } while ((l_iter = l_iter->next) != l_first);
 
-                       if (!f2) {
-                               BM_edge_select_set(bm, l->e, false);
+               /* flush down to verts */
+               l_iter = l_first = BM_FACE_FIRST_LOOP(f);
+               do {
+                       if (bm_vert_is_edge_select_any_other(l_iter->v, 
l_iter->e) == false) {
+                               BM_vert_select_set(bm, l_iter->v, false);
                        }
+               } while ((l_iter = l_iter->next) != l_first);
+       }
+}
+
+/** \name Non flushing versions element selection.
+ * \{ */
+
+void BM_edge_select_set_noflush(BMesh *bm, BMEdge *e, const bool select)
+{
+       BLI_assert(e->head.htype == BM_EDGE);
+
+       if (BM_elem_flag_test(e, BM_ELEM_HIDDEN)) {
+               return;
+       }
+
+       if (select) {
+               if (!BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+                       BM_elem_flag_enable(e, BM_ELEM_SELECT);
+                       bm->totedgesel += 1;
                }
+       }
+       else {
+               if (BM_elem_flag_test(e, BM_ELEM_SELECT)) {
+                       BM_elem_flag_disable(e, BM_ELEM_SELECT);
+                       bm->totedgesel -= 1;
+               }
+       }
+}
 
-               /* flush down to verts */
-               BM_ITER_ELEM (l, &liter, f, BM_LOOPS_OF_FACE) {
-                       BMIter eiter;
-                       BMEdge *e;
-                       BM_ITER_ELEM (e, &eiter, l->v, BM_EDGES_OF_VERT) {
-                               if (BM_elem_flag_test(e, BM_ELEM_SELECT))
-                                       break;
-                       }
+void BM_face_select_set_noflush(BMesh *bm, BMFace *f, const bool select)
+{
+       BLI_assert(f->head.htype == BM_FACE);
 
-                       if (!e) {
-                               BM_vert_select_set(bm, l->v, false);
-                       }
+       if (BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
+               return;
+       }
+
+       if (select) {
+               if (!BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+                       BM_elem_flag_enable(f, BM_ELEM_SELECT);
+                       bm->totfacesel += 1;
+               }
+       }
+       else {
+               if (BM_elem_flag_test(f, BM_ELEM_SELECT)) {
+                       BM_elem_flag_disable(f, BM_ELEM_SELECT);
+                       bm->totfacesel -= 1;
                }
        }
 }
 
+/** \} */
+
 /**
  * Select Mode Set
  *
diff --git a/source/blender/bmesh/intern/bmesh_marking.h 
b/source/blender/bmesh/intern/bmesh_marking.h
index 9e0c092..15f972c 100644
--- a/source/blender/bmesh/intern/bmesh_marking.h
+++ b/source/blender/bmesh/intern/bmesh_marking.h
@@ -59,6 +59,10 @@ void BM_vert_select_set(BMesh *bm, BMVert *v, const bool 
select);
 void BM_edge_select_set(BMesh *bm, BMEdge *e, const bool select);
 void BM_face_select_set(BMesh *bm, BMFace *f, const bool select);
 
+/* lower level functions which don't do flushing */
+void BM_edge_select_set_noflush(BMesh *bm, BMEdge *e, const bool select);
+void BM_face_select_set_noflush(BMesh *bm, BMFace *e, const bool select);
+
 void BM_mesh_select_mode_clean_ex(BMesh *bm, const short selectmode);
 void BM_mesh_select_mode_clean(BMesh *bm);

_______________________________________________
Bf-blender-cvs mailing list
Bf-blender-cvs@blender.org
http://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to