Merging r58475 through r58700 from trunk into soc-2013-depsgraph_mt
[blender.git] / source / blender / editors / mesh / editface.c
index 29139c5154fc909a436dd958d58902386d219c5c..db5635d6ea394c812cf96f3a02cce5a3fbbe6e7b 100644 (file)
@@ -15,9 +15,6 @@
  * along with this program; if not, write to the Free Software Foundation,
  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  *
- * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
- * All rights reserved.
- *
  * Contributor(s): Blender Foundation, Campbell Barton
  *
  * ***** END GPL LICENSE BLOCK *****
@@ -33,6 +30,9 @@
 #include "BLI_blenlib.h"
 #include "BLI_math.h"
 #include "BLI_edgehash.h"
+#include "BLI_bitmap.h"
+
+#include "BLF_translation.h"
 
 #include "IMB_imbuf_types.h"
 #include "IMB_imbuf.h"
@@ -44,7 +44,8 @@
 #include "BKE_global.h"
 #include "BKE_mesh.h"
 #include "BKE_context.h"
-#include "BKE_tessmesh.h"
+#include "BKE_editmesh.h"
+#include "BKE_utildefines.h"
 
 #include "BIF_gl.h"
 
@@ -69,7 +70,16 @@ void paintface_flush_flags(Object *ob)
        int totface, totpoly;
        int i;
        
-       if (me == NULL || dm == NULL)
+       if (me == NULL)
+               return;
+
+       /* note, call #BKE_mesh_flush_hidden_from_verts_ex first when changing hidden flags */
+
+       /* we could call this directly in all areas that change selection,
+        * since this could become slow for realtime updates (circle-select for eg) */
+       BKE_mesh_flush_select_from_polys(me);
+
+       if (dm == NULL)
                return;
 
        /*
@@ -85,9 +95,11 @@ void paintface_flush_flags(Object *ob)
                
                /* loop over tessfaces */
                for (i = 0; i < totface; i++) {
-                       /* Copy flags onto the original tessface from its original poly */
-                       mp_orig = me->mpoly + index_array[i];
-                       faces[i].flag = mp_orig->flag;
+                       if (index_array[i] != ORIGINDEX_NONE) {
+                               /* Copy flags onto the original tessface from its original poly */
+                               mp_orig = me->mpoly + index_array[i];
+                               faces[i].flag = mp_orig->flag;
+                       }
                }
        }
 
@@ -97,9 +109,11 @@ void paintface_flush_flags(Object *ob)
 
                /* loop over final derived polys */
                for (i = 0; i < totpoly; i++) {
-                       /* Copy flags onto the final derived poly from the original mesh poly */
-                       mp_orig = me->mpoly + index_array[i];
-                       polys[i].flag = mp_orig->flag;
+                       if (index_array[i] != ORIGINDEX_NONE) {
+                               /* Copy flags onto the final derived poly from the original mesh poly */
+                               mp_orig = me->mpoly + index_array[i];
+                               polys[i].flag = mp_orig->flag;
+                       }
                }
        }
 
@@ -110,14 +124,16 @@ void paintface_flush_flags(Object *ob)
 
                /* loop over tessfaces */
                for (i = 0; i < totface; i++) {
-                       /* Copy flags onto the final tessface from its final poly */
-                       mp_orig = polys + index_array[i];
-                       faces[i].flag = mp_orig->flag;
+                       if (index_array[i] != ORIGINDEX_NONE) {
+                               /* Copy flags onto the final tessface from its final poly */
+                               mp_orig = polys + index_array[i];
+                               faces[i].flag = mp_orig->flag;
+                       }
                }
        }
 }
 
-void paintface_hide(Object *ob, const int unselected)
+void paintface_hide(Object *ob, const bool unselected)
 {
        Mesh *me;
        MPoly *mpoly;
@@ -130,18 +146,20 @@ void paintface_hide(Object *ob, const int unselected)
        a = me->totpoly;
        while (a--) {
                if ((mpoly->flag & ME_HIDE) == 0) {
-                       if (unselected) {
-                               if ((mpoly->flag & ME_FACE_SEL) == 0) mpoly->flag |= ME_HIDE;
-                       }
-                       else {
-                               if ((mpoly->flag & ME_FACE_SEL)) mpoly->flag |= ME_HIDE;
+                       if (((mpoly->flag & ME_FACE_SEL) == 0) == unselected) {
+                               mpoly->flag |= ME_HIDE;
                        }
                }
-               if (mpoly->flag & ME_HIDE) mpoly->flag &= ~ME_FACE_SEL;
+
+               if (mpoly->flag & ME_HIDE) {
+                       mpoly->flag &= ~ME_FACE_SEL;
+               }
                
                mpoly++;
        }
        
+       BKE_mesh_flush_hidden_from_polys(me);
+
        paintface_flush_flags(ob);
 }
 
@@ -165,44 +183,29 @@ void paintface_reveal(Object *ob)
                mpoly++;
        }
 
