changes to mirror tools
authorCampbell Barton <ideasman42@gmail.com>
Wed, 5 Jun 2013 05:58:51 +0000 (05:58 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Wed, 5 Jun 2013 05:58:51 +0000 (05:58 +0000)
- give feedback on how many mirror verts succeed/fail (for select mirror, shape key mirror, weight mirror)
... when a mirror failed it was confusing and not obvious what was going on.

- slight change to select mirror, now center vertices will remain selected.

- speedup to EDBM_verts_mirror_cache_begin, cache customdata layer offset.

source/blender/editors/include/ED_mesh.h
source/blender/editors/mesh/editmesh_select.c
source/blender/editors/mesh/editmesh_tools.c
source/blender/editors/mesh/editmesh_utils.c
source/blender/editors/mesh/mesh_data.c
source/blender/editors/object/object_shapekey.c
source/blender/editors/object/object_vgroup.c
source/blender/editors/transform/transform_conversions.c

index 9aa405eda1d4c5b6c38888e76a68a935215c845c..e3d762dccfb497a3ddc04d2370e4e3ccab2fc364 100644 (file)
@@ -76,7 +76,7 @@ struct MeshStatVis;
 
 
 /* editmesh_utils.c */
-void           EDBM_verts_mirror_cache_begin(struct BMEditMesh *em, const bool use_select); /* note, replaces EM_cache_x_mirror_vert in trunk */
+void           EDBM_verts_mirror_cache_begin(struct BMEditMesh *em, const bool use_self, const bool use_select);
 void           EDBM_verts_mirror_apply(struct BMEditMesh *em, const int sel_from, const int sel_to);
 struct BMVert *EDBM_verts_mirror_get(struct BMEditMesh *em, struct BMVert *v);
 void           EDBM_verts_mirror_cache_clear(struct BMEditMesh *em, struct BMVert *v);
@@ -141,7 +141,8 @@ bool BMBVH_EdgeVisible(struct BMBVHTree *tree, struct BMEdge *e,
                        struct ARegion *ar, struct View3D *v3d, struct Object *obedit);
 
 /* editmesh_select.c */
-void EDBM_select_mirrored(struct Object *obedit, struct BMEditMesh *em, bool extend);
+void EDBM_select_mirrored(struct BMEditMesh *em, bool extend,
+                          int *r_totmirr, int *r_totfail);
 void EDBM_automerge(struct Scene *scene, struct Object *ob, bool update);
 
 bool EDBM_backbuf_border_init(struct ViewContext *vc, short xmin, short ymin, short xmax, short ymax);
@@ -237,7 +238,8 @@ void                 ED_vgroup_data_clamp_range(struct ID *id, const int total);
 bool                 ED_vgroup_give_array(struct ID *id, struct MDeformVert **dvert_arr, int *dvert_tot);
 bool                 ED_vgroup_copy_array(struct Object *ob, struct Object *ob_from);
 void                 ED_vgroup_mirror(struct Object *ob,
-                                      const bool mirror_weights, const bool flip_vgroups, const bool all_vgroups);
+                                      const bool mirror_weights, const bool flip_vgroups, const bool all_vgroups,
+                                      int *r_totmirr, int *r_totfail);
 
 bool                 ED_vgroup_object_is_edit_mode(struct Object *ob);
 
@@ -273,6 +275,8 @@ bool ED_mesh_color_remove_index(struct Mesh *me, const int n);
 bool ED_mesh_color_remove_active(struct Mesh *me);
 bool ED_mesh_color_remove_named(struct Mesh *me, const char *name);
 
