Merge branch 'master' into blender2.8
[blender.git] / source / blender / editors / physics / particle_edit.c
index 2a15fb2..c705434 100644 (file)
 #include "BLI_math.h"
 #include "BLI_lasso_2d.h"
 #include "BLI_listbase.h"
+#include "BLI_string.h"
 #include "BLI_kdtree.h"
 #include "BLI_rand.h"
 #include "BLI_utildefines.h"
 
 #include "BKE_context.h"
-#include "BKE_depsgraph.h"
 #include "BKE_DerivedMesh.h"
 #include "BKE_global.h"
 #include "BKE_object.h"
+#include "BKE_library.h"
 #include "BKE_mesh.h"
 #include "BKE_modifier.h"
 #include "BKE_particle.h"
 #include "BKE_bvhutils.h"
 #include "BKE_pointcache.h"
 
+#include "DEG_depsgraph.h"
+
 #include "BIF_gl.h"
-#include "BIF_glutil.h"
 
 #include "ED_object.h"
 #include "ED_physics.h"
 #include "ED_mesh.h"
 #include "ED_particle.h"
+#include "ED_screen.h"
 #include "ED_view3d.h"
 
+#include "GPU_immediate.h"
+#include "GPU_immediate_util.h"
+
 #include "UI_resources.h"
 
 #include "WM_api.h"
 #include "WM_types.h"
+#include "WM_message.h"
+#include "WM_toolsystem.h"
 
 #include "RNA_access.h"
 #include "RNA_define.h"
 
+#include "DEG_depsgraph_query.h"
+
 #include "physics_intern.h"
 
 #include "particle_edit_utildefines.h"
@@ -90,9 +100,9 @@ int PE_poll(bContext *C)
        Scene *scene= CTX_data_scene(C);
        Object *ob= CTX_data_active_object(C);
 
-       if (!scene || !ob || !(ob->mode & OB_MODE_PARTICLE_EDIT))
+       if (!scene || !ob || !(ob->mode & OB_MODE_PARTICLE_EDIT)) {
                return 0;
-
+       }
        return (PE_get_current(scene, ob) != NULL);
 }
 
@@ -102,9 +112,9 @@ int PE_hair_poll(bContext *C)
        Object *ob= CTX_data_active_object(C);
        PTCacheEdit *edit;
 
-       if (!scene || !ob || !(ob->mode & OB_MODE_PARTICLE_EDIT))
+       if (!scene || !ob || !(ob->mode & OB_MODE_PARTICLE_EDIT)) {
                return 0;
-
+       }
        edit= PE_get_current(scene, ob);
 
        return (edit && edit->psys);
@@ -183,12 +193,30 @@ static float pe_brush_size_get(const Scene *UNUSED(scene), ParticleBrushData *br
        return brush->size * U.pixelsize;
 }
 
+PTCacheEdit *PE_get_current_from_psys(ParticleSystem *psys)
+{
+       if (psys->part && psys->part->type == PART_HAIR) {
+               if ((psys->flag & PSYS_HAIR_DYNAMICS) != 0 &&
+                   (psys->pointcache->flag & PTCACHE_BAKED) != 0)
+               {
+                       return psys->pointcache->edit;
+               }
+               else {
+                       return psys->edit;
+               }
+       }
+       else if (psys->pointcache->flag & PTCACHE_BAKED) {
+               return psys->pointcache->edit;
+       }
+       return NULL;
+}
 
 /* always gets at least the first particlesystem even if PSYS_CURRENT flag is not set
  *
  * note: this function runs on poll, therefor it can runs many times a second
  * keep it fast! */
