Merge branch 'master' into blender2.8
[blender.git] / source / blender / editors / mesh / meshtools.c
index 6953473..786b27e 100644 (file)
 #include "DNA_scene_types.h"
 #include "DNA_screen_types.h"
 #include "DNA_view3d_types.h"
+#include "DNA_workspace_types.h"
 
 #include "BLI_math.h"
 #include "BLI_blenlib.h"
 
 #include "BKE_context.h"
-#include "BKE_depsgraph.h"
 #include "BKE_deform.h"
 #include "BKE_DerivedMesh.h"
 #include "BKE_key.h"
 #include "BKE_report.h"
 #include "BKE_editmesh.h"
 #include "BKE_multires.h"
+#include "BKE_layer.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
 
 #include "ED_mesh.h"
 #include "ED_object.h"
@@ -76,7 +80,7 @@
  * return 0 if no join is made (error) and 1 if the join is done */
 
 static void join_mesh_single(
-        Main *bmain, Scene *scene,
+        Depsgraph *depsgraph, Main *bmain, Scene *scene,
         Object *ob_dst, Object *ob_src, float imat[4][4],
         MVert **mvert_pp, MEdge **medge_pp, MLoop **mloop_pp, MPoly **mpoly_pp,
         CustomData *vdata, CustomData *edata, CustomData *ldata, CustomData *pdata,
@@ -204,7 +208,7 @@ static void join_mesh_single(
                if (ob_src != ob_dst) {
                        MultiresModifierData *mmd;
 
-                       multiresModifier_prepare_join(scene, ob_src, ob_dst);
+                       multiresModifier_prepare_join(depsgraph, scene, ob_src, ob_dst);
 
                        if ((mmd = get_multires_modifier(scene, ob_src, true))) {
                                ED_object_iter_other(bmain, ob_src, true,
@@ -278,7 +282,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
        bDeformGroup *dg, *odg;
        CustomData vdata, edata, fdata, ldata, pdata;
 
-       if (scene->obedit) {
+       if (ob->mode & OB_MODE_EDIT) {
                BKE_report(op->reports, RPT_WARNING, "Cannot join while in edit mode");
                return OPERATOR_CANCELLED;
        }
@@ -289,6 +293,8 @@ int join_mesh_exec(bContext *C, wmOperator *op)
                return OPERATOR_CANCELLED;
        }
 
+       Depsgraph *depsgraph = CTX_data_depsgraph(C);
+
        /* count & check */
        CTX_DATA_BEGIN (C, Base *, base, selected_editable_bases)
        {
@@ -483,7 +489,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
         * active mesh will remain first ones in new result of the merge, in same order for CD layers, etc. See also T50084.
         */
        join_mesh_single(
-                   bmain, scene,
+                   depsgraph, bmain, scene,
                    ob, ob, imat,
                    &mvert, &medge, &mloop, &mpoly,
                    &vdata, &edata, &ldata, &pdata,
@@ -500,7 +506,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
                /* only join if this is a mesh */
                if (base->object->type == OB_MESH) {
                        join_mesh_single(
-                                   bmain, scene,
+                                   depsgraph, bmain, scene,
                                    ob, base->object, imat,
                                    &mvert, &medge, &mloop, &mpoly,
                                    &vdata, &edata, &ldata, &pdata,
@@ -511,7 +517,7 @@ int join_mesh_exec(bContext *C, wmOperator *op)
 
                        /* free base, now that data is merged */
                        if (base->object != ob) {
-                               ED_base_object_free_and_unlink(bmain, scene, base);
+                               ED_object_base_free_and_unlink(bmain, scene, base->object);
                        }
                }
        }
@@ -582,9 +588,9 @@ int join_mesh_exec(bContext *C, wmOperator *op)
        /* Due to dependnecy cycle some other object might access old derived data. */
        BKE_object_free_derived_caches(ob);
 
-       DAG_relations_tag_update(bmain);   /* removed objects, need to rebuild dag */
+       DEG_relations_tag_update(bmain);   /* removed objects, need to rebuild dag */
 
-       DAG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);
+       DEG_id_tag_update(&ob->id, OB_RECALC_OB | OB_RECALC_DATA);
 
        WM_event_add_notifier(C, NC_SCENE | ND_OB_ACTIVE, scene);
 
@@ -600,6 +606,7 @@ int join_mesh_shapes_exec(bContext *C, wmOperator *op)
 {
        Scene *scene = CTX_data_scene(C);
        Object *ob = CTX_data_active_object(C);
+       Depsgraph *depsgraph = CTX_data_depsgraph(C);
        Mesh *me = (Mesh *)ob->data;
        Mesh *selme = NULL;
        DerivedMesh *dm = NULL;
@@ -648,7 +655,7 @@ int join_mesh_shapes_exec(bContext *C, wmOperator *op)
                        selme = (Mesh *)base->object->data;
 
                        if (selme->totvert == me->totvert) {
-                               dm = mesh_get_derived_deform(scene, base->object, CD_MASK_BAREMESH);
+                               dm = mesh_get_derived_deform(depsgraph, scene, base->object, CD_MASK_BAREMESH);
 
                                if (!dm) continue;
 
@@ -679,15 +686,40 @@ static MirrTopoStore_t mesh_topo_store = {NULL, -1. - 1, -1};
 /* mode is 's' start, or 'e' end, or 'u' use */
 /* if end, ob can be NULL */
 /* note, is supposed return -1 on error, which callers are currently checking for, but is not used so far */
-int ED_mesh_mirror_topo_table(Object *ob, DerivedMesh *dm, char mode)
+int ED_mesh_mirror_topo_table(
+        Object *ob, DerivedMesh *dm, char mode)
 {
        if (mode == 'u') {        /* use table */
-               if (ED_mesh_mirrtopo_recalc_check(ob->data, dm, ob->mode, &mesh_topo_store)) {
+               if (ED_mesh_mirrtopo_recalc_check(ob->data, dm, &mesh_topo_store)) {
                        ED_mesh_mirror_topo_table(ob, dm, 's');
                }
        }
        else if (mode == 's') { /* start table */
-               ED_mesh_mirrtopo_init(ob->data, dm, ob->mode, &mesh_topo_store, false);
+               ED_mesh_mirrtopo_init(ob->data, dm, &mesh_topo_store, false);
+       }
+       else if (mode == 'e') { /* end table */
+               ED_mesh_mirrtopo_free(&mesh_topo_store);
+       }
+       else {
+               BLI_assert(0);
+       }
+
+       return 0;
+}
+
+/* mode is 's' start, or 'e' end, or 'u' use */
+/* if end, ob can be NULL */
+/* note, is supposed return -1 on error, which callers are currently checking for, but is not used so far */
+int ED_mesh_mirror_topo_table__real_mesh(
+        Object *ob, Mesh *mesh, char mode)
+{
+       if (mode == 'u') {        /* use table */
+               if (ED_mesh_mirrtopo_recalc_check__real_mesh(ob->data, mesh, &mesh_topo_store)) {
+                       ED_mesh_mirror_topo_table__real_mesh(ob, mesh, 's');
+               }
+       }
+       else if (mode == 's') { /* start table */
+               ED_mesh_mirrtopo_init__real_mesh(ob->data, mesh, &mesh_topo_store, false);
        }
        else if (mode == 'e') { /* end table */
                ED_mesh_mirrtopo_free(&mesh_topo_store);
@@ -734,6 +766,38 @@ int mesh_get_x_mirror_vert(Object *ob, DerivedMesh *dm, int index, const bool us
        }
 }
 
+static int mesh_get_x_mirror_vert_spatial__real_mesh(Object *ob, Mesh *mesh, int index)
+{
+       Mesh *me = ob->data;
+       MVert *mvert = mesh ? mesh->mvert : me->mvert;
+       float vec[3];
+
+       mvert = &mvert[index];
+       vec[0] = -mvert->co[0];
+       vec[1] = mvert->co[1];
+       vec[2] = mvert->co[2];
+
+       return ED_mesh_mirror_spatial_table__real_mesh(ob, NULL, mesh, vec, 'u');
+}
+
+static int mesh_get_x_mirror_vert_topo__real_mesh(Object *ob, Mesh *mesh, int index)
+{
+       if (ED_mesh_mirror_topo_table__real_mesh(ob, mesh, 'u') == -1)
+               return -1;
+
+       return mesh_topo_store.index_lookup[index];
+}
+
+int mesh_get_x_mirror_vert__real_mesh(Object *ob, Mesh *mesh, int index, const bool use_topology)
+{
+       if (use_topology) {
+               return mesh_get_x_mirror_vert_topo__real_mesh(ob, mesh, index);
+       }
+       else {
+               return mesh_get_x_mirror_vert_spatial__real_mesh(ob, mesh, index);
+       }
+}
+
 static BMVert *editbmesh_get_x_mirror_vert_spatial(Object *ob, BMEditMesh *em, const float co[3])
 {
        float vec[3];
@@ -987,6 +1051,66 @@ int *mesh_get_x_mirror_faces(Object *ob, BMEditMesh *em, DerivedMesh *dm)
        return mirrorfaces;
 }
 
+/* This is a Mesh-based copy of mesh_get_x_mirror_faces() */
+int *mesh_get_x_mirror_faces__real_mesh(Object *ob, BMEditMesh *em, Mesh *mesh)
+{
+       Mesh *me = ob->data;
+       MVert *mv, *mvert;
+       MFace mirrormf, *mf, *hashmf, *mface;
+       GHash *fhash;
+       int *mirrorverts, *mirrorfaces;
+
+       BLI_assert(em == NULL);  /* Does not work otherwise, currently... */
+
+       const bool use_topology = (me->editflag & ME_EDIT_MIRROR_TOPO) != 0;
+       const int totvert = mesh ? mesh->totvert : me->totvert;
+       const int totface = mesh ? mesh->totface : me->totface;
+       int a;
+
+       mirrorverts = MEM_callocN(sizeof(int) * totvert, "MirrorVerts");
+       mirrorfaces = MEM_callocN(sizeof(int) * 2 * totface, "MirrorFaces");
+
+       mvert = mesh ? mesh->mvert : me->mvert;
+       mface = mesh ? mesh->mface : me->mface;
+
+       ED_mesh_mirror_spatial_table__real_mesh(ob, em, mesh, NULL, 's');
+
+       for (a = 0, mv = mvert; a < totvert; a++, mv++)
+               mirrorverts[a] = mesh_get_x_mirror_vert__real_mesh(ob, mesh, a, use_topology);
+
+       ED_mesh_mirror_spatial_table__real_mesh(ob, em, mesh, NULL, 'e');
+
+       fhash = BLI_ghash_new_ex(mirror_facehash, mirror_facecmp, "mirror_facehash gh", me->totface);
+       for (a = 0, mf = mface; a < totface; a++, mf++)
+               BLI_ghash_insert(fhash, mf, mf);
+
+       for (a = 0, mf = mface; a < totface; a++, mf++) {
+               mirrormf.v1 = mirrorverts[mf->v3];
+               mirrormf.v2 = mirrorverts[mf->v2];
+               mirrormf.v3 = mirrorverts[mf->v1];
+               mirrormf.v4 = (mf->v4) ? mirrorverts[mf->v4] : 0;
+
+               /* make sure v4 is not 0 if a quad */
+               if (mf->v4 && mirrormf.v4 == 0) {
+                       SWAP(unsigned int, mirrormf.v1, mirrormf.v3);
+                       SWAP(unsigned int, mirrormf.v2, mirrormf.v4);
+               }
+
+               hashmf = BLI_ghash_lookup(fhash, &mirrormf);
+               if (hashmf) {
+                       mirrorfaces[a * 2] = hashmf - mface;
+                       mirrorfaces[a * 2 + 1] = mirror_facerotation(&mirrormf, hashmf);
+               }
+               else
+                       mirrorfaces[a * 2] = -1;
+       }
+
+       BLI_ghash_free(fhash, NULL, NULL);
+       MEM_freeN(mirrorverts);
+
+       return mirrorfaces;
+}
+
 /* selection, vertex and face */
 /* returns 0 if not found, otherwise 1 */
 
@@ -1030,21 +1154,22 @@ bool ED_mesh_pick_face(bContext *C, Object *ob, const int mval[2], unsigned int
 static void ed_mesh_pick_face_vert__mpoly_find(
         /* context */
         struct ARegion *ar, const float mval[2],
-        /* mesh data */
-        DerivedMesh *dm, MPoly *mp, MLoop *mloop,
+        /* mesh data (evaluated) */
+        const MPoly *mp,
+        const MVert *mvert, const MLoop *mloop,
         /* return values */
         float *r_len_best, int *r_v_idx_best)
 {
        const MLoop *ml;
        int j = mp->totloop;
        for (ml = &mloop[mp->loopstart]; j--; ml++) {
-               float co[3], sco[2], len;
+               float sco[2];
                const int v_idx = ml->v;
-               dm->getVertCo(dm, v_idx, co);
+               const float *co = mvert[v_idx].co;
                if (ED_view3d_project_float_object(ar, co, sco, V3D_PROJ_TEST_NOP) == V3D_PROJ_RET_OK) {
-                       len = len_manhattan_v2v2(mval, sco);
-                       if (len < *r_len_best) {
-                               *r_len_best = len;
+                       const float len_test = len_manhattan_v2v2(mval, sco);
+                       if (len_test < *r_len_best) {
+                               *r_len_best = len_test;
                                *r_v_idx_best = v_idx;
                        }
                }
@@ -1056,6 +1181,7 @@ static void ed_mesh_pick_face_vert__mpoly_find(
  */
 bool ED_mesh_pick_face_vert(bContext *C, Object *ob, const int mval[2], unsigned int *index, int size)
 {
+       Depsgraph *depsgraph = CTX_data_depsgraph(C);
        unsigned int poly_index;
        Mesh *me = ob->data;
 
@@ -1066,7 +1192,7 @@ bool ED_mesh_pick_face_vert(bContext *C, Object *ob, const int mval[2], unsigned
                struct ARegion *ar = CTX_wm_region(C);
 
                /* derived mesh to find deformed locations */
-               DerivedMesh *dm = mesh_get_derived_final(scene, ob, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX);
+               Mesh *me_eval = mesh_get_eval_final(depsgraph, scene, ob, CD_MASK_BAREMESH | CD_MASK_ORIGINDEX);
 
                int v_idx_best = ORIGINDEX_NONE;
 
@@ -1074,36 +1200,38 @@ bool ED_mesh_pick_face_vert(bContext *C, Object *ob, const int mval[2], unsigned
                const float mval_f[2] = {UNPACK2(mval)};
                float len_best = FLT_MAX;
 
-               MPoly *dm_mpoly;
-               MLoop *dm_mloop;
-               unsigned int dm_mpoly_tot;
+               MPoly *me_eval_mpoly;
+               MLoop *me_eval_mloop;
+               MVert *me_eval_mvert;
+               unsigned int me_eval_mpoly_len;
                const int *index_mp_to_orig;
 
-               dm_mpoly = dm->getPolyArray(dm);
-               dm_mloop = dm->getLoopArray(dm);
+               me_eval_mpoly = me_eval->mpoly;
+               me_eval_mloop = me_eval->mloop;
+               me_eval_mvert = me_eval->mvert;
 
-               dm_mpoly_tot = dm->getNumPolys(dm);
+               me_eval_mpoly_len = me_eval->totpoly;
 
-               index_mp_to_orig = dm->getPolyDataArray(dm, CD_ORIGINDEX);
+               index_mp_to_orig = CustomData_get_layer(&me_eval->pdata, CD_ORIGINDEX);
 
                /* tag all verts using this face */
                if (index_mp_to_orig) {
                        unsigned int i;
 
-                       for (i = 0; i < dm_mpoly_tot; i++) {
+                       for (i = 0; i < me_eval_mpoly_len; i++) {
                                if (index_mp_to_orig[i] == poly_index) {
                                        ed_mesh_pick_face_vert__mpoly_find(
                                                ar, mval_f,
-                                               dm, &dm_mpoly[i], dm_mloop,
+                                               &me_eval_mpoly[i], me_eval_mvert, me_eval_mloop,
                                                &len_best, &v_idx_best);
                                }
                        }
                }
                else {
-                       if (poly_index < dm_mpoly_tot) {
+                       if (poly_index < me_eval_mpoly_len) {
                                ed_mesh_pick_face_vert__mpoly_find(
                                        ar, mval_f,
-                                       dm, &dm_mpoly[poly_index], dm_mloop,
+                                       &me_eval_mpoly[poly_index], me_eval_mvert, me_eval_mloop,
                                        &len_best, &v_idx_best);
                        }
                }
@@ -1111,15 +1239,12 @@ bool ED_mesh_pick_face_vert(bContext *C, Object *ob, const int mval[2], unsigned
                /* map 'dm -> me' index if possible */
                if (v_idx_best != ORIGINDEX_NONE) {
                        const int *index_mv_to_orig;
-
-                       index_mv_to_orig = dm->getVertDataArray(dm, CD_ORIGINDEX);
+                       index_mv_to_orig = CustomData_get_layer(&me_eval->vdata, CD_ORIGINDEX);
                        if (index_mv_to_orig) {
                                v_idx_best = index_mv_to_orig[v_idx_best];
                        }
                }
 
-               dm->release(dm);
-
                if ((v_idx_best != ORIGINDEX_NONE) && (v_idx_best < me->totvert)) {
                        *index = v_idx_best;
                        return true;
@@ -1193,7 +1318,7 @@ bool ED_mesh_pick_vert(bContext *C, Object *ob, const int mval[2], unsigned int
        }
        else {
                /* derived mesh to find deformed locations */
-               DerivedMesh *dm = mesh_get_derived_final(vc.scene, ob, CD_MASK_BAREMESH);
+               DerivedMesh *dm = mesh_get_derived_final(vc.depsgraph, vc.scene, ob, CD_MASK_BAREMESH);
                ARegion *ar = vc.ar;
                RegionView3D *rv3d = ar->regiondata;
 
@@ -1279,3 +1404,47 @@ MDeformVert *ED_mesh_active_dvert_get_only(Object *ob)
                return NULL;
        }
 }
+
+void EDBM_mesh_stats_multi(
+        struct Object **objects, const uint objects_len,
+        int totelem[3], int totelem_sel[3])
+{
+       if (totelem) {
+               totelem[0] = 0;
+               totelem[1] = 0;
+               totelem[2] = 0;
+       }
+       if (totelem_sel) {
+               totelem_sel[0] = 0;
+               totelem_sel[1] = 0;
+               totelem_sel[2] = 0;
+       }
+
+       for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+               Object *obedit = objects[ob_index];
+               BMEditMesh *em = BKE_editmesh_from_object(obedit);
+               BMesh *bm = em->bm;
+               if (totelem) {
+                       totelem[0] += bm->totvert;
+                       totelem[1] += bm->totedge;
+                       totelem[2] += bm->totface;
+               }
+               if (totelem_sel) {
+                       totelem_sel[0] += bm->totvertsel;
+                       totelem_sel[1] += bm->totedgesel;
+                       totelem_sel[2] += bm->totfacesel;
+               }
+       }
+}
+
+
+void EDBM_mesh_elem_index_ensure_multi(Object **objects, const uint objects_len, const char htype)
+{
+       int elem_offset[4] = {0, 0, 0, 0};
+       for (uint ob_index = 0; ob_index < objects_len; ob_index++) {
+               Object *obedit = objects[ob_index];
+               BMEditMesh *em = BKE_editmesh_from_object(obedit);
+               BMesh *bm = em->bm;
+               BM_mesh_elem_index_ensure_ex(bm, htype, elem_offset);
+       }
+}