+void ED_mesh_report_mirror(struct wmOperator *op, int totmirr, int totfail);
+
 /* mesh backup */
 typedef struct BMBackup {
        struct BMesh *bmcopy;
index 996331d2f8c592240856a140fc708216e32a36ec..b0c76d2366440272c9d9dcfc8120e2812dd799d0 100644 (file)
 
 /* ****************************** MIRROR **************** */
 
-void EDBM_select_mirrored(Object *UNUSED(obedit), BMEditMesh *em, bool extend)
+void EDBM_select_mirrored(BMEditMesh *em, bool extend,
+                          int *r_totmirr, int *r_totfail)
 {
        BMVert *v1, *v2;
        BMIter iter;
+       int totmirr = 0;
+       int totfail = 0;
+
+       *r_totmirr = *r_totfail = 0;
 
        BM_ITER_MESH (v1, &iter, em->bm, BM_VERTS_OF_MESH) {
                if (!BM_elem_flag_test(v1, BM_ELEM_SELECT) || BM_elem_flag_test(v1, BM_ELEM_HIDDEN)) {
@@ -87,7 +92,7 @@ void EDBM_select_mirrored(Object *UNUSED(obedit), BMEditMesh *em, bool extend)
                }
        }
 
-       EDBM_verts_mirror_cache_begin(em, true);
+       EDBM_verts_mirror_cache_begin(em, true, true);
 
        if (!extend)
                EDBM_flag_disable_all(em, BM_ELEM_SELECT);
@@ -97,12 +102,21 @@ void EDBM_select_mirrored(Object *UNUSED(obedit), BMEditMesh *em, bool extend)
                        continue;
 
                v2 = EDBM_verts_mirror_get(em, v1);
-               if (v2 && !BM_elem_flag_test(v2, BM_ELEM_HIDDEN)) {
-                       BM_vert_select_set(em->bm, v2, true);
+               if (v2) {
+                       if (!BM_elem_flag_test(v2, BM_ELEM_HIDDEN)) {
+                               BM_vert_select_set(em->bm, v2, true);
+                               totmirr++;
+                       }
+               }
+               else {
+                       totfail++;
                }
        }
 
        EDBM_verts_mirror_cache_end(em);
+
+       *r_totmirr = totmirr;
+       *r_totfail = totfail;
 }
 
 void EDBM_automerge(Scene *scene, Object *obedit, bool update)
@@ -2206,9 +2220,14 @@ static int edbm_select_mirror_exec(bContext *C, wmOperator *op)
        bool extend = RNA_boolean_get(op->ptr, "extend");
 
        if (em->bm->totvert && em->bm->totvertsel) {
-               EDBM_select_mirrored(obedit, em, extend);
-               EDBM_selectmode_flush(em);
-               WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+               int totmirr, totfail;
+               EDBM_select_mirrored(em, extend, &totmirr, &totfail);
+               if (totmirr) {
+                       EDBM_selectmode_flush(em);
+                       WM_event_add_notifier(C, NC_GEOM | ND_SELECT, obedit->data);
+               }
+
+               ED_mesh_report_mirror(op, totmirr, totfail);
        }
 
        return OPERATOR_FINISHED;
index 70f841e5e595f701589d80cc6b483bc9febedfdb..b34639150809458366515e237c37634a76e66eee 100644 (file)
@@ -1121,7 +1121,7 @@ static int edbm_do_smooth_vertex_exec(bContext *C, wmOperator *op)
 
        /* mirror before smooth */
        if (((Mesh *)obedit->data)->editflag & ME_EDIT_MIRROR_X) {
-               EDBM_verts_mirror_cache_begin(em, true);
+               EDBM_verts_mirror_cache_begin(em, false, true);
        }
 
        /* if there is a mirror modifier with clipping, flag the verts that
@@ -1212,7 +1212,7 @@ static int edbm_do_smooth_laplacian_vertex_exec(bContext *C, wmOperator *op)
 
        /* mirror before smooth */
        if (((Mesh *)obedit->data)->editflag & ME_EDIT_MIRROR_X) {
-               EDBM_verts_mirror_cache_begin(em, true);
+               EDBM_verts_mirror_cache_begin(em, false, true);
        }
 
        repeat = RNA_int_get(op->ptr, "repeat");
index c2c79d337eaa139c8c6990446504effb52f5e105..fa857edb6fcac451589a01c38fae3da986193cac 100644 (file)
@@ -1134,6 +1134,9 @@ static BMVert *cache_mirr_intptr_as_bmvert(intptr_t *index_lookup, int index)
  *  ...
  *  EDBM_verts_mirror_cache_end(em);
  *
+ * \param use_self  Allow a vertex to reference its self.
+ * \param use_select  Only cache selected verts.
+ *
  * \note why do we only allow x axis mirror editing?
  */
 
@@ -1141,13 +1144,14 @@ static BMVert *cache_mirr_intptr_as_bmvert(intptr_t *index_lookup, int index)
  * preference */
 #define BM_SEARCH_MAXDIST_MIRR 0.00002f
 #define BM_CD_LAYER_ID "__mirror_index"
-void EDBM_verts_mirror_cache_begin(BMEditMesh *em, const bool use_select)
+void EDBM_verts_mirror_cache_begin(BMEditMesh *em, const bool use_self, const bool use_select)
 {
        Mesh *me = (Mesh *)em->ob->data;
        BMesh *bm = em->bm;
        BMIter iter;
        BMVert *v;
-       int li, topo = 0;
+       bool topo = false;
+       int cd_vmirr_offset;
 
        /* one or the other is used depending if topo is enabled */
        struct BMBVHTree *tree = NULL;
@@ -1159,13 +1163,16 @@ void EDBM_verts_mirror_cache_begin(BMEditMesh *em, const bool use_select)
 
        EDBM_index_arrays_ensure(em, BM_VERT);
 
-       if (!CustomData_get_layer_named(&bm->vdata, CD_PROP_INT, BM_CD_LAYER_ID)) {
+       em->mirror_cdlayer = CustomData_get_named_layer_index(&bm->vdata, CD_PROP_INT, BM_CD_LAYER_ID);
+       if (em->mirror_cdlayer == -1) {
                BM_data_layer_add_named(bm, &bm->vdata, CD_PROP_INT, BM_CD_LAYER_ID);
+               em->mirror_cdlayer = CustomData_get_named_layer_index(&bm->vdata, CD_PROP_INT, BM_CD_LAYER_ID);
        }
 
-       li = CustomData_get_named_layer_index(&bm->vdata, CD_PROP_INT, BM_CD_LAYER_ID);
+       cd_vmirr_offset = CustomData_get_n_offset(&bm->vdata, CD_PROP_INT,
+                                                 em->mirror_cdlayer - CustomData_get_layer_index(&bm->vdata, CD_PROP_INT));
 
-       bm->vdata.layers[li].flag |= CD_FLAG_TEMPORARY;
+       bm->vdata.layers[em->mirror_cdlayer].flag |= CD_FLAG_TEMPORARY;
 
        BM_mesh_elem_index_ensure(bm, BM_VERT);
 
@@ -1183,20 +1190,20 @@ void EDBM_verts_mirror_cache_begin(BMEditMesh *em, const bool use_select)
                        /* do nothing */
                }
                else {
-                       BMVert *mirr;
-                       int *idx = CustomData_bmesh_get_layer_n(&bm->vdata, v->head.data, li);
+                       BMVert *v_mirr;
+                       int *idx = BM_ELEM_CD_GET_VOID_P(v, cd_vmirr_offset);
 
                        if (topo) {
-                               mirr = cache_mirr_intptr_as_bmvert(mesh_topo_store.index_lookup, BM_elem_index_get(v));
+                               v_mirr = cache_mirr_intptr_as_bmvert(mesh_topo_store.index_lookup, BM_elem_index_get(v));
                        }
                        else {
                                float co[3] = {-v->co[0], v->co[1], v->co[2]};
-                               mirr = BKE_bmbvh_find_vert_closest(tree, co, BM_SEARCH_MAXDIST_MIRR);
+                               v_mirr = BKE_bmbvh_find_vert_closest(tree, co, BM_SEARCH_MAXDIST_MIRR);
                        }
 
-                       if (mirr && mirr != v) {
-                               *idx = BM_elem_index_get(mirr);
-                               idx = CustomData_bmesh_get_layer_n(&bm->vdata, mirr->head.data, li);
+                       if (v_mirr && (use_self || (v_mirr != v))) {
+                               *idx = BM_elem_index_get(v_mirr);
+                               idx = BM_ELEM_CD_GET_VOID_P(v_mirr, cd_vmirr_offset);
                                *idx = BM_elem_index_get(v);
                        }
                        else {
@@ -1213,8 +1220,6 @@ void EDBM_verts_mirror_cache_begin(BMEditMesh *em, const bool use_select)
        else {
                BKE_bmbvh_free(tree);
        }
-
-       em->mirror_cdlayer = li;
 }
 
 BMVert *EDBM_verts_mirror_get(BMEditMesh *em, BMVert *v)
index 869b2fb8f2db741a86e2aaf0fa1b790366c4d521..d0869a30cbf499f8d3e9ce7591fd5a3187002fdc 100644 (file)
@@ -1243,3 +1243,13 @@ void ED_mesh_calc_tessface(Mesh *mesh)
                BKE_mesh_tessface_calc(mesh);
        }
 }
+
+void ED_mesh_report_mirror(wmOperator *op, int totmirr, int totfail)
+{
+       if (totfail) {
+               BKE_reportf(op->reports, RPT_WARNING, "%d vertices mirrored, %d failed", totmirr, totfail);
+       }
+       else {
+               BKE_reportf(op->reports, RPT_INFO, "%d vertices mirrored", totmirr);
+       }
+}
index 2008e5ad4f37850f1b15606a023d9c0348f62456..af9f7220c2636f6b706b24ea505df436d57570b1 100644 (file)
@@ -152,10 +152,14 @@ static int ED_object_shape_key_remove(bContext *C, Object *ob)
        return 1;
 }
 
-static int object_shape_key_mirror(bContext *C, Object *ob)
+static bool object_shape_key_mirror(bContext *C, Object *ob,
+                                    int *r_totmirr, int *r_totfail)
 {
        KeyBlock *kb;
        Key *key;
+       int totmirr = 0, totfail = 0;
+
+       *r_totmirr = *r_totfail = 0;
 
        key = BKE_key_from_object(ob);
        if (key == NULL)
@@ -182,6 +186,7 @@ static int object_shape_key_mirror(bContext *C, Object *ob)
                                        fp1 = ((float *)kb->data) + i1 * 3;
                                        fp1[0] = -fp1[0];
                                        tag_elem[i1] = 1;
+                                       totmirr++;
                                }
                                else if (i2 != -1) {
                                        if (tag_elem[i1] == 0 && tag_elem[i2] == 0) {
@@ -195,9 +200,13 @@ static int object_shape_key_mirror(bContext *C, Object *ob)
                                                /* flip x axis */
                                                fp1[0] = -fp1[0];
                                                fp2[0] = -fp2[0];
+                                               totmirr++;
                                        }
                                        tag_elem[i1] = tag_elem[i2] = 1;
                                }
+                               else {
+                                       totfail++;
+                               }
                        }
 
                        mesh_octree_table(ob, NULL, NULL, 'e');
