Merge branch 'master' into blender2.8
authorCampbell Barton <ideasman42@gmail.com>
Tue, 14 Aug 2018 00:02:43 +0000 (10:02 +1000)
committerCampbell Barton <ideasman42@gmail.com>
Tue, 14 Aug 2018 00:08:34 +0000 (10:08 +1000)
1  2 
source/blender/editors/physics/particle_boids.c
source/blender/editors/physics/particle_edit.c
source/blender/editors/physics/particle_edit_undo.c
source/blender/editors/physics/particle_object.c

index ac031079434ebfc44d6140125b5ec1127c88a048,bb7dd64fb470e7976944a63d588b9ae67fe1054b..f1e0fd390142327f599d9004d9245dd1f70b9ad6
@@@ -77,7 -75,7 +77,7 @@@ static int rule_add_exec(bContext *C, w
  
        BLI_addtail(&state->rules, rule);
  
-       DEG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET);
 -      DAG_id_tag_update(&part->id, OB_RECALC_DATA | PSYS_RECALC_RESET);
++      DEG_id_tag_update(&part->id, OB_RECALC_DATA | PSYS_RECALC_RESET);
  
        return OPERATOR_FINISHED;
  }
@@@ -123,8 -121,8 +123,8 @@@ static int rule_del_exec(bContext *C, w
        if (rule)
                rule->flag |= BOIDRULE_CURRENT;
  
 -      DAG_relations_tag_update(bmain);
 -      DAG_id_tag_update(&part->id, OB_RECALC_DATA | PSYS_RECALC_RESET);
 +      DEG_relations_tag_update(bmain);
-       DEG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET);
++      DEG_id_tag_update(&part->id, OB_RECALC_DATA | PSYS_RECALC_RESET);
  
        return OPERATOR_FINISHED;
  }
@@@ -160,7 -158,7 +160,7 @@@ static int rule_move_up_exec(bContext *
                        BLI_remlink(&state->rules, rule);
                        BLI_insertlinkbefore(&state->rules, rule->prev, rule);
  
-                       DEG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET);
 -                      DAG_id_tag_update(&part->id, OB_RECALC_DATA | PSYS_RECALC_RESET);
++                      DEG_id_tag_update(&part->id, OB_RECALC_DATA | PSYS_RECALC_RESET);
                        break;
                }
        }
@@@ -196,7 -194,7 +196,7 @@@ static int rule_move_down_exec(bContex
                        BLI_remlink(&state->rules, rule);
                        BLI_insertlinkafter(&state->rules, rule->next, rule);
  
-                       DEG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET);
 -                      DAG_id_tag_update(&part->id, OB_RECALC_DATA | PSYS_RECALC_RESET);
++                      DEG_id_tag_update(&part->id, OB_RECALC_DATA | PSYS_RECALC_RESET);
                        break;
                }
        }
@@@ -279,8 -277,8 +279,8 @@@ static int state_del_exec(bContext *C, 
  
        state->flag |= BOIDSTATE_CURRENT;
  
 -      DAG_relations_tag_update(bmain);
 -      DAG_id_tag_update(&part->id, OB_RECALC_DATA | PSYS_RECALC_RESET);
 +      DEG_relations_tag_update(bmain);
-       DEG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET);
++      DEG_id_tag_update(&part->id, OB_RECALC_DATA | PSYS_RECALC_RESET);
  
        return OPERATOR_FINISHED;
  }
@@@ -351,7 -349,7 +351,7 @@@ static int state_move_down_exec(bContex
                if (state->flag & BOIDSTATE_CURRENT && state->next) {
                        BLI_remlink(&boids->states, state);
                        BLI_insertlinkafter(&boids->states, state->next, state);
-                       DEG_id_tag_update(&part->id, OB_RECALC_DATA|PSYS_RECALC_RESET);
 -                      DAG_id_tag_update(&part->id, OB_RECALC_DATA | PSYS_RECALC_RESET);
++                      DEG_id_tag_update(&part->id, OB_RECALC_DATA | PSYS_RECALC_RESET);
                        break;
                }
        }
index 1b82e60b98612b879f3700bf3b2e9ffc44489933,5699c1f59f8f71d59e16402d670b496e38584943..40a7c65385c0e8522b9612afb3b11bede02ef79e
  
  bool PE_poll(bContext *C)
  {
-       Scene *scene= CTX_data_scene(C);
-       Object *ob= CTX_data_active_object(C);
 -      Main *bmain = CTX_data_main(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(bmain, scene, ob) != NULL);
 +      }
 +      return (PE_get_current(scene, ob) != NULL);
  }
  
  bool PE_hair_poll(bContext *C)
  {
-       Scene *scene= CTX_data_scene(C);
-       Object *ob= CTX_data_active_object(C);
 -      Main *bmain = CTX_data_main(C);
+       Scene *scene = CTX_data_scene(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(bmain, scene, ob);
 +      }
 +      edit = PE_get_current(scene, ob);
  
        return (edit && edit->psys);
  }
@@@ -246,10 -191,9 +246,10 @@@ static void pe_update_hair_particle_edi
   *
   * note: this function runs on poll, therefor it can runs many times a second
   * keep it fast! */
 -static PTCacheEdit *pe_get_current(Main *bmain, Scene *scene, Object *ob, int create)
 +static PTCacheEdit *pe_get_current(
 +        Depsgraph *depsgraph, Scene *scene, Object *ob, int create)
  {
-       ParticleEditSettings *pset= PE_settings(scene);
+       ParticleEditSettings *pset = PE_settings(scene);
        PTCacheEdit *edit = NULL;
        ListBase pidlist;
        PTCacheID *pid;
@@@ -506,8 -418,9 +506,8 @@@ static void PE_free_random_generator(PE
  
  static bool key_test_depth(PEData *data, const float co[3], const int screen_co[2])
  {
-       View3D *v3d= data->vc.v3d;
+       View3D *v3d = data->vc.v3d;
        ViewDepths *vd = data->vc.rv3d->depths;
 -      double ux, uy, uz;
        float depth;
  
        /* nothing to do */
@@@ -699,60 -612,55 +699,60 @@@ static void foreach_mouse_hit_point(PED
        }
  }
  
 -static void foreach_mouse_hit_key(PEData *data, ForKeyMatFunc func, int selected)
 +typedef struct KeyIterData {
 +      PEData *data;
 +      PTCacheEdit *edit;
 +      int selected;
 +      ForKeyMatFunc func;
 +} KeyIterData;
 +
 +static void foreach_mouse_hit_key_iter(
 +        void *__restrict iter_data_v,
 +        const int iter,
 +        const ParallelRangeTLS *__restrict UNUSED(tls))
  {
 +      KeyIterData *iter_data = (KeyIterData *)iter_data_v;
 +      PEData *data = iter_data->data;
        PTCacheEdit *edit = data->edit;
 +      PTCacheEditPoint *point = &edit->points[iter];
 +      if (point->flag & PEP_HIDE) {
 +              return;
 +      }
        ParticleSystem *psys = edit->psys;
 -      ParticleSystemModifierData *psmd = NULL;
 +      ParticleSystemModifierData *psmd_eval = iter_data->edit->psmd_eval;
        ParticleEditSettings *pset = PE_settings(data->scene);
 -      POINT_P; KEY_K;
 +      const int selected = iter_data->selected;
        float mat[4][4], imat[4][4];
 -
        unit_m4(mat);
        unit_m4(imat);
-       if (pset->selectmode==SCE_SELECT_END) {
 -
 -      if (edit->psys)
 -              psmd = psys_get_modifier(data->ob, edit->psys);
 -
 -      /* all is selected in path mode */
 -      if (pset->selectmode == SCE_SELECT_PATH)
 -              selected = 0;
 -
 -      LOOP_VISIBLE_POINTS {
 -              if (pset->selectmode == SCE_SELECT_END) {
 -                      if (point->totkey) {
 -                              /* only do end keys */
 -                              key = point->keys + point->totkey - 1;
 -
 -                              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);
 -                                                      invert_m4_m4(imat, mat);
 -                                              }
 -
 -                                              func(data, mat, imat, p, point->totkey - 1, key);
++      if (pset->selectmode == SCE_SELECT_END) {
 +              if (point->totkey) {
 +                      /* only do end keys */
-                       PTCacheEditKey *key = point->keys + point->totkey-1;
++                      PTCacheEditKey *key = point->keys + point->totkey - 1;
 +
-                       if (selected==0 || key->flag & PEK_SELECT) {
++                      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_eval->mesh_final, psys->part->from, psys->particles + iter, mat);
 +                                              invert_m4_m4(imat, mat);
                                        }
-                                       iter_data->func(data, mat, imat, iter, point->totkey-1, key);
++                                      iter_data->func(data, mat, imat, iter, point->totkey - 1, key);
                                }
                        }
                }
 -              else {
 -                      /* do all keys */
 -                      LOOP_VISIBLE_KEYS {
 -                              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);
 -                                                      invert_m4_m4(imat, mat);
 -                                              }
 -
 -                                              func(data, mat, imat, p, k, key);
 +      }
 +      else {
 +              /* do all keys */
 +              PTCacheEditKey *key;
 +              int k;
 +              LOOP_VISIBLE_KEYS {
-                       if (selected==0 || key->flag & PEK_SELECT) {
++                      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_eval->mesh_final, psys->part->from, psys->particles + iter, mat);
 +                                              invert_m4_m4(imat, mat);
                                        }
 +                                      iter_data->func(data, mat, imat, iter, k, key);
                                }
                        }
                }