+       BKE_mesh_flush_hidden_from_polys(me);
+
        paintface_flush_flags(ob);
 }
 
 /* Set tface seams based on edge data, uses hash table to find seam edges. */
 
-static void hash_add_face(EdgeHash *ehash, MPoly *mp, MLoop *mloop)
-{
-       MLoop *ml;
-       int i;
-
-       for (i = 0, ml = mloop; i < mp->totloop; i++, ml++) {
-               BLI_edgehash_insert(ehash, ml->v, ME_POLY_LOOP_NEXT(mloop, mp, i)->v, NULL);
-       }
-}
-
-
-static void select_linked_tfaces_with_seams(int mode, Mesh *me, unsigned int index)
+static void select_linked_tfaces_with_seams(Mesh *me, const unsigned int index, const bool select)
 {
-       EdgeHash *ehash, *seamhash;
        MPoly *mp;
        MLoop *ml;
-       MEdge *med;
-       char *linkflag;
-       int a, b, do_it = TRUE, mark = 0;
-
-       ehash = BLI_edgehash_new();
-       seamhash = BLI_edgehash_new();
-       linkflag = MEM_callocN(sizeof(char) * me->totpoly, "linkflaguv");
+       int a, b;
+       bool do_it = true;
+       bool mark = false;
 
-       for (med = me->medge, a = 0; a < me->totedge; a++, med++)
-               if (med->flag & ME_SEAM)
-                       BLI_edgehash_insert(seamhash, med->v1, med->v2, NULL);
+       BLI_bitmap *edge_tag = BLI_BITMAP_NEW(me->totedge, __func__);
+       BLI_bitmap *poly_tag = BLI_BITMAP_NEW(me->totpoly, __func__);
 
-       if (mode == 0 || mode == 1) {
+       if (index != (unsigned int)-1) {
                /* only put face under cursor in array */
-               mp = ((MPoly *)me->mpoly) + index;
-               hash_add_face(ehash, mp, me->mloop + mp->loopstart);
-               linkflag[index] = 1;
+               mp = &me->mpoly[index];
+               BKE_mesh_poly_edgebitmap_insert(edge_tag, mp, me->mloop + mp->loopstart);
+               BLI_BITMAP_SET(poly_tag, index);
        }
        else {
                /* fill array by selection */
@@ -212,14 +215,14 @@ static void select_linked_tfaces_with_seams(int mode, Mesh *me, unsigned int ind
                                /* pass */
                        }
                        else if (mp->flag & ME_FACE_SEL) {
-                               hash_add_face(ehash, mp, me->mloop + mp->loopstart);
-                               linkflag[a] = 1;
+                               BKE_mesh_poly_edgebitmap_insert(edge_tag, mp, me->mloop + mp->loopstart);
+                               BLI_BITMAP_SET(poly_tag, a);
                        }
                }
        }
 
        while (do_it) {
-               do_it = FALSE;
+               do_it = false;
 
                /* expand selection */
                mp = me->mpoly;
@@ -227,80 +230,59 @@ static void select_linked_tfaces_with_seams(int mode, Mesh *me, unsigned int ind
                        if (mp->flag & ME_HIDE)
                                continue;
 
-                       if (!linkflag[a]) {
-                               MLoop *mnextl;
-                               mark = 0;
+                       if (!BLI_BITMAP_GET(poly_tag, a)) {
+                               mark = false;
 
                                ml = me->mloop + mp->loopstart;
                                for (b = 0; b < mp->totloop; b++, ml++) {
-                                       mnextl = b < mp->totloop - 1 ? ml - 1 : me->mloop + mp->loopstart;
-                                       if (!BLI_edgehash_haskey(seamhash, ml->v, mnextl->v))
-                                               if (!BLI_edgehash_haskey(ehash, ml->v, mnextl->v))
-                                                       mark = 1;
+                                       if ((me->medge[ml->e].flag & ME_SEAM) == 0) {
+                                               if (BLI_BITMAP_GET(edge_tag, ml->e)) {
+                                                       mark = true;
+                                                       break;
+                                               }
+                                       }
                                }
 
                                if (mark) {
-                                       linkflag[a] = 1;
-                                       hash_add_face(ehash, mp, me->mloop + mp->loopstart);
-                                       do_it = TRUE;
+                                       BLI_BITMAP_SET(poly_tag, a);
+                                       BKE_mesh_poly_edgebitmap_insert(edge_tag, mp, me->mloop + mp->loopstart);
+                                       do_it = true;
                                }
                        }
                }
-
        }
 
-       BLI_edgehash_free(ehash, NULL);
-       BLI_edgehash_free(seamhash, NULL);
-
-       if (mode == 0 || mode == 2) {
-               for (a = 0, mp = me->mpoly; a < me->totpoly; a++, mp++)
-                       if (linkflag[a])
-                               mp->flag |= ME_FACE_SEL;
-                       else
-                               mp->flag &= ~ME_FACE_SEL;
-       }
-       else if (mode == 1) {
-               for (a = 0, mp = me->mpoly; a < me->totpoly; a++, mp++)
-                       if (linkflag[a] && (mp->flag & ME_FACE_SEL))
-                               break;
+       MEM_freeN(edge_tag);
 
-               if (a < me->totpoly) {
-                       for (a = 0, mp = me->mpoly; a < me->totpoly; a++, mp++)
-                               if (linkflag[a])
-                                       mp->flag &= ~ME_FACE_SEL;
-               }
-               else {
-                       for (a = 0, mp = me->mpoly; a < me->totpoly; a++, mp++)
-                               if (linkflag[a])
-                                       mp->flag |= ME_FACE_SEL;
+       for (a = 0, mp = me->mpoly; a < me->totpoly; a++, mp++) {
+               if (BLI_BITMAP_GET(poly_tag, a)) {
+                       BKE_BIT_TEST_SET(mp->flag, select, ME_FACE_SEL);
                }
        }
 
-       MEM_freeN(linkflag);
+       MEM_freeN(poly_tag);
 }
 
-void paintface_select_linked(bContext *UNUSED(C), Object *ob, int UNUSED(mval[2]), int mode)
+void paintface_select_linked(bContext *C, Object *ob, const int mval[2], const bool select)
 {
        Mesh *me;
-       unsigned int index = 0;
+       unsigned int index = (unsigned int)-1;
 
        me = BKE_mesh_from_object(ob);
        if (me == NULL || me->totpoly == 0) return;
 
-       if (mode == 0 || mode == 1) {
-               /* XXX - Causes glitches, not sure why */
-#if 0
-               if (!ED_mesh_pick_face(C, me, mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE))
+       if (mval) {
+               if (!ED_mesh_pick_face(C, ob, mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE)) {
                        return;
-#endif
+               }
        }
 
-       select_linked_tfaces_with_seams(mode, me, index);
+       select_linked_tfaces_with_seams(me, index, select);
 
        paintface_flush_flags(ob);
 }
 
-void paintface_deselect_all_visible(Object *ob, int action, short flush_flags)
+void paintface_deselect_all_visible(Object *ob, int action, bool flush_flags)
 {
        Mesh *me;
        MPoly *mpoly;
@@ -359,14 +341,15 @@ void paintface_deselect_all_visible(Object *ob, int action, short flush_flags)
        }
 }
 
-int paintface_minmax(Object *ob, float r_min[3], float r_max[3])
+bool paintface_minmax(Object *ob, float r_min[3], float r_max[3])
 {
        Mesh *me;
        MPoly *mp;
        MTexPoly *tf;
        MLoop *ml;
        MVert *mvert;
-       int a, b, ok = FALSE;
+       int a, b;
+       bool ok = false;
        float vec[3], bmat[3][3];
 
        me = BKE_mesh_from_object(ob);
@@ -389,86 +372,13 @@ int paintface_minmax(Object *ob, float r_min[3], float r_max[3])
                        minmax_v3v3_v3(r_min, r_max, vec);
                }
 
-               ok = TRUE;
+               ok = true;
        }
 
        return ok;
 }
 
-/* *************************************** */
-#if 0
-static void seam_edgehash_insert_face(EdgeHash *ehash, MPoly *mp, MLoop *loopstart)
-{
-       MLoop *ml1, *ml2;
-       int a;
-
-       for (a = 0; a < mp->totloop; a++) {
-               ml1 = loopstart + a;
-               ml2 = loopstart + (a + 1) % mp->totloop;
-
-               BLI_edgehash_insert(ehash, ml1->v, ml2->v, NULL);
-       }
-}
-
-void seam_mark_clear_tface(Scene *scene, short mode)
-{
-       Mesh *me;
-       MPoly *mp;
-       MLoop *ml1, *ml2;
-       MEdge *med;
-       int a, b;
-       
-       me = BKE_mesh_from_object(OBACT);
-       if (me == 0 ||  me->totpoly == 0) return;
-
-       if (mode == 0)
-               mode = pupmenu("Seams %t|Mark Border Seam %x1|Clear Seam %x2");
-
-       if (mode != 1 && mode != 2)
-               return;
-
-       if (mode == 2) {
-               EdgeHash *ehash = BLI_edgehash_new();
-
-               for (a = 0, mp = me->mpoly; a < me->totpoly; a++, mp++)
-                       if (!(mp->flag & ME_HIDE) && (mp->flag & ME_FACE_SEL))
-                               seam_edgehash_insert_face(ehash, mp, me->mloop + mp->loopstart);
-
-               for (a = 0, med = me->medge; a < me->totedge; a++, med++)
-                       if (BLI_edgehash_haskey(ehash, med->v1, med->v2))
-                               med->flag &= ~ME_SEAM;
-
-               BLI_edgehash_free(ehash, NULL);
-       }
-       else {
-               /* mark edges that are on both selected and deselected faces */
-               EdgeHash *ehash1 = BLI_edgehash_new();
-               EdgeHash *ehash2 = BLI_edgehash_new();
-
-               for (a = 0, mp = me->mpoly; a < me->totpoly; a++, mp++) {
-                       if ((mp->flag & ME_HIDE) || !(mp->flag & ME_FACE_SEL))
-                               seam_edgehash_insert_face(ehash1, mp, me->mloop + mp->loopstart);
-                       else
-                               seam_edgehash_insert_face(ehash2, mp, me->mloop + mp->loopstart);
-               }
-
-               for (a = 0, med = me->medge; a < me->totedge; a++, med++)
-                       if (BLI_edgehash_haskey(ehash1, med->v1, med->v2) &&
-                           BLI_edgehash_haskey(ehash2, med->v1, med->v2))
-                               med->flag |= ME_SEAM;
-
-               BLI_edgehash_free(ehash1, NULL);
-               BLI_edgehash_free(ehash2, NULL);
-       }
-
-// XXX if (G.debug_value == 8)
-//             unwrap_lscm(1);
-
-       me->drawflag |= ME_DRAWSEAMS;
-}
-#endif
-
-int paintface_mouse_select(struct bContext *C, Object *ob, const int mval[2], int extend, int deselect, int toggle)
+bool paintface_mouse_select(struct bContext *C, Object *ob, const int mval[2], bool extend, bool deselect, bool toggle)
 {
        Mesh *me;
        MPoly *mpoly, *mpoly_sel;
@@ -477,14 +387,14 @@ int paintface_mouse_select(struct bContext *C, Object *ob, const int mval[2], in
        /* Get the face under the cursor */
        me = BKE_mesh_from_object(ob);
 
-       if (!ED_mesh_pick_face(C, me, mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE))
-               return 0;
+       if (!ED_mesh_pick_face(C, ob, mval, &index, ED_MESH_PICK_DEFAULT_FACE_SIZE))
+               return false;
        
        if (index >= me->totpoly)
-               return 0;
+               return false;
 
        mpoly_sel = me->mpoly + index;
-       if (mpoly_sel->flag & ME_HIDE) return 0;
+       if (mpoly_sel->flag & ME_HIDE) return false;
        
        /* clear flags */
        mpoly = me->mpoly;
@@ -510,17 +420,19 @@ int paintface_mouse_select(struct bContext *C, Object *ob, const int mval[2], in
                else
                        mpoly_sel->flag |= ME_FACE_SEL;
        }
-       else mpoly_sel->flag |= ME_FACE_SEL;
+       else {
+               mpoly_sel->flag |= ME_FACE_SEL;
+       }
        
        /* image window redraw */
        
        paintface_flush_flags(ob);
        WM_event_add_notifier(C, NC_GEOM | ND_SELECT, ob->data);
        ED_region_tag_redraw(CTX_wm_region(C)); // XXX - should redraw all 3D views
-       return 1;
+       return true;
 }
 
-int do_paintface_box_select(ViewContext *vc, rcti *rect, int select, int extend)
+int do_paintface_box_select(ViewContext *vc, rcti *rect, bool select, bool extend)
 {
        Object *ob = vc->obact;
        Mesh *me;
@@ -539,8 +451,8 @@ int do_paintface_box_select(ViewContext *vc, rcti *rect, int select, int extend)
 
        selar = MEM_callocN(me->totpoly + 1, "selar");
 
-       if (extend == 0 && select) {
-               paintface_deselect_all_visible(vc->obact, SEL_DESELECT, FALSE);
+       if (extend == false && select) {
+               paintface_deselect_all_visible(vc->obact, SEL_DESELECT, false);
 
                mpoly = me->mpoly;
                for (a = 1; a <= me->totpoly; a++, mpoly++) {
@@ -553,7 +465,7 @@ int do_paintface_box_select(ViewContext *vc, rcti *rect, int select, int extend)
 
        ibuf = IMB_allocImBuf(sx, sy, 32, IB_rect);
        rt = ibuf->rect;
-       glReadPixels(rect->xmin + vc->ar->winrct.xmin,  rect->ymin + vc->ar->winrct.ymin, sx, sy, GL_RGBA, GL_UNSIGNED_BYTE,  ibuf->rect);
+       view3d_opengl_read_pixels(vc->ar, rect->xmin, rect->ymin, sx, sy, GL_RGBA, GL_UNSIGNED_BYTE,  ibuf->rect);
        if (ENDIAN_ORDER == B_ENDIAN) IMB_convert_rgba_to_abgr(ibuf);
 
        a = sx * sy;
@@ -603,7 +515,14 @@ void paintvert_flush_flags(Object *ob)
        int totvert;
        int i;
 
-       if (me == NULL || dm == NULL)
+       if (me == NULL)
+               return;
+
+       /* we could call this directly in all areas that change selection,
+        * since this could become slow for realtime updates (circle-select for eg) */
+       BKE_mesh_flush_select_from_verts(me);
+
+       if (dm == NULL)
                return;
 
        index_array = dm->getVertDataArray(dm, CD_ORIGINDEX);
@@ -628,8 +547,8 @@ void paintvert_flush_flags(Object *ob)
                }
        }
 }
-/*  note: if the caller passes FALSE to flush_flags, then they will need to run paintvert_flush_flags(ob) themselves */
-void paintvert_deselect_all_visible(Object *ob, int action, short flush_flags)
+/*  note: if the caller passes false to flush_flags, then they will need to run paintvert_flush_flags(ob) themselves */
+void paintvert_deselect_all_visible(Object *ob, int action, bool flush_flags)
 {
        Mesh *me;
        MVert *mvert;
@@ -683,17 +602,59 @@ void paintvert_deselect_all_visible(Object *ob, int action, short flush_flags)
                }
        }
 
+       /* handle mselect */
+       if (action == SEL_SELECT) {
+               /* pass */
+       }
+       else if (ELEM(action, SEL_DESELECT, SEL_INVERT)) {
+               BKE_mesh_mselect_clear(me);
+       }
+       else {
+               BKE_mesh_mselect_validate(me);
+       }
+
        if (flush_flags) {
                paintvert_flush_flags(ob);
        }
 }
 
+void paintvert_select_ungrouped(Object *ob, bool extend, bool flush_flags)
+{
+       Mesh *me = BKE_mesh_from_object(ob);
+       MVert *mv;
+       MDeformVert *dv;
+       int a, tot;
+
+       if (me == NULL || me->dvert == NULL) {
+               return;
+       }
+
+       if (!extend) {
+               paintvert_deselect_all_visible(ob, SEL_DESELECT, false);
+       }
+
+       dv = me->dvert;
+       tot = me->totvert;
+
+       for (a = 0, mv = me->mvert; a < tot; a++, mv++, dv++) {
+               if ((mv->flag & ME_HIDE) == 0) {
+                       if (dv->dw == NULL) {
+                               /* if null weight then not grouped */
+                               mv->flag |= SELECT;
+                       }
+               }
+       }
+
+       if (flush_flags) {
+               paintvert_flush_flags(ob);
+       }
+}
 
 /* ********************* MESH VERTEX MIRR TOPO LOOKUP *************** */
 /* note, this is not the best place for the function to be but moved
  * here to for the purpose of syncing with bmesh */
 
-typedef int MirrTopoHash_t;
+typedef unsigned int MirrTopoHash_t;
 
 typedef struct MirrTopoVert_t {
        MirrTopoHash_t hash;
@@ -714,7 +675,7 @@ static int mirrtopo_vert_sort(const void *v1, const void *v2)
        return 0;
 }
 
-int ED_mesh_mirrtopo_recalc_check(Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_topo_store)
+bool ED_mesh_mirrtopo_recalc_check(Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_topo_store)
 {
        int totvert;
        int totedge;
@@ -733,16 +694,16 @@ int ED_mesh_mirrtopo_recalc_check(Mesh *me, const int ob_mode, MirrTopoStore_t *
            (totvert != mesh_topo_store->prev_vert_tot) ||
            (totedge != mesh_topo_store->prev_edge_tot))
        {
-               return TRUE;
+               return true;
        }
        else {
-               return FALSE;
+               return false;
        }
 
 }
 
 void ED_mesh_mirrtopo_init(Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_topo_store,
-                           const short skip_em_vert_array_init)
+                           const bool skip_em_vert_array_init)
 {
        MEdge *medge;
        BMEditMesh *em = me->edit_btmesh;
@@ -758,6 +719,7 @@ void ED_mesh_mirrtopo_init(Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_to
        MirrTopoHash_t *topo_hash = NULL;
        MirrTopoHash_t *topo_hash_prev = NULL;
        MirrTopoVert_t *topo_pairs;
+       MirrTopoHash_t  topo_pass = 1;
 
        intptr_t *index_lookup; /* direct access to mesh_topo_store->index_lookup */
 
@@ -803,15 +765,15 @@ void ED_mesh_mirrtopo_init(Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_to
 
                if (em) {
                        BM_ITER_MESH (eed, &iter, em->bm, BM_EDGES_OF_MESH) {
-                               topo_hash[BM_elem_index_get(eed->v1)] += topo_hash_prev[BM_elem_index_get(eed->v2)];
-                               topo_hash[BM_elem_index_get(eed->v2)] += topo_hash_prev[BM_elem_index_get(eed->v1)];
+                               topo_hash[BM_elem_index_get(eed->v1)] += topo_hash_prev[BM_elem_index_get(eed->v2)] * topo_pass;
+                               topo_hash[BM_elem_index_get(eed->v2)] += topo_hash_prev[BM_elem_index_get(eed->v1)] * topo_pass;
                        }
                }
                else {
                        for (a = 0, medge = me->medge; a < me->totedge; a++, medge++) {
                                /* This can make really big numbers, wrapping around here is fine */
-                               topo_hash[medge->v1] += topo_hash_prev[medge->v2];
-                               topo_hash[medge->v2] += topo_hash_prev[medge->v1];
+                               topo_hash[medge->v1] += topo_hash_prev[medge->v2] * topo_pass;
+                               topo_hash[medge->v2] += topo_hash_prev[medge->v1] * topo_pass;
                        }
                }
                memcpy(topo_hash_prev, topo_hash, sizeof(MirrTopoHash_t) * totvert);
@@ -836,6 +798,8 @@ void ED_mesh_mirrtopo_init(Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_to
                }
                /* Copy the hash calculated this iter, so we can use them next time */
                memcpy(topo_hash_prev, topo_hash, sizeof(MirrTopoHash_t) * totvert);
+
+               topo_pass++;
        }
 
        /* Hash/Index pairs are needed for sorting to find index pairs */
@@ -845,7 +809,7 @@ void ED_mesh_mirrtopo_init(Mesh *me, const int ob_mode, MirrTopoStore_t *mesh_to
        index_lookup = MEM_mallocN(totvert * sizeof(*index_lookup), "mesh_topo_lookup");
 
        if (em) {
-               if (skip_em_vert_array_init == FALSE) {
+               if (skip_em_vert_array_init == false) {
                        EDBM_index_arrays_ensure(em, BM_VERT);
                }
        }