@@ -224,6 +233,7 @@ static int object_shape_key_mirror(bContext *C, Object *ob)
                                                        i1 = LT_INDEX(lt, u, v, w);
                                                        fp1 = ((float *)kb->data) + i1 * 3;
                                                        fp1[0] = -fp1[0];
+                                                       totmirr++;
                                                }
                                                else {
                                                        i1 = LT_INDEX(lt, u, v, w);
@@ -237,6 +247,7 @@ static int object_shape_key_mirror(bContext *C, Object *ob)
                                                        copy_v3_v3(fp2, tvec);
                                                        fp1[0] = -fp1[0];
                                                        fp2[0] = -fp2[0];
+                                                       totmirr++;
                                                }
                                        }
                                }
@@ -246,6 +257,9 @@ static int object_shape_key_mirror(bContext *C, Object *ob)
                MEM_freeN(tag_elem);
        }
        
+       *r_totmirr = totmirr;
+       *r_totfail = totfail;
+
        DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
        WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
 
@@ -390,13 +404,16 @@ void OBJECT_OT_shape_key_retime(wmOperatorType *ot)
        ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 }
 
-static int shape_key_mirror_exec(bContext *C, wmOperator *UNUSED(op))
+static int shape_key_mirror_exec(bContext *C, wmOperator *op)
 {
        Object *ob = ED_object_context(C);
+       int totmirr = 0, totfail = 0;
 
-       if (!object_shape_key_mirror(C, ob))
+       if (!object_shape_key_mirror(C, ob, &totmirr, &totfail))
                return OPERATOR_CANCELLED;
 
+       ED_mesh_report_mirror(op, totmirr, totfail);
+
        return OPERATOR_FINISHED;
 }
 