@@@ -851,14 -738,14 +851,14 @@@ static void PE_update_mirror_cache(Obje
        float mat[4][4], co[3];
        int index, totpart;
  
-       edit= psys->edit;
+       edit = psys->edit;
 -      psmd = psys_get_modifier(ob, psys);
 +      psmd_eval = edit->psmd_eval;
-       totpart= psys->totpart;
+       totpart = psys->totpart;
  
 -      if (!psmd->dm_final)
 +      if (!psmd_eval->mesh_final)
                return;
  
-       tree= BLI_kdtree_new(totpart);
+       tree = BLI_kdtree_new(totpart);
  
        /* insert particles into kd tree */
        LOOP_PARTICLES {
@@@ -954,15 -841,15 +954,15 @@@ static void PE_mirror_particle(Object *
        }
  
        /* 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;
-       mhkey=mpa->hair;
-       key= point->keys;
-       mkey= mpoint->keys;
-       for (k=0; k<pa->totkey; k++, hkey++, mhkey++, key++, mkey++) {
+       hkey = pa->hair;
+       mhkey = mpa->hair;
+       key = point->keys;
+       mkey = mpoint->keys;
+       for (k = 0; k < pa->totkey; k++, hkey++, mhkey++, key++, mkey++) {
                copy_v3_v3(mhkey->co, hkey->co);
                mul_m4_v3(mat, mhkey->co);
                mhkey->co[0] = -mhkey->co[0];
@@@ -989,10 -876,10 +989,10 @@@ static void PE_apply_mirror(Object *ob
        if (!psys)
                return;
  
-       edit= psys->edit;
-       psmd_eval= edit->psmd_eval;
+       edit = psys->edit;
 -      psmd = psys_get_modifier(ob, psys);
++      psmd_eval = edit->psmd_eval;
  
 -      if (!psmd->dm_final)
 +      if (!psmd_eval->mesh_final)
                return;
  
        if (!edit->mirror_cache)
  /************************************************/
  /*                    Edit Calculation                                        */
  /************************************************/
 -/* tries to stop edited particles from going through the emitter's surface */
 -static void pe_deflect_emitter(Scene *scene, Object *ob, PTCacheEdit *edit)
 -{
 -      ParticleEditSettings *pset = PE_settings(scene);
 +
 +typedef struct DeflectEmitterIter {
 +      Object *object;
        ParticleSystem *psys;
 -      ParticleSystemModifierData *psmd;
 -      POINT_P; KEY_K;
 +      PTCacheEdit *edit;
 +      float dist;
 +      float emitterdist;
 +} DeflectEmitterIter;
 +
 +static void deflect_emitter_iter(
 +        void *__restrict iter_data_v,
 +        const int iter,
 +        const ParallelRangeTLS *__restrict UNUSED(tls))
-  {
++{
 +      DeflectEmitterIter *iter_data = (DeflectEmitterIter *)iter_data_v;
 +      PTCacheEdit *edit = iter_data->edit;
 +      PTCacheEditPoint *point = &edit->points[iter];
 +      if ((point->flag & PEP_EDIT_RECALC) == 0) {
 +              return;
 +      }
 +      Object *object = iter_data->object;
 +      ParticleSystem *psys = iter_data->psys;
 +      ParticleSystemModifierData *psmd_eval = iter_data->edit->psmd_eval;
 +      PTCacheEditKey *key;
 +      int k;
 +      float hairimat[4][4], hairmat[4][4];
        int index;
-       float *vec, *nor, dvec[3], dot, dist_1st=0.0f;
+       float *vec, *nor, dvec[3], dot, dist_1st = 0.0f;
 -      float hairimat[4][4], hairmat[4][4];
 -      const float dist = ED_view3d_select_dist_px() * 0.01f;
 -
 -      if (edit == NULL || edit->psys == NULL || (pset->flag & PE_DEFLECT_EMITTER) == 0 || (edit->psys->flag & PSYS_GLOBAL_HAIR))
 -              return;
 -
 -      psys = edit->psys;
 -      psmd = psys_get_modifier(ob, psys);
 +      const float dist = iter_data->dist;
 +      const float emitterdist = iter_data->emitterdist;
 +      psys_mat_hair_to_object(object,
 +                              psmd_eval->mesh_final,
 +                              psys->part->from,
 +                              psys->particles + iter,
 +                              hairmat);
  
 -      if (!psmd->dm_final)
 -              return;
 -
 -      LOOP_EDITED_POINTS {
 -              psys_mat_hair_to_object(ob, psmd->dm_final, psys->part->from, psys->particles + p, hairmat);
 +      LOOP_KEYS {
 +              mul_m4_v3(hairmat, key->co);
 +      }
  
 -              LOOP_KEYS {
 -                      mul_m4_v3(hairmat, key->co);
 +      LOOP_KEYS {
 +              if (k == 0) {
 +                      dist_1st = len_v3v3((key + 1)->co, key->co);
 +                      dist_1st *= dist * emitterdist;
                }
 +              else {
 +                      index = BLI_kdtree_find_nearest(edit->emitter_field, key->co, NULL);
  
 -              LOOP_KEYS {
 -                      if (k == 0) {
 -                              dist_1st = len_v3v3((key + 1)->co, key->co);
 -                              dist_1st *= dist * pset->emitterdist;
 -                      }
 -                      else {
 -                              index = BLI_kdtree_find_nearest(edit->emitter_field, key->co, NULL);
 -
 -                              vec = edit->emitter_cosnos + index * 6;
 -                              nor = vec + 3;
 +                      vec = edit->emitter_cosnos + index * 6;
 +                      nor = vec + 3;
  
 -                              sub_v3_v3v3(dvec, key->co, vec);
 +                      sub_v3_v3v3(dvec, key->co, vec);
  
 -                              dot = dot_v3v3(dvec, nor);
 -                              copy_v3_v3(dvec, nor);
 +                      dot = dot_v3v3(dvec, nor);
 +                      copy_v3_v3(dvec, nor);
  
 -                              if (dot > 0.0f) {
 -                                      if (dot < dist_1st) {
 -                                              normalize_v3(dvec);
 -                                              mul_v3_fl(dvec, dist_1st - dot);
 -                                              add_v3_v3(key->co, dvec);
 -                                      }
 -                              }
 -                              else {
 +                      if (dot > 0.0f) {
 +                              if (dot < dist_1st) {
                                        normalize_v3(dvec);
                                        mul_v3_fl(dvec, dist_1st - dot);
                                        add_v3_v3(key->co, dvec);
                                }
 -                              if (k == 1)
 -                                      dist_1st *= 1.3333f;
 +                      }
 +                      else {
 +                              normalize_v3(dvec);
 +                              mul_v3_fl(dvec, dist_1st - dot);
 +                              add_v3_v3(key->co, dvec);
 +                      }
 +                      if (k == 1) {
 +                              dist_1st *= 1.3333f;
                        }
                }
 +      }
  
 -              invert_m4_m4(hairimat, hairmat);
 +      invert_m4_m4(hairimat, hairmat);
  
 -              LOOP_KEYS {
 -                      mul_m4_v3(hairimat, key->co);
 -              }
 +      LOOP_KEYS {
 +              mul_m4_v3(hairimat, key->co);
        }
  }
 -/* force set distances between neighboring keys */
 -static void PE_apply_lengths(Scene *scene, PTCacheEdit *edit)
 -{
  
 +/* tries to stop edited particles from going through the emitter's surface */
 +static void pe_deflect_emitter(Scene *scene, Object *ob, PTCacheEdit *edit)
 +{
        ParticleEditSettings *pset = PE_settings(scene);
 -      POINT_P; KEY_K;
 -      float dv1[3];
 +      ParticleSystem *psys;
 +      const float dist = ED_view3d_select_dist_px() * 0.01f;
  
 -      if (edit == 0 || (pset->flag & PE_KEEP_LENGTHS) == 0)
 +      if (edit == NULL || edit->psys == NULL ||
 +          (pset->flag & PE_DEFLECT_EMITTER) == 0 ||
 +          (edit->psys->flag & PSYS_GLOBAL_HAIR))
 +      {
                return;
 +      }
  
 -      if (edit->psys && edit->psys->flag & PSYS_GLOBAL_HAIR)
 +      psys = edit->psys;
 +
 +      if (!edit->psmd_eval->mesh_final) {
                return;
 +      }
  
 -      LOOP_EDITED_POINTS {
 -              LOOP_KEYS {
 -                      if (k) {
 -                              sub_v3_v3v3(dv1, key->co, (key - 1)->co);
 -                              normalize_v3(dv1);
 -                              mul_v3_fl(dv1, (key - 1)->length);
 -                              add_v3_v3v3(key->co, (key - 1)->co, dv1);
 -                      }
 +      DeflectEmitterIter iter_data;
 +      iter_data.object = ob;
 +      iter_data.psys = psys;
 +      iter_data.edit = edit;
 +      iter_data.dist = dist;
 +      iter_data.emitterdist = pset->emitterdist;
 +
 +      ParallelRangeSettings settings;
 +      BLI_parallel_range_settings_defaults(&settings);
 +      settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC;
 +      BLI_task_parallel_range(0, edit->totpoint, &iter_data, deflect_emitter_iter, &settings);
 +}
 +
 +typedef struct ApplyLengthsIterData {
 +      PTCacheEdit *edit;
 +} ApplyLengthsIterData;
 +
 +static void apply_lengths_iter(
 +        void *__restrict iter_data_v,
 +        const int iter,
 +        const ParallelRangeTLS *__restrict UNUSED(tls))
-  {
++{
 +      ApplyLengthsIterData *iter_data = (ApplyLengthsIterData *)iter_data_v;
 +      PTCacheEdit *edit = iter_data->edit;
 +      PTCacheEditPoint *point = &edit->points[iter];
 +      if ((point->flag & PEP_EDIT_RECALC) == 0) {
 +              return;
 +      }
 +      PTCacheEditKey *key;
 +      int k;
 +      LOOP_KEYS {
 +              if (k) {
 +                      float dv1[3];
 +                      sub_v3_v3v3(dv1, key->co, (key - 1)->co);
 +                      normalize_v3(dv1);
 +                      mul_v3_fl(dv1, (key - 1)->length);
 +                      add_v3_v3v3(key->co, (key - 1)->co, dv1);
                }
        }
  }
 -/* try to find a nice solution to keep distances between neighboring keys */
 -static void pe_iterate_lengths(Scene *scene, PTCacheEdit *edit)
 +
 +/* force set distances between neighboring keys */
 +static void PE_apply_lengths(Scene *scene, PTCacheEdit *edit)
  {
-       ParticleEditSettings *pset=PE_settings(scene);
+       ParticleEditSettings *pset = PE_settings(scene);
 -      POINT_P;
 -      PTCacheEditKey *key;
 -      int j, k;
 -      float tlen;
 -      float dv0[3] = {0.0f, 0.0f, 0.0f};
 -      float dv1[3] = {0.0f, 0.0f, 0.0f};
 -      float dv2[3] = {0.0f, 0.0f, 0.0f};
  
-       if (edit==0 || (pset->flag & PE_KEEP_LENGTHS)==0)
+       if (edit == 0 || (pset->flag & PE_KEEP_LENGTHS) == 0)
                return;
  
        if (edit->psys && edit->psys->flag & PSYS_GLOBAL_HAIR)
                return;
  
 -      LOOP_EDITED_POINTS {
 -              for (j = 1; j < point->totkey; j++) {
 -                      float mul = 1.0f / (float)point->totkey;
 -
 -                      if (pset->flag & PE_LOCK_FIRST) {
 -                              key = point->keys + 1;
 -                              k = 1;
 -                              dv1[0] = dv1[1] = dv1[2] = 0.0;
 -                      }
 -                      else {
 -                              key = point->keys;
 -                              k = 0;
 -                              dv0[0] = dv0[1] = dv0[2] = 0.0;
 -                      }
 -
 -                      for (; k < point->totkey; k++, key++) {
 -                              if (k) {
 -                                      sub_v3_v3v3(dv0, (key - 1)->co, key->co);
 -                                      tlen = normalize_v3(dv0);
 -                                      mul_v3_fl(dv0, (mul * (tlen - (key - 1)->length)));
 -                              }
 +      ApplyLengthsIterData iter_data;
 +      iter_data.edit = edit;
  
 -                              if (k < point->totkey - 1) {
 -                                      sub_v3_v3v3(dv2, (key + 1)->co, key->co);
 -                                      tlen = normalize_v3(dv2);
 -                                      mul_v3_fl(dv2, mul * (tlen - key->length));
 -                              }
 +      ParallelRangeSettings settings;
 +      BLI_parallel_range_settings_defaults(&settings);
 +      settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC;
 +      BLI_task_parallel_range(0, edit->totpoint, &iter_data, apply_lengths_iter, &settings);
 +}
  
 -                              if (k) {
 -                                      add_v3_v3((key - 1)->co, dv1);
 -                              }
 +typedef struct IterateLengthsIterData {
 +      PTCacheEdit *edit;
 +      ParticleEditSettings *pset;
 +} IterateLengthsIterData;
 +
 +static void iterate_lengths_iter(
 +        void *__restrict iter_data_v,
 +        const int iter,
 +        const ParallelRangeTLS *__restrict UNUSED(tls))
 +{
 +      IterateLengthsIterData *iter_data = (IterateLengthsIterData *)iter_data_v;
 +      PTCacheEdit *edit = iter_data->edit;
 +      PTCacheEditPoint *point = &edit->points[iter];
 +      if ((point->flag & PEP_EDIT_RECALC) == 0) {
 +              return;
 +      }
 +      ParticleEditSettings *pset = iter_data->pset;
 +      float tlen;
 +      float dv0[3] = {0.0f, 0.0f, 0.0f};
 +      float dv1[3] = {0.0f, 0.0f, 0.0f};
 +      float dv2[3] = {0.0f, 0.0f, 0.0f};
 +      for (int j = 1; j < point->totkey; j++) {
 +              PTCacheEditKey *key;
 +              int k;
 +              float mul = 1.0f / (float)point->totkey;
 +              if (pset->flag & PE_LOCK_FIRST) {
 +                      key = point->keys + 1;
 +                      k = 1;
 +                      dv1[0] = dv1[1] = dv1[2] = 0.0;
 +              }
 +              else {
 +                      key = point->keys;
 +                      k = 0;
 +                      dv0[0] = dv0[1] = dv0[2] = 0.0;
 +              }
  
 -                              add_v3_v3v3(dv1, dv0, dv2);
 +              for (; k < point->totkey; k++, key++) {
 +                      if (k) {
 +                              sub_v3_v3v3(dv0, (key - 1)->co, key->co);
 +                              tlen = normalize_v3(dv0);
 +                              mul_v3_fl(dv0, (mul * (tlen - (key - 1)->length)));
 +                      }
 +                      if (k < point->totkey - 1) {
 +                              sub_v3_v3v3(dv2, (key + 1)->co, key->co);
 +                              tlen = normalize_v3(dv2);
 +                              mul_v3_fl(dv2, mul * (tlen - key->length));
 +                      }
 +                      if (k) {
-                               add_v3_v3((key-1)->co, dv1);
++                              add_v3_v3((key - 1)->co, dv1);
                        }
 +                      add_v3_v3v3(dv1, dv0, dv2);
                }
        }
  }
-       if (edit==0 || (pset->flag & PE_KEEP_LENGTHS)==0) {
 +
 +/* try to find a nice solution to keep distances between neighboring keys */
 +static void pe_iterate_lengths(Scene *scene, PTCacheEdit *edit)
 +{
 +      ParticleEditSettings *pset = PE_settings(scene);
++      if (edit == 0 || (pset->flag & PE_KEEP_LENGTHS) == 0) {
 +              return;
 +      }
 +      if (edit->psys && edit->psys->flag & PSYS_GLOBAL_HAIR) {
 +              return;
 +      }
 +
 +      IterateLengthsIterData iter_data;
 +      iter_data.edit = edit;
 +      iter_data.pset = pset;
 +
 +      ParallelRangeSettings settings;
 +      BLI_parallel_range_settings_defaults(&settings);
 +      settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC;
 +      BLI_task_parallel_range(0, edit->totpoint, &iter_data, iterate_lengths_iter, &settings);
 +}
 +
  /* set current distances to be kept between neighbouting keys */
  void recalc_lengths(PTCacheEdit *edit)
  {
@@@ -1292,21 -1089,21 +1292,21 @@@ void recalc_emitter_field(Depsgraph *UN
  
        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");
+       edit->emitter_cosnos = MEM_callocN(totface * 6 * sizeof(float), "emitter cosnos");
  
-       edit->emitter_field= BLI_kdtree_new(totface);
+       edit->emitter_field = BLI_kdtree_new(totface);
  
-       vec=edit->emitter_cosnos;
-       nor=vec+3;
+       vec = edit->emitter_cosnos;
+       nor = vec + 3;
  
-       for (i=0; i<totface; i++, vec+=6, nor+=6) {
+       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);
  
@@@ -1350,14 -1147,14 +1350,14 @@@ static void PE_update_selection(Depsgra
        /* flush edit key flag to hair key flag to preserve selection
         * on save */
        if (edit->psys) LOOP_POINTS {
-               hkey = edit->psys->particles[p].hair;
-               LOOP_KEYS {
-                       hkey->editflag= key->flag;
-                       hkey++;
+                       hkey = edit->psys->particles[p].hair;
+                       LOOP_KEYS {
+                               hkey->editflag = key->flag;
+                               hkey++;
+                       }
                }
-       }
  
 -              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 */
@@@ -1379,7 -1174,7 +1379,7 @@@ void update_world_cos(Depsgraph *UNUSED
  
        LOOP_POINTS {
                if (!(psys->flag & PSYS_GLOBAL_HAIR))
-                       psys_mat_hair_to_global(ob, psmd_eval->mesh_final, psys->part->from, psys->particles+p, hairmat);
 -                      psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, psys->particles + p, hairmat);
++                      psys_mat_hair_to_global(ob, psmd_eval->mesh_final, psys->part->from, psys->particles + p, hairmat);
  
                LOOP_KEYS {
                        copy_v3_v3(key->world_co, key->co);
@@@ -1449,8 -1244,8 +1449,8 @@@ void PE_update_object(Depsgraph *depsgr
  {
        /* use this to do partial particle updates, not usable when adding or
         * removing, then a full redo is necessary and calling this may crash */
-       ParticleEditSettings *pset= PE_settings(scene);
+       ParticleEditSettings *pset = PE_settings(scene);
 -      PTCacheEdit *edit = PE_get_current(bmain, scene, ob);
 +      PTCacheEdit *edit = PE_get_current(scene, ob);
        POINT_P;
  
        if (!edit)
@@@ -1584,10 -1379,10 +1584,10 @@@ static void select_action_apply(PTCache
  
  static int pe_select_all_exec(bContext *C, wmOperator *op)
  {
-       Scene *scene= CTX_data_scene(C);
 -      Main *bmain = CTX_data_main(C);
+       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);
+       Object *ob = CTX_data_active_object(C);
 -      PTCacheEdit *edit = PE_get_current(bmain, scene, ob);
++      PTCacheEdit *edit = PE_get_current(scene, ob);
        POINT_P; KEY_K;
        int action = RNA_enum_get(op->ptr, "action");
  
                }
        }
  
 -      PE_update_selection(bmain, scene, ob, 1);
 +      PE_update_selection(depsgraph, scene, ob, 1);
-       WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
+       WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, ob);
  
        return OPERATOR_FINISHED;
  }
@@@ -1637,10 -1432,11 +1637,10 @@@ void PARTICLE_OT_select_all(wmOperatorT
  
  int PE_mouse_particles(bContext *C, const int mval[2], bool extend, bool deselect, bool toggle)
  {
 -      Main *bmain = CTX_data_main(C);
        PEData data;
-       Scene *scene= CTX_data_scene(C);
-       Object *ob= CTX_data_active_object(C);
-       PTCacheEdit *edit= PE_get_current(scene, ob);
+       Scene *scene = CTX_data_scene(C);
+       Object *ob = CTX_data_active_object(C);
 -      PTCacheEdit *edit = PE_get_current(bmain, scene, ob);
++      PTCacheEdit *edit = PE_get_current(scene, ob);
        POINT_P; KEY_K;
  
        if (!PE_start_edit(edit))
        else
                for_mouse_hit_keys(&data, toggle_key_select, 1);
  
 -      PE_update_selection(bmain, scene, ob, 1);
 +      PE_update_selection(data.depsgraph, scene, ob, 1);
-       WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, data.ob);
+       WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, data.ob);
  
        return OPERATOR_FINISHED;
  }
@@@ -1708,8 -1504,8 +1708,8 @@@ static int select_roots_exec(bContext *
        data.select_action = action;
        foreach_point(&data, select_root);
  
 -      PE_update_selection(data.bmain, 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);
+       WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, data.ob);
  
        return OPERATOR_FINISHED;
  }
@@@ -1773,8 -1569,8 +1773,8 @@@ static int select_tips_exec(bContext *C
        data.select_action = action;
        foreach_point(&data, select_tip);
  
 -      PE_update_selection(data.bmain, 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);
+       WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, data.ob);
  
        return OPERATOR_FINISHED;
  }
@@@ -1853,8 -1649,8 +1853,8 @@@ static int select_random_exec(bContext 
  
        BLI_rng_free(rng);
  
 -      PE_update_selection(data.bmain, 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);
+       WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, data.ob);
  
        return OPERATOR_FINISHED;
  }
@@@ -1892,13 -1688,13 +1892,13 @@@ static int select_linked_exec(bContext 
        mval[1] = location[1];
  
        PE_set_view3d_data(C, &data);
-       data.mval= mval;
-       data.rad=75.0f;
-       data.select= !RNA_boolean_get(op->ptr, "deselect");
+       data.mval = mval;
+       data.rad = 75.0f;
+       data.select = !RNA_boolean_get(op->ptr, "deselect");
  
        for_mouse_hit_keys(&data, select_keys, 1);  /* nearest only */
 -      PE_update_selection(data.bmain, 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);
+       WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, data.ob);
  
        return OPERATOR_FINISHED;
  }
@@@ -1944,9 -1740,10 +1944,9 @@@ void PE_deselect_all_visible(PTCacheEdi
  
  int PE_border_select(bContext *C, rcti *rect, bool select, bool extend)
  {
-       Scene *scene= CTX_data_scene(C);
-       Object *ob= CTX_data_active_object(C);
-       PTCacheEdit *edit= PE_get_current(scene, ob);
 -      Main *bmain = CTX_data_main(C);
+       Scene *scene = CTX_data_scene(C);
+       Object *ob = CTX_data_active_object(C);
 -      PTCacheEdit *edit = PE_get_current(bmain, scene, ob);
++      PTCacheEdit *edit = PE_get_current(scene, ob);
        PEData data;
  
        if (!PE_start_edit(edit))
  
        for_mouse_hit_keys(&data, select_key, 0);
  
 -      PE_update_selection(bmain, scene, ob, 1);
 +      PE_update_selection(data.depsgraph, scene, ob, 1);
-       WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
+       WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, ob);
  
        return OPERATOR_FINISHED;
  }
  
  int PE_circle_select(bContext *C, int selecting, const int mval[2], float rad)
  {
-       Scene *scene= CTX_data_scene(C);
-       Object *ob= CTX_data_active_object(C);
-       PTCacheEdit *edit= PE_get_current(scene, ob);
 -      Main *bmain = CTX_data_main(C);
+       Scene *scene = CTX_data_scene(C);
+       Object *ob = CTX_data_active_object(C);
 -      PTCacheEdit *edit = PE_get_current(bmain, scene, ob);
++      PTCacheEdit *edit = PE_get_current(scene, ob);
        PEData data;
  
        if (!PE_start_edit(edit))
  
        for_mouse_hit_keys(&data, select_key, 0);
  
 -      PE_update_selection(bmain, scene, ob, 1);
 +      PE_update_selection(data.depsgraph, scene, ob, 1);
-       WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
+       WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, ob);
  
        return OPERATOR_FINISHED;
  }
  
  int PE_lasso_select(bContext *C, const int mcords[][2], const short moves, bool extend, bool select)
  {
-       Scene *scene= CTX_data_scene(C);
-       Object *ob= CTX_data_active_object(C);
-       ARegion *ar= CTX_wm_region(C);
-       ParticleEditSettings *pset= PE_settings(scene);
 -      Main *bmain = CTX_data_main(C);
+       Scene *scene = CTX_data_scene(C);
+       Object *ob = CTX_data_active_object(C);
+       ARegion *ar = CTX_wm_region(C);
+       ParticleEditSettings *pset = PE_settings(scene);
 -      PTCacheEdit *edit = PE_get_current(bmain, scene, ob);
 +      PTCacheEdit *edit = PE_get_current(scene, ob);
        ParticleSystem *psys = edit->psys;
 -      ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
 +      ParticleSystemModifierData *psmd_eval = edit->psmd_eval;
        POINT_P; KEY_K;
        float co[3], mat[4][4];
        int screen_co[2];
  
        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_eval->mesh_final, psys->part->from, psys->particles + p, mat);
  
-               if (pset->selectmode==SCE_SELECT_POINT) {
+               if (pset->selectmode == SCE_SELECT_POINT) {
                        LOOP_KEYS {
                                copy_v3_v3(co, key->co);
                                mul_m4_v3(mat, co);
                }
        }
  
 -      PE_update_selection(bmain, scene, ob, 1);
 +      PE_update_selection(data.depsgraph, scene, ob, 1);
-       WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
+       WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, ob);
  
        return OPERATOR_FINISHED;
  }
  
  static int hide_exec(bContext *C, wmOperator *op)
  {
-       Object *ob= CTX_data_active_object(C);
-       Scene *scene= CTX_data_scene(C);
 -      Main *bmain = CTX_data_main(C);
+       Object *ob = CTX_data_active_object(C);
+       Scene *scene = CTX_data_scene(C);
 -      PTCacheEdit *edit = PE_get_current(bmain, scene, ob);
 +      Depsgraph *depsgraph = CTX_data_depsgraph(C);
 +
-       PTCacheEdit *edit= PE_get_current(scene, ob);
++      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;
                }
        }
  
 -      PE_update_selection(bmain, scene, ob, 1);
 +      PE_update_selection(depsgraph, scene, ob, 1);
-       WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
+       WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, ob);
  
        return OPERATOR_FINISHED;
  }
@@@ -2139,10 -1936,10 +2139,10 @@@ void PARTICLE_OT_hide(wmOperatorType *o
  
  static int reveal_exec(bContext *C, wmOperator *op)
  {
-       Object *ob= CTX_data_active_object(C);
-       Scene *scene= CTX_data_scene(C);
 -      Main *bmain = CTX_data_main(C);
+       Object *ob = CTX_data_active_object(C);
+       Scene *scene = CTX_data_scene(C);
 -      PTCacheEdit *edit = PE_get_current(bmain, scene, ob);
 +      Depsgraph *depsgraph = CTX_data_depsgraph(C);
-       PTCacheEdit *edit= PE_get_current(scene, ob);
++      PTCacheEdit *edit = PE_get_current(scene, ob);
        const bool select = RNA_boolean_get(op->ptr, "select");
        POINT_P; KEY_K;
  
                }
        }
  
 -      PE_update_selection(bmain, scene, ob, 1);
 +      PE_update_selection(depsgraph, scene, ob, 1);
-       WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_SELECTED, ob);
+       WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, ob);
  
        return OPERATOR_FINISHED;
  }
@@@ -2219,8 -2016,8 +2219,8 @@@ static int select_less_exec(bContext *C
        PE_set_data(C, &data);
        foreach_point(&data, select_less_keys);
  
 -      PE_update_selection(data.bmain, 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);
+       WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, data.ob);
  
        return OPERATOR_FINISHED;
  }
@@@ -2281,8 -2078,8 +2281,8 @@@ static int select_more_exec(bContext *C
        PE_set_data(C, &data);
        foreach_point(&data, select_more_keys);
  
 -      PE_update_selection(data.bmain, 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);
+       WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_SELECTED, data.ob);
  
        return OPERATOR_FINISHED;
  }
@@@ -2379,8 -2175,8 +2379,8 @@@ static int rekey_exec(bContext *C, wmOp
        foreach_selected_point(&data, rekey_particle);
  
        recalc_lengths(data.edit);
 -      PE_update_object(data.bmain, 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);
+       WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_EDITED, data.ob);
  
        return OPERATOR_FINISHED;
  }
@@@ -2404,9 -2200,9 +2404,9 @@@ void PARTICLE_OT_rekey(wmOperatorType *
        RNA_def_int(ot->srna, "keys_number", 2, 2, INT_MAX, "Number of Keys", "", 2, 100);
  }
  
 -static void rekey_particle_to_time(Main *bmain, 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);
 -      PTCacheEdit *edit = PE_get_current(bmain, scene, ob);
++      PTCacheEdit *edit = PE_get_current(scene, ob);
        ParticleSystem *psys;
        ParticleSimulationData sim = {0};
        ParticleData *pa;
  static int remove_tagged_particles(Object *ob, ParticleSystem *psys, int mirror)
  {
        PTCacheEdit *edit = psys->edit;
-       ParticleData *pa, *npa=0, *new_pars=0;
+       ParticleData *pa, *npa = 0, *new_pars = 0;
        POINT_P;
-       PTCacheEditPoint *npoint=0, *new_points=0;
+       PTCacheEditPoint *npoint = 0, *new_points = 0;
 -      ParticleSystemModifierData *psmd;
 +      ParticleSystemModifierData *psmd_eval;
-       int i, new_totpart= psys->totpart, removed= 0;
+       int i, new_totpart = psys->totpart, removed = 0;
  
        if (mirror) {
                /* mirror tags */
  
  static void remove_tagged_keys(Object *ob, ParticleSystem *psys)
  {
-       PTCacheEdit *edit= psys->edit;
+       PTCacheEdit *edit = psys->edit;
        ParticleData *pa;
-       HairKey *hkey, *nhkey, *new_hkeys=0;
+       HairKey *hkey, *nhkey, *new_hkeys = 0;
        POINT_P; KEY_K;
        PTCacheEditKey *nkey, *new_keys;
 -      ParticleSystemModifierData *psmd;
 +      ParticleSystemModifierData *psmd_eval;
        short new_totkey;
  
        if (pe_x_mirror(ob)) {
@@@ -2634,10 -2429,9 +2634,10 @@@ static void subdivide_particle(PEData *
        PTCacheEditKey *ekey, *nekey, *new_ekeys;
  
        int k;
-       short totnewkey=0;
+       short totnewkey = 0;
        float endtime;
  
 +      sim.depsgraph = data->depsgraph;
        sim.scene = data->scene;
        sim.ob = data->ob;
        sim.psys = edit->psys;
@@@ -2712,8 -2506,8 +2712,8 @@@ static int subdivide_exec(bContext *C, 
        foreach_point(&data, subdivide_particle);
  
        recalc_lengths(data.edit);
 -      PE_update_object(data.bmain, 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);
+       WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_EDITED, data.ob);
  
        return OPERATOR_FINISHED;
  }
@@@ -2737,11 -2531,12 +2737,11 @@@ void PARTICLE_OT_subdivide(wmOperatorTy
  
  static int remove_doubles_exec(bContext *C, wmOperator *op)
  {
-       Scene *scene= CTX_data_scene(C);
-       Object *ob= CTX_data_active_object(C);
-       PTCacheEdit *edit= PE_get_current(scene, ob);
 -      Main *bmain = CTX_data_main(C);
+       Scene *scene = CTX_data_scene(C);
+       Object *ob = CTX_data_active_object(C);
 -      PTCacheEdit *edit = PE_get_current(bmain, scene, ob);
++      PTCacheEdit *edit = PE_get_current(scene, ob);
        ParticleSystem *psys = edit->psys;
 -      ParticleSystemModifierData *psmd;
 +      ParticleSystemModifierData *psmd_eval;
        KDTree *tree;
        KDTreeNearest nearest[10];
        POINT_P;
        if (psys->flag & PSYS_GLOBAL_HAIR)
                return OPERATOR_CANCELLED;
  
-       edit= psys->edit;
+       edit = psys->edit;
 -      psmd = psys_get_modifier(ob, psys);
 +      psmd_eval = edit->psmd_eval;
-       totremoved= 0;
+       totremoved = 0;
  
        do {
-               removed= 0;
+               removed = 0;
  
-               tree=BLI_kdtree_new(psys->totpart);
+               tree = BLI_kdtree_new(psys->totpart);
  
                /* insert particles into kd tree */
                LOOP_SELECTED_POINTS {
-                       psys_mat_hair_to_object(ob, psmd_eval->mesh_final, psys->part->from, psys->particles+p, mat);
 -                      psys_mat_hair_to_object(ob, psmd->dm_final, psys->part->from, psys->particles + p, mat);
++                      psys_mat_hair_to_object(ob, psmd_eval->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);
  
                /* tag particles to be removed */
                LOOP_SELECTED_POINTS {
-                       psys_mat_hair_to_object(ob, psmd_eval->mesh_final, psys->part->from, psys->particles+p, mat);
 -                      psys_mat_hair_to_object(ob, psmd->dm_final, psys->part->from, psys->particles + p, mat);
++                      psys_mat_hair_to_object(ob, psmd_eval->mesh_final, psys->part->from, psys->particles + p, mat);
                        copy_v3_v3(co, point->keys->co);
                        mul_m4_v3(mat, co);
  
  
        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);
+       WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_EDITED, ob);
  
        return OPERATOR_FINISHED;
  }
@@@ -2829,10 -2624,11 +2829,10 @@@ void PARTICLE_OT_remove_doubles(wmOpera
  
  static int weight_set_exec(bContext *C, wmOperator *op)
  {
-       Scene *scene= CTX_data_scene(C);
-       ParticleEditSettings *pset= PE_settings(scene);
-       Object *ob= CTX_data_active_object(C);
-       PTCacheEdit *edit= PE_get_current(scene, ob);
 -      Main *bmain = CTX_data_main(C);
+       Scene *scene = CTX_data_scene(C);
+       ParticleEditSettings *pset = PE_settings(scene);
+       Object *ob = CTX_data_active_object(C);
 -      PTCacheEdit *edit = PE_get_current(bmain, scene, ob);
++      PTCacheEdit *edit = PE_get_current(scene, ob);
        ParticleSystem *psys = edit->psys;
        POINT_P;
        KEY_K;
                }
        }
  
 -      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);
+       WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_EDITED, ob);
  
        return OPERATOR_FINISHED;
  }
@@@ -2882,12 -2678,11 +2882,12 @@@ void PARTICLE_OT_weight_set(wmOperatorT
  static void brush_drawcursor(bContext *C, int x, int y, void *UNUSED(customdata))
  {
        Scene *scene = CTX_data_scene(C);
-       ParticleEditSettings *pset= PE_settings(scene);
+       ParticleEditSettings *pset = PE_settings(scene);
        ParticleBrushData *brush;
  
 -      if (pset->brushtype < 0)
 +      if (pset->brushtype < 0) {
                return;
 +      }
  
        brush = &pset->brush[pset->brushtype];
  
@@@ -2962,8 -2756,8 +2963,8 @@@ static int delete_exec(bContext *C, wmO
                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);
+       WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE | NA_EDITED, data.ob);
  
        return OPERATOR_FINISHED;
  }
@@@ -2989,12 -2783,11 +2990,12 @@@ void PARTICLE_OT_delete(wmOperatorType 
  
  /*************************** mirror operator **************************/
  
 -static void PE_mirror_x(Main *bmain, Scene *scene, Object *ob, int tagged)
 +static void PE_mirror_x(
 +        Scene *scene, Object *ob, int tagged)
  {
-       Mesh *me= (Mesh *)(ob->data);
+       Mesh *me = (Mesh *)(ob->data);
 -      ParticleSystemModifierData *psmd;
 -      PTCacheEdit *edit = PE_get_current(bmain, scene, ob);
 +      ParticleSystemModifierData *psmd_eval;
 +      PTCacheEdit *edit = PE_get_current(scene, ob);
        ParticleSystem *psys = edit->psys;
        ParticleData *pa, *newpa, *new_pars;
        PTCacheEditPoint *newpoint, *new_points;
        }
  
        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_eval->mesh_final->mface : me->mface;
  
                /* allocate new arrays and copy existing */
-               new_pars= MEM_callocN(newtotpart*sizeof(ParticleData), "ParticleData new");
-               new_points= MEM_callocN(newtotpart*sizeof(PTCacheEditPoint), "PTCacheEditPoint new");
+               new_pars = MEM_callocN(newtotpart * sizeof(ParticleData), "ParticleData new");
+               new_points = MEM_callocN(newtotpart * sizeof(PTCacheEditPoint), "PTCacheEditPoint new");
  
                if (psys->particles) {
-                       memcpy(new_pars, psys->particles, totpart*sizeof(ParticleData));
+                       memcpy(new_pars, psys->particles, totpart * sizeof(ParticleData));
                        MEM_freeN(psys->particles);
                }
-               psys->particles= new_pars;
+               psys->particles = new_pars;
  
                if (edit->points) {
-                       memcpy(new_points, edit->points, totpart*sizeof(PTCacheEditPoint));
+                       memcpy(new_points, edit->points, totpart * sizeof(PTCacheEditPoint));
                        MEM_freeN(edit->points);
                }
-               edit->points= new_points;
+               edit->points = new_points;
  
                if (edit->mirror_cache) {
                        MEM_freeN(edit->mirror_cache);
                        }
                        else {
                                newpa->num_dmcache = psys_particle_dm_face_lookup(
-                                                        psmd_eval->mesh_final, psmd_eval->mesh_original, newpa->num, newpa->fuv, NULL);
 -                                      psmd->dm_final, psmd->dm_deformed, newpa->num, newpa->fuv, NULL);
++                                      psmd_eval->mesh_final, psmd_eval->mesh_original, newpa->num, newpa->fuv, NULL);
                        }
  
                        /* update edit key pointers */
  
  static int mirror_exec(bContext *C, wmOperator *UNUSED(op))
  {
-       Scene *scene= CTX_data_scene(C);
-       Object *ob= CTX_data_active_object(C);
-       PTCacheEdit *edit= PE_get_current(scene, ob);
 -      Main *bmain = CTX_data_main(C);
+       Scene *scene = CTX_data_scene(C);
+       Object *ob = CTX_data_active_object(C);
 -      PTCacheEdit *edit = PE_get_current(bmain, scene, ob);
++      PTCacheEdit *edit = PE_get_current(scene, ob);
  
 -      PE_mirror_x(bmain, scene, ob, 0);
 +      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);
+       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;
  }
@@@ -3190,20 -2984,17 +3191,20 @@@ static void brush_comb(PEData *data, fl
  static void brush_cut(PEData *data, int pa_index)
  {
        PTCacheEdit *edit = data->edit;
-       ARegion *ar= data->vc.ar;
-       Object *ob= data->ob;
-       ParticleEditSettings *pset= PE_settings(data->scene);
-       ParticleCacheKey *key= edit->pathcache[pa_index];
-       float rad2, cut_time= 1.0;
+       ARegion *ar = data->vc.ar;
+       Object *ob = data->ob;
+       ParticleEditSettings *pset = PE_settings(data->scene);
+       ParticleCacheKey *key = edit->pathcache[pa_index];
+       float rad2, cut_time = 1.0;
        float x0, x1, v0, v1, o0, o1, xo0, xo1, d, dv;
-       int k, cut, keys= (int)pow(2.0, (double)pset->draw_step);
+       int k, cut, keys = (int)pow(2.0, (double)pset->draw_step);
        int screen_co[2];
  
 +      BLI_assert(data->rng != NULL);
        /* blunt scissors */
 -      if (BLI_frand() > data->cutfac) return;
 +      if (BLI_rng_get_float(data->rng) > data->cutfac) {
 +              return;
 +      }
  
        /* don't cut hidden */
        if (edit->points[pa_index].flag & PEP_HIDE)
@@@ -3531,17 -3322,17 +3532,17 @@@ static void intersect_dm_quad_weights(c
        interp_weights_poly_v3(w, vert, 4, co);
  }
  
 -/* check intersection with a derivedmesh */
 -static int particle_intersect_dm(Scene *scene, Object *ob, DerivedMesh *dm,
 -                                 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)
 +/** Check intersection with an evaluated mesh. */
 +static int particle_intersect_mesh(Depsgraph *depsgraph, 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)
  {
-       MFace *mface= NULL;
-       MVert *mvert= NULL;
-       int i, totface, intersect=0;
+       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];
  
        }
  
        /* BMESH_ONLY, deform dm may not have tessface */
 -      DM_ensure_tessface(dm);
 +      BKE_mesh_tessface_ensure(mesh);
  
  
-       if (pa_minmax==0) {
+       if (pa_minmax == 0) {
                INIT_MINMAX(p_min, p_max);
                minmax_v3v3_v3(p_min, p_max, co1);
                minmax_v3v3_v3(p_min, p_max, co2);
        }
        else {
                copy_v3_v3(p_min, pa_minmax);
-               copy_v3_v3(p_max, pa_minmax+3);
+               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++) {
+       for (i = 0; i < totface; i++, mface++) {
                if (vert_cos) {
-                       copy_v3_v3(v1, vert_cos+3*mface->v1);
-                       copy_v3_v3(v2, vert_cos+3*mface->v2);
-                       copy_v3_v3(v3, vert_cos+3*mface->v3);
+                       copy_v3_v3(v1, vert_cos + 3 * mface->v1);
+                       copy_v3_v3(v2, vert_cos + 3 * mface->v2);
+                       copy_v3_v3(v3, vert_cos + 3 * mface->v3);
                        if (mface->v4)
-                               copy_v3_v3(v4, vert_cos+3*mface->v4);
+                               copy_v3_v3(v4, vert_cos + 3 * mface->v4);
                }
                else {
                        copy_v3_v3(v1, mvert[mface->v1].co);
        return intersect;
  }
  
 -static int brush_add(PEData *data, short number)
 +typedef struct BrushAddCountIterData {
 +      Depsgraph *depsgraph;
 +      Scene *scene;
 +      Object *object;
 +      Mesh *mesh;
 +      PEData *data;
 +      int number;
 +      short size;
 +      float imat[4][4];
 +      ParticleData *add_pars;
 +      int num_added;
 +} BrushAddCountIterData;
 +
 +typedef struct BrushAddCountIterTLSData {
 +      RNG *rng;
 +      int num_added;
 +} BrushAddCountIterTLSData;
 +
 +static void brush_add_count_iter(
 +        void *__restrict iter_data_v,
 +        const int iter,
 +        const ParallelRangeTLS *__restrict tls_v)
 +{
 +      BrushAddCountIterData *iter_data = (BrushAddCountIterData *)iter_data_v;
 +      Depsgraph *depsgraph = iter_data->depsgraph;
 +      PEData *data = iter_data->data;
 +      PTCacheEdit *edit = data->edit;
 +      ParticleSystem *psys = edit->psys;
 +      ParticleSystemModifierData *psmd_eval = edit->psmd_eval;
 +      ParticleData *add_pars = iter_data->add_pars;
 +      BrushAddCountIterTLSData *tls = tls_v->userdata_chunk;
 +      const int number = iter_data->number;
 +      const short size = iter_data->size;
-       const short size2 = size*size;
++      const short size2 = size * size;
 +      float dmx, dmy;
 +      if (number > 1) {
 +              dmx = size;
 +              dmy = size;
 +              if (tls->rng == NULL) {
 +                      tls->rng = BLI_rng_new_srandom(
 +                              psys->seed + data->mval[0] + data->mval[1] + tls_v->thread_id);
 +              }
 +              /* rejection sampling to get points in circle */
-               while (dmx*dmx + dmy*dmy > size2) {
-                       dmx = (2.0f*BLI_rng_get_float(tls->rng) - 1.0f)*size;
-                       dmy = (2.0f*BLI_rng_get_float(tls->rng) - 1.0f)*size;
++              while (dmx * dmx + dmy * dmy > size2) {
++                      dmx = (2.0f * BLI_rng_get_float(tls->rng) - 1.0f) * size;
++                      dmy = (2.0f * BLI_rng_get_float(tls->rng) - 1.0f) * size;
 +              }
 +      }
 +      else {
 +              dmx = 0.0f;
 +              dmy = 0.0f;
 +      }
 +
 +      float mco[2];
 +      mco[0] = data->mval[0] + dmx;
 +      mco[1] = data->mval[1] + dmy;
 +
 +      float co1[3], co2[3];
 +      ED_view3d_win_to_segment(depsgraph, data->vc.ar, data->vc.v3d, mco, co1, co2, true);
 +
 +      mul_m4_v3(iter_data->imat, co1);
 +      mul_m4_v3(iter_data->imat, co2);
 +      float min_d = 2.0;
 +
 +      /* warning, returns the derived mesh face */
 +      BLI_assert(iter_data->mesh != NULL);
 +      if (particle_intersect_mesh(depsgraph, iter_data->scene, iter_data->object, iter_data->mesh,
 +                                  0, co1, co2,
 +                                  &min_d,
 +                                  &add_pars[iter].num_dmcache,
 +                                  add_pars[iter].fuv,
 +                                  0, 0, 0, 0)) {
 +              if (psys->part->use_modifier_stack && !psmd_eval->mesh_final->runtime.deformed_only) {
 +                      add_pars[iter].num = add_pars[iter].num_dmcache;
 +                      add_pars[iter].num_dmcache = DMCACHE_ISCHILD;
 +              }
 +              else if (iter_data->mesh == psmd_eval->mesh_original) {
 +                      /* Final DM is not same topology as orig mesh, we have to map num_dmcache to real final dm. */
 +                      add_pars[iter].num = add_pars[iter].num_dmcache;
 +                      add_pars[iter].num_dmcache = psys_particle_dm_face_lookup(
-                                                     psmd_eval->mesh_final, psmd_eval->mesh_original,
-                                                     add_pars[iter].num, add_pars[iter].fuv, NULL);
++                              psmd_eval->mesh_final, psmd_eval->mesh_original,
++                              add_pars[iter].num, add_pars[iter].fuv, NULL);
 +              }
 +              else {
 +                      add_pars[iter].num = add_pars[iter].num_dmcache;
 +              }
 +              if (add_pars[iter].num != DMCACHE_NOTFOUND) {
 +                      tls->num_added++;
 +              }
 +      }
 +}
 +
 +static void brush_add_count_iter_finalize(void *__restrict userdata_v,
 +                                          void *__restrict userdata_chunk_v)
  {
-       Scene *scene= data->scene;
-       Object *ob= data->ob;
 +      BrushAddCountIterData *iter_data = (BrushAddCountIterData *)userdata_v;
 +      BrushAddCountIterTLSData *tls = (BrushAddCountIterTLSData *)userdata_chunk_v;
 +      iter_data->num_added += tls->num_added;
 +      if (tls->rng != NULL) {
 +              BLI_rng_free(tls->rng);
 +      }
 +}
 +
 +static int brush_add(const bContext *C, PEData *data, short number)
 +{
 +      Depsgraph *depsgraph = CTX_data_depsgraph(C);
 -      DerivedMesh *dm;
+       Scene *scene = data->scene;
+       Object *ob = data->ob;
 +      Mesh *mesh;
        PTCacheEdit *edit = data->edit;
-       ParticleSystem *psys= edit->psys;
+       ParticleSystem *psys = edit->psys;
        ParticleData *add_pars;
 -      ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
 +      ParticleSystemModifierData *psmd_eval = edit->psmd_eval;
-       ParticleSimulationData sim= {0};
-       ParticleEditSettings *pset= PE_settings(scene);
-       int i, k, n= 0, totpart= psys->totpart;
+       ParticleSimulationData sim = {0};
+       ParticleEditSettings *pset = PE_settings(scene);
+       int i, k, n = 0, totpart = psys->totpart;
 -      float mco[2];
 -      float dmx, dmy;
 -      float co1[3], co2[3], min_d, imat[4][4];
 +      float co1[3], imat[4][4];
        float framestep, timestep;
-       short size= pset->brush[PE_BRUSH_ADD].size;
+       short size = pset->brush[PE_BRUSH_ADD].size;
 -      short size2 = size * size;
        RNG *rng;
  
        invert_m4_m4(imat, ob->obmat);
  
        add_pars = MEM_callocN(number * sizeof(ParticleData), "ParticleData add");
  
-       rng = BLI_rng_new_srandom(psys->seed+data->mval[0]+data->mval[1]);
+       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;
  
        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_eval->mesh_final->runtime.deformed_only) {
 +              mesh = psmd_eval->mesh_final;
        }
        else {
 -              dm = psmd->dm_deformed;
 +              mesh = psmd_eval->mesh_original;
        }
 -      BLI_assert(dm);
 -
 -      for (i = 0; i < number; i++) {
 -              if (number > 1) {
 -                      dmx = size;
 -                      dmy = size;
 -
 -                      /* rejection sampling to get points in circle */
 -                      while (dmx * dmx + dmy * dmy > size2) {
 -                              dmx = (2.0f * BLI_rng_get_float(rng) - 1.0f) * size;
 -                              dmy = (2.0f * BLI_rng_get_float(rng) - 1.0f) * size;
 -                      }
 +      BLI_assert(mesh);
 +
 +      /* Calculate positions of new particles to add, based on brush interseciton
 +       * with object. New particle data is assigned to a correponding to check
 +       * index element of add_pars array. This means, that add_pars is a sparse
 +       * array.
 +       */
 +      BrushAddCountIterData iter_data;
 +      iter_data.depsgraph = depsgraph;
 +      iter_data.scene = scene;
 +      iter_data.object = ob;
 +      iter_data.mesh = mesh;
 +      iter_data.data = data;
 +      iter_data.number = number;
 +      iter_data.size = size;
 +      iter_data.add_pars = add_pars;
 +      iter_data.num_added = 0;
 +      copy_m4_m4(iter_data.imat, imat);
 +
 +      BrushAddCountIterTLSData tls = {NULL};
 +
 +      ParallelRangeSettings settings;
 +      BLI_parallel_range_settings_defaults(&settings);
 +      settings.scheduling_mode = TASK_SCHEDULING_DYNAMIC;
 +      settings.userdata_chunk = &tls;
 +      settings.userdata_chunk_size = sizeof(BrushAddCountIterTLSData);
 +      settings.func_finalize = brush_add_count_iter_finalize;
 +      BLI_task_parallel_range(0, number, &iter_data, brush_add_count_iter, &settings);
 +
 +      /* Convert add_parse to a dense array, where all new particles are in the
 +       * beginnign of the array.
 +       */
 +      n = iter_data.num_added;
 +      for (int current_iter = 0, new_index = 0; current_iter < number; current_iter++) {
 +              if (add_pars[current_iter].num == DMCACHE_NOTFOUND) {
 +                      continue;
                }
 -              else {
 -                      dmx = 0.0f;
 -                      dmy = 0.0f;
 -              }
 -
 -              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);
 -
 -              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) {
 -                              add_pars[n].num = add_pars[n].num_dmcache;
 -                              add_pars[n].num_dmcache = DMCACHE_ISCHILD;
 -                      }
 -                      else if (dm == psmd->dm_deformed) {
 -                              /* 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,
 -                                      add_pars[n].num, add_pars[n].fuv, NULL);
 -                      }
 -                      else {
 -                              add_pars[n].num = add_pars[n].num_dmcache;
 -                      }
 -
 -                      if (add_pars[n].num != DMCACHE_NOTFOUND) {
 -                              n++;
 -                      }
 +              if (new_index != current_iter) {
 +                      new_index++;
 +                      continue;
                }
 +              memcpy(add_pars + new_index, add_pars + current_iter, sizeof(ParticleData));
 +              new_index++;
        }
 +
 +      /* TODO(sergey): Consider multi-threading this part as well. */
        if (n) {
-               int newtotpart=totpart+n;
+               int newtotpart = totpart + n;
                float hairmat[4][4], cur_co[3];
-               KDTree *tree=0;
-               ParticleData *pa, *new_pars = MEM_callocN(newtotpart*sizeof(ParticleData), "ParticleData new");
-               PTCacheEditPoint *point, *new_points = MEM_callocN(newtotpart*sizeof(PTCacheEditPoint), "PTCacheEditPoint array new");
+               KDTree *tree = 0;
+               ParticleData *pa, *new_pars = MEM_callocN(newtotpart * sizeof(ParticleData), "ParticleData new");
+               PTCacheEditPoint *point, *new_points = MEM_callocN(newtotpart * sizeof(PTCacheEditPoint), "PTCacheEditPoint array new");
                PTCacheEditKey *key;
                HairKey *hkey;
  
  
                /* create tree for interpolation */
                if (pset->flag & PE_INTERPOLATE_ADDED && psys->totpart) {
-                       tree=BLI_kdtree_new(psys->totpart);
+                       tree = BLI_kdtree_new(psys->totpart);
  
-                       for (i=0, pa=psys->particles; i<totpart; i++, pa++) {
+                       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_eval->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);
                        }
  
                                ParticleKey key3[3];
                                KDTreeNearest ptn[3];
                                int w, maxw;
-                               float maxd, totw=0.0, weight[3];
+                               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_eval->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;
+                               maxd = ptn[maxw - 1].dist;
  
-                               for (w=0; w<maxw; w++) {
+                               for (w = 0; w < maxw; w++) {
                                        weight[w] = (float)pow(2.0, (double)(-6.0f * ptn[w].dist / maxd));
                                        totw += weight[w];
                                }
                                }
                        }
                        else {
-                               for (k=0, hkey=pa->hair; k<pset->totaddkey; k++, hkey++) {
+                               for (k = 0, hkey = pa->hair; k < pset->totaddkey; k++, hkey++) {
                                        madd_v3_v3v3fl(hkey->co, pa->state.co, pa->state.vel, k * framestep * timestep);
                                        hkey->time += k * framestep;
-                                       hkey->weight = 1.f - (float)k/(float)(pset->totaddkey-1);
+                                       hkey->weight = 1.f - (float)k / (float)(pset->totaddkey - 1);
                                }
                        }
-                       for (k=0, hkey=pa->hair; k<pset->totaddkey; k++, hkey++) {
+                       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_eval->mesh_final, psys->part->from, pa, hairmat);
                                invert_m4_m4(imat, hairmat);
                                mul_m4_v3(imat, hkey->co);
                        }
@@@ -4029,12 -3717,12 +4030,12 @@@ typedef struct BrushEdit 
  
  static int brush_edit_init(bContext *C, wmOperator *op)
  {
-       Scene *scene= CTX_data_scene(C);
 -      Main *bmain = CTX_data_main(C);
+       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);
-       ARegion *ar= CTX_wm_region(C);
+       Object *ob = CTX_data_active_object(C);
+       ParticleEditSettings *pset = PE_settings(scene);
 -      PTCacheEdit *edit = PE_get_current(bmain, scene, ob);
++      PTCacheEdit *edit = PE_get_current(scene, ob);
+       ARegion *ar = CTX_wm_region(C);
        BrushEdit *bedit;
        float min[3], max[3];
  
  
        /* set the 'distance factor' for grabbing (used in comb etc) */
        INIT_MINMAX(min, max);
 -      PE_minmax(bmain, scene, min, max);
 +      PE_minmax(scene, view_layer, min, max);
        mid_v3_v3v3(min, min, max);
  
-       bedit= MEM_callocN(sizeof(BrushEdit), "BrushEdit");
-       bedit->first= 1;
-       op->customdata= bedit;
+       bedit = MEM_callocN(sizeof(BrushEdit), "BrushEdit");
+       bedit->first = 1;
+       op->customdata = bedit;
  
-       bedit->scene= scene;
+       bedit->scene = scene;
 +      bedit->view_layer = view_layer;
-       bedit->ob= ob;
-       bedit->edit= edit;
+       bedit->ob = ob;
+       bedit->edit = edit;
  
        bedit->zfac = ED_view3d_calc_zfac(ar->regiondata, min, NULL);
  
  
  static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
  {
-       BrushEdit *bedit= op->customdata;
 -      Main *bmain = CTX_data_main(C);
+       BrushEdit *bedit = op->customdata;
 +      Depsgraph *depsgraph = CTX_data_depsgraph(C);
-       Scene *scene= bedit->scene;
-       Object *ob= bedit->ob;
-       PTCacheEdit *edit= bedit->edit;
-       ParticleEditSettings *pset= PE_settings(scene);
+       Scene *scene = bedit->scene;
+       Object *ob = bedit->ob;
+       PTCacheEdit *edit = bedit->edit;
+       ParticleEditSettings *pset = PE_settings(scene);
 -      ParticleSystemModifierData *psmd = edit->psys ? psys_get_modifier(ob, edit->psys) : NULL;
 +      ParticleSystemModifierData *psmd_eval = edit->psmd_eval;
-       ParticleBrushData *brush= &pset->brush[pset->brushtype];
-       ARegion *ar= CTX_wm_region(C);
+       ParticleBrushData *brush = &pset->brush[pset->brushtype];
+       ARegion *ar = CTX_wm_region(C);
        float vec[3], mousef[2];
        int mval[2];
-       int flip, mouse[2], removed= 0, added=0, selected= 0, tot_steps= 1, step= 1;
+       int flip, mouse[2], removed = 0, added = 0, selected = 0, tot_steps = 1, step = 1;
        float dx, dy, dmax;
        int lock_root = pset->flag & PE_LOCK_FIRST;
  
             (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);
+               selected = (short)count_selected_keys(scene, edit);
  
                dmax = max_ff(fabsf(dx), fabsf(dy));
-               tot_steps = dmax/(0.2f * pe_brush_size_get(scene, brush)) + 1;
+               tot_steps = dmax / (0.2f * pe_brush_size_get(scene, brush)) + 1;
  
                dx /= (float)tot_steps;
                dy /= (float)tot_steps;
                                case PE_BRUSH_PUFF:
                                {
                                        if (edit->psys) {
 -                                              data.dm = psmd->dm_final;
 +                                              data.mesh = psmd_eval->mesh_final;
-                                               data.mval= mval;
-                                               data.rad= pe_brush_size_get(scene, brush);
-                                               data.select= selected;
+                                               data.mval = mval;
+                                               data.rad = pe_brush_size_get(scene, brush);
+                                               data.select = selected;
  
-                                               data.pufffac= (brush->strength - 0.5f) * 2.0f;
+                                               data.pufffac = (brush->strength - 0.5f) * 2.0f;
                                                if (data.pufffac < 0.0f)
-                                                       data.pufffac= 1.0f - 9.0f * data.pufffac;
+                                                       data.pufffac = 1.0f - 9.0f * data.pufffac;
                                                else
-                                                       data.pufffac= 1.0f - data.pufffac;
+                                                       data.pufffac = 1.0f - data.pufffac;
  
-                                               data.invert= (brush->invert ^ flip);
+                                               data.invert = (brush->invert ^ flip);
                                                invert_m4_m4(ob->imat, ob->obmat);
  
                                                foreach_mouse_hit_point(&data, brush_puff, selected);
                                }
                                case PE_BRUSH_ADD:
                                {
-                                       if (edit->psys && edit->psys->part->from==PART_FROM_FACE) {
-                                               data.mval= mval;
+                                       if (edit->psys && edit->psys->part->from == PART_FROM_FACE) {
+                                               data.mval = mval;
  
-                                               added= brush_add(C, &data, brush->count);
 -                                              added = brush_add(&data, brush->count);
++                                              added = brush_add(C, &data, brush->count);
  
                                                if (pset->flag & PE_KEEP_LENGTHS)
                                                        recalc_lengths(edit);
                                case PE_BRUSH_WEIGHT:
                                {
                                        if (edit->psys) {
 -                                              data.dm = psmd->dm_final;
 +                                              data.mesh = psmd_eval->mesh_final;
-                                               data.mval= mval;
-                                               data.rad= pe_brush_size_get(scene, brush);
+                                               data.mval = mval;
+                                               data.rad = pe_brush_size_get(scene, brush);
  
                                                data.weightfac = brush->strength; /* note that this will never be zero */
  
                }
  
                if (edit->psys) {
-                       WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
+                       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_SELECT_UPDATE);
                }
                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);
+                       WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
                }
  
                bedit->lastmouse[0] = mouse[0];
  
  static void brush_edit_exit(wmOperator *op)
  {
-       BrushEdit *bedit= op->customdata;
+       BrushEdit *bedit = op->customdata;
  
 +      PE_free_random_generator(&bedit->data);
        MEM_freeN(bedit);
  }
  
@@@ -4532,22 -4213,19 +4533,22 @@@ static int shape_cut_exec(bContext *C, 
                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(bmain, scene, ob, 1);
  
                if (edit->psys) {
-                       WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
+                       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_SELECT_UPDATE);
                }
                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);
+                       WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
                }
  
                PE_free_shape_tree(&data);
@@@ -4575,15 -4253,15 +4576,15 @@@ void PARTICLE_OT_shape_cut(wmOperatorTy
  
  /************************ utilities ******************************/
  
 -int PE_minmax(Main *bmain, 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(view_layer);
-       PTCacheEdit *edit= PE_get_current(scene, ob);
 -      Object *ob = OBACT;
 -      PTCacheEdit *edit = PE_get_current(bmain, scene, ob);
++      Object *ob = OBACT(view_layer);
++      PTCacheEdit *edit = PE_get_current(scene, ob);
        ParticleSystem *psys;
 -      ParticleSystemModifierData *psmd = NULL;
 +      ParticleSystemModifierData *psmd_eval = NULL;
        POINT_P; KEY_K;
        float co[3], mat[4][4];
-       int ok= 0;
+       int ok = 0;
  
        if (!edit) return ok;
  
  
        LOOP_VISIBLE_POINTS {
                if (psys)
-                       psys_mat_hair_to_global(ob, psmd_eval->mesh_final, psys->part->from, psys->particles+p, mat);
 -                      psys_mat_hair_to_global(ob, psmd->dm_final, psys->part->from, psys->particles + p, mat);
++                      psys_mat_hair_to_global(ob, psmd_eval->mesh_final, psys->part->from, psys->particles + p, mat);
  
                LOOP_SELECTED_KEYS {
                        copy_v3_v3(co, key->co);
  
  /************************ particle edit toggle operator ************************/
  
- static struct ParticleSystem *psys_eval_get(Depsgraph *depsgraph,
-                                              Object *object,
-                                              ParticleSystem *psys)
- {
++static struct ParticleSystem *psys_eval_get(
++        Depsgraph *depsgraph,
++        Object *object,
++        ParticleSystem *psys){
 +      Object *object_eval = DEG_get_evaluated_object(depsgraph, object);
 +      if (object_eval == object) {
 +              return psys;
 +      }
 +      ParticleSystem *psys_eval = object_eval->particlesystem.first;
 +      while (psys_eval != NULL) {
 +              if (psys_eval->orig_psys == psys) {
 +                      return psys_eval;
 +              }
 +              psys_eval = psys_eval->next;
 +      }
 +      return psys_eval;
 +}
 +
  /* initialize needed data for bake edit */
 -void PE_create_particle_edit(Main *bmain, Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys)
 +void PE_create_particle_edit(
 +        Depsgraph *depsgraph, Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys)
  {
 +      Object *ob_eval = DEG_get_evaluated_object(depsgraph, ob);
        PTCacheEdit *edit;
        ParticleSystemModifierData *psmd = (psys) ? psys_get_modifier(ob, psys) : NULL;
 +      ParticleSystemModifierData *psmd_eval = NULL;
        POINT_P; KEY_K;
        ParticleData *pa = NULL;
        HairKey *hkey;
        edit = (psys) ? psys->edit : cache->edit;
  
        if (!edit) {
 +              ParticleSystem *psys_eval = psys_eval_get(depsgraph, ob, psys);
 +              psys_copy_particles(psys, psys_eval);
 +
                totpoint = psys ? psys->totpart : (int)((PTCacheMem *)cache->mem_cache.first)->totpoint;
  
-               edit= MEM_callocN(sizeof(PTCacheEdit), "PE_create_particle_edit");
-               edit->points=MEM_callocN(totpoint*sizeof(PTCacheEditPoint), "PTCacheEditPoints");
+               edit = MEM_callocN(sizeof(PTCacheEdit), "PE_create_particle_edit");
+               edit->points = MEM_callocN(totpoint * sizeof(PTCacheEditPoint), "PTCacheEditPoints");
                edit->totpoint = totpoint;
  
                if (psys && !cache) {
 +                      edit->psmd = psmd;
 +                      edit->psmd_eval = psmd_eval;
                        psys->edit = edit;
                        edit->psys = psys;
 +                      edit->psys_eval = psys_eval;
  
-                       psys->free_edit= PE_free_ptcache_edit;
+                       psys->free_edit = PE_free_ptcache_edit;
  
                        edit->pathcache = NULL;
                        BLI_listbase_clear(&edit->pathcachebufs);
@@@ -4790,30 -4430,24 +4791,30 @@@ static int particle_edit_toggle_exec(bC
  
        if (!is_mode_set) {
                PTCacheEdit *edit;
 +
                ob->mode |= mode_flag;
 -              edit = PE_create_current(bmain, scene, ob);
 +
-               edit= PE_create_current(depsgraph, 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);
+               WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_PARTICLE, NULL);
        }
        else {
                ob->mode &= ~mode_flag;
                toggle_particle_cursor(C, 0);
-               WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, NULL);
+               WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL);
        }
  
 -      DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 +      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;
  }
@@@ -4853,16 -4487,16 +4854,16 @@@ static int clear_edited_exec(bContext *
                        psys->flag &= ~PSYS_EDITED;
  
                        psys_reset(psys, PSYS_RESET_DEPSGRAPH);
-                       WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
+                       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 */
                psys->recalc |= PSYS_RECALC_RESET;
                psys->flag &= ~PSYS_GLOBAL_HAIR;
                psys->flag &= ~PSYS_EDITED;
-               WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE|NA_EDITED, ob);
+               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;
@@@ -4975,13 -4607,13 +4976,13 @@@ static int unify_length_exec(bContext *
        }
        scale_points_to_length(edit, average_length);
  
 -      PE_update_object(bmain, 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);
+               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);
+               WM_event_add_notifier(C, NC_OBJECT | ND_MODIFIER, ob);
        }
  
        return OPERATOR_FINISHED;
index 4431e4f4a548d675ed2c0b84b3d1de1e12f4b75f,e6b8ac596e9c4616018f5a5fbf137ad7a647ef73..fa272ffe34d650f1b26e1f60466a88719025302e
@@@ -130,8 -125,8 +130,8 @@@ static int particle_system_remove_exec(
         */
        if (mode_orig & OB_MODE_PARTICLE_EDIT) {
                if ((ob->mode & OB_MODE_PARTICLE_EDIT) == 0) {
 -                      if (scene->basact && scene->basact->object == ob) {
 +                      if (view_layer->basact && view_layer->basact->object == ob) {
-                               WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, NULL);
+                               WM_event_add_notifier(C, NC_SCENE | ND_MODE | NS_MODE_OBJECT, NULL);
                        }
                }
        }
@@@ -192,10 -187,10 +192,10 @@@ static int new_particle_settings_exec(b
  
        psys_check_boid_data(psys);
  
 -      DAG_relations_tag_update(bmain);
 -      DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 +      DEG_relations_tag_update(bmain);
 +      DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
  
-       WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
+       WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob);
  
        return OPERATOR_FINISHED;
  }
@@@ -240,10 -235,10 +240,10 @@@ static int new_particle_target_exec(bCo
  
        BLI_addtail(&psys->targets, pt);
  
 -      DAG_relations_tag_update(bmain);
 -      DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 +      DEG_relations_tag_update(bmain);
 +      DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
  
-       WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
+       WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob);
  
        return OPERATOR_FINISHED;
  }
@@@ -288,10 -283,10 +288,10 @@@ static int remove_particle_target_exec(
        if (pt)
                pt->flag |= PTARGET_CURRENT;
  
 -      DAG_relations_tag_update(bmain);
 -      DAG_id_tag_update(&ob->id, OB_RECALC_DATA);
 +      DEG_relations_tag_update(bmain);
 +      DEG_id_tag_update(&ob->id, OB_RECALC_DATA);
  
-       WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, ob);
+       WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob);
  
        return OPERATOR_FINISHED;
  }
@@@ -328,8 -323,8 +328,8 @@@ static int target_move_up_exec(bContex
                        BLI_remlink(&psys->targets, pt);
                        BLI_insertlinkbefore(&psys->targets, pt->prev, pt);
  
 -                      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, ob);
+                       WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob);
                        break;
                }
        }
@@@ -366,8 -361,8 +366,8 @@@ static int target_move_down_exec(bConte
                        BLI_remlink(&psys->targets, pt);
                        BLI_insertlinkafter(&psys->targets, pt->next, pt);
  
 -                      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, ob);
+                       WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob);
                        break;
                }
        }
@@@ -384,38 -379,9 +384,38 @@@ void PARTICLE_OT_target_move_down(wmOpe
        ot->exec = target_move_down_exec;
  
        /* flags */
-       ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
+       ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
  }
  
-       ParticleSystem *psys= ptr.data;
 +/************************ refresh dupli objects *********************/
 +
 +static int dupliob_refresh_exec(bContext *C, wmOperator *UNUSED(op))
 +{
 +      PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
-       WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, NULL);
++      ParticleSystem *psys = ptr.data;
 +
 +      if (!psys)
 +              return OPERATOR_CANCELLED;
 +
 +      psys_check_group_weights(psys->part);
 +      DEG_id_tag_update(&psys->part->id, OB_RECALC_DATA | PSYS_RECALC_REDO);
-       ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO;
++      WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, NULL);
 +
 +      return OPERATOR_FINISHED;
 +}
 +
 +void PARTICLE_OT_dupliob_refresh(wmOperatorType *ot)
 +{
 +      ot->name = "Refresh Dupli Objects";
 +      ot->idname = "PARTICLE_OT_dupliob_refresh";
 +      ot->description = "Refresh list of dupli objects and their weights";
 +
 +      ot->exec = dupliob_refresh_exec;
 +
 +      /* flags */
++      ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
 +}
 +
  /************************ move up particle dupliweight operator *********************/
  
  static int dupliob_move_up_exec(bContext *C, wmOperator *UNUSED(op))
                        BLI_remlink(&part->dupliweights, dw);
                        BLI_insertlinkbefore(&part->dupliweights, dw->prev, dw);
  
-                       WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, NULL);
 +                      DEG_id_tag_update(&part->id, OB_RECALC_DATA | PSYS_RECALC_REDO);
+                       WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, NULL);
                        break;
                }
        }
@@@ -474,8 -439,7 +474,8 @@@ static int copy_particle_dupliob_exec(b
                        dw->flag |= PART_DUPLIW_CURRENT;
                        BLI_addhead(&part->dupliweights, dw);
  
-                       WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, NULL);
 +                      DEG_id_tag_update(&part->id, OB_RECALC_DATA | PSYS_RECALC_REDO);
+                       WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, NULL);
                        break;
                }
        }