-static PTCacheEdit *pe_get_current(Scene *scene, Object *ob, int create)
+static PTCacheEdit *pe_get_current(
+        Depsgraph *depsgraph, Scene *scene, Object *ob, int create)
 {
        ParticleEditSettings *pset= PE_settings(scene);
        PTCacheEdit *edit = NULL;
@@ -227,18 +255,22 @@ static PTCacheEdit *pe_get_current(Scene *scene, Object *ob, int create)
                                if (psys->part && psys->part->type == PART_HAIR) {
                                        if (psys->flag & PSYS_HAIR_DYNAMICS && psys->pointcache->flag & PTCACHE_BAKED) {
                                                if (create && !psys->pointcache->edit)
-                                                       PE_create_particle_edit(scene, ob, pid->cache, NULL);
+                                                       PE_create_particle_edit(depsgraph, scene, ob, pid->cache, NULL);
                                                edit = pid->cache->edit;
                                        }
                                        else {
-                                               if (create && !psys->edit && psys->flag & PSYS_HAIR_DONE)
-                                                       PE_create_particle_edit(scene, ob, NULL, psys);
+                                               if (create && !psys->edit) {
+                                                       ParticleSystem *psys_eval = psys_eval_get(depsgraph, ob, psys);
+                                                       if (psys_eval->flag & PSYS_HAIR_DONE) {
+                                                               PE_create_particle_edit(depsgraph, scene, ob, NULL, psys);
+                                                       }
+                                               }
                                                edit = psys->edit;
                                        }
                                }
                                else {
                                        if (create && pid->cache->flag & PTCACHE_BAKED && !pid->cache->edit)
-                                               PE_create_particle_edit(scene, ob, pid->cache, psys);
+                                               PE_create_particle_edit(depsgraph, scene, ob, pid->cache, psys);
                                        edit = pid->cache->edit;
                                }
 
@@ -249,7 +281,7 @@ static PTCacheEdit *pe_get_current(Scene *scene, Object *ob, int create)
                        if (create && pid->cache->flag & PTCACHE_BAKED && !pid->cache->edit) {
                                pset->flag |= PE_FADE_TIME;
                                // NICE TO HAVE but doesn't work: pset->brushtype = PE_BRUSH_COMB;
-                               PE_create_particle_edit(scene, ob, pid->cache, NULL);
+                               PE_create_particle_edit(depsgraph, scene, ob, pid->cache, NULL);
                        }
                        edit = pid->cache->edit;
                        break;
@@ -258,7 +290,7 @@ static PTCacheEdit *pe_get_current(Scene *scene, Object *ob, int create)
                        if (create && pid->cache->flag & PTCACHE_BAKED && !pid->cache->edit) {
                                pset->flag |= PE_FADE_TIME;
                                // NICE TO HAVE but doesn't work: pset->brushtype = PE_BRUSH_COMB;
-                               PE_create_particle_edit(scene, ob, pid->cache, NULL);
+                               PE_create_particle_edit(depsgraph, scene, ob, pid->cache, NULL);
                        }
                        edit = pid->cache->edit;
                        break;
@@ -275,18 +307,19 @@ static PTCacheEdit *pe_get_current(Scene *scene, Object *ob, int create)
 
 PTCacheEdit *PE_get_current(Scene *scene, Object *ob)
 {
-       return pe_get_current(scene, ob, 0);
+       return pe_get_current(NULL, scene, ob, 0);
 }
 
-PTCacheEdit *PE_create_current(Scene *scene, Object *ob)
+PTCacheEdit *PE_create_current(Depsgraph *depsgraph, Scene *scene, Object *ob)
 {
-       return pe_get_current(scene, ob, 1);
+       return pe_get_current(depsgraph, scene, ob, 1);
 }
 
-void PE_current_changed(Scene *scene, Object *ob)
+void PE_current_changed(Depsgraph *depsgraph, Scene *scene, Object *ob)
 {
-       if (ob->mode == OB_MODE_PARTICLE_EDIT)
-               PE_create_current(scene, ob);
+       if (ob->mode == OB_MODE_PARTICLE_EDIT) {
+               PE_create_current(depsgraph, scene, ob);
+       }
 }
 
 void PE_hide_keys_time(Scene *scene, PTCacheEdit *edit, float cfra)
@@ -328,13 +361,15 @@ static int pe_x_mirror(Object *ob)
 
 typedef struct PEData {
        ViewContext vc;
-       bglMats mats;
 
+       const bContext *context;
        Scene *scene;
+       ViewLayer *view_layer;
        Object *ob;
-       DerivedMesh *dm;
+       Mesh *mesh;
        PTCacheEdit *edit;
        BVHTreeFromMesh shape_bvh;
+       Depsgraph *depsgraph;
 
        const int *mval;
        rcti *rect;
@@ -364,9 +399,11 @@ static void PE_set_data(bContext *C, PEData *data)
 {
        memset(data, 0, sizeof(*data));
 
-       data->scene= CTX_data_scene(C);
-       data->ob= CTX_data_active_object(C);
-       data->edit= PE_get_current(data->scene, data->ob);
+       data->scene = CTX_data_scene(C);
+       data->view_layer = CTX_data_view_layer(C);
+       data->ob = CTX_data_active_object(C);
+       data->depsgraph = CTX_data_depsgraph(C);
+       data->edit = PE_get_current(data->scene, data->ob);
 }
 
 static void PE_set_view3d_data(bContext *C, PEData *data)
@@ -374,8 +411,6 @@ static void PE_set_view3d_data(bContext *C, PEData *data)
        PE_set_data(C, data);
 
        ED_view3d_viewcontext_init(C, &data->vc);
-       /* note, the object argument means the modelview matrix does not account for the objects matrix, use viewmat rather than (obmat * viewmat) */
-       view3d_get_transformation(data->vc.ar, data->vc.rv3d, NULL, &data->mats);
 
        if (V3D_IS_ZBUF(data->vc.v3d)) {
                if (data->vc.v3d->flag & V3D_INVALID_BACKBUF) {
@@ -393,15 +428,15 @@ static void PE_set_view3d_data(bContext *C, PEData *data)
 
 static bool PE_create_shape_tree(PEData *data, Object *shapeob)
 {
-       DerivedMesh *dm = shapeob->derivedFinal;
+       Mesh *mesh = BKE_object_get_evaluated_mesh(data->depsgraph, shapeob);
 
        memset(&data->shape_bvh, 0, sizeof(data->shape_bvh));
 
-       if (!dm) {
+       if (!mesh) {
                return false;
        }
 
-       return (bvhtree_from_mesh_get(&data->shape_bvh, dm, BVHTREE_FROM_LOOPTRI, 4) != NULL);
+       return (BKE_bvhtree_from_mesh_get(&data->shape_bvh, mesh, BVHTREE_FROM_LOOPTRI, 4) != NULL);
 }
 
 static void PE_free_shape_tree(PEData *data)
@@ -415,7 +450,6 @@ static bool key_test_depth(PEData *data, const float co[3], const int screen_co[
 {
        View3D *v3d= data->vc.v3d;
        ViewDepths *vd = data->vc.rv3d->depths;
-       double ux, uy, uz;
        float depth;
 
        /* nothing to do */
@@ -431,9 +465,6 @@ static bool key_test_depth(PEData *data, const float co[3], const int screen_co[
        }
 #endif
 
-       gluProject(co[0], co[1], co[2], data->mats.modelview, data->mats.projection,
-                  (GLint *)data->mats.viewport, &ux, &uy, &uz);
-
        /* check if screen_co is within bounds because brush_cut uses out of screen coords */
        if (screen_co[0] >= 0 && screen_co[0] < vd->w && screen_co[1] >= 0 && screen_co[1] < vd->h) {
                BLI_assert(vd && vd->depths);
@@ -443,7 +474,10 @@ static bool key_test_depth(PEData *data, const float co[3], const int screen_co[
        else
                return 0;
 
-       if ((float)uz - 0.00001f > depth)
+       float win[3];
+       ED_view3d_project(data->vc.ar, co, win);
+
+       if (win[2] - 0.00001f > depth)
                return 0;
        else
                return 1;
@@ -609,9 +643,11 @@ static void foreach_mouse_hit_point(PEData *data, ForPointFunc func, int selecte
 
 static void foreach_mouse_hit_key(PEData *data, ForKeyMatFunc func, int selected)
 {
+       Object *ob_eval = DEG_get_evaluated_object(data->depsgraph, data->ob);
        PTCacheEdit *edit = data->edit;
        ParticleSystem *psys = edit->psys;
        ParticleSystemModifierData *psmd = NULL;
+       ParticleSystemModifierData *psmd_eval = NULL;
        ParticleEditSettings *pset= PE_settings(data->scene);
        POINT_P; KEY_K;
        float mat[4][4], imat[4][4];
@@ -622,6 +658,10 @@ static void foreach_mouse_hit_key(PEData *data, ForKeyMatFunc func, int selected
        if (edit->psys)
                psmd= psys_get_modifier(data->ob, edit->psys);
 
+       if (psmd != NULL) {
+               psmd_eval = (ParticleSystemModifierData *)modifiers_findByName(ob_eval, psmd->modifier.name);
+       }
+
        /* all is selected in path mode */
        if (pset->selectmode==SCE_SELECT_PATH)
                selected= 0;
@@ -635,7 +675,7 @@ static void foreach_mouse_hit_key(PEData *data, ForKeyMatFunc func, int selected
                                if (selected==0 || key->flag & PEK_SELECT) {
                                        if (key_inside_circle(data, data->rad, KEY_WCO, &data->dist)) {
                                                if (edit->psys && !(edit->psys->flag & PSYS_GLOBAL_HAIR)) {
-                                                       psys_mat_hair_to_global(data->ob, psmd->dm_final, psys->part->from, psys->particles + p, mat);
+                                                       psys_mat_hair_to_global(data->ob, psmd_eval->mesh_final, psys->part->from, psys->particles + p, mat);
                                                        invert_m4_m4(imat, mat);
                                                }
 
@@ -650,7 +690,7 @@ static void foreach_mouse_hit_key(PEData *data, ForKeyMatFunc func, int selected
                                if (selected==0 || key->flag & PEK_SELECT) {
                                        if (key_inside_circle(data, data->rad, KEY_WCO, &data->dist)) {
                                                if (edit->psys && !(edit->psys->flag & PSYS_GLOBAL_HAIR)) {
-                                                       psys_mat_hair_to_global(data->ob, psmd->dm_final, psys->part->from, psys->particles + p, mat);
+                                                       psys_mat_hair_to_global(data->ob, psmd_eval->mesh_final, psys->part->from, psys->particles + p, mat);
                                                        invert_m4_m4(imat, mat);
                                                }
 
@@ -737,7 +777,7 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys)
        psmd= psys_get_modifier(ob, psys);
        totpart= psys->totpart;
 
-       if (!psmd->dm_final)
+       if (!psmd->mesh_final)
                return;
 
        tree= BLI_kdtree_new(totpart);
@@ -745,7 +785,7 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys)
        /* insert particles into kd tree */
        LOOP_PARTICLES {
                key = pa->hair;
-               psys_mat_hair_to_orco(ob, psmd->dm_final, psys->part->from, pa, mat);
+               psys_mat_hair_to_orco(ob, psmd->mesh_final, psys->part->from, pa, mat);
                copy_v3_v3(co, key->co);
                mul_m4_v3(mat, co);
                BLI_kdtree_insert(tree, p, co);
@@ -759,7 +799,7 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys)
 
        LOOP_PARTICLES {
                key = pa->hair;
-               psys_mat_hair_to_orco(ob, psmd->dm_final, psys->part->from, pa, mat);
+               psys_mat_hair_to_orco(ob, psmd->mesh_final, psys->part->from, pa, mat);
                copy_v3_v3(co, key->co);
                mul_m4_v3(mat, co);
                co[0] = -co[0];
@@ -785,7 +825,7 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys)
        BLI_kdtree_free(tree);
 }
 
-static void PE_mirror_particle(Object *ob, DerivedMesh *dm, ParticleSystem *psys, ParticleData *pa, ParticleData *mpa)
+static void PE_mirror_particle(Object *ob, Mesh *mesh, ParticleSystem *psys, ParticleData *pa, ParticleData *mpa)
 {
        HairKey *hkey, *mhkey;
        PTCacheEditPoint *point, *mpoint;
@@ -836,8 +876,8 @@ static void PE_mirror_particle(Object *ob, DerivedMesh *dm, ParticleSystem *psys
        }
 
        /* mirror positions and tags */
-       psys_mat_hair_to_orco(ob, dm, psys->part->from, pa, mat);
-       psys_mat_hair_to_orco(ob, dm, psys->part->from, mpa, mmat);
+       psys_mat_hair_to_orco(ob, mesh, psys->part->from, pa, mat);
+       psys_mat_hair_to_orco(ob, mesh, psys->part->from, mpa, mmat);
        invert_m4_m4(immat, mmat);
 
        hkey=pa->hair;
@@ -874,7 +914,7 @@ static void PE_apply_mirror(Object *ob, ParticleSystem *psys)
        edit= psys->edit;
        psmd= psys_get_modifier(ob, psys);
 
-       if (!psmd->dm_final)
+       if (!psmd->mesh_final)
                return;
 
        if (!edit->mirror_cache)
@@ -887,7 +927,7 @@ static void PE_apply_mirror(Object *ob, ParticleSystem *psys)
         * to avoid doing mirror twice */
        LOOP_POINTS {
                if (point->flag & PEP_EDIT_RECALC) {
-                       PE_mirror_particle(ob, psmd->dm_final, psys, psys->particles + p, NULL);
+                       PE_mirror_particle(ob, psmd->mesh_final, psys, psys->particles + p, NULL);
 
                        if (edit->mirror_cache[p] != -1)
                                edit->points[edit->mirror_cache[p]].flag &= ~PEP_EDIT_RECALC;
@@ -922,11 +962,11 @@ static void pe_deflect_emitter(Scene *scene, Object *ob, PTCacheEdit *edit)
        psys = edit->psys;
        psmd = psys_get_modifier(ob, psys);
 
-       if (!psmd->dm_final)
+       if (!psmd->mesh_final)
                return;
 
        LOOP_EDITED_POINTS {
-               psys_mat_hair_to_object(ob, psmd->dm_final, psys->part->from, psys->particles + p, hairmat);
+               psys_mat_hair_to_object(ob, psmd->mesh_final, psys->part->from, psys->particles + p, hairmat);
 
                LOOP_KEYS {
                        mul_m4_v3(hairmat, key->co);
@@ -1069,14 +1109,16 @@ void recalc_lengths(PTCacheEdit *edit)
 }
 
 /* calculate a tree for finding nearest emitter's vertice */
-void recalc_emitter_field(Object *ob, ParticleSystem *psys)
+void recalc_emitter_field(Depsgraph *depsgraph, Object *ob, ParticleSystem *psys)
 {
-       DerivedMesh *dm=psys_get_modifier(ob, psys)->dm_final;
-       PTCacheEdit *edit= psys->edit;
+       Object *object_eval = DEG_get_evaluated_object(depsgraph, ob);
+       ParticleSystem *psys_eval = psys_eval_get(depsgraph, ob, psys);
+       Mesh *mesh = psys_get_modifier(object_eval, psys_eval)->mesh_final;
+       PTCacheEdit *edit = psys->edit;
        float *vec, *nor;
        int i, totface /*, totvert*/;
 
-       if (!dm)
+       if (!mesh)
                return;
 
        if (edit->emitter_cosnos)
@@ -1084,7 +1126,7 @@ void recalc_emitter_field(Object *ob, ParticleSystem *psys)
 
        BLI_kdtree_free(edit->emitter_field);
 
-       totface=dm->getNumTessFaces(dm);
+       totface = mesh->totface;
        /*totvert=dm->getNumVerts(dm);*/ /*UNSUED*/
 
        edit->emitter_cosnos=MEM_callocN(totface*6*sizeof(float), "emitter cosnos");
@@ -1095,23 +1137,23 @@ void recalc_emitter_field(Object *ob, ParticleSystem *psys)
        nor=vec+3;
 
        for (i=0; i<totface; i++, vec+=6, nor+=6) {
-               MFace *mface=dm->getTessFaceData(dm, i, CD_MFACE);
+               MFace *mface = &mesh->mface[i];
                MVert *mvert;
 
-               mvert=dm->getVertData(dm, mface->v1, CD_MVERT);
+               mvert = &mesh->mvert[mface->v1];
                copy_v3_v3(vec, mvert->co);
                VECCOPY(nor, mvert->no);
 
-               mvert=dm->getVertData(dm, mface->v2, CD_MVERT);
+               mvert = &mesh->mvert[mface->v2];
                add_v3_v3v3(vec, vec, mvert->co);
                VECADD(nor, nor, mvert->no);
 
-               mvert=dm->getVertData(dm, mface->v3, CD_MVERT);
+               mvert = &mesh->mvert[mface->v3];
                add_v3_v3v3(vec, vec, mvert->co);
                VECADD(nor, nor, mvert->no);
 
                if (mface->v4) {
-                       mvert=dm->getVertData(dm, mface->v4, CD_MVERT);
+                       mvert = &mesh->mvert[mface->v4];
                        add_v3_v3v3(vec, vec, mvert->co);
                        VECADD(nor, nor, mvert->no);
 
@@ -1128,9 +1170,9 @@ void recalc_emitter_field(Object *ob, ParticleSystem *psys)
        BLI_kdtree_balance(edit->emitter_field);
 }
 
-static void PE_update_selection(Scene *scene, Object *ob, int useflag)
+static void PE_update_selection(Depsgraph *depsgraph, Scene *scene, Object *ob, int useflag)
 {
-       PTCacheEdit *edit= PE_get_current(scene, ob);
+       PTCacheEdit *edit = PE_get_current(scene, ob);
        HairKey *hkey;
        POINT_P; KEY_K;
 
@@ -1149,27 +1191,37 @@ static void PE_update_selection(Scene *scene, Object *ob, int useflag)
                }
        }
 
-       psys_cache_edit_paths(scene, ob, edit, CFRA, G.is_rendering);
+       psys_cache_edit_paths(depsgraph, scene, ob, edit, CFRA, G.is_rendering);
 
 
        /* disable update flag */
        LOOP_POINTS
                point->flag &= ~PEP_EDIT_RECALC;
+
+       DEG_id_tag_update(&ob->id, DEG_TAG_SELECT_UPDATE);
 }
 
-void update_world_cos(Object *ob, PTCacheEdit *edit)
+void update_world_cos(Depsgraph *depsgraph, Object *ob, PTCacheEdit *edit)
 {
+       Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
        ParticleSystem *psys = edit->psys;
-       ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys);
+       ParticleSystem *psys_eval = NULL;
+       ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
+       ParticleSystemModifierData *psmd_eval = NULL;
        POINT_P; KEY_K;
        float hairmat[4][4];
 
-       if (psys==0 || psys->edit==0 || psmd->dm_final==NULL)
+       if (psmd != NULL) {
+               psmd_eval = (ParticleSystemModifierData *)modifiers_findByName(ob_eval, psmd->modifier.name);
+               psys_eval = psmd_eval->psys;
+       }
+
+       if (psys == 0 || psys->edit == 0 || psmd_eval->mesh_final == NULL)
                return;
 
        LOOP_POINTS {
                if (!(psys->flag & PSYS_GLOBAL_HAIR))
-                       psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, psys->particles+p, hairmat);
+                       psys_mat_hair_to_global(ob_eval, psmd_eval->mesh_final, psys->part->from, psys_eval->particles+p, hairmat);
 
                LOOP_KEYS {
                        copy_v3_v3(key->world_co, key->co);
@@ -1235,7 +1287,7 @@ static void update_velocities(PTCacheEdit *edit)
        }
 }
 
-void PE_update_object(Scene *scene, Object *ob, int useflag)
+void PE_update_object(Depsgraph *depsgraph, Scene *scene, Object *ob, int useflag)
 {
        /* use this to do partial particle updates, not usable when adding or
         * removing, then a full redo is necessary and calling this may crash */
@@ -1259,13 +1311,13 @@ void PE_update_object(Scene *scene, Object *ob, int useflag)
        if (pe_x_mirror(ob))
                PE_apply_mirror(ob, edit->psys);
        if (edit->psys)
-               update_world_cos(ob, edit);
+               update_world_cos(depsgraph, ob, edit);
        if (pset->flag & PE_AUTO_VELOCITY)
                update_velocities(edit);
        PE_hide_keys_time(scene, edit, CFRA);
 
        /* regenerate path caches */
-       psys_cache_edit_paths(scene, ob, edit, CFRA, G.is_rendering);
+       psys_cache_edit_paths(depsgraph, scene, ob, edit, CFRA, G.is_rendering);
 
        /* disable update flag */
        LOOP_POINTS {
@@ -1375,6 +1427,7 @@ static void select_action_apply(PTCacheEditPoint *point, PTCacheEditKey *key, in
 static int pe_select_all_exec(bContext *C, wmOperator *op)
 {
        Scene *scene= CTX_data_scene(C);
+       Depsgraph *depsgraph = CTX_data_depsgraph(C);
        Object *ob= CTX_data_active_object(C);
        PTCacheEdit *edit= PE_get_current(scene, ob);
        POINT_P; KEY_K;
@@ -1399,7 +1452,7 @@ static int pe_select_all_exec(bContext *C, wmOperator *op)
                }
        }
 
-       PE_update_selection(scene, ob, 1);
+       PE_update_selection(depsgraph, scene, ob, 1);
        WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
 
        return OPERATOR_FINISHED;
@@ -1456,7 +1509,7 @@ int PE_mouse_particles(bContext *C, const int mval[2], bool extend, bool deselec
        else
                for_mouse_hit_keys(&data, toggle_key_select, 1);
 
-       PE_update_selection(scene, ob, 1);
+       PE_update_selection(data.depsgraph, scene, ob, 1);
        WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
 
        return OPERATOR_FINISHED;
@@ -1497,7 +1550,7 @@ static int select_roots_exec(bContext *C, wmOperator *op)
        data.select_action = action;
        foreach_point(&data, select_root);
 
-       PE_update_selection(data.scene, data.ob, 1);
+       PE_update_selection(data.depsgraph, data.scene, data.ob, 1);
        WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
 
        return OPERATOR_FINISHED;
@@ -1562,7 +1615,7 @@ static int select_tips_exec(bContext *C, wmOperator *op)
        data.select_action = action;
        foreach_point(&data, select_tip);
 
-       PE_update_selection(data.scene, data.ob, 1);
+       PE_update_selection(data.depsgraph, data.scene, data.ob, 1);
        WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
 
        return OPERATOR_FINISHED;
@@ -1646,7 +1699,7 @@ static int select_random_exec(bContext *C, wmOperator *op)
 
        BLI_rng_free(rng);
 
-       PE_update_selection(data.scene, data.ob, 1);
+       PE_update_selection(data.depsgraph, data.scene, data.ob, 1);
        WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
 
        return OPERATOR_FINISHED;
@@ -1690,7 +1743,7 @@ static int select_linked_exec(bContext *C, wmOperator *op)
        data.select= !RNA_boolean_get(op->ptr, "deselect");
 
        for_mouse_hit_keys(&data, select_keys, 1);  /* nearest only */
-       PE_update_selection(data.scene, data.ob, 1);
+       PE_update_selection(data.depsgraph, data.scene, data.ob, 1);
        WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
 
        return OPERATOR_FINISHED;
@@ -1754,7 +1807,7 @@ int PE_border_select(bContext *C, rcti *rect, bool select, bool extend)
 
        for_mouse_hit_keys(&data, select_key, 0);
 
-       PE_update_selection(scene, ob, 1);
+       PE_update_selection(data.depsgraph, scene, ob, 1);
        WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
 
        return OPERATOR_FINISHED;
@@ -1779,7 +1832,7 @@ int PE_circle_select(bContext *C, int selecting, const int mval[2], float rad)
 
        for_mouse_hit_keys(&data, select_key, 0);
 
-       PE_update_selection(scene, ob, 1);
+       PE_update_selection(data.depsgraph, scene, ob, 1);
        WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
 
        return OPERATOR_FINISHED;
@@ -1815,7 +1868,7 @@ int PE_lasso_select(bContext *C, const int mcords[][2], const short moves, bool
 
        LOOP_VISIBLE_POINTS {
                if (edit->psys && !(psys->flag & PSYS_GLOBAL_HAIR))
-                       psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, psys->particles + p, mat);
+                       psys_mat_hair_to_global(ob, psmd->mesh_final, psys->part->from, psys->particles + p, mat);
 
                if (pset->selectmode==SCE_SELECT_POINT) {
                        LOOP_KEYS {
@@ -1867,7 +1920,7 @@ int PE_lasso_select(bContext *C, const int mcords[][2], const short moves, bool
                }
        }
 
-       PE_update_selection(scene, ob, 1);
+       PE_update_selection(data.depsgraph, scene, ob, 1);
        WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
 
        return OPERATOR_FINISHED;
@@ -1879,9 +1932,12 @@ static int hide_exec(bContext *C, wmOperator *op)
 {
        Object *ob= CTX_data_active_object(C);
        Scene *scene= CTX_data_scene(C);
+       Depsgraph *depsgraph = CTX_data_depsgraph(C);
+
        PTCacheEdit *edit= PE_get_current(scene, ob);
        POINT_P; KEY_K;
 
+
        if (RNA_enum_get(op->ptr, "unselected")) {
                LOOP_UNSELECTED_POINTS {
                        point->flag |= PEP_HIDE;
@@ -1901,7 +1957,7 @@ static int hide_exec(bContext *C, wmOperator *op)
                }
        }
 
-       PE_update_selection(scene, ob, 1);
+       PE_update_selection(depsgraph, scene, ob, 1);
        WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
 
        return OPERATOR_FINISHED;
@@ -1931,7 +1987,8 @@ static int reveal_exec(bContext *C, wmOperator *op)
 {
        Object *ob= CTX_data_active_object(C);
        Scene *scene= CTX_data_scene(C);
-       PTCacheEdit *edit = PE_get_current(scene, ob);
+       Depsgraph *depsgraph = CTX_data_depsgraph(C);
+       PTCacheEdit *edit= PE_get_current(scene, ob);
        const bool select = RNA_boolean_get(op->ptr, "select");
        POINT_P; KEY_K;
 
@@ -1946,7 +2003,7 @@ static int reveal_exec(bContext *C, wmOperator *op)
                }
        }
 
-       PE_update_selection(scene, ob, 1);
+       PE_update_selection(depsgraph, scene, ob, 1);
        WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
 
        return OPERATOR_FINISHED;
@@ -2008,7 +2065,7 @@ static int select_less_exec(bContext *C, wmOperator *UNUSED(op))
        PE_set_data(C, &data);
        foreach_point(&data, select_less_keys);
 
-       PE_update_selection(data.scene, data.ob, 1);
+       PE_update_selection(data.depsgraph, data.scene, data.ob, 1);
        WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
 
        return OPERATOR_FINISHED;
@@ -2070,7 +2127,7 @@ static int select_more_exec(bContext *C, wmOperator *UNUSED(op))
        PE_set_data(C, &data);
        foreach_point(&data, select_more_keys);
 
-       PE_update_selection(data.scene, data.ob, 1);
+       PE_update_selection(data.depsgraph, data.scene, data.ob, 1);
        WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
 
        return OPERATOR_FINISHED;
@@ -2106,9 +2163,10 @@ static void rekey_particle(PEData *data, int pa_index)
        float dval, sta, end;
        int k;
 
-       sim.scene= data->scene;
-       sim.ob= data->ob;
-       sim.psys= edit->psys;
+       sim.depsgraph = data->depsgraph;
+       sim.scene = data->scene;
+       sim.ob = data->ob;
+       sim.psys = edit->psys;
 
        pa->flag |= PARS_REKEY;
 
@@ -2167,7 +2225,7 @@ static int rekey_exec(bContext *C, wmOperator *op)
        foreach_selected_point(&data, rekey_particle);
 
        recalc_lengths(data.edit);
-       PE_update_object(data.scene, data.ob, 1);
+       PE_update_object(data.depsgraph, data.scene, data.ob, 1);
        WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, data.ob);
 
        return OPERATOR_FINISHED;
@@ -2192,11 +2250,11 @@ void PARTICLE_OT_rekey(wmOperatorType *ot)
        RNA_def_int(ot->srna, "keys_number", 2, 2, INT_MAX, "Number of Keys", "", 2, 100);
 }
 
-static void rekey_particle_to_time(Scene *scene, Object *ob, int pa_index, float path_time)
+static void rekey_particle_to_time(const bContext *C, Scene *scene, Object *ob, int pa_index, float path_time)
 {
        PTCacheEdit *edit= PE_get_current(scene, ob);
        ParticleSystem *psys;
-       ParticleSimulationData sim= {0};
+       ParticleSimulationData sim = {0};
        ParticleData *pa;
        ParticleKey state;
        HairKey *new_keys, *key;
@@ -2207,9 +2265,10 @@ static void rekey_particle_to_time(Scene *scene, Object *ob, int pa_index, float
 
        psys = edit->psys;
 
-       sim.scene= scene;
-       sim.ob= ob;
-       sim.psys= psys;
+       sim.depsgraph = CTX_data_depsgraph(C);
+       sim.scene = scene;
+       sim.ob = ob;
+       sim.psys = psys;
 
        pa= psys->particles + pa_index;
 
@@ -2254,7 +2313,7 @@ static int remove_tagged_particles(Object *ob, ParticleSystem *psys, int mirror)
                psmd= psys_get_modifier(ob, psys);
 
                LOOP_TAGGED_POINTS {
-                       PE_mirror_particle(ob, psmd->dm_final, psys, psys->particles + p, NULL);
+                       PE_mirror_particle(ob, psmd->mesh_final, psys, psys->particles + p, NULL);
                }
        }
 
@@ -2334,7 +2393,7 @@ static void remove_tagged_keys(Object *ob, ParticleSystem *psys)
 
                LOOP_POINTS {
                        LOOP_TAGGED_KEYS {
-                               PE_mirror_particle(ob, psmd->dm_final, psys, psys->particles + p, NULL);
+                               PE_mirror_particle(ob, psmd->mesh_final, psys, psys->particles + p, NULL);
                                break;
                        }
                }
@@ -2424,9 +2483,10 @@ static void subdivide_particle(PEData *data, int pa_index)
        short totnewkey=0;
        float endtime;
 
-       sim.scene= data->scene;
-       sim.ob= data->ob;
-       sim.psys= edit->psys;
+       sim.depsgraph = data->depsgraph;
+       sim.scene = data->scene;
+       sim.ob = data->ob;
+       sim.psys = edit->psys;
 
        for (k=0, ekey=point->keys; k<pa->totkey-1; k++, ekey++) {
                if (ekey->flag&PEK_SELECT && (ekey+1)->flag&PEK_SELECT)
@@ -2498,7 +2558,7 @@ static int subdivide_exec(bContext *C, wmOperator *UNUSED(op))
        foreach_point(&data, subdivide_particle);
 
        recalc_lengths(data.edit);
-       PE_update_object(data.scene, data.ob, 1);
+       PE_update_object(data.depsgraph, data.scene, data.ob, 1);
        WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, data.ob);
 
        return OPERATOR_FINISHED;
@@ -2548,7 +2608,7 @@ static int remove_doubles_exec(bContext *C, wmOperator *op)
 
                /* insert particles into kd tree */
                LOOP_SELECTED_POINTS {
-                       psys_mat_hair_to_object(ob, psmd->dm_final, psys->part->from, psys->particles+p, mat);
+                       psys_mat_hair_to_object(ob, psmd->mesh_final, psys->part->from, psys->particles+p, mat);
                        copy_v3_v3(co, point->keys->co);
                        mul_m4_v3(mat, co);
                        BLI_kdtree_insert(tree, p, co);
@@ -2558,7 +2618,7 @@ static int remove_doubles_exec(bContext *C, wmOperator *op)
 
                /* tag particles to be removed */
                LOOP_SELECTED_POINTS {
-                       psys_mat_hair_to_object(ob, psmd->dm_final, psys->part->from, psys->particles+p, mat);
+                       psys_mat_hair_to_object(ob, psmd->mesh_final, psys->part->from, psys->particles+p, mat);
                        copy_v3_v3(co, point->keys->co);
                        mul_m4_v3(mat, co);
 
@@ -2587,7 +2647,7 @@ static int remove_doubles_exec(bContext *C, wmOperator *op)
 
        BKE_reportf(op->reports, RPT_INFO, "Removed %d double particles", totremoved);
 
-       DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+       DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
        WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
 
        return OPERATOR_FINISHED;
@@ -2639,7 +2699,7 @@ static int weight_set_exec(bContext *C, wmOperator *op)
                }
        }
 
-       DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+       DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
        WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
 
        return OPERATOR_FINISHED;
@@ -2671,24 +2731,27 @@ static void brush_drawcursor(bContext *C, int x, int y, void *UNUSED(customdata)
        ParticleEditSettings *pset= PE_settings(scene);
        ParticleBrushData *brush;
 
-       if (pset->brushtype < 0)
+       if (pset->brushtype < 0) {
                return;
+       }
 
-       brush= &pset->brush[pset->brushtype];
+       brush = &pset->brush[pset->brushtype];
 
        if (brush) {
-               glPushMatrix();
+               unsigned int pos = GWN_vertformat_attr_add(immVertexFormat(), "pos", GWN_COMP_F32, 2, GWN_FETCH_FLOAT);
+               immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
 
-               glTranslatef((float)x, (float)y, 0.0f);
+               immUniformColor4ub(255, 255, 255, 128);
 
-               glColor4ub(255, 255, 255, 128);
                glEnable(GL_LINE_SMOOTH);
                glEnable(GL_BLEND);
-               glutil_draw_lined_arc(0.0, M_PI*2.0, pe_brush_size_get(scene, brush), 40);
+
+               imm_draw_circle_wire_2d(pos, (float)x, (float)y, pe_brush_size_get(scene, brush), 40);
+
                glDisable(GL_BLEND);
                glDisable(GL_LINE_SMOOTH);
 
-               glPopMatrix();
+               immUnbindProgram();
        }
 }
 
@@ -2745,7 +2808,7 @@ static int delete_exec(bContext *C, wmOperator *op)
                recalc_lengths(data.edit);
        }
 
-       DAG_id_tag_update(&data.ob->id, OB_RECALC_DATA);
+       DEG_id_tag_update(&data.ob->id, OB_RECALC_DATA);
        WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, data.ob);
 
        return OPERATOR_FINISHED;
@@ -2772,11 +2835,12 @@ void PARTICLE_OT_delete(wmOperatorType *ot)
 
 /*************************** mirror operator **************************/
 
-static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
+static void PE_mirror_x(
+        Scene *scene, Object *ob, int tagged)
 {
        Mesh *me= (Mesh *)(ob->data);
        ParticleSystemModifierData *psmd;
-       PTCacheEdit *edit= PE_get_current(scene, ob);
+       PTCacheEdit *edit = PE_get_current(scene, ob);
        ParticleSystem *psys = edit->psys;
        ParticleData *pa, *newpa, *new_pars;
        PTCacheEditPoint *newpoint, *new_points;
@@ -2789,17 +2853,17 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
                return;
 
        psmd= psys_get_modifier(ob, psys);
-       if (!psmd->dm_final)
+       if (!psmd->mesh_final)
                return;
 
-       const bool use_dm_final_indices = (psys->part->use_modifier_stack && !psmd->dm_final->deformedOnly);
+       const bool use_dm_final_indices = (psys->part->use_modifier_stack && !psmd->mesh_final->runtime.deformed_only);
 
        /* NOTE: this is not nice to use tessfaces but hard to avoid since pa->num uses tessfaces */
        BKE_mesh_tessface_ensure(me);
 
-       /* Note: In case psys uses DM tessface indices, we mirror final DM itself, not orig mesh. Avoids an (impossible)
-        *       dm -> orig -> dm tessface indices conversion... */
-       mirrorfaces = mesh_get_x_mirror_faces(ob, NULL, use_dm_final_indices ? psmd->dm_final : NULL);
+       /* Note: In case psys uses Mesh tessface indices, we mirror final Mesh itself, not orig mesh. Avoids an (impossible)
+        *       mesh -> orig -> mesh tessface indices conversion... */
+       mirrorfaces = mesh_get_x_mirror_faces__real_mesh(ob, NULL, use_dm_final_indices ? psmd->mesh_final : NULL);
 
        if (!edit->mirror_cache)
                PE_update_mirror_cache(ob, psys);
@@ -2813,7 +2877,7 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
                        if (point_is_selected(point)) {
                                if (edit->mirror_cache[p] != -1) {
                                        /* already has a mirror, don't need to duplicate */
-                                       PE_mirror_particle(ob, psmd->dm_final, psys, pa, NULL);
+                                       PE_mirror_particle(ob, psmd->mesh_final, psys, pa, NULL);
                                        continue;
                                }
                                else
@@ -2826,7 +2890,7 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
        }
 
        if (newtotpart != psys->totpart) {
-               MFace *mtessface = use_dm_final_indices ? psmd->dm_final->getTessFaceArray(psmd->dm_final) : me->mface;
+               MFace *mtessface = use_dm_final_indices ? psmd->mesh_final->mface : me->mface;
 
                /* allocate new arrays and copy existing */
                new_pars= MEM_callocN(newtotpart*sizeof(ParticleData), "ParticleData new");
@@ -2895,7 +2959,7 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
                        }
                        else {
                                newpa->num_dmcache = psys_particle_dm_face_lookup(
-                                                        psmd->dm_final, psmd->dm_deformed, newpa->num, newpa->fuv, NULL);
+                                                        psmd->mesh_final, psmd->mesh_original, newpa->num, newpa->fuv, NULL);
                        }
 
                        /* update edit key pointers */
@@ -2906,7 +2970,7 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
                        }
 
                        /* map key positions as mirror over x axis */
-                       PE_mirror_particle(ob, psmd->dm_final, psys, pa, newpa);
+                       PE_mirror_particle(ob, psmd->mesh_final, psys, pa, newpa);
 
                        newpa++;
                        newpoint++;
@@ -2928,9 +2992,9 @@ static int mirror_exec(bContext *C, wmOperator *UNUSED(op))
 
        PE_mirror_x(scene, ob, 0);
 
-       update_world_cos(ob, edit);
+       update_world_cos(CTX_data_depsgraph(C), ob, edit);
        WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
-       DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+       DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
 
        return OPERATOR_FINISHED;
 }
@@ -3063,7 +3127,7 @@ static void brush_cut(PEData *data, int pa_index)
                        edit->points[pa_index].flag |= PEP_TAG;
                }
                else {
-                       rekey_particle_to_time(data->scene, ob, pa_index, cut_time);
+                       rekey_particle_to_time(data->context, data->scene, ob, pa_index, cut_time);
                        edit->points[pa_index].flag |= PEP_EDIT_RECALC;
                }
        }
@@ -3116,7 +3180,7 @@ static void brush_puff(PEData *data, int point_index)
        }
 
        if (psys && !(psys->flag & PSYS_GLOBAL_HAIR)) {
-               psys_mat_hair_to_global(data->ob, data->dm, psys->part->from, psys->particles + point_index, mat);
+               psys_mat_hair_to_global(data->ob, data->mesh, psys->part->from, psys->particles + point_index, mat);
                invert_m4_m4(imat, mat);
        }
        else {
@@ -3311,34 +3375,39 @@ static void intersect_dm_quad_weights(const float v1[3], const float v2[3], cons
 }
 
 /* check intersection with a derivedmesh */
-static int particle_intersect_dm(Scene *scene, Object *ob, DerivedMesh *dm,
+static int particle_intersect_mesh(const bContext *C, Scene *scene, Object *ob, Mesh *mesh,
                                  float *vert_cos,
                                  const float co1[3], const float co2[3],
                                  float *min_d, int *min_face, float *min_w,
                                  float *face_minmax, float *pa_minmax,
                                  float radius, float *ipoint)
 {
+       Depsgraph *depsgraph = CTX_data_depsgraph(C);
        MFace *mface= NULL;
        MVert *mvert= NULL;
        int i, totface, intersect=0;
        float cur_d, cur_uv[2], v1[3], v2[3], v3[3], v4[3], min[3], max[3], p_min[3], p_max[3];
        float cur_ipoint[3];
 
-       if (dm == NULL) {
+       if (mesh == NULL) {
                psys_disable_all(ob);
 
-               dm=mesh_get_derived_final(scene, ob, 0);
+               /* TODO(Sybren): port to Mesh when we have decided how to handle derivedFinal and derivedDeform */
+               DerivedMesh *dm = mesh_get_derived_final(depsgraph, scene, ob, 0);
                if (dm == NULL)
-                       dm=mesh_get_derived_deform(scene, ob, 0);
+                       dm = mesh_get_derived_deform(depsgraph, scene, ob, 0);
 
                psys_enable_all(ob);
 
                if (dm == NULL)
                        return 0;
+
+               mesh = BKE_id_new_nomain(ID_ME, NULL);
+               DM_to_mesh(dm, mesh, ob, CD_MASK_EVERYTHING, false);
        }
 
        /* BMESH_ONLY, deform dm may not have tessface */
-       DM_ensure_tessface(dm);
+       BKE_mesh_tessface_ensure(mesh);
 
 
        if (pa_minmax==0) {
@@ -3351,9 +3420,9 @@ static int particle_intersect_dm(Scene *scene, Object *ob, DerivedMesh *dm,
                copy_v3_v3(p_max, pa_minmax+3);
        }
 
-       totface=dm->getNumTessFaces(dm);
-       mface=dm->getTessFaceDataArray(dm, CD_MFACE);
-       mvert=dm->getVertDataArray(dm, CD_MVERT);
+       totface = mesh->totface;
+       mface = mesh->mface;
+       mvert = mesh->mvert;
 
        /* lets intersect the faces */
        for (i=0; i<totface; i++, mface++) {
@@ -3442,11 +3511,12 @@ static int particle_intersect_dm(Scene *scene, Object *ob, DerivedMesh *dm,
        return intersect;
 }
 
-static int brush_add(PEData *data, short number)
+static int brush_add(const bContext *C, PEData *data, short number)
 {
+       Depsgraph *depsgraph = CTX_data_depsgraph(C);
        Scene *scene= data->scene;
        Object *ob= data->ob;
-       DerivedMesh *dm;
+       Mesh *mesh;
        PTCacheEdit *edit = data->edit;
        ParticleSystem *psys= edit->psys;
        ParticleData *add_pars;
@@ -3471,6 +3541,7 @@ static int brush_add(PEData *data, short number)
 
        rng = BLI_rng_new_srandom(psys->seed+data->mval[0]+data->mval[1]);
 
+       sim.depsgraph = depsgraph;
        sim.scene= scene;
        sim.ob= ob;
        sim.psys= psys;
@@ -3478,13 +3549,13 @@ static int brush_add(PEData *data, short number)
 
        timestep= psys_get_timestep(&sim);
 
-       if (psys->part->use_modifier_stack || psmd->dm_final->deformedOnly) {
-               dm = psmd->dm_final;
+       if (psys->part->use_modifier_stack || psmd->mesh_final->runtime.deformed_only) {
+               mesh = psmd->mesh_final;
        }
        else {
-               dm = psmd->dm_deformed;
+               mesh = psmd->mesh_original;
        }
-       BLI_assert(dm);
+       BLI_assert(mesh);
 
        for (i=0; i<number; i++) {
                if (number>1) {
@@ -3504,23 +3575,23 @@ static int brush_add(PEData *data, short number)
 
                mco[0] = data->mval[0] + dmx;
                mco[1] = data->mval[1] + dmy;
-               ED_view3d_win_to_segment(data->vc.ar, data->vc.v3d, mco, co1, co2, true);
+               ED_view3d_win_to_segment(depsgraph, data->vc.ar, data->vc.v3d, mco, co1, co2, true);
 
                mul_m4_v3(imat, co1);
                mul_m4_v3(imat, co2);
                min_d=2.0;
 
                /* warning, returns the derived mesh face */
-               if (particle_intersect_dm(scene, ob, dm, 0, co1, co2, &min_d, &add_pars[n].num_dmcache, add_pars[n].fuv, 0, 0, 0, 0)) {
-                       if (psys->part->use_modifier_stack && !psmd->dm_final->deformedOnly) {
+               if (particle_intersect_mesh(C, scene, ob, mesh, 0, co1, co2, &min_d, &add_pars[n].num_dmcache, add_pars[n].fuv, 0, 0, 0, 0)) {
+                       if (psys->part->use_modifier_stack && !psmd->mesh_final->runtime.deformed_only) {
                                add_pars[n].num = add_pars[n].num_dmcache;
                                add_pars[n].num_dmcache = DMCACHE_ISCHILD;
                        }
-                       else if (dm == psmd->dm_deformed) {
+                       else if (mesh == psmd->mesh_original) {
                                /* Final DM is not same topology as orig mesh, we have to map num_dmcache to real final dm. */
                                add_pars[n].num = add_pars[n].num_dmcache;
                                add_pars[n].num_dmcache = psys_particle_dm_face_lookup(
-                                                             psmd->dm_final, psmd->dm_deformed,
+                                                             psmd->mesh_final, psmd->mesh_original,
                                                              add_pars[n].num, add_pars[n].fuv, NULL);
                        }
                        else {
@@ -3562,7 +3633,7 @@ static int brush_add(PEData *data, short number)
                        tree=BLI_kdtree_new(psys->totpart);
 
                        for (i=0, pa=psys->particles; i<totpart; i++, pa++) {
-                               psys_particle_on_dm(psmd->dm_final, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, cur_co, 0, 0, 0, 0, 0);
+                               psys_particle_on_dm(psmd->mesh_final, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, cur_co, 0, 0, 0, 0);
                                BLI_kdtree_insert(tree, i, cur_co);
                        }
 
@@ -3606,7 +3677,7 @@ static int brush_add(PEData *data, short number)
                                int w, maxw;
                                float maxd, totw=0.0, weight[3];
 
-                               psys_particle_on_dm(psmd->dm_final, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co1, 0, 0, 0, 0, 0);
+                               psys_particle_on_dm(psmd->mesh_final, psys->part->from, pa->num, pa->num_dmcache, pa->fuv, pa->foffset, co1, 0, 0, 0, 0);
                                maxw = BLI_kdtree_find_nearest_n(tree, co1, ptn, 3);
 
                                maxd= ptn[maxw-1].dist;
@@ -3671,7 +3742,7 @@ static int brush_add(PEData *data, short number)
                                }
                        }
                        for (k=0, hkey=pa->hair; k<pset->totaddkey; k++, hkey++) {
-                               psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, pa, hairmat);
+                               psys_mat_hair_to_global(ob, psmd->mesh_final, psys->part->from, pa, hairmat);
                                invert_m4_m4(imat, hairmat);
                                mul_m4_v3(imat, hkey->co);
                        }
@@ -3692,6 +3763,7 @@ static int brush_add(PEData *data, short number)
 
 typedef struct BrushEdit {
        Scene *scene;
+       ViewLayer *view_layer;
        Object *ob;
        PTCacheEdit *edit;
 
@@ -3706,6 +3778,7 @@ typedef struct BrushEdit {
 static int brush_edit_init(bContext *C, wmOperator *op)
 {
        Scene *scene= CTX_data_scene(C);
+       ViewLayer *view_layer = CTX_data_view_layer(C);
        Object *ob= CTX_data_active_object(C);
        ParticleEditSettings *pset= PE_settings(scene);
        PTCacheEdit *edit= PE_get_current(scene, ob);
@@ -3718,7 +3791,7 @@ static int brush_edit_init(bContext *C, wmOperator *op)
 
        /* set the 'distance factor' for grabbing (used in comb etc) */
        INIT_MINMAX(min, max);
-       PE_minmax(scene, min, max);
+       PE_minmax(scene, view_layer, min, max);
        mid_v3_v3v3(min, min, max);
 
        bedit= MEM_callocN(sizeof(BrushEdit), "BrushEdit");
@@ -3726,6 +3799,7 @@ static int brush_edit_init(bContext *C, wmOperator *op)
        op->customdata= bedit;
 
        bedit->scene= scene;
+       bedit->view_layer = view_layer;
        bedit->ob= ob;
        bedit->edit= edit;
 
@@ -3740,6 +3814,7 @@ static int brush_edit_init(bContext *C, wmOperator *op)
 static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
 {
        BrushEdit *bedit= op->customdata;
+       Depsgraph *depsgraph = CTX_data_depsgraph(C);
        Scene *scene= bedit->scene;
        Object *ob= bedit->ob;
        PTCacheEdit *edit= bedit->edit;
@@ -3781,6 +3856,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
             (sqrtf(dx * dx + dy * dy) > pset->brush[PE_BRUSH_ADD].step) : (dx != 0 || dy != 0)) || bedit->first)
        {
                PEData data= bedit->data;
+               data.context = C; // TODO(mai): why isnt this set in bedit->data?
 
                view3d_operator_needs_opengl(C);
                selected= (short)count_selected_keys(scene, edit);
@@ -3858,7 +3934,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
                                case PE_BRUSH_PUFF:
                                {
                                        if (edit->psys) {
-                                               data.dm= psmd->dm_final;
+                                               data.mesh = psmd->mesh_final;
                                                data.mval= mval;
                                                data.rad= pe_brush_size_get(scene, brush);
                                                data.select= selected;
@@ -3881,7 +3957,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
                                        if (edit->psys && edit->psys->part->from==PART_FROM_FACE) {
                                                data.mval= mval;
 
-                                               added= brush_add(&data, brush->count);
+                                               added= brush_add(C, &data, brush->count);
 
                                                if (pset->flag & PE_KEEP_LENGTHS)
                                                        recalc_lengths(edit);
@@ -3914,7 +3990,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
                                case PE_BRUSH_WEIGHT:
                                {
                                        if (edit->psys) {
-                                               data.dm= psmd->dm_final;
+                                               data.mesh = psmd->mesh_final;
                                                data.mval= mval;
                                                data.rad= pe_brush_size_get(scene, brush);
 
@@ -3933,19 +4009,22 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
                                if (pset->brushtype == PE_BRUSH_ADD && pe_x_mirror(ob))
                                        PE_mirror_x(scene, ob, 1);
 
-                               update_world_cos(ob, edit);
+                               update_world_cos(depsgraph, ob, edit);
                                psys_free_path_cache(NULL, edit);
-                               DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+                               DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+                       }
+                       else {
+                               PE_update_object(depsgraph, scene, ob, 1);
                        }
-                       else
-                               PE_update_object(scene, ob, 1);
                }
 
                if (edit->psys) {
                        WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
+                       BKE_particle_batch_cache_dirty(edit->psys, BKE_PARTICLE_BATCH_DIRTY_ALL);
+                       DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE);
                }
                else {
-                       DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+                       DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
                        WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
                }
 
@@ -4153,7 +4232,7 @@ static void shape_cut(PEData *data, int pa_index)
                        edit->points[pa_index].flag |= PEP_TAG;
                }
                else {
-                       rekey_particle_to_time(data->scene, ob, pa_index, cut_time);
+                       rekey_particle_to_time(data->context, data->scene, ob, pa_index, cut_time);
                        edit->points[pa_index].flag |= PEP_EDIT_RECALC;
                }
        }
@@ -4161,6 +4240,7 @@ static void shape_cut(PEData *data, int pa_index)
 
 static int shape_cut_exec(bContext *C, wmOperator *UNUSED(op))
 {
+       Depsgraph *depsgraph = CTX_data_depsgraph(C);
        Scene *scene = CTX_data_scene(C);
        Object *ob = CTX_data_active_object(C);
        ParticleEditSettings *pset = PE_settings(scene);
@@ -4195,18 +4275,21 @@ static int shape_cut_exec(bContext *C, wmOperator *UNUSED(op))
                recalc_lengths(edit);
 
                if (removed) {
-                       update_world_cos(ob, edit);
+                       update_world_cos(depsgraph, ob, edit);
                        psys_free_path_cache(NULL, edit);
-                       DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+                       DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
+               }
+               else {
+                       PE_update_object(data.depsgraph, scene, ob, 1);
                }
-               else
-                       PE_update_object(scene, ob, 1);
 
                if (edit->psys) {
                        WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
+                       BKE_particle_batch_cache_dirty(edit->psys, BKE_PARTICLE_BATCH_DIRTY_ALL);
+                       DEG_id_tag_update(&ob->id, DEG_TAG_COPY_ON_WRITE);
                }
                else {
-                       DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+                       DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
                        WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
                }
 
@@ -4235,9 +4318,9 @@ void PARTICLE_OT_shape_cut(wmOperatorType *ot)
 
 /************************ utilities ******************************/
 
-int PE_minmax(Scene *scene, float min[3], float max[3])
+int PE_minmax(Scene *scene, ViewLayer *view_layer, float min[3], float max[3])
 {
-       Object *ob= OBACT;
+       Object *ob= OBACT(view_layer);
        PTCacheEdit *edit= PE_get_current(scene, ob);
        ParticleSystem *psys;
        ParticleSystemModifierData *psmd = NULL;
@@ -4254,7 +4337,7 @@ int PE_minmax(Scene *scene, float min[3], float max[3])
 
        LOOP_VISIBLE_POINTS {
                if (psys)
-                       psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, psys->particles+p, mat);
+                       psys_mat_hair_to_global(ob, psmd->mesh_final, psys->part->from, psys->particles+p, mat);
 
                LOOP_SELECTED_KEYS {
                        copy_v3_v3(co, key->co);
@@ -4275,17 +4358,24 @@ int PE_minmax(Scene *scene, float min[3], float max[3])
 /************************ particle edit toggle operator ************************/
 
 /* initialize needed data for bake edit */
-void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys)
+void PE_create_particle_edit(
+        Depsgraph *depsgraph, Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys)
 {
        PTCacheEdit *edit;
+       Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
        ParticleSystemModifierData *psmd = (psys) ? psys_get_modifier(ob, psys) : NULL;
+       ParticleSystemModifierData *psmd_eval = NULL;
        POINT_P; KEY_K;
        ParticleData *pa = NULL;
        HairKey *hkey;
        int totpoint;
 
+       if (psmd != NULL) {
+               psmd_eval = (ParticleSystemModifierData *)modifiers_findByName(ob_eval, psmd->modifier.name);
+       }
+
        /* no psmd->dm happens in case particle system modifier is not enabled */
-       if (!(psys && psmd && psmd->dm_final) && !cache)
+       if (!(psys && psmd_eval && psmd_eval->mesh_final) && !cache)
                return;
 
        if (cache && cache->flag & PTCACHE_DISK_CACHE)
@@ -4332,7 +4422,7 @@ void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, Partic
                                }
                                pa++;
                        }
-                       update_world_cos(ob, edit);
+                       update_world_cos(depsgraph, ob, edit);
                }
                else {
                        PTCacheMem *pm;
@@ -4375,8 +4465,9 @@ void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, Partic
 
                recalc_lengths(edit);
                if (psys && !cache)
-                       recalc_emitter_field(ob, psys);
-               PE_update_object(scene, ob, 1);
+                       recalc_emitter_field(depsgraph, ob, psys);
+
+               PE_update_object(depsgraph, scene, ob, 1);
        }
 }
 
@@ -4398,6 +4489,8 @@ static int particle_edit_toggle_poll(bContext *C)
 
 static int particle_edit_toggle_exec(bContext *C, wmOperator *op)
 {
+       struct wmMsgBus *mbus = CTX_wm_message_bus(C);
+       Depsgraph *depsgraph = CTX_data_depsgraph(C);
        Scene *scene = CTX_data_scene(C);
        Object *ob = CTX_data_active_object(C);
        const int mode_flag = OB_MODE_PARTICLE_EDIT;
@@ -4411,13 +4504,14 @@ static int particle_edit_toggle_exec(bContext *C, wmOperator *op)
 
        if (!is_mode_set) {
                PTCacheEdit *edit;
+
                ob->mode |= mode_flag;
-               edit= PE_create_current(scene, ob);
+               edit= PE_create_current(depsgraph, scene, ob);
 
                /* mesh may have changed since last entering editmode.
                 * note, this may have run before if the edit data was just created, so could avoid this and speed up a little */
                if (edit && edit->psys)
-                       recalc_emitter_field(ob, edit->psys);
+                       recalc_emitter_field(depsgraph, ob, edit->psys);
 
                toggle_particle_cursor(C, 1);
                WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_PARTICLE, NULL);
@@ -4428,7 +4522,13 @@ static int particle_edit_toggle_exec(bContext *C, wmOperator *op)
                WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, NULL);
        }
 
-       DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+       // ED_workspace_object_mode_sync_from_object(wm, workspace, ob);
+
+       DEG_id_tag_update(&ob->id, OB_RECALC_DATA | DEG_TAG_COPY_ON_WRITE);
+
+       WM_msg_publish_rna_prop(mbus, &ob->id, ob, Object, mode);
+
+       WM_toolsystem_update_from_context_view3d(C);
 
        return OPERATOR_FINISHED;
 }
@@ -4469,7 +4569,7 @@ static int clear_edited_exec(bContext *C, wmOperator *UNUSED(op))
 
                        psys_reset(psys, PSYS_RESET_DEPSGRAPH);
                        WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
-                       DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+                       DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
                }
        }
        else { /* some operation might have protected hair from editing so let's clear the flag */
@@ -4477,7 +4577,7 @@ static int clear_edited_exec(bContext *C, wmOperator *UNUSED(op))
                psys->flag &= ~PSYS_GLOBAL_HAIR;
                psys->flag &= ~PSYS_EDITED;
                WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
-               DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+               DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
        }
 
        return OPERATOR_FINISHED;
@@ -4580,19 +4680,23 @@ static int unify_length_exec(bContext *C, wmOperator *UNUSED(op))
 {
        Object *ob = CTX_data_active_object(C);
        Scene *scene = CTX_data_scene(C);
+       Depsgraph *depsgraph = CTX_data_depsgraph(C);
+
        PTCacheEdit *edit = PE_get_current(scene, ob);
        float average_length = calculate_average_length(edit);
+
        if (average_length == 0.0f) {
                return OPERATOR_CANCELLED;
        }
        scale_points_to_length(edit, average_length);
 
-       PE_update_object(scene, ob, 1);
+
+       PE_update_object(depsgraph, scene, ob, 1);
        if (edit->psys) {
                WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
        }
        else {
-               DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
+               DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
                WM_event_add_notifier(C, NC_OBJECT|ND_MODIFIER, ob);
        }