index b3c8b1f720b4e8ebb35ecf1e4c57276e51558cda..0b1fe03f5d587e7c625cf72deadd53cb8bb142ca 100644 (file)
@@ -2122,7 +2122,8 @@ static void dvert_mirror_op(MDeformVert *dvert, MDeformVert *dvert_mirr,
 /* TODO, vgroup locking */
 /* TODO, face masking */
 void ED_vgroup_mirror(Object *ob,
-                      const bool mirror_weights, const bool flip_vgroups, const bool all_vgroups)
+                      const bool mirror_weights, const bool flip_vgroups, const bool all_vgroups,
+                      int *r_totmirr, int *r_totfail)
 {
 
 #define VGROUP_MIRR_OP                                                        \
@@ -2136,8 +2137,11 @@ void ED_vgroup_mirror(Object *ob,
        BMVert *eve, *eve_mirr;
        MDeformVert *dvert, *dvert_mirr;
        char sel, sel_mirr;
-       int *flip_map, flip_map_len;
+       int *flip_map = NULL, flip_map_len;
        const int def_nr = ob->actdef - 1;
+       int totmirr = 0, totfail = 0;
+
+       *r_totmirr = *r_totfail = 0;
 
        if ((mirror_weights == false && flip_vgroups == false) ||
            (BLI_findlink(&ob->defbase, def_nr) == NULL))
@@ -2175,25 +2179,31 @@ void ED_vgroup_mirror(Object *ob,
                                goto cleanup;
                        }
 
-                       EDBM_verts_mirror_cache_begin(em, false);
+                       EDBM_verts_mirror_cache_begin(em, true, false);
 
                        /* Go through the list of editverts and assign them */
                        BM_ITER_MESH (eve, &iter, em->bm, BM_VERTS_OF_MESH) {
                                if ((eve_mirr = EDBM_verts_mirror_get(em, eve))) {
-                                       sel = BM_elem_flag_test(eve, BM_ELEM_SELECT);
-                                       sel_mirr = BM_elem_flag_test(eve_mirr, BM_ELEM_SELECT);
+                                       if (eve_mirr != eve) {
+                                               sel = BM_elem_flag_test(eve, BM_ELEM_SELECT);
+                                               sel_mirr = BM_elem_flag_test(eve_mirr, BM_ELEM_SELECT);
 
-                                       if ((sel || sel_mirr) && (eve != eve_mirr)) {
-                                               dvert      = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
-                                               dvert_mirr = BM_ELEM_CD_GET_VOID_P(eve_mirr, cd_dvert_offset);
+                                               if ((sel || sel_mirr) && (eve != eve_mirr)) {
+                                                       dvert      = BM_ELEM_CD_GET_VOID_P(eve, cd_dvert_offset);
+                                                       dvert_mirr = BM_ELEM_CD_GET_VOID_P(eve_mirr, cd_dvert_offset);
 
-                                               VGROUP_MIRR_OP;
+                                                       VGROUP_MIRR_OP;
+                                                       totmirr++;
+                                               }
                                        }
 
                                        /* don't use these again */
                                        EDBM_verts_mirror_cache_clear(em, eve);
                                        EDBM_verts_mirror_cache_clear(em, eve_mirr);
                                }
+                               else {
+                                       totfail++;
+                               }
                        }
                        EDBM_verts_mirror_cache_end(em);
                }
@@ -2217,26 +2227,33 @@ void ED_vgroup_mirror(Object *ob,
                        }
 
                        for (vidx = 0, mv = me->mvert; vidx < me->totvert; vidx++, mv++) {
-                               if (    ((mv->flag & ME_VERT_TMP_TAG) == 0) &&
-                                       ((vidx_mirr = mesh_get_x_mirror_vert(ob, vidx)) != -1) &&
-                                       (vidx != vidx_mirr) &&
-                                       ((((mv_mirr = me->mvert + vidx_mirr)->flag) & ME_VERT_TMP_TAG) == 0))
-                               {
-
-                                       if (use_vert_sel) {
-                                               sel = mv->flag & SELECT;
-                                               sel_mirr = mv_mirr->flag & SELECT;
+                               if ((mv->flag & ME_VERT_TMP_TAG) == 0) {
+                                       if ((vidx_mirr = mesh_get_x_mirror_vert(ob, vidx)) != -1) {
+                                               if (vidx != vidx_mirr) {
+                                                       mv_mirr = &me->mvert[vidx_mirr];
+                                                       if ((mv_mirr->flag & ME_VERT_TMP_TAG) == 0) {
+
+                                                               if (use_vert_sel) {
+                                                                       sel = mv->flag & SELECT;
+                                                                       sel_mirr = mv_mirr->flag & SELECT;
+                                                               }
+
+                                                               if (sel || sel_mirr) {
+                                                                       dvert = &me->dvert[vidx];
+                                                                       dvert_mirr = &me->dvert[vidx_mirr];
+
+                                                                       VGROUP_MIRR_OP;
+                                                                       totmirr++;
+                                                               }
+
+                                                               mv->flag |= ME_VERT_TMP_TAG;
+                                                               mv_mirr->flag |= ME_VERT_TMP_TAG;
+                                                       }
+                                               }
                                        }
-
-                                       if (sel || sel_mirr) {
-                                               dvert = &me->dvert[vidx];
-                                               dvert_mirr = &me->dvert[vidx_mirr];
-
-                                               VGROUP_MIRR_OP;
+                                       else {
+                                               totfail++;
                                        }
-
-                                       mv->flag |= ME_VERT_TMP_TAG;
-                                       mv_mirr->flag |= ME_VERT_TMP_TAG;
                                }
                        }
                }
@@ -2278,6 +2295,7 @@ void ED_vgroup_mirror(Object *ob,
                                                        dvert_mirr = &lt->dvert[i2];
 
                                                        VGROUP_MIRR_OP;
+                                                       totmirr++;
                                                }
                                        }
                                }
@@ -2293,6 +2311,9 @@ void ED_vgroup_mirror(Object *ob,
 #endif
 
 cleanup:
+       *r_totmirr = totmirr;
+       *r_totfail = totfail;
+
        if (flip_map) MEM_freeN(flip_map);
 
 #undef VGROUP_MIRR_OP
@@ -3362,11 +3383,15 @@ void OBJECT_OT_vertex_group_limit_total(wmOperatorType *ot)
 static int vertex_group_mirror_exec(bContext *C, wmOperator *op)
 {
        Object *ob = ED_object_context(C);
+       int totmirr = 0, totfail = 0;
 
        ED_vgroup_mirror(ob,
                         RNA_boolean_get(op->ptr, "mirror_weights"),
                         RNA_boolean_get(op->ptr, "flip_group_names"),
-                        RNA_boolean_get(op->ptr, "all_groups"));
+                        RNA_boolean_get(op->ptr, "all_groups"),
+                        &totmirr, &totfail);
+
+       ED_mesh_report_mirror(op, totmirr, totfail);
 
        DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
        WM_event_add_notifier(C, NC_OBJECT | ND_DRAW, ob);
index 2c548d330c0ead191dab130ca0bdb0635a5959c8..b93f03bea0bf9e6331cc5398829679d7672d7157 100644 (file)
@@ -1984,7 +1984,7 @@ static void createTransEditVerts(TransInfo *t)
        int cd_vert_bweight_offset = -1;
 
        if (t->flag & T_MIRROR) {
-               EDBM_verts_mirror_cache_begin(em, TRUE);
+               EDBM_verts_mirror_cache_begin(em, false, true);
                mirror = 1;
        }