@@@ -521,8 -485,7 +521,8 @@@ static int remove_particle_dupliob_exec
        if (dw)
                dw->flag |= PART_DUPLIW_CURRENT;
  
-       WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, NULL);
 +      DEG_id_tag_update(&part->id, OB_RECALC_DATA | PSYS_RECALC_REDO);
+       WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, NULL);
  
        return OPERATOR_FINISHED;
  }
@@@ -559,8 -522,7 +559,8 @@@ static int dupliob_move_down_exec(bCont
                        BLI_remlink(&part->dupliweights, dw);
                        BLI_insertlinkafter(&part->dupliweights, dw->next, dw);
  
-                       WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, NULL);
 +                      DEG_id_tag_update(&part->id, OB_RECALC_DATA | PSYS_RECALC_REDO);
+                       WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, NULL);
                        break;
                }
        }
@@@ -582,12 -544,10 +582,12 @@@ void PARTICLE_OT_dupliob_move_down(wmOp
  
  /************************ connect/disconnect hair operators *********************/
  
 -static void disconnect_hair(Main *bmain, Scene *scene, Object *ob, ParticleSystem *psys)
 +static void disconnect_hair(
 +        Depsgraph *depsgraph, Scene *scene,
 +        Object *ob, ParticleSystem *psys)
  {
        ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
-       ParticleEditSettings *pset= PE_settings(scene);
+       ParticleEditSettings *pset = PE_settings(scene);
        ParticleData *pa;
        PTCacheEdit *edit;
        PTCacheEditPoint *point;
                        point++;
                }
  
 -              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);
  
-               for (k=0, key=pa->hair; k<pa->totkey; k++, key++) {
+               for (k = 0, key = pa->hair; k < pa->totkey; k++, key++) {
                        mul_m4_v3(hairmat, key->co);
  
                        if (ekey) {
  
  static int disconnect_hair_exec(bContext *C, wmOperator *op)
  {
 -      Main *bmain = CTX_data_main(C);
 +      Depsgraph *depsgraph = CTX_data_depsgraph(C);
-       Scene *scene= CTX_data_scene(C);
-       Object *ob= ED_object_context(C);
-       ParticleSystem *psys= NULL;
+       Scene *scene = CTX_data_scene(C);
+       Object *ob = ED_object_context(C);
+       ParticleSystem *psys = NULL;
        const bool all = RNA_boolean_get(op->ptr, "all");
  
        if (!ob)
                return OPERATOR_CANCELLED;
  
        if (all) {
-               for (psys=ob->particlesystem.first; psys; psys=psys->next) {
+               for (psys = ob->particlesystem.first; psys; psys = psys->next) {
 -                      disconnect_hair(bmain, scene, ob, psys);
 +                      disconnect_hair(depsgraph, scene, ob, psys);
                }
        }
        else {
                psys = psys_get_current(ob);
 -              disconnect_hair(bmain, scene, ob, psys);
 +              disconnect_hair(depsgraph, scene, ob, psys);
        }
  
 -      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, ob);
+       WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob);
  
        return OPERATOR_FINISHED;
  }
@@@ -722,34 -681,28 +722,34 @@@ static bool remap_hair_emitter
                return false;
        }
        /* don't modify the original vertices */
 -      dm = CDDM_copy(dm);
 +      BKE_id_copy_ex(
 +                  NULL, &mesh->id, (ID **)&mesh,
 +                  LIB_ID_CREATE_NO_MAIN |
 +                  LIB_ID_CREATE_NO_USER_REFCOUNT |
 +                  LIB_ID_CREATE_NO_DEG_TAG |
 +                  LIB_ID_COPY_NO_PREVIEW,
 +                  false);
  
        /* BMESH_ONLY, deform dm may not have tessface */
 -      DM_ensure_tessface(dm);
 +      BKE_mesh_tessface_ensure(mesh);
  
 -      numverts = dm->getNumVerts(dm);
 -      mvert = dm->getVertArray(dm);
 +      numverts = mesh->totvert;
 +      mvert = mesh->mvert;
  
        /* convert to global coordinates */
-       for (i=0; i<numverts; i++)
+       for (i = 0; i < numverts; i++)
                mul_m4_v3(to_mat, mvert[i].co);
  
 -      if (dm->getNumTessFaces(dm) != 0) {
 -              mface = dm->getTessFaceArray(dm);
 -              bvhtree_from_mesh_get(&bvhtree, dm, BVHTREE_FROM_FACES, 2);
 +      if (mesh->totface != 0) {
 +              mface = mesh->mface;
 +              BKE_bvhtree_from_mesh_get(&bvhtree, mesh, BVHTREE_FROM_FACES, 2);
        }
 -      else if (dm->getNumEdges(dm) != 0) {
 -              medge = dm->getEdgeArray(dm);
 -              bvhtree_from_mesh_get(&bvhtree, dm, BVHTREE_FROM_EDGES, 2);
 +      else if (mesh->totedge != 0) {
 +              medge = mesh->medge;
 +              BKE_bvhtree_from_mesh_get(&bvhtree, mesh, BVHTREE_FROM_EDGES, 2);
        }
        else {
 -              dm->release(dm);
 +              BKE_id_free(NULL, mesh);
                return false;
        }
  
@@@ -894,10 -844,10 +894,10 @@@ static bool connect_hair
  
  static int connect_hair_exec(bContext *C, wmOperator *op)
  {
 -      Main *bmain = CTX_data_main(C);
 +      Depsgraph *depsgraph = CTX_data_depsgraph(C);
-       Scene *scene= CTX_data_scene(C);
-       Object *ob= ED_object_context(C);
-       ParticleSystem *psys= NULL;
+       Scene *scene = CTX_data_scene(C);
+       Object *ob = ED_object_context(C);
+       ParticleSystem *psys = NULL;
        const bool all = RNA_boolean_get(op->ptr, "all");
        bool any_connected = false;
  
                return OPERATOR_CANCELLED;
  
        if (all) {
-               for (psys=ob->particlesystem.first; psys; psys=psys->next) {
+               for (psys = ob->particlesystem.first; psys; psys = psys->next) {
 -                      any_connected |= connect_hair(bmain, scene, ob, psys);
 +                      any_connected |= connect_hair(depsgraph, scene, ob, psys);
                }
        }
        else {
                return OPERATOR_CANCELLED;
        }
  
 -      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, ob);
+       WM_event_add_notifier(C, NC_OBJECT | ND_PARTICLE, ob);
  
        return OPERATOR_FINISHED;
  }