Undo revision 23130 which was a merge with 2.5, a messy one because I did something...
[blender.git] / source / blender / editors / physics / editparticle.c
index dbb11f7..b92632b 100644 (file)
@@ -57,8 +57,7 @@
 #include "BKE_particle.h"
 #include "BKE_report.h"
 #include "BKE_scene.h"
-#include "BKE_utildefines.h"
-#include "BKE_pointcache.h"
+#include "BKE_utildefines.h" 
 
 #include "BLI_arithb.h"
 #include "BLI_blenlib.h"
 
 #include "physics_intern.h"
 
-static void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys);
-static void PTCacheUndo_clear(PTCacheEdit *edit);
+static void PE_create_particle_edit(Scene *scene, Object *ob, ParticleSystem *psys);
+static void ParticleUndo_clear(ParticleSystem *psys);
 
-#define KEY_K                                  PTCacheEditKey *key; int k
-#define POINT_P                                        PTCacheEditPoint *point; int p
-#define LOOP_POINTS                            for(p=0, point=edit->points; p<edit->totpoint; p++, point++)
-#define LOOP_VISIBLE_POINTS            for(p=0, point=edit->points; p<edit->totpoint; p++, point++) if(!(point->flag & PEP_HIDE))
-#define LOOP_SELECTED_POINTS   for(p=0, point=edit->points; p<edit->totpoint; p++, point++) if(point_is_selected(point))
-#define LOOP_UNSELECTED_POINTS for(p=0, point=edit->points; p<edit->totpoint; p++, point++) if(!point_is_selected(point))
-#define LOOP_EDITED_POINTS             for(p=0, point=edit->points; p<edit->totpoint; p++, point++) if(point->flag & PEP_EDIT_RECALC)
-#define LOOP_TAGGED_POINTS             for(p=0, point=edit->points; p<edit->totpoint; p++, point++) if(point->flag & PEP_TAG)
-#define LOOP_KEYS                              for(k=0, key=point->keys; k<point->totkey; k++, key++)
-#define LOOP_VISIBLE_KEYS              for(k=0, key=point->keys; k<point->totkey; k++, key++) if(!(key->flag & PEK_HIDE))
-#define LOOP_SELECTED_KEYS             for(k=0, key=point->keys; k<point->totkey; k++, key++) if((key->flag & PEK_SELECT) && !(key->flag & PEK_HIDE))
-#define LOOP_TAGGED_KEYS               for(k=0, key=point->keys; k<point->totkey; k++, key++) if(key->flag & PEK_TAG)
-
-#define LOOP_PARTICLES(i, pa)  for(i=0, pa=psys->particles; i<psys->totpart; i++, pa++)
-
-#define KEY_WCO                                        (key->flag & PEK_USE_WCO ? key->world_co : key->co)
+#define LOOP_PARTICLES(i, pa) for(i=0, pa=psys->particles; i<totpart; i++, pa++)
+#define LOOP_KEYS(k, key) if(psys->edit)for(k=0, key=psys->edit->keys[i]; k<pa->totkey; k++, key++)
 
 /**************************** utilities *******************************/
 
@@ -112,14 +97,14 @@ static int PE_poll(bContext *C)
 {
        Scene *scene= CTX_data_scene(C);
        Object *ob= CTX_data_active_object(C);
-       PTCacheEdit *edit;
+       ParticleSystem *psys;
 
        if(!scene || !ob)
                return 0;
        
-       edit= PE_get_current(scene, ob);
+       psys= PE_get_current(scene, ob);
 
-       return (edit && (ob->mode & OB_MODE_PARTICLE_EDIT));
+       return (psys && psys->edit && (ob && ob->mode & OB_MODE_PARTICLE_EDIT));
 }
 
 static int PE_poll_3dview(bContext *C)
@@ -128,21 +113,22 @@ static int PE_poll_3dview(bContext *C)
                CTX_wm_region(C)->regiontype == RGN_TYPE_WINDOW;
 }
 
-void PE_free_ptcache_edit(PTCacheEdit *edit)
+static void PE_free_particle_edit(ParticleSystem *psys)
 {
-       POINT_P;
+       ParticleEdit *edit= psys->edit;
+       int i, totpart= psys->totpart;
 
        if(edit==0) return;
 
-       PTCacheUndo_clear(edit);
+       ParticleUndo_clear(psys);
 
-       if(edit->points) {
-               LOOP_POINTS {
-                       if(point->keys) 
-                               MEM_freeN(point->keys);
+       if(edit->keys) {
+               for(i=0; i<totpart; i++) {
+                       if(edit->keys[i])
+                               MEM_freeN(edit->keys[i]);
                }
 
-               MEM_freeN(edit->points);
+               MEM_freeN(edit->keys);
        }
 
        if(edit->mirror_cache)
@@ -158,23 +144,19 @@ void PE_free_ptcache_edit(PTCacheEdit *edit)
                edit->emitter_field= 0;
        }
 
-       psys_free_path_cache(NULL, edit);
-
        MEM_freeN(edit);
+
+       psys->edit= NULL;
+       psys->free_edit= NULL;
 }
 
 /************************************************/
 /*                     Edit Mode Helpers                                       */
 /************************************************/
 
-int PE_start_edit(PTCacheEdit *edit)
+int PE_can_edit(ParticleSystem *psys)
 {
-       if(edit) {
-               edit->edited = 1;
-               return 1;
-       }
-
-       return 0;
+       return (psys && psys->edit);
 }
 
 ParticleEditSettings *PE_settings(Scene *scene)
@@ -183,99 +165,73 @@ ParticleEditSettings *PE_settings(Scene *scene)
 }
 
 /* always gets atleast the first particlesystem even if PSYS_CURRENT flag is not set */
-PTCacheEdit *PE_get_current(Scene *scene, Object *ob)
+ParticleSystem *PE_get_current(Scene *scene, Object *ob)
 {
-       ParticleEditSettings *pset= PE_settings(scene);
-       PTCacheEdit *edit = NULL;
-       ListBase pidlist;
-       PTCacheID *pid;
-
-       pset->scene = scene;
-       pset->object = ob;
+       ParticleSystem *psys;
 
        if(ob==NULL)
                return NULL;
 
-       BKE_ptcache_ids_from_object(&pidlist, ob);
-
-       /* in the case of only one editable thing, set pset->edittype accordingly */
-       if(pidlist.first == pidlist.last) {
-               pid = pidlist.first;
-               switch(pid->type) {
-                       case PTCACHE_TYPE_PARTICLES:
-                               pset->edittype = PE_TYPE_PARTICLES;
-                               break;
-                       case PTCACHE_TYPE_SOFTBODY:
-                               pset->edittype = PE_TYPE_SOFTBODY;
-                               break;
-                       case PTCACHE_TYPE_CLOTH:
-                               pset->edittype = PE_TYPE_CLOTH;
-                               break;
-               }
+       psys= ob->particlesystem.first;
+       while(psys) {
+               if(psys->flag & PSYS_CURRENT)
+                       break;
+               psys=psys->next;
        }
 
-       for(pid=pidlist.first; pid; pid=pid->next) {
-               if(pset->edittype == PE_TYPE_PARTICLES && pid->type == PTCACHE_TYPE_PARTICLES) {
-                       ParticleSystem *psys = pid->calldata;
+       if(psys==NULL && ob->particlesystem.first) {
+               psys=ob->particlesystem.first;
+               psys->flag |= PSYS_CURRENT;
+       }
 
-                       if(psys->flag & PSYS_CURRENT) {
-                               if(psys->part && psys->part->type == PART_HAIR) {
-                                       if(!psys->edit && psys->flag & PSYS_HAIR_DONE)
-                                               PE_create_particle_edit(scene, ob, NULL, psys);
-                                       edit = psys->edit;
-                               }
-                               else {
-                                       if(pid->cache->flag & PTCACHE_BAKED && !pid->cache->edit)
-                                               PE_create_particle_edit(scene, ob, pid->cache, psys);
-                                       edit = pid->cache->edit;
-                               }
+       /* this happens when Blender is started with particle
+        * edit mode enabled XXX there's a draw error then? */
+       if(psys && psys_check_enabled(ob, psys) && (ob == OBACT) && (ob->mode & OB_MODE_PARTICLE_EDIT))
+               if(psys->part->type == PART_HAIR && psys->flag & PSYS_EDITED)
+                       if(psys->edit == NULL)
+                               PE_create_particle_edit(scene, ob, psys);
 
-                               break;
-                       }
-               }
-               else if(pset->edittype == PE_TYPE_SOFTBODY && pid->type == PTCACHE_TYPE_SOFTBODY) {
-                       if(pid->cache->flag & PTCACHE_BAKED && !pid->cache->edit)
-                               PE_create_particle_edit(scene, ob, pid->cache, NULL);
-                       edit = pid->cache->edit;
-                       break;
-               }
-               else if(pset->edittype == PE_TYPE_CLOTH && pid->type == PTCACHE_TYPE_CLOTH) {
-                       if(pid->cache->flag & PTCACHE_BAKED && !pid->cache->edit)
-                               PE_create_particle_edit(scene, ob, pid->cache, NULL);
-                       edit = pid->cache->edit;
-                       break;
-               }
-       }
+       return psys;
+}
 
-       if(edit)
-               edit->pid = *pid;
+/* returns -1 if no system has PSYS_CURRENT flag */
+short PE_get_current_num(Object *ob)
+{
+       short num=0;
+       ParticleSystem *psys= ob->particlesystem.first;
 
-       BLI_freelistN(&pidlist);
+       while(psys) {
+               if(psys->flag & PSYS_CURRENT)
+                       return num;
+               num++;
+               psys=psys->next;
+       }
 
-       return edit;
+       return -1;
 }
 
-void PE_hide_keys_time(Scene *scene, PTCacheEdit *edit, float cfra)
+void PE_hide_keys_time(Scene *scene, ParticleSystem *psys, float cfra)
 {
+       ParticleData *pa;
+       ParticleEditKey *key;
        ParticleEditSettings *pset=PE_settings(scene);
-       POINT_P; KEY_K;
+       int i, k, totpart= psys->totpart;
 
-
-       if(pset->flag & PE_FADE_TIME && pset->selectmode==SCE_SELECT_POINT) {
-               LOOP_POINTS {
-                       LOOP_KEYS {
-                               if(fabs(cfra-*key->time) < pset->fade_frames)
+       if(pset->draw_timed && pset->selectmode==SCE_SELECT_POINT) {
+               LOOP_PARTICLES(i, pa) {
+                       LOOP_KEYS(k, key) {
+                               if(fabs(cfra-*key->time) < pset->draw_timed)
                                        key->flag &= ~PEK_HIDE;
                                else {
                                        key->flag |= PEK_HIDE;
-                                       //key->flag &= ~PEK_SELECT;
+                                       key->flag &= ~PEK_SELECT;
                                }
                        }
                }
        }
        else {
-               LOOP_POINTS {
-                       LOOP_KEYS {
+               LOOP_PARTICLES(i, pa) {
+                       LOOP_KEYS(k, key) {
                                key->flag &= ~PEK_HIDE;
                        }
                }
@@ -291,7 +247,7 @@ typedef struct PEData {
        Scene *scene;
        Object *ob;
        DerivedMesh *dm;
-       PTCacheEdit *edit;
+       ParticleSystem *psys;
 
        short *mval;
        rcti *rect;
@@ -320,7 +276,7 @@ static void PE_set_data(bContext *C, PEData *data)
 
        data->scene= CTX_data_scene(C);
        data->ob= CTX_data_active_object(C);
-       data->edit= PE_get_current(data->scene, data->ob);
+       data->psys= PE_get_current(data->scene, data->ob);
 }
 
 static void PE_set_view3d_data(bContext *C, PEData *data)
@@ -432,103 +388,121 @@ static int key_inside_test(PEData *data, float co[3])
                return key_inside_rect(data, co);
 }
 
-static int point_is_selected(PTCacheEditPoint *point)
+static int particle_is_selected(ParticleSystem *psys, ParticleData *pa)
 {
-       KEY_K;
-       int sel;
+       ParticleEditKey *key;
+       int sel, i, k;
 
-       if(point->flag & PEP_HIDE)
+       if(pa->flag & PARS_HIDE)
                return 0;
 
        sel= 0;
+       i= pa - psys->particles;
 
-       LOOP_SELECTED_KEYS {
-               return 1;
-       }
+       LOOP_KEYS(k, key)
+               if(key->flag & PEK_SELECT)
+                       return 1;
        
        return 0;
 }
 
 /*************************** iterators *******************************/
 
-typedef void (*ForPointFunc)(PEData *data, int point_index);
-typedef void (*ForKeyFunc)(PEData *data, int point_index, int key_index);
-typedef void (*ForKeyMatFunc)(PEData *data, float mat[][4], float imat[][4], int point_index, int key_index, PTCacheEditKey *key);
+typedef void (*ForParticleFunc)(PEData *data, int pa_index);
+typedef void (*ForKeyFunc)(PEData *data, int pa_index, int key_index);
+typedef void (*ForKeyMatFunc)(PEData *data, float mat[][4], float imat[][4], int pa_index, int key_index);
 
 static void for_mouse_hit_keys(PEData *data, ForKeyFunc func, int nearest)
 {
+       ParticleSystem *psys= data->psys;
+       ParticleEdit *edit= psys->edit;
+       ParticleData *pa;
+       ParticleEditKey *key;
        ParticleEditSettings *pset= PE_settings(data->scene);
-       PTCacheEdit *edit= data->edit;
-       POINT_P; KEY_K;
-       int nearest_point, nearest_key;
+       int i, k, totpart, nearest_pa, nearest_key;
        float dist= data->rad;
 
        /* in path select mode we have no keys */
        if(pset->selectmode==SCE_SELECT_PATH)
                return;
 
-       nearest_point= -1;
+       totpart= psys->totpart;
+       nearest_pa= -1;
        nearest_key= -1;
 
-       LOOP_VISIBLE_POINTS {
+       LOOP_PARTICLES(i, pa) {
+               if(pa->flag & PARS_HIDE) continue;
+
                if(pset->selectmode == SCE_SELECT_END) {
                        /* only do end keys */
-                       key= point->keys + point->totkey-1;
+                       key= edit->keys[i] + pa->totkey-1;
 
                        if(nearest) {
-                               if(key_inside_circle(data, dist, KEY_WCO, &dist)) {
-                                       nearest_point= p;
-                                       nearest_key= point->totkey-1;
+                               if(key_inside_circle(data, dist, key->world_co, &dist)) {
+                                       nearest_pa= i;
+                                       nearest_key= pa->totkey-1;
                                }
                        }
-                       else if(key_inside_test(data, KEY_WCO))
-                               func(data, p, point->totkey-1);
+                       else if(key_inside_test(data, key->world_co))
+                               func(data, i, pa->totkey-1);
                }
                else {
                        /* do all keys */
-                       LOOP_VISIBLE_KEYS {
+                       key= edit->keys[i];
+
+                       LOOP_KEYS(k, key) {
+                               if(key->flag & PEK_HIDE) continue;
+
                                if(nearest) {
-                                       if(key_inside_circle(data, dist, KEY_WCO, &dist)) {
-                                               nearest_point= p;
+                                       if(key_inside_circle(data, dist, key->world_co, &dist)) {
+                                               nearest_pa= i;
                                                nearest_key= k;
                                        }
                                }
-                               else if(key_inside_test(data, KEY_WCO))
-                                       func(data, p, k);
+                               else if(key_inside_test(data, key->world_co))
+                                       func(data, i, k);
                        }
                }
        }
 
        /* do nearest only */
-       if(nearest && nearest_point > -1)
-               func(data, nearest_point, nearest_key);
+       if(nearest && nearest_pa > -1)
+               func(data, nearest_pa, nearest_key);
 }
 
-static void foreach_mouse_hit_point(PEData *data, ForPointFunc func, int selected)
+static void foreach_mouse_hit_particle(PEData *data, ForParticleFunc func, int selected)
 {
+       ParticleSystem *psys= data->psys;
+       ParticleData *pa;
+       ParticleEditKey *key;
        ParticleEditSettings *pset= PE_settings(data->scene);
-       PTCacheEdit *edit= data->edit;
-       POINT_P; KEY_K;
+       int i, k, totpart;
+
+       totpart= psys->totpart;
 
        /* all is selected in path mode */
        if(pset->selectmode==SCE_SELECT_PATH)
                selected=0;
 
-       LOOP_VISIBLE_POINTS {
+       LOOP_PARTICLES(i, pa) {
+               if(pa->flag & PARS_HIDE) continue;
+
                if(pset->selectmode==SCE_SELECT_END) {
                        /* only do end keys */
-                       key= point->keys + point->totkey - 1;
+                       key= psys->edit->keys[i] + pa->totkey-1;
 
                        if(selected==0 || key->flag & PEK_SELECT)
-                               if(key_inside_circle(data, data->rad, KEY_WCO, &data->dist))
-                                       func(data, p);
+                               if(key_inside_circle(data, data->rad, key->world_co, &data->dist))
+                                       func(data, i);
                }
                else {
                        /* do all keys */
-                       LOOP_VISIBLE_KEYS {
+                       LOOP_KEYS(k, key) {
+                               if(key->flag & PEK_HIDE) continue;
+
                                if(selected==0 || key->flag & PEK_SELECT) {
-                                       if(key_inside_circle(data, data->rad, KEY_WCO, &data->dist)) {
-                                               func(data, p);
+                                       if(key_inside_circle(data, data->rad, key->world_co, &data->dist)) {
+                                               func(data, i);
                                                break;
                                        }
                                }
@@ -539,15 +513,16 @@ static void foreach_mouse_hit_point(PEData *data, ForPointFunc func, int selecte
 
 static void foreach_mouse_hit_key(PEData *data, ForKeyMatFunc func, int selected)
 {
-       PTCacheEdit *edit = data->edit;
-       ParticleSystem *psys = edit->psys;
-       ParticleSystemModifierData *psmd = NULL;
+       ParticleSystem *psys= data->psys;
+       ParticleData *pa;
+       ParticleEditKey *key;
+       ParticleSystemModifierData *psmd=0;
        ParticleEditSettings *pset= PE_settings(data->scene);
-       POINT_P; KEY_K;
+       int i, k, totpart;
        float mat[4][4], imat[4][4];
 
-       if(edit->psys)
-               psmd= psys_get_modifier(data->ob, edit->psys);
+       psmd= psys_get_modifier(data->ob,psys);
+       totpart= psys->totpart;
 
        /* all is selected in path mode */
        if(pset->selectmode==SCE_SELECT_PATH)
@@ -556,77 +531,99 @@ static void foreach_mouse_hit_key(PEData *data, ForKeyMatFunc func, int selected
        Mat4One(imat);
        Mat4One(mat);
 
-       LOOP_VISIBLE_POINTS {
-               if(edit->psys) {
-                       psys_mat_hair_to_global(data->ob, psmd->dm, psys->part->from, psys->particles + p, mat);
-                       Mat4Invert(imat,mat);
-               }
+       LOOP_PARTICLES(i, pa) {
+               if(pa->flag & PARS_HIDE) continue;
+
+               psys_mat_hair_to_global(data->ob, psmd->dm, psys->part->from, pa, mat);
+               Mat4Invert(imat,mat);
 
                if(pset->selectmode==SCE_SELECT_END) {
                        /* only do end keys */
-                       key= point->keys + point->totkey-1;
+                       key= psys->edit->keys[i] + pa->totkey-1;
 
                        if(selected==0 || key->flag & PEK_SELECT)
-                               if(key_inside_circle(data, data->rad, KEY_WCO, &data->dist))
-                                       func(data, mat, imat, p, point->totkey-1, key);
+                               if(key_inside_circle(data, data->rad, key->world_co, &data->dist))
+                                       func(data, mat, imat, i, pa->totkey-1);
                }
                else {
                        /* do all keys */
-                       LOOP_VISIBLE_KEYS {
+                       LOOP_KEYS(k, key) {
+                               if(key->flag&PEK_HIDE) continue;
+
                                if(selected==0 || key->flag & PEK_SELECT)
-                                       if(key_inside_circle(data, data->rad, KEY_WCO, &data->dist))
-                                               func(data, mat, imat, p, k, key);
+                                       if(key_inside_circle(data, data->rad, key->world_co, &data->dist))
+                                               func(data, mat, imat, i, k);
                        }
                }
        }
 }
 
-static void foreach_selected_point(PEData *data, ForPointFunc func)
+static void foreach_selected_particle(PEData *data, ForParticleFunc func)
 {
-       PTCacheEdit *edit = data->edit;
-       POINT_P;
+       ParticleSystem *psys= data->psys;
+       ParticleData *pa;
+       int i, totpart;
 
-       LOOP_SELECTED_POINTS {
-               func(data, p);
-       }
+       totpart= psys->totpart;
+
+       LOOP_PARTICLES(i, pa)
+               if(particle_is_selected(psys, pa))
+                       func(data, i);
 }
 
 static void foreach_selected_key(PEData *data, ForKeyFunc func)
 {
-       PTCacheEdit *edit = data->edit;
-       POINT_P; KEY_K;
+       ParticleSystem *psys= data->psys;
+       ParticleData *pa;
+       ParticleEditKey *key;
+       int i, k, totpart;
 
-       LOOP_VISIBLE_POINTS {
-               LOOP_SELECTED_KEYS {
-                       func(data, p, k);
-               }
+       totpart= psys->totpart;
+
+       LOOP_PARTICLES(i, pa) {
+               if(pa->flag & PARS_HIDE) continue;
+
+               key= psys->edit->keys[i];
+
+               LOOP_KEYS(k, key)
+                       if(key->flag & PEK_SELECT)
+                               func(data, i, k);
        }
 }
 
-static void foreach_point(PEData *data, ForPointFunc func)
+void PE_foreach_particle(PEData *data, ForParticleFunc func)
 {
-       PTCacheEdit *edit = data->edit;
-       POINT_P;
+       ParticleSystem *psys= data->psys;
+       int i, totpart;
 
-       LOOP_POINTS { 
-               func(data, p);
-       }
+       totpart= psys->totpart;
+
+       for(i=0; i<totpart; i++)
+               func(data, i);
 }
 
-static int count_selected_keys(Scene *scene, PTCacheEdit *edit)
+static int count_selected_keys(Scene *scene, ParticleSystem *psys)
 {
+       ParticleData *pa;
+       ParticleEditKey *key;
        ParticleEditSettings *pset= PE_settings(scene);
-       POINT_P; KEY_K;
-       int sel= 0;
+       int i, k, totpart, sel= 0;
+
+       totpart= psys->totpart;
+
+       LOOP_PARTICLES(i, pa) {
+               if(pa->flag & PARS_HIDE) continue;
+
+               key= psys->edit->keys[i];
 
-       LOOP_VISIBLE_POINTS {
                if(pset->selectmode==SCE_SELECT_POINT) {
-                       LOOP_SELECTED_KEYS {
-                               sel++;
-                       }
+                       for(k=0; k<pa->totkey; k++,key++)
+                               if(key->flag & PEK_SELECT)
+                                       sel++;
                }
                else if(pset->selectmode==SCE_SELECT_END) {
-                       key = point->keys + point->totkey - 1;
+                       key += pa->totkey-1;
+
                        if(key->flag & PEK_SELECT)
                                sel++;
                }
@@ -641,7 +638,7 @@ static int count_selected_keys(Scene *scene, PTCacheEdit *edit)
 
 static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys)
 {
-       PTCacheEdit *edit;
+       ParticleEdit *edit;
        ParticleData *pa;
        ParticleSystemModifierData *psmd;
        KDTree *tree;
@@ -699,9 +696,8 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys)
 static void PE_mirror_particle(Object *ob, DerivedMesh *dm, ParticleSystem *psys, ParticleData *pa, ParticleData *mpa)
 {
        HairKey *hkey, *mhkey;
-       PTCacheEditPoint *point, *mpoint;
-       PTCacheEditKey *key, *mkey;
-       PTCacheEdit *edit;
+       ParticleEditKey *key, *mkey;
+       ParticleEdit *edit;
        float mat[4][4], mmat[4][4], immat[4][4];
        int i, mi, k;
 
@@ -721,20 +717,17 @@ static void PE_mirror_particle(Object *ob, DerivedMesh *dm, ParticleSystem *psys
        else
                mi= mpa - psys->particles;
 
-       point = edit->points + i;
-       mpoint = edit->points + mi;
-
        /* make sure they have the same amount of keys */
        if(pa->totkey != mpa->totkey) {
                if(mpa->hair) MEM_freeN(mpa->hair);
-               if(mpoint->keys) MEM_freeN(mpoint->keys);
+               if(edit->keys[mi]) MEM_freeN(edit->keys[mi]);
 
                mpa->hair= MEM_dupallocN(pa->hair);
-               mpoint->keys= MEM_dupallocN(point->keys);
-               mpoint->totkey= point->totkey;
+               edit->keys[mi]= MEM_dupallocN(edit->keys[i]);
+               mpa->totkey= pa->totkey;
 
                mhkey= mpa->hair;
-               mkey= mpoint->keys;
+               mkey= edit->keys[mi];
                for(k=0; k<mpa->totkey; k++, mkey++, mhkey++) {
                        mkey->co= mhkey->co;
                        mkey->time= &mhkey->time;
@@ -749,8 +742,8 @@ static void PE_mirror_particle(Object *ob, DerivedMesh *dm, ParticleSystem *psys
 
        hkey=pa->hair;
        mhkey=mpa->hair;
-       key= point->keys;
-       mkey= mpoint->keys;
+       key= edit->keys[i];
+       mkey= edit->keys[mi];
        for(k=0; k<pa->totkey; k++, hkey++, mhkey++, key++, mkey++) {
                VECCOPY(mhkey->co, hkey->co);
                Mat4MulVecfl(mat, mhkey->co);
@@ -761,172 +754,199 @@ static void PE_mirror_particle(Object *ob, DerivedMesh *dm, ParticleSystem *psys
                        mkey->flag |= PEK_TAG;
        }
 
-       if(point->flag & PEP_TAG)
-               mpoint->flag |= PEP_TAG;
-       if(point->flag & PEP_EDIT_RECALC)
-               mpoint->flag |= PEP_EDIT_RECALC;
+       if(pa->flag & PARS_TAG)
+               mpa->flag |= PARS_TAG;
+       if(pa->flag & PARS_EDIT_RECALC)
+               mpa->flag |= PARS_EDIT_RECALC;
 }
 
 static void PE_apply_mirror(Object *ob, ParticleSystem *psys)
 {
-       PTCacheEdit *edit;
+       ParticleEdit *edit;
+       ParticleData *pa;
        ParticleSystemModifierData *psmd;
-       POINT_P;
-
-       if(!psys)
-               return;
+       int i, totpart;
 
        edit= psys->edit;
        psmd= psys_get_modifier(ob, psys);
+       totpart= psys->totpart;
 
        /* we delay settings the PARS_EDIT_RECALC for mirrored particles
         * to avoid doing mirror twice */
-       LOOP_POINTS {
-               if(point->flag & PEP_EDIT_RECALC) {
-                       PE_mirror_particle(ob, psmd->dm, psys, psys->particles + p, NULL);
+       LOOP_PARTICLES(i, pa) {
+               if(pa->flag & PARS_EDIT_RECALC) {
+                       PE_mirror_particle(ob, psmd->dm, psys, pa, NULL);
 
-                       if(edit->mirror_cache[p] != -1)
-                               edit->points[edit->mirror_cache[p]].flag &= ~PEP_EDIT_RECALC;
+                       if(edit->mirror_cache[i] != -1)
+                               psys->particles[edit->mirror_cache[i]].flag &= ~PARS_EDIT_RECALC;
                }
        }
 
-       LOOP_POINTS {
-               if(point->flag & PEP_EDIT_RECALC)
-                       if(edit->mirror_cache[p] != -1)
-                               edit->points[edit->mirror_cache[p]].flag |= PEP_EDIT_RECALC;
-       }
+       LOOP_PARTICLES(i, pa)
+               if(pa->flag & PARS_EDIT_RECALC)
+                       if(edit->mirror_cache[i] != -1)
+                               psys->particles[edit->mirror_cache[i]].flag |= PARS_EDIT_RECALC;
+
+       edit->totkeys= psys_count_keys(psys);
 }
 
 /************************************************/
 /*                     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)
+static void pe_deflect_emitter(Scene *scene, Object *ob, ParticleSystem *psys)
 {
+       ParticleEdit *edit;
+       ParticleData *pa;
+       ParticleEditKey *key;
        ParticleEditSettings *pset= PE_settings(scene);
-       ParticleSystem *psys;
-       ParticleSystemModifierData *psmd;
-       POINT_P; KEY_K;
-       int index;
+       ParticleSystemModifierData *psmd= psys_get_modifier(ob,psys);
+       int i, k, totpart,index;
        float *vec, *nor, dvec[3], dot, dist_1st;
        float hairimat[4][4], hairmat[4][4];
 
-       if(edit==NULL || edit->psys==NULL || (pset->flag & PE_DEFLECT_EMITTER)==0)
+       if(psys==0)
                return;
 
-       psys = edit->psys;
-       psmd = psys_get_modifier(ob,psys);
+       if((pset->flag & PE_DEFLECT_EMITTER)==0)
+               return;
 
-       LOOP_EDITED_POINTS {
-               psys_mat_hair_to_object(ob, psmd->dm, psys->part->from, psys->particles + p, hairmat);
-       
-               LOOP_KEYS {
+       edit= psys->edit;
+       totpart= psys->totpart;
+
+       LOOP_PARTICLES(i, pa) {
+               if(!(pa->flag & PARS_EDIT_RECALC))
+                       continue;
+               
+               psys_mat_hair_to_object(ob, psmd->dm, psys->part->from, pa, hairmat);
+               
+               LOOP_KEYS(k, key) {
                        Mat4MulVecfl(hairmat, key->co);
                }
+       //}
 
-               LOOP_KEYS {
-                       if(k==0) {
-                               dist_1st = VecLenf((key+1)->co, key->co);
-                               dist_1st *= 0.75f * pset->emitterdist;
-                       }
-                       else {
-                               index= BLI_kdtree_find_nearest(edit->emitter_field,key->co,NULL,NULL);
-                               
-                               vec=edit->emitter_cosnos +index*6;
-                               nor=vec+3;
+       //LOOP_PARTICLES(i, pa) {
+               key=psys->edit->keys[i]+1;
 
-                               VecSubf(dvec, key->co, vec);
+               dist_1st=VecLenf((key-1)->co,key->co);
+               dist_1st*=0.75f*pset->emitterdist;
 
-                               dot=Inpf(dvec,nor);
-                               VECCOPY(dvec,nor);
+               for(k=1; k<pa->totkey; k++, key++) {
+                       index= BLI_kdtree_find_nearest(edit->emitter_field,key->co,NULL,NULL);
+                       
+                       vec=edit->emitter_cosnos +index*6;
+                       nor=vec+3;
 
-                               if(dot>0.0f) {
-                                       if(dot<dist_1st) {
-                                               Normalize(dvec);
-                                               VecMulf(dvec,dist_1st-dot);
-                                               VecAddf(key->co,key->co,dvec);
-                                       }
-                               }
-                               else {
+                       VecSubf(dvec, key->co, vec);
+
+                       dot=Inpf(dvec,nor);
+                       VECCOPY(dvec,nor);
+
+                       if(dot>0.0f) {
+                               if(dot<dist_1st) {
                                        Normalize(dvec);
                                        VecMulf(dvec,dist_1st-dot);
                                        VecAddf(key->co,key->co,dvec);
                                }
-                               if(k==1)
-                                       dist_1st*=1.3333f;
                        }
+                       else {
+                               Normalize(dvec);
+                               VecMulf(dvec,dist_1st-dot);
+                               VecAddf(key->co,key->co,dvec);
+                       }
+                       if(k==1)
+                               dist_1st*=1.3333f;
                }
+       //}
+
+       //LOOP_PARTICLES(i, pa) {
                
                Mat4Invert(hairimat,hairmat);
 
-               LOOP_KEYS {
+               LOOP_KEYS(k, key) {
                        Mat4MulVecfl(hairimat, key->co);
                }
        }
 }
 /* force set distances between neighbouring keys */
-void PE_apply_lengths(Scene *scene, PTCacheEdit *edit)
+void PE_apply_lengths(Scene *scene, ParticleSystem *psys)
 {
-       
+       ParticleEdit *edit;
+       ParticleData *pa;
+       ParticleEditKey *key;
        ParticleEditSettings *pset=PE_settings(scene);
-       POINT_P; KEY_K;
+       int i, k, totpart;
        float dv1[3];
 
-       if(edit==0 || (pset->flag & PE_KEEP_LENGTHS)==0)
+       if(psys==0)
                return;
 
-       LOOP_EDITED_POINTS {
-               LOOP_KEYS {
-                       if(k) {
-                               VecSubf(dv1, key->co, (key - 1)->co);
-                               Normalize(dv1);
-                               VecMulf(dv1, (key - 1)->length);
-                               VecAddf(key->co, (key - 1)->co, dv1);
-                       }
+       if((pset->flag & PE_KEEP_LENGTHS)==0)
+               return;
+
+       edit= psys->edit;
+       totpart= psys->totpart;
+
+       LOOP_PARTICLES(i, pa) {
+               if(!(pa->flag & PARS_EDIT_RECALC))
+                       continue;
+               
+               for(k=1, key=edit->keys[i] + 1; k<pa->totkey; k++, key++) {
+                       VecSubf(dv1, key->co, (key - 1)->co);
+                       Normalize(dv1);
+                       VecMulf(dv1, (key - 1)->length);
+                       VecAddf(key->co, (key - 1)->co, dv1);
                }
        }
 }
 /* try to find a nice solution to keep distances between neighbouring keys */
-static void pe_iterate_lengths(Scene *scene, PTCacheEdit *edit)
+static void pe_iterate_lengths(Scene *scene, ParticleSystem *psys)
 {
+       ParticleEdit *edit;
+       ParticleData *pa;
+       ParticleEditKey *key;
        ParticleEditSettings *pset=PE_settings(scene);
-       POINT_P;
-       PTCacheEditKey *key;
-       int j, k;
+       int i, j, k, totpart;
        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)
+       if(psys==0)
                return;
 
        if((pset->flag & PE_KEEP_LENGTHS)==0)
                return;
 
-       LOOP_EDITED_POINTS {
-               for(j=1; j<point->totkey; j++) {
-                       float mul= 1.0f / (float)point->totkey;
+       edit= psys->edit;
+       totpart= psys->totpart;
+
+       LOOP_PARTICLES(i, pa) {
+               if(!(pa->flag & PARS_EDIT_RECALC))
+                       continue;
+
+               for(j=1; j<pa->totkey; j++) {
+                       float mul= 1.0f / (float)pa->totkey;
 
                        if(pset->flag & PE_LOCK_FIRST) {
-                               key= point->keys + 1;
+                               key= edit->keys[i] + 1;
                                k= 1;
                                dv1[0]= dv1[1]= dv1[2]= 0.0;
                        }
                        else {
-                               key= point->keys;
+                               key= edit->keys[i];
                                k= 0;
                                dv0[0]= dv0[1]= dv0[2]= 0.0;
                        }
 
-                       for(; k<point->totkey; k++, key++) {
+                       for(; k<pa->totkey; k++, key++) {
                                if(k) {
                                        VecSubf(dv0, (key - 1)->co, key->co);
                                        tlen= Normalize(dv0);
                                        VecMulf(dv0, (mul * (tlen - (key - 1)->length)));
                                }
 
-                               if(k < point->totkey - 1) {
+                               if(k < pa->totkey - 1) {
                                        VecSubf(dv2, (key + 1)->co, key->co);
                                        tlen= Normalize(dv2);
                                        VecMulf(dv2, mul * (tlen - key->length));
@@ -942,16 +962,20 @@ static void pe_iterate_lengths(Scene *scene, PTCacheEdit *edit)
        }
 }
 /* set current distances to be kept between neighbouting keys */
-static void recalc_lengths(PTCacheEdit *edit)
+static void recalc_lengths(ParticleSystem *psys)
 {
-       POINT_P; KEY_K;
+       ParticleData *pa;
+       ParticleEditKey *key;
+       int i, k, totpart;
 
-       if(edit==0)
+       if(psys==0)
                return;
 
-       LOOP_EDITED_POINTS {
-               key= point->keys;
-               for(k=0; k<point->totkey-1; k++, key++) {
+       totpart= psys->totpart;
+
+       LOOP_PARTICLES(i, pa) {
+               key= psys->edit->keys[i];
+               for(k=0; k<pa->totkey-1; k++, key++) {
                        key->length= VecLenf(key->co, (key + 1)->co);
                }
        }
@@ -961,7 +985,7 @@ static void recalc_lengths(PTCacheEdit *edit)
 static void recalc_emitter_field(Object *ob, ParticleSystem *psys)
 {
        DerivedMesh *dm=psys_get_modifier(ob,psys)->dm;
-       PTCacheEdit *edit= psys->edit;
+       ParticleEdit *edit= psys->edit;
        MFace *mface;
        MVert *mvert;
        float *vec, *nor;
@@ -1018,145 +1042,74 @@ static void recalc_emitter_field(Object *ob, ParticleSystem *psys)
 
 static void PE_update_selection(Scene *scene, Object *ob, int useflag)
 {
+       ParticleSystem *psys= PE_get_current(scene, ob);
+       ParticleEdit *edit= psys->edit;
        ParticleEditSettings *pset= PE_settings(scene);
-       PTCacheEdit *edit= PE_get_current(scene, ob);
+       ParticleSettings *part= psys->part;
+       ParticleData *pa;
        HairKey *hkey;
-       POINT_P; KEY_K;
+       ParticleEditKey *key;
+       float cfra= CFRA;
+       int i, k, totpart;
+
+       totpart= psys->totpart;
 
        /* flag all particles to be updated if not using flag */
        if(!useflag)
-               LOOP_POINTS
-                       point->flag |= PEP_EDIT_RECALC;
+               LOOP_PARTICLES(i, pa)
+                       pa->flag |= PARS_EDIT_RECALC;
 
        /* 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 {
+       LOOP_PARTICLES(i, pa) {
+               key= edit->keys[i];
+
+               for(k=0, hkey=pa->hair; k<pa->totkey; k++, hkey++, key++)
                        hkey->editflag= key->flag;
-                       hkey++;
-               }
        }
 
-       psys_cache_edit_paths(scene, ob, edit, CFRA);
+       psys_cache_paths(scene, ob, psys, CFRA, 1);
 
+       if(part->childtype && (pset->flag & PE_SHOW_CHILD))
+               psys_cache_child_paths(scene, ob, psys, cfra, 1);
 
        /* disable update flag */
-       LOOP_POINTS
-               point->flag &= ~PEP_EDIT_RECALC;
+       LOOP_PARTICLES(i, pa)
+               pa->flag &= ~PARS_EDIT_RECALC;
 }
 
-static void update_world_cos(Object *ob, PTCacheEdit *edit)
-{
-       ParticleSystem *psys = edit->psys;
-       ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys);
-       POINT_P; KEY_K;
-       float hairmat[4][4];
-
-       if(psys==0 || psys->edit==0)
-               return;
-
-       LOOP_POINTS {
-               psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, psys->particles+p, hairmat);
-
-               LOOP_KEYS {
-                       VECCOPY(key->world_co,key->co);
-                       Mat4MulVecfl(hairmat, key->world_co);
-               }
-       }
-}
-static void update_velocities(Object *ob, PTCacheEdit *edit)
-{
-       /*TODO: get frs_sec properly */
-       float vec1[3], vec2[3], frs_sec, dfra;
-       POINT_P; KEY_K;
-
-       /* hair doesn't use velocities */
-       if(edit->psys || !edit->points || !edit->points->keys->vel)
-               return;
-
-       frs_sec = edit->pid.flag & PTCACHE_VEL_PER_SEC ? 25.0f : 1.0f;
-
-       LOOP_EDITED_POINTS {
-               LOOP_KEYS {
-                       if(k==0) {
-                               dfra = *(key+1)->time - *key->time;
-
-                               if(dfra <= 0.0f)
-                                       continue;
-
-                               VECSUB(key->vel, (key+1)->co, key->co);
-
-                               if(point->totkey>2) {
-                                       VECSUB(vec1, (key+1)->co, (key+2)->co);
-                                       Projf(vec2, vec1, key->vel);
-                                       VECSUB(vec2, vec1, vec2);
-                                       VECADDFAC(key->vel, key->vel, vec2, 0.5f);
-                               }
-                       }
-                       else if(k==point->totkey-1) {
-                               dfra = *key->time - *(key-1)->time;
-
-                               if(dfra <= 0.0f)
-                                       continue;
-
-                               VECSUB(key->vel, key->co, (key-1)->co);
-
-                               if(point->totkey>2) {
-                                       VECSUB(vec1, (key-2)->co, (key-1)->co);
-                                       Projf(vec2, vec1, key->vel);
-                                       VECSUB(vec2, vec1, vec2);
-                                       VECADDFAC(key->vel, key->vel, vec2, 0.5f);
-                               }
-                       }
-                       else {
-                               dfra = *(key+1)->time - *(key-1)->time;
-                               
-                               if(dfra <= 0.0f)
-                                       continue;
-
-                               VECSUB(key->vel, (key+1)->co, (key-1)->co);
-                       }
-                       VecMulf(key->vel, frs_sec/dfra);
-               }
-       }
-}
 void PE_update_object(Scene *scene, Object *ob, int useflag)
 {
+       ParticleSystem *psys= PE_get_current(scene, ob);
        ParticleEditSettings *pset= PE_settings(scene);
-       PTCacheEdit *edit = PE_get_current(scene, ob);
-       POINT_P;
-
-       if(!edit)
-               return;
+       ParticleSettings *part= psys->part;
+       ParticleData *pa;
+       float cfra= CFRA;
+       int i, totpart= psys->totpart;
 
        /* flag all particles to be updated if not using flag */
        if(!useflag)
-               LOOP_POINTS {
-                       point->flag |= PEP_EDIT_RECALC;
-               }
+               LOOP_PARTICLES(i, pa)
+                       pa->flag |= PARS_EDIT_RECALC;
 
        /* do post process on particle edit keys */
-       pe_iterate_lengths(scene, edit);
-       pe_deflect_emitter(scene, ob, edit);
-       PE_apply_lengths(scene, edit);
+       pe_iterate_lengths(scene, psys);
+       pe_deflect_emitter(scene, ob, psys);
+       PE_apply_lengths(scene, psys);
        if(pset->flag & PE_X_MIRROR)
-               PE_apply_mirror(ob,edit->psys);
-       if(edit->psys)
-               update_world_cos(ob, edit);
-       if(pset->flag & PE_AUTO_VELOCITY)
-               update_velocities(ob, edit);
-       PE_hide_keys_time(scene, edit, CFRA);
+               PE_apply_mirror(ob,psys);
+       psys_update_world_cos(ob,psys);
+       PE_hide_keys_time(scene, psys, cfra);
 
        /* regenerate path caches */
-       psys_cache_edit_paths(scene, ob, edit, CFRA);
+       psys_cache_paths(scene, ob, psys, cfra, 1);
 
-       /* disable update flag */
-       LOOP_POINTS {
-               point->flag &= ~PEP_EDIT_RECALC;
-       }
+       if(part->childtype && (pset->flag & PE_SHOW_CHILD))
+               psys_cache_child_paths(scene, ob, psys, cfra, 1);
 
-       DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+       /* disable update flag */
+       LOOP_PARTICLES(i, pa)
+               pa->flag &= ~PARS_EDIT_RECALC;
 }
 
 /************************************************/
@@ -1165,44 +1118,48 @@ void PE_update_object(Scene *scene, Object *ob, int useflag)
 
 /*-----selection callbacks-----*/
 
-static void select_key(PEData *data, int point_index, int key_index)
+static void select_key(PEData *data, int pa_index, int key_index)
 {
-       PTCacheEdit *edit = data->edit;
-       PTCacheEditPoint *point = edit->points + point_index;
-       PTCacheEditKey *key = point->keys + key_index;
+       ParticleSystem *psys= data->psys;
+       ParticleData *pa= psys->particles + pa_index;
+       ParticleEditKey *key= psys->edit->keys[pa_index] + key_index;
 
        if(data->select)
                key->flag |= PEK_SELECT;
        else
                key->flag &= ~PEK_SELECT;
 
-       point->flag |= PEP_EDIT_RECALC;
+       pa->flag |= PARS_EDIT_RECALC;
 }
 
-static void select_keys(PEData *data, int point_index, int key_index)
+static void select_keys(PEData *data, int pa_index, int key_index)
 {
-       PTCacheEdit *edit = data->edit;
-       PTCacheEditPoint *point = edit->points + point_index;
-       KEY_K;
+       ParticleSystem *psys= data->psys;
+       ParticleData *pa= psys->particles + pa_index;
+       ParticleEditKey *key= psys->edit->keys[pa_index];
+       int k;
 
-       LOOP_KEYS {
+       for(k=0; k<pa->totkey; k++,key++) {
                if(data->select)
                        key->flag |= PEK_SELECT;
                else
                        key->flag &= ~PEK_SELECT;
        }
 
-       point->flag |= PEP_EDIT_RECALC;
+       pa->flag |= PARS_EDIT_RECALC;
 }
 
-static void toggle_key_select(PEData *data, int point_index, int key_index)
+static void toggle_key_select(PEData *data, int pa_index, int key_index)
 {
-       PTCacheEdit *edit = data->edit;
-       PTCacheEditPoint *point = edit->points + point_index;
-       PTCacheEditKey *key = point->keys + key_index;
+       ParticleSystem *psys= data->psys;
+       ParticleData *pa= psys->particles + pa_index;
 
-       key->flag ^= PEK_SELECT;
-       point->flag |= PEP_EDIT_RECALC;
+       if(psys->edit->keys[pa_index][key_index].flag&PEK_SELECT)
+               psys->edit->keys[pa_index][key_index].flag &= ~PEK_SELECT;
+       else
+               psys->edit->keys[pa_index][key_index].flag |= PEK_SELECT;
+       
+       pa->flag |= PARS_EDIT_RECALC;
 }
 
 /************************ de select all operator ************************/
@@ -1211,24 +1168,33 @@ static int de_select_all_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);
-       POINT_P; KEY_K;
-       int sel= 0;
+       ParticleSystem *psys= PE_get_current(scene, ob);
+       ParticleEdit *edit= 0;
+       ParticleData *pa;
+       ParticleEditKey *key;
+       int i, k, totpart, sel= 0;
        
-       LOOP_VISIBLE_POINTS {
-               LOOP_SELECTED_KEYS {
-                       sel= 1;
-                       key->flag &= ~PEK_SELECT;
-                       point->flag |= PEP_EDIT_RECALC;
+       edit= psys->edit;
+       totpart= psys->totpart;
+       
+       LOOP_PARTICLES(i, pa) {
+               if(pa->flag & PARS_HIDE) continue;
+               LOOP_KEYS(k, key) {
+                       if(key->flag & PEK_SELECT) {
+                               sel= 1;
+                               key->flag &= ~PEK_SELECT;
+                               pa->flag |= PARS_EDIT_RECALC;
+                       }
                }
        }
 
        if(sel==0) {
-               LOOP_VISIBLE_POINTS {
-                       LOOP_KEYS {
+               LOOP_PARTICLES(i, pa) {
+                       if(pa->flag & PARS_HIDE) continue;
+                       LOOP_KEYS(k, key) {
                                if(!(key->flag & PEK_SELECT)) {
                                        key->flag |= PEK_SELECT;
-                                       point->flag |= PEP_EDIT_RECALC;
+                                       pa->flag |= PARS_EDIT_RECALC;
                                }
                        }
                }
@@ -1261,17 +1227,26 @@ int PE_mouse_particles(bContext *C, short *mval, int extend)
        PEData data;
        Scene *scene= CTX_data_scene(C);
        Object *ob= CTX_data_active_object(C);
-       PTCacheEdit *edit= PE_get_current(scene, ob);
-       POINT_P; KEY_K;
+       ParticleSystem *psys= PE_get_current(scene, ob);
+       ParticleEdit *edit= 0;
+       ParticleData *pa;
+       ParticleEditKey *key;
+       int i, k, totpart;
        
-       if(!PE_start_edit(edit))
+       if(!PE_can_edit(psys))
                return OPERATOR_CANCELLED;
 
+       edit= psys->edit;
+       totpart= psys->totpart;
+
        if(!extend) {
-               LOOP_VISIBLE_POINTS {
-                       LOOP_SELECTED_KEYS {
-                               key->flag &= ~PEK_SELECT;
-                               point->flag |= PEP_EDIT_RECALC;
+               LOOP_PARTICLES(i, pa) {
+                       if(pa->flag & PARS_HIDE) continue;
+                       LOOP_KEYS(k, key) {
+                               if(key->flag & PEK_SELECT) {
+                                       key->flag &= ~PEK_SELECT;
+                                       pa->flag |= PARS_EDIT_RECALC;
+                               }
                        }
                }
        }
@@ -1290,9 +1265,11 @@ int PE_mouse_particles(bContext *C, short *mval, int extend)
 
 /************************ select first operator ************************/
 
-static void select_root(PEData *data, int point_index)
+static void select_root(PEData *data, int pa_index)
 {
-       data->edit->points[point_index].keys->flag |= PEK_SELECT;
+       ParticleSystem *psys= data->psys;
+
+       psys->edit->keys[pa_index]->flag |= PEK_SELECT;
 }
 
 static int select_first_exec(bContext *C, wmOperator *op)
@@ -1300,7 +1277,7 @@ static int select_first_exec(bContext *C, wmOperator *op)
        PEData data;
 
        PE_set_data(C, &data);
-       foreach_point(&data, select_root);
+       PE_foreach_particle(&data, select_root);
        WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, data.ob);
 
        return OPERATOR_FINISHED;
@@ -1322,10 +1299,13 @@ void PARTICLE_OT_select_first(wmOperatorType *ot)
 
 /************************ select last operator ************************/
 
-static void select_tip(PEData *data, int point_index)
+static void select_tip(PEData *data, int pa_index)
 {
-       PTCacheEditPoint *point = data->edit->points + point_index;
-       point->keys[point->totkey - 1].flag |= PEK_SELECT;
+       ParticleSystem *psys= data->psys;
+       ParticleData *pa= psys->particles + pa_index;
+       ParticleEditKey *key= psys->edit->keys[pa_index] + pa->totkey-1;
+
+       key->flag |= PEK_SELECT;
 }
 
 static int select_last_exec(bContext *C, wmOperator *op)
@@ -1333,7 +1313,7 @@ static int select_last_exec(bContext *C, wmOperator *op)
        PEData data;
 
        PE_set_data(C, &data);
-       foreach_point(&data, select_tip);
+       PE_foreach_particle(&data, select_tip);
        WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, data.ob);
 
        return OPERATOR_FINISHED;
@@ -1416,10 +1396,10 @@ int PE_border_select(bContext *C, rcti *rect, int select)
 {
        Scene *scene= CTX_data_scene(C);
        Object *ob= CTX_data_active_object(C);
-       PTCacheEdit *edit= PE_get_current(scene, ob);
+       ParticleSystem *psys= PE_get_current(scene, ob);
        PEData data;
 
-       if(!PE_start_edit(edit))
+       if(!PE_can_edit(psys))
                return OPERATOR_CANCELLED;
 
        PE_set_view3d_data(C, &data);
@@ -1440,10 +1420,10 @@ int PE_circle_select(bContext *C, int selecting, short *mval, float rad)
 {
        Scene *scene= CTX_data_scene(C);
        Object *ob= CTX_data_active_object(C);
-       PTCacheEdit *edit= PE_get_current(scene, ob);
+       ParticleSystem *psys= PE_get_current(scene, ob);
        PEData data;
 
-       if(!PE_start_edit(edit))
+       if(!PE_can_edit(psys))
                return OPERATOR_FINISHED;
 
        PE_set_view3d_data(C, &data);
@@ -1466,42 +1446,47 @@ int PE_lasso_select(bContext *C, short mcords[][2], short moves, short select)
        Scene *scene= CTX_data_scene(C);
        Object *ob= CTX_data_active_object(C);
        ARegion *ar= CTX_wm_region(C);
+       ParticleSystem *psys= PE_get_current(scene, ob);
+       ParticleSystemModifierData *psmd;
+       ParticleEdit *edit;
+       ParticleData *pa;
+       ParticleEditKey *key;
        ParticleEditSettings *pset= PE_settings(scene);
-       PTCacheEdit *edit = PE_get_current(scene, ob);
-       ParticleSystem *psys = edit->psys;
-       ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys);
-       POINT_P; KEY_K;
        float co[3], mat[4][4];
        short vertco[2];
+       int i, k, totpart;
 
-       if(!PE_start_edit(edit))
+       if(!PE_can_edit(psys))
                return OPERATOR_CANCELLED;
 
-       Mat4One(mat);
+       psmd= psys_get_modifier(ob, psys);
+       edit= psys->edit;
+       totpart= psys->totpart;
+
+       LOOP_PARTICLES(i, pa) {
+               if(pa->flag & PARS_HIDE) continue;
 
-       LOOP_VISIBLE_POINTS {
-               if(edit->psys)
-                       psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, psys->particles + p, mat);
+               psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, mat);
 
                if(pset->selectmode==SCE_SELECT_POINT) {
-                       LOOP_KEYS {
+                       LOOP_KEYS(k, key) {
                                VECCOPY(co, key->co);
                                Mat4MulVecfl(mat, co);
                                project_short(ar, co, vertco);
                                if((vertco[0] != IS_CLIPPED) && lasso_inside(mcords,moves,vertco[0],vertco[1])) {
                                        if(select && !(key->flag & PEK_SELECT)) {
                                                key->flag |= PEK_SELECT;
-                                               point->flag |= PEP_EDIT_RECALC;
+                                               pa->flag |= PARS_EDIT_RECALC;
                                        }
                                        else if(key->flag & PEK_SELECT) {
                                                key->flag &= ~PEK_SELECT;
-                                               point->flag |= PEP_EDIT_RECALC;
+                                               pa->flag |= PARS_EDIT_RECALC;
                                        }
                                }
                        }
                }
                else if(pset->selectmode==SCE_SELECT_END) {
-                       key= point->keys + point->totkey - 1;
+                       key= edit->keys[i] + pa->totkey - 1;
 
                        VECCOPY(co, key->co);
                        Mat4MulVecfl(mat, co);
@@ -1509,11 +1494,11 @@ int PE_lasso_select(bContext *C, short mcords[][2], short moves, short select)
                        if((vertco[0] != IS_CLIPPED) && lasso_inside(mcords,moves,vertco[0],vertco[1])) {
                                if(select && !(key->flag & PEK_SELECT)) {
                                        key->flag |= PEK_SELECT;
-                                       point->flag |= PEP_EDIT_RECALC;
+                                       pa->flag |= PARS_EDIT_RECALC;
                                }
                                else if(key->flag & PEK_SELECT) {
                                        key->flag &= ~PEK_SELECT;
-                                       point->flag |= PEP_EDIT_RECALC;
+                                       pa->flag |= PARS_EDIT_RECALC;
                                }
                        }
                }
@@ -1531,25 +1516,35 @@ static int hide_exec(bContext *C, wmOperator *op)
 {
        Object *ob= CTX_data_active_object(C);
        Scene *scene= CTX_data_scene(C);
-       PTCacheEdit *edit= PE_get_current(scene, ob);
-       POINT_P; KEY_K;
+       ParticleSystem *psys= PE_get_current(scene, ob);
+       ParticleEdit *edit;
+       ParticleEditKey *key;
+       ParticleData *pa;
+       int i, k, totpart;
+
+       edit= psys->edit;
+       totpart= psys->totpart;
        
        if(RNA_enum_get(op->ptr, "unselected")) {
-               LOOP_UNSELECTED_POINTS {
-                       point->flag |= PEP_HIDE;
-                       point->flag |= PEP_EDIT_RECALC;
+               LOOP_PARTICLES(i, pa) {
+                       if(!particle_is_selected(psys, pa)) {
+                               pa->flag |= PARS_HIDE;
+                               pa->flag |= PARS_EDIT_RECALC;
 
-                       LOOP_KEYS
-                               key->flag &= ~PEK_SELECT;
+                               LOOP_KEYS(k, key)
+                                       key->flag &= ~PEK_SELECT;
+                       }
                }
        }
        else {
-               LOOP_SELECTED_POINTS {
-                       point->flag |= PEP_HIDE;
-                       point->flag |= PEP_EDIT_RECALC;
+               LOOP_PARTICLES(i, pa) {
+                       if(particle_is_selected(psys, pa)) {
+                               pa->flag |= PARS_HIDE;
+                               pa->flag |= PARS_EDIT_RECALC;
 
-                       LOOP_KEYS
-                               key->flag &= ~PEK_SELECT;
+                               LOOP_KEYS(k, key)
+                                       key->flag &= ~PEK_SELECT;
+                       }
                }
        }
 
@@ -1582,15 +1577,21 @@ static int reveal_exec(bContext *C, wmOperator *op)
 {
        Object *ob= CTX_data_active_object(C);
        Scene *scene= CTX_data_scene(C);
-       PTCacheEdit *edit= PE_get_current(scene, ob);
-       POINT_P; KEY_K;
+       ParticleSystem *psys= PE_get_current(scene, ob);
+       ParticleEdit *edit;
+       ParticleEditKey *key;
+       ParticleData *pa;
+       int i, k, totpart;
+
+       edit= psys->edit;
+       totpart= psys->totpart;
 
-       LOOP_POINTS {
-               if(point->flag & PEP_HIDE) {
-                       point->flag &= ~PEP_HIDE;
-                       point->flag |= PEP_EDIT_RECALC;
+       LOOP_PARTICLES(i, pa) {
+               if(pa->flag & PARS_HIDE) {
+                       pa->flag &= ~PARS_HIDE;
+                       pa->flag |= PARS_EDIT_RECALC;
 
-                       LOOP_KEYS
+                       LOOP_KEYS(k, key)
                                key->flag |= PEK_SELECT;
                }
        }
@@ -1617,30 +1618,34 @@ void PARTICLE_OT_reveal(wmOperatorType *ot)
 
 /************************ select less operator ************************/
 
-static void select_less_keys(PEData *data, int point_index)
+static void select_less_keys(PEData *data, int pa_index)
 {
-       PTCacheEdit *edit= data->edit;
-       PTCacheEditPoint *point = edit->points + point_index;
-       KEY_K;
+       ParticleSystem *psys= data->psys;
+       ParticleEdit *edit= psys->edit;
+       ParticleData *pa= &psys->particles[pa_index];
+       ParticleEditKey *key;
+       int k;
+
+       for(k=0,key=edit->keys[pa_index]; k<pa->totkey; k++,key++) {
+               if((key->flag & PEK_SELECT)==0) continue;
 
-       LOOP_SELECTED_KEYS {
                if(k==0) {
                        if(((key+1)->flag&PEK_SELECT)==0)
-                               key->flag |= PEK_TAG;
+                               key->flag |= PEK_TO_SELECT;
                }
-               else if(k==point->totkey-1) {
+               else if(k==pa->totkey-1) {
                        if(((key-1)->flag&PEK_SELECT)==0)
-                               key->flag |= PEK_TAG;
+                               key->flag |= PEK_TO_SELECT;
                }
                else {
                        if((((key-1)->flag & (key+1)->flag) & PEK_SELECT)==0)
-                               key->flag |= PEK_TAG;
+                               key->flag |= PEK_TO_SELECT;
                }
        }
 
-       LOOP_KEYS {
-               if(key->flag&PEK_TAG)
-                       key->flag &= ~(PEK_TAG|PEK_SELECT);
+       for(k=0,key=edit->keys[pa_index]; k<pa->totkey; k++,key++) {
+               if(key->flag&PEK_TO_SELECT)
+                       key->flag &= ~(PEK_TO_SELECT|PEK_SELECT);
        }
 }
 
@@ -1649,7 +1654,7 @@ static int select_less_exec(bContext *C, wmOperator *op)
        PEData data;
 
        PE_set_data(C, &data);
-       foreach_point(&data, select_less_keys);
+       PE_foreach_particle(&data, select_less_keys);
        WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, data.ob);
 
        return OPERATOR_FINISHED;
@@ -1671,32 +1676,34 @@ void PARTICLE_OT_select_less(wmOperatorType *ot)
 
 /************************ select more operator ************************/
 
-static void select_more_keys(PEData *data, int point_index)
+static void select_more_keys(PEData *data, int pa_index)
 {
-       PTCacheEdit *edit= data->edit;
-       PTCacheEditPoint *point = edit->points + point_index;
-       KEY_K;
+       ParticleSystem *psys= data->psys;
+       ParticleEdit *edit= psys->edit;
+       ParticleData *pa= &psys->particles[pa_index];
+       ParticleEditKey *key;
+       int k;
 
-       LOOP_KEYS {
+       for(k=0,key=edit->keys[pa_index]; k<pa->totkey; k++,key++) {
                if(key->flag & PEK_SELECT) continue;
 
                if(k==0) {
                        if((key+1)->flag&PEK_SELECT)
-                               key->flag |= PEK_TAG;
+                               key->flag |= PEK_TO_SELECT;
                }
-               else if(k==point->totkey-1) {
+               else if(k==pa->totkey-1) {
                        if((key-1)->flag&PEK_SELECT)
-                               key->flag |= PEK_TAG;
+                               key->flag |= PEK_TO_SELECT;
                }
                else {
                        if(((key-1)->flag | (key+1)->flag) & PEK_SELECT)
-                               key->flag |= PEK_TAG;
+                               key->flag |= PEK_TO_SELECT;
                }
        }
 
-       LOOP_KEYS {
-               if(key->flag&PEK_TAG) {
-                       key->flag &= ~PEK_TAG;
+       for(k=0,key=edit->keys[pa_index]; k<pa->totkey; k++,key++) {
+               if(key->flag&PEK_TO_SELECT) {
+                       key->flag &= ~PEK_TO_SELECT;
                        key->flag |= PEK_SELECT;
                }
        }
@@ -1707,7 +1714,7 @@ static int select_more_exec(bContext *C, wmOperator *op)
        PEData data;
 
        PE_set_data(C, &data);
-       foreach_point(&data, select_more_keys);
+       PE_foreach_particle(&data, select_more_keys);
        WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, data.ob);
 
        return OPERATOR_FINISHED;
@@ -1731,13 +1738,12 @@ void PARTICLE_OT_select_more(wmOperatorType *ot)
 
 static void rekey_particle(PEData *data, int pa_index)
 {
-       PTCacheEdit *edit= data->edit;
-       ParticleSystem *psys= edit->psys;
-       ParticleData *pa= psys->particles + pa_index;
-       PTCacheEditPoint *point = edit->points + pa_index;
+       ParticleSystem *psys= data->psys;
+       ParticleData *pa= &psys->particles[pa_index];
+       ParticleEdit *edit= psys->edit;
        ParticleKey state;
        HairKey *key, *new_keys;
-       PTCacheEditKey *ekey;
+       ParticleEditKey *ekey;
        float dval, sta, end;
        int k;
 
@@ -1766,21 +1772,19 @@ static void rekey_particle(PEData *data, int pa_index)
                MEM_freeN(pa->hair);
        pa->hair= new_keys;
 
-       point->totkey=pa->totkey=data->totrekey;
+       pa->totkey=data->totrekey;
 
-
-       if(point->keys)
-               MEM_freeN(point->keys);
-       ekey= point->keys= MEM_callocN(pa->totkey * sizeof(PTCacheEditKey),"Hair re-key edit keys");
+       if(edit->keys[pa_index])
+               MEM_freeN(edit->keys[pa_index]);
+       ekey= edit->keys[pa_index]= MEM_callocN(pa->totkey * sizeof(ParticleEditKey),"Hair re-key edit keys");
                
        for(k=0, key=pa->hair; k<pa->totkey; k++, key++, ekey++) {
                ekey->co= key->co;
                ekey->time= &key->time;
-               ekey->flag |= PEK_USE_WCO;
        }
 
        pa->flag &= ~PARS_REKEY;
-       point->flag |= PEP_EDIT_RECALC;
+       pa->flag |= PARS_EDIT_RECALC;
 }
 
 static int rekey_exec(bContext *C, wmOperator *op)
@@ -1792,9 +1796,11 @@ static int rekey_exec(bContext *C, wmOperator *op)
        data.dval= 1.0f / (float)(data.totrekey-1);
        data.totrekey= RNA_int_get(op->ptr, "keys");
 
-       foreach_selected_point(&data, rekey_particle);
+       foreach_selected_particle(&data, rekey_particle);
+       
+       data.psys->edit->totkeys= psys_count_keys(data.psys);
+       recalc_lengths(data.psys);
        
-       recalc_lengths(data.edit);
        PE_update_object(data.scene, data.ob, 1);
        WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, data.ob);
 
@@ -1821,19 +1827,19 @@ void PARTICLE_OT_rekey(wmOperatorType *ot)
 
 static void rekey_particle_to_time(Scene *scene, Object *ob, int pa_index, float path_time)
 {
-       PTCacheEdit *edit= PE_get_current(scene, ob);
-       ParticleSystem *psys;
+       ParticleSystem *psys= PE_get_current(scene, ob);
+       ParticleEdit *edit=0;
        ParticleData *pa;
        ParticleKey state;
        HairKey *new_keys, *key;
-       PTCacheEditKey *ekey;
+       ParticleEditKey *ekey;
        int k;
 
-       if(!edit || !edit->psys) return;
+       if(psys==0) return;
 
-       psys = edit->psys;
+       edit= psys->edit;
 
-       pa= psys->particles + pa_index;
+       pa= &psys->particles[pa_index];
 
        pa->flag |= PARS_REKEY;
 
@@ -1852,7 +1858,7 @@ static void rekey_particle_to_time(Scene *scene, Object *ob, int pa_index, float
        pa->hair= new_keys;
 
        /* update edit pointers */
-       for(k=0, key=pa->hair, ekey=edit->points[pa_index].keys; k<pa->totkey; k++, key++, ekey++) {
+       for(k=0, key=pa->hair, ekey=edit->keys[pa_index]; k<pa->totkey; k++, key++, ekey++) {
                ekey->co= key->co;
                ekey->time= &key->time;
        }
@@ -1864,11 +1870,10 @@ static void rekey_particle_to_time(Scene *scene, Object *ob, int pa_index, float
 
 static int remove_tagged_particles(Scene *scene, Object *ob, ParticleSystem *psys)
 {
-       PTCacheEdit *edit = psys->edit;
+       ParticleEdit *edit= psys->edit;
        ParticleEditSettings *pset= PE_settings(scene);
        ParticleData *pa, *npa=0, *new_pars=0;
-       POINT_P;
-       PTCacheEditPoint *npoint=0, *new_points=0;
+       ParticleEditKey **key, **nkey=0, **new_keys=0;
        ParticleSystemModifierData *psmd;
        int i, totpart, new_totpart= psys->totpart, removed= 0;
 
@@ -1877,51 +1882,55 @@ static int remove_tagged_particles(Scene *scene, Object *ob, ParticleSystem *psy
                psmd= psys_get_modifier(ob, psys);
                totpart= psys->totpart;
 
-               LOOP_TAGGED_POINTS {
-                       PE_mirror_particle(ob, psmd->dm, psys, psys->particles + p, NULL);
-               }
+               LOOP_PARTICLES(i, pa)
+                       if(pa->flag & PARS_TAG)
+                               PE_mirror_particle(ob, psmd->dm, psys, pa, NULL);
        }
 
-       LOOP_TAGGED_POINTS {
-               new_totpart--;
-               removed++;
+       for(i=0, pa=psys->particles; i<psys->totpart; i++, pa++) {
+               if(pa->flag & PARS_TAG) {
+                       new_totpart--;
+                       removed++;
+               }
        }
 
        if(new_totpart != psys->totpart) {
                if(new_totpart) {
                        npa= new_pars= MEM_callocN(new_totpart * sizeof(ParticleData), "ParticleData array");
-                       npoint= new_points= MEM_callocN(new_totpart * sizeof(PTCacheEditPoint), "PTCacheEditKey array");
+                       nkey= new_keys= MEM_callocN(new_totpart * sizeof(ParticleEditKey *), "ParticleEditKey array");
                }
 
                pa= psys->particles;
-               point= edit->points;
-               for(i=0; i<psys->totpart; i++, pa++, point++) {
-                       if(point->flag & PEP_TAG) {
-                               if(point->keys)
-                                       MEM_freeN(point->keys);
+               key= edit->keys;
+               for(i=0; i<psys->totpart; i++, pa++, key++) {
+                       if(pa->flag & PARS_TAG) {
+                               if(*key)
+                                       MEM_freeN(*key);
                                if(pa->hair)
                                        MEM_freeN(pa->hair);
                        }
                        else {
                                memcpy(npa, pa, sizeof(ParticleData));
-                               memcpy(npoint, point, sizeof(PTCacheEditPoint));
+                               memcpy(nkey, key, sizeof(ParticleEditKey*));
                                npa++;
-                               npoint++;
+                               nkey++;
                        }
                }
 
                if(psys->particles) MEM_freeN(psys->particles);
                psys->particles= new_pars;
 
-               if(edit->points) MEM_freeN(edit->points);
-               edit->points= new_points;
+               if(edit->keys) MEM_freeN(edit->keys);
+               edit->keys= new_keys;
 
                if(edit->mirror_cache) {
                        MEM_freeN(edit->mirror_cache);
                        edit->mirror_cache= NULL;
                }
 
-               edit->totpoint= psys->totpart= new_totpart;
+               psys->totpart= new_totpart;
+
+               edit->totkeys= psys_count_keys(psys);
        }
 
        return removed;
@@ -1929,82 +1938,84 @@ static int remove_tagged_particles(Scene *scene, Object *ob, ParticleSystem *psy
 
 static void remove_tagged_keys(Scene *scene, Object *ob, ParticleSystem *psys)
 {
-       PTCacheEdit *edit= psys->edit;
+       ParticleEdit *edit= psys->edit;
        ParticleEditSettings *pset= PE_settings(scene);
        ParticleData *pa;
-       HairKey *hkey, *nhkey, *new_hkeys=0;
-       POINT_P; KEY_K;
+       HairKey *key, *nkey, *new_keys=0;
+       ParticleEditKey *ekey;
        ParticleSystemModifierData *psmd;
+       int i, k, totpart= psys->totpart;
        short new_totkey;
 
        if(pset->flag & PE_X_MIRROR) {
                /* mirror key tags */
                psmd= psys_get_modifier(ob, psys);
 
-               LOOP_POINTS {
-                       LOOP_TAGGED_KEYS {
-                               PE_mirror_particle(ob, psmd->dm, psys, psys->particles + p, NULL);
-                               break;
+               LOOP_PARTICLES(i, pa) {
+                       LOOP_KEYS(k,ekey) {
+                               if(ekey->flag & PEK_TAG) {
+                                       PE_mirror_particle(ob, psmd->dm, psys, pa, NULL);
+                                       break;
+                               }
                        }
                }
        }
 
-       LOOP_POINTS {
-               new_totkey= point->totkey;
-               LOOP_TAGGED_KEYS {
-                       new_totkey--;
+       LOOP_PARTICLES(i, pa) {
+               new_totkey= pa->totkey;
+               LOOP_KEYS(k,ekey) {
+                       if(ekey->flag & PEK_TAG)
+                               new_totkey--;
                }
                /* we can't have elements with less than two keys*/
                if(new_totkey < 2)
-                       point->flag |= PEP_TAG;
+                       pa->flag |= PARS_TAG;
        }
        remove_tagged_particles(scene, ob, psys);
 
-       LOOP_POINTS {
-               pa = psys->particles + p;
-               new_totkey= pa->totkey;
+       totpart= psys->totpart;
 
-               LOOP_TAGGED_KEYS {
-                       new_totkey--;
+       LOOP_PARTICLES(i, pa) {
+               new_totkey= pa->totkey;
+               LOOP_KEYS(k,ekey) {
+                       if(ekey->flag & PEK_TAG)
+                               new_totkey--;
                }
-
                if(new_totkey != pa->totkey) {
-                       hkey= pa->hair;
-                       nhkey= new_hkeys= MEM_callocN(new_totkey*sizeof(HairKey), "HairKeys");
+                       key= pa->hair;
+                       nkey= new_keys= MEM_callocN(new_totkey*sizeof(HairKey), "HairKeys");
 
-                       LOOP_KEYS {
-                               while(key->flag & PEK_TAG && hkey < pa->hair + pa->totkey) {
+                       for(k=0, ekey=edit->keys[i]; k<new_totkey; k++, key++, nkey++, ekey++) {
+                               while(ekey->flag & PEK_TAG && key < pa->hair + pa->totkey) {
                                        key++;
-                                       hkey++;
+                                       ekey++;
                                }
 
-                               if(hkey < pa->hair + pa->totkey) {
-                                       VECCOPY(nhkey->co, hkey->co);
-                                       nhkey->time= hkey->time;
-                                       nhkey->weight= hkey->weight;
+                               if(key < pa->hair + pa->totkey) {
+                                       VECCOPY(nkey->co, key->co);
+                                       nkey->time= key->time;
+                                       nkey->weight= key->weight;
                                }
-                               hkey++;
-                               nhkey++;
                        }
                        if(pa->hair)
                                MEM_freeN(pa->hair);
                        
-                       pa->hair= new_hkeys;
+                       pa->hair= new_keys;
 
-                       point->totkey= pa->totkey= new_totkey;
+                       pa->totkey=new_totkey;
 
-                       if(point->keys)
-                               MEM_freeN(point->keys);
-                       key= point->keys= MEM_callocN(new_totkey*sizeof(PTCacheEditKey), "particle edit keys");
+                       if(edit->keys[i])
+                               MEM_freeN(edit->keys[i]);
+                       ekey= edit->keys[i]= MEM_callocN(new_totkey*sizeof(ParticleEditKey), "particle edit keys");
 
-                       hkey = pa->hair;
-                       LOOP_KEYS {
-                               key->co= hkey->co;
-                               key->time= &hkey->time;
-                               hkey++;
+                       for(k=0, key=pa->hair; k<pa->totkey; k++, key++, ekey++) {
+                               ekey->co= key->co;
+                               ekey->time= &key->time;
                        }
                }
        }
+
+       edit->totkeys= psys_count_keys(psys);
 }
 
 /************************ subdivide opertor *********************/
@@ -2012,19 +2023,19 @@ static void remove_tagged_keys(Scene *scene, Object *ob, ParticleSystem *psys)
 /* works like normal edit mode subdivide, inserts keys between neighbouring selected keys */
 static void subdivide_particle(PEData *data, int pa_index)
 {
-       PTCacheEdit *edit= data->edit;
-       ParticleSystem *psys= edit->psys;
-       ParticleData *pa= psys->particles + pa_index;
-       PTCacheEditPoint *point = edit->points + pa_index;
+       ParticleSystem *psys= data->psys;
+       ParticleEdit *edit= psys->edit;
+       ParticleData *pa= &psys->particles[pa_index];
+       
        ParticleKey state;
        HairKey *key, *nkey, *new_keys;
-       PTCacheEditKey *ekey, *nekey, *new_ekeys;
+       ParticleEditKey *ekey, *nekey, *new_ekeys;
 
        int k;
        short totnewkey=0;
        float endtime;
 
-       for(k=0, ekey=point->keys; k<pa->totkey-1; k++,ekey++) {
+       for(k=0, ekey=edit->keys[pa_index]; k<pa->totkey-1; k++,ekey++) {
                if(ekey->flag&PEK_SELECT && (ekey+1)->flag&PEK_SELECT)
                        totnewkey++;
        }
@@ -2034,13 +2045,13 @@ static void subdivide_particle(PEData *data, int pa_index)
        pa->flag |= PARS_REKEY;
 
        nkey= new_keys= MEM_callocN((pa->totkey+totnewkey)*(sizeof(HairKey)),"Hair subdivide keys");
-       nekey= new_ekeys= MEM_callocN((pa->totkey+totnewkey)*(sizeof(PTCacheEditKey)),"Hair subdivide edit keys");
+       nekey= new_ekeys= MEM_callocN((pa->totkey+totnewkey)*(sizeof(ParticleEditKey)),"Hair subdivide edit keys");
        endtime= pa->hair[pa->totkey-1].time;
 
-       for(k=0, key=pa->hair, ekey=point->keys; k<pa->totkey-1; k++, key++, ekey++) {
+       for(k=0, key=pa->hair, ekey=edit->keys[pa_index]; k<pa->totkey-1; k++, key++, ekey++) {
 
                memcpy(nkey,key,sizeof(HairKey));
-               memcpy(nekey,ekey,sizeof(PTCacheEditKey));
+               memcpy(nekey,ekey,sizeof(ParticleEditKey));
 
                nekey->co= nkey->co;
                nekey->time= &nkey->time;
@@ -2056,7 +2067,7 @@ static void subdivide_particle(PEData *data, int pa_index)
 
                        nekey->co= nkey->co;
                        nekey->time= &nkey->time;
-                       nekey->flag |= (PEK_SELECT|PEK_USE_WCO);
+                       nekey->flag |= PEK_SELECT;
 
                        nekey++;
                        nkey++;
@@ -2064,7 +2075,7 @@ static void subdivide_particle(PEData *data, int pa_index)
        }
        /*tip still not copied*/
        memcpy(nkey,key,sizeof(HairKey));
-       memcpy(nekey,ekey,sizeof(PTCacheEditKey));
+       memcpy(nekey,ekey,sizeof(ParticleEditKey));
 
        nekey->co= nkey->co;
        nekey->time= &nkey->time;
@@ -2073,12 +2084,13 @@ static void subdivide_particle(PEData *data, int pa_index)
                MEM_freeN(pa->hair);
        pa->hair= new_keys;
 
-       if(point->keys)
-               MEM_freeN(point->keys);
-       point->keys= new_ekeys;
+       if(edit->keys[pa_index])
+               MEM_freeN(edit->keys[pa_index]);
 
-       point->totkey = pa->totkey = pa->totkey + totnewkey;
-       point->flag |= PEP_EDIT_RECALC;
+       edit->keys[pa_index]= new_ekeys;
+
+       pa->totkey += totnewkey;
+       pa->flag |= PARS_EDIT_RECALC;
        pa->flag &= ~PARS_REKEY;
 }
 
@@ -2087,9 +2099,13 @@ static int subdivide_exec(bContext *C, wmOperator *op)
        PEData data;
 
        PE_set_data(C, &data);
-       foreach_point(&data, subdivide_particle);
+       PE_foreach_particle(&data, subdivide_particle);
+       
+       data.psys->edit->totkeys= psys_count_keys(data.psys);
        
-       recalc_lengths(data.edit);
+       recalc_lengths(data.psys);
+       psys_update_world_cos(data.ob, data.psys);
+
        PE_update_object(data.scene, data.ob, 1);
        WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, data.ob);
 
@@ -2116,15 +2132,15 @@ static int remove_doubles_exec(bContext *C, wmOperator *op)
 {
        Scene *scene= CTX_data_scene(C);
        Object *ob= CTX_data_active_object(C);
+       ParticleSystem *psys= PE_get_current(scene, ob);
        ParticleEditSettings *pset=PE_settings(scene);
-       PTCacheEdit *edit= PE_get_current(scene, ob);
-       ParticleSystem *psys = edit->psys;
+       ParticleData *pa;
+       ParticleEdit *edit;
        ParticleSystemModifierData *psmd;
        KDTree *tree;
        KDTreeNearest nearest[10];
-       POINT_P;
        float mat[4][4], co[3], threshold= RNA_float_get(op->ptr, "threshold");
-       int n, totn, removed, flag, totremoved;
+       int i, n, totn, removed, totpart, flag, totremoved;
 
        edit= psys->edit;
        psmd= psys_get_modifier(ob, psys);
@@ -2133,32 +2149,37 @@ static int remove_doubles_exec(bContext *C, wmOperator *op)
        do {
                removed= 0;
 
-               tree=BLI_kdtree_new(psys->totpart);
+               totpart= psys->totpart;
+               tree=BLI_kdtree_new(totpart);
                        
                /* insert particles into kd tree */
-               LOOP_SELECTED_POINTS {
-                       psys_mat_hair_to_object(ob, psmd->dm, psys->part->from, psys->particles+p, mat);
-                       VECCOPY(co, point->keys->co);
-                       Mat4MulVecfl(mat, co);
-                       BLI_kdtree_insert(tree, p, co, NULL);
+               LOOP_PARTICLES(i, pa) {
+                       if(particle_is_selected(psys, pa)) {
+                               psys_mat_hair_to_object(ob, psmd->dm, psys->part->from, pa, mat);
+                               VECCOPY(co, pa->hair[0].co);
+                               Mat4MulVecfl(mat, co);
+                               BLI_kdtree_insert(tree, i, co, NULL);
+                       }
                }
 
                BLI_kdtree_balance(tree);
 
                /* tag particles to be removed */
-               LOOP_SELECTED_POINTS {
-                       psys_mat_hair_to_object(ob, psmd->dm, psys->part->from, psys->particles+p, mat);
-                       VECCOPY(co, point->keys->co);
-                       Mat4MulVecfl(mat, co);
+               LOOP_PARTICLES(i, pa) {
+                       if(particle_is_selected(psys, pa)) {
+                               psys_mat_hair_to_object(ob, psmd->dm, psys->part->from, pa, mat);
+                               VECCOPY(co, pa->hair[0].co);
+                               Mat4MulVecfl(mat, co);
 
-                       totn= BLI_kdtree_find_n_nearest(tree,10,co,NULL,nearest);
+                               totn= BLI_kdtree_find_n_nearest(tree,10,co,NULL,nearest);
 
-                       for(n=0; n<totn; n++) {
-                               /* this needs a custom threshold still */
-                               if(nearest[n].index > p && nearest[n].dist < threshold) {
-                                       if(!(point->flag & PEP_TAG)) {
-                                               point->flag |= PEP_TAG;
-                                               removed++;
+                               for(n=0; n<totn; n++) {
+                                       /* this needs a custom threshold still */
+                                       if(nearest[n].index > i && nearest[n].dist < threshold) {
+                                               if(!(pa->flag & PARS_TAG)) {
+                                                       pa->flag |= PARS_TAG;
+                                                       removed++;
+                                               }
                                        }
                                }
                        }
@@ -2179,7 +2200,7 @@ static int remove_doubles_exec(bContext *C, wmOperator *op)
 
        BKE_reportf(op->reports, RPT_INFO, "Remove %d double particles.", totremoved);
 
-       PE_update_object(scene, ob, 0);
+       psys_update_world_cos(ob, psys);
        DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
        WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
 
@@ -2326,16 +2347,16 @@ static EnumPropertyItem delete_type_items[]= {
 
 static void set_delete_particle(PEData *data, int pa_index)
 {
-       PTCacheEdit *edit= data->edit;
+       ParticleSystem *psys= data->psys;
 
-       edit->points[pa_index].flag |= PEP_TAG;
+       psys->particles[pa_index].flag |= PARS_TAG;
 }
 
 static void set_delete_particle_key(PEData *data, int pa_index, int key_index)
 {
-       PTCacheEdit *edit= data->edit;
+       ParticleSystem *psys= data->psys;
 
-       edit->points[pa_index].keys[key_index].flag |= PEK_TAG;
+       psys->edit->keys[pa_index][key_index].flag |= PEK_TAG;
 }
 
 static int delete_exec(bContext *C, wmOperator *op)
@@ -2347,17 +2368,15 @@ static int delete_exec(bContext *C, wmOperator *op)
 
        if(type == DEL_KEY) {
                foreach_selected_key(&data, set_delete_particle_key);
-               remove_tagged_keys(data.scene, data.ob, data.edit->psys);
-               recalc_lengths(data.edit);
+               remove_tagged_keys(data.scene, data.ob, data.psys);
+               recalc_lengths(data.psys);
        }
        else if(type == DEL_PARTICLE) {
-               foreach_selected_point(&data, set_delete_particle);
-               remove_tagged_particles(data.scene, data.ob, data.edit->psys);
-               recalc_lengths(data.edit);
+               foreach_selected_particle(&data, set_delete_particle);
+               remove_tagged_particles(data.scene, data.ob, data.psys);
+               recalc_lengths(data.psys);
        }
 
-       PE_update_object(data.scene, data.ob, 0);
-
        DAG_object_flush_update(data.scene, data.ob, OB_RECALC_DATA);
        WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, data.ob);
 
@@ -2388,15 +2407,15 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
 {
        Mesh *me= (Mesh*)(ob->data);
        ParticleSystemModifierData *psmd;
-       PTCacheEdit *edit= PE_get_current(scene, ob);
-       ParticleSystem *psys = edit->psys;
+       ParticleSystem *psys= PE_get_current(scene, ob);
+       ParticleEdit *edit;
        ParticleData *pa, *newpa, *new_pars;
-       PTCacheEditPoint *newpoint, *new_points;
-       POINT_P; KEY_K;
+       ParticleEditKey *ekey, **newkey, **key, **new_keys;
        HairKey *hkey;
        int *mirrorfaces;
-       int rotation, totpart, newtotpart;
+       int i, k, rotation, totpart, newtotpart;
 
+       edit= psys->edit;
        psmd= psys_get_modifier(ob, psys);
 
        mirrorfaces= mesh_get_x_mirror_faces(ob, NULL);
@@ -2406,28 +2425,29 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
 
        totpart= psys->totpart;
        newtotpart= psys->totpart;
-       LOOP_VISIBLE_POINTS {
-               pa = psys->particles + p;
+       LOOP_PARTICLES(i, pa) {
+               if(pa->flag & PARS_HIDE) continue;
+
                if(!tagged) {
-                       if(point_is_selected(point)) {
-                               if(edit->mirror_cache[p] != -1) {
+                       if(particle_is_selected(psys, pa)) {
+                               if(edit->mirror_cache[i] != -1) {
                                        /* already has a mirror, don't need to duplicate */
                                        PE_mirror_particle(ob, psmd->dm, psys, pa, NULL);
                                        continue;
                                }
                                else
-                                       point->flag |= PEP_TAG;
+                                       pa->flag |= PARS_TAG;
                        }
                }
 
-               if((point->flag & PEP_TAG) && mirrorfaces[pa->num*2] != -1)
+               if((pa->flag & PARS_TAG) && mirrorfaces[pa->num*2] != -1)
                        newtotpart++;
        }
 
        if(newtotpart != psys->totpart) {
                /* 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_keys= MEM_callocN(newtotpart*sizeof(ParticleEditKey*), "ParticleEditKey new");
 
                if(psys->particles) {
                        memcpy(new_pars, psys->particles, totpart*sizeof(ParticleData));
@@ -2435,35 +2455,36 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
                }
                psys->particles= new_pars;
 
-               if(edit->points) {
-                       memcpy(new_points, edit->points, totpart*sizeof(PTCacheEditPoint));
-                       MEM_freeN(edit->points);
+               if(edit->keys) {
+                       memcpy(new_keys, edit->keys, totpart*sizeof(ParticleEditKey*));
+                       MEM_freeN(edit->keys);
                }
-               edit->points= new_points;
+               edit->keys= new_keys;
 
                if(edit->mirror_cache) {
                        MEM_freeN(edit->mirror_cache);
                        edit->mirror_cache= NULL;
                }
 
-               edit->totpoint= psys->totpart= newtotpart;
+               psys->totpart= newtotpart;
                        
                /* create new elements */
+               pa= psys->particles;
                newpa= psys->particles + totpart;
-               newpoint= edit->points + totpart;
+               key= edit->keys;
+               newkey= edit->keys + totpart;
 
-               LOOP_VISIBLE_POINTS {
-                       pa = psys->particles + p;
+               for(i=0; i<totpart; i++, pa++, key++) {
+                       if(pa->flag & PARS_HIDE) continue;
 
-                       if(!(point->flag & PEP_TAG) || mirrorfaces[pa->num*2] == -1)
+                       if(!(pa->flag & PARS_TAG) || mirrorfaces[pa->num*2] == -1)
                                continue;
 
                        /* duplicate */
                        *newpa= *pa;
-                       *newpoint= *point;
                        if(pa->hair) newpa->hair= MEM_dupallocN(pa->hair);
                        if(pa->keys) newpa->keys= MEM_dupallocN(pa->keys);
-                       if(point->keys) newpoint->keys= MEM_dupallocN(point->keys);
+                       if(*key) *newkey= MEM_dupallocN(*key);
 
                        /* rotate weights according to vertex index rotation */
                        rotation= mirrorfaces[pa->num*2+1];
@@ -2482,24 +2503,25 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged)
                        newpa->num_dmcache= psys_particle_dm_face_lookup(ob,psmd->dm,newpa->num,newpa->fuv, NULL);
 
                        /* update edit key pointers */
-                       key= newpoint->keys;
-                       for(k=0, hkey=newpa->hair; k<newpa->totkey; k++, hkey++, key++) {
-                               key->co= hkey->co;
-                               key->time= &hkey->time;
+                       ekey= *newkey;
+                       for(k=0, hkey=newpa->hair; k<newpa->totkey; k++, hkey++, ekey++) {
+                               ekey->co= hkey->co;
+                               ekey->time= &hkey->time;
                        }
 
                        /* map key positions as mirror over x axis */
                        PE_mirror_particle(ob, psmd->dm, psys, pa, newpa);
 
                        newpa++;
-                       newpoint++;
+                       newkey++;
                }
-       }
 
-       LOOP_POINTS {
-               point->flag &= ~PEP_TAG;
+               edit->totkeys= psys_count_keys(psys);
        }
 
+       for(pa=psys->particles, i=0; i<psys->totpart; i++, pa++)
+               pa->flag &= ~PARS_TAG;
+
        MEM_freeN(mirrorfaces);
 }
 
@@ -2507,11 +2529,11 @@ static int mirror_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);
+       ParticleSystem *psys= PE_get_current(scene, ob);
        
        PE_mirror_x(scene, ob, 0);
 
-       update_world_cos(ob, edit);
+       psys_update_world_cos(ob, psys);
        WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, ob);
        DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
 
@@ -2538,6 +2560,7 @@ static EnumPropertyItem brush_type_items[]= {
        {PE_BRUSH_NONE, "NONE", 0, "None", ""},
        {PE_BRUSH_COMB, "COMB", 0, "Comb", ""},
        {PE_BRUSH_SMOOTH, "SMOOTH", 0, "Smooth", ""},
+       {PE_BRUSH_WEIGHT, "WEIGHT", 0, "Weight", ""},
        {PE_BRUSH_ADD, "ADD", 0, "Add", ""},
        {PE_BRUSH_LENGTH, "LENGTH", 0, "Length", ""},
        {PE_BRUSH_PUFF, "PUFF", 0, "Puff", ""},
@@ -2570,46 +2593,14 @@ void PARTICLE_OT_brush_set(wmOperatorType *ot)
        RNA_def_enum(ot->srna, "type", brush_type_items, PE_BRUSH_NONE, "Type", "Brush type to select for editing.");
 }
 
-
-/*********************** set mode operator **********************/
-
-static EnumPropertyItem edit_type_items[]= {
-       {PE_TYPE_PARTICLES, "PARTICLES", 0, "Particles", ""},
-       {PE_TYPE_SOFTBODY, "SOFTBODY", 0, "Soft body", ""},
-       {PE_TYPE_CLOTH, "CLOTH", 0, "Cloth", ""},
-       {0, NULL, 0, NULL, NULL}
-};
-
-static int set_edit_mode_exec(bContext *C, wmOperator *op)
-{
-       Scene *scene= CTX_data_scene(C);
-       ParticleEditSettings *pset= PE_settings(scene);
-
-       pset->edittype= RNA_enum_get(op->ptr, "type");
-
-       return OPERATOR_FINISHED;
-}
-
-void PARTICLE_OT_edit_type_set(wmOperatorType *ot)
-{
-       /* identifiers */
-       ot->name= "Set Brush";
-       ot->idname= "PARTICLE_OT_edit_type_set";
-       
-       /* api callbacks */
-       ot->exec= set_brush_exec;
-       ot->invoke= WM_menu_invoke;
-       ot->poll= PE_poll;
-
-       /* properties */
-       RNA_def_enum(ot->srna, "type", edit_type_items, PE_TYPE_PARTICLES, "Type", "Edit type to select for editing.");
-}
-
 /************************* brush edit callbacks ********************/
 
-static void brush_comb(PEData *data, float mat[][4], float imat[][4], int point_index, int key_index, PTCacheEditKey *key)
+static void brush_comb(PEData *data, float mat[][4], float imat[][4], int pa_index, int key_index)
 {
+       ParticleSystem *psys= data->psys;
+       ParticleData *pa= &psys->particles[pa_index];
        ParticleEditSettings *pset= PE_settings(data->scene);
+       HairKey *key= pa->hair + key_index;
        float cvec[3], fac;
 
        if(pset->flag & PE_LOCK_FIRST && key_index == 0) return;
@@ -2621,21 +2612,19 @@ static void brush_comb(PEData *data, float mat[][4], float imat[][4], int point_
        VecMulf(cvec, fac);
        VECADD(key->co, key->co, cvec);
 
-       (data->edit->points + point_index)->flag |= PEP_EDIT_RECALC;
+       pa->flag |= PARS_EDIT_RECALC;
 }
 
 static void brush_cut(PEData *data, int pa_index)
 {
-       PTCacheEdit *edit = data->edit;
-       ParticleSystem *psys= edit->psys;
+       ParticleSystem *psys= data->psys;
        ARegion *ar= data->vc.ar;
        Object *ob= data->ob;
-       ParticleEditSettings *pset= PE_settings(data->scene);
        ParticleData *pa= &psys->particles[pa_index];
-       ParticleCacheKey *key= edit->pathcache[pa_index];
+       ParticleCacheKey *key= psys->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)psys->part->draw_step);
        short vertco[2];
 
        /* blunt scissors */
@@ -2710,97 +2699,93 @@ static void brush_cut(PEData *data, int pa_index)
 
        if(cut) {
                if(cut_time < 0.0f) {
-                       edit->points[pa_index].flag |= PEP_TAG;
+                       pa->flag |= PARS_TAG;
                }
                else {
                        rekey_particle_to_time(data->scene, ob, pa_index, cut_time);
-                       edit->points[pa_index].flag |= PEP_EDIT_RECALC;
+                       pa->flag |= PARS_EDIT_RECALC;
                }
        }
 }
 
-static void brush_length(PEData *data, int point_index)
+static void brush_length(PEData *data, int pa_index)
 {
-       PTCacheEdit *edit= data->edit;
-       PTCacheEditPoint *point = edit->points + point_index;
-       KEY_K;
+       ParticleSystem *psys= data->psys;
+       ParticleData *pa= &psys->particles[pa_index];
+       HairKey *key;
        float dvec[3],pvec[3];
+       int k;
 
-       LOOP_KEYS {
-               if(k==0) {
-                       VECCOPY(pvec,key->co);
-               }
-               else {
-                       VECSUB(dvec,key->co,pvec);
-                       VECCOPY(pvec,key->co);
-                       VecMulf(dvec,data->growfac);
-                       VECADD(key->co,(key-1)->co,dvec);
-               }
+       key= pa->hair;
+       VECCOPY(pvec,key->co);
+
+       for(k=1, key++; k<pa->totkey; k++,key++) {
+               VECSUB(dvec,key->co,pvec);
+               VECCOPY(pvec,key->co);
+               VecMulf(dvec,data->growfac);
+               VECADD(key->co,(key-1)->co,dvec);
        }
 
-       point->flag |= PEP_EDIT_RECALC;
+       pa->flag |= PARS_EDIT_RECALC;
 }
 
-static void brush_puff(PEData *data, int point_index)
+static void brush_puff(PEData *data, int pa_index)
 {
-       PTCacheEdit *edit = data->edit;
-       ParticleSystem *psys = edit->psys;
-       PTCacheEditPoint *point = edit->points + point_index;
-       KEY_K;
+       ParticleSystem *psys= data->psys;
+       ParticleData *pa= &psys->particles[pa_index];
+       ParticleEdit *edit= psys->edit;
+       HairKey *key;
        float mat[4][4], imat[4][4];
        float lastco[3], rootco[3], co[3], nor[3], kco[3], dco[3], fac, length;
+       int k;
 
-       if(psys) {
-               psys_mat_hair_to_global(data->ob, data->dm, psys->part->from, psys->particles + point_index, mat);
-               Mat4Invert(imat,mat);
-       }
-       else {
-               Mat4One(mat);
-               Mat4One(imat);
-       }
+       psys_mat_hair_to_global(data->ob, data->dm, psys->part->from, pa, mat);
+       Mat4Invert(imat,mat);
 
-       LOOP_KEYS {
-               if(k==0) {
-                       /* find root coordinate and normal on emitter */
-                       VECCOPY(co, key->co);
-                       Mat4MulVecfl(mat, co);
+       /* find root coordinate and normal on emitter */
+       key= pa->hair;
+       VECCOPY(co, key->co);
+       Mat4MulVecfl(mat, co);
 
-                       point_index= BLI_kdtree_find_nearest(edit->emitter_field, co, NULL, NULL);
-                       if(point_index == -1) return;
+       pa_index= BLI_kdtree_find_nearest(edit->emitter_field, co, NULL, NULL);
+       if(pa_index == -1) return;
 
-                       VECCOPY(rootco, co);
-                       VecCopyf(nor, &edit->emitter_cosnos[point_index*6+3]);
-                       Normalize(nor);
-                       length= 0.0f;
+       VECCOPY(rootco, co);
+       VecCopyf(nor, &psys->edit->emitter_cosnos[pa_index*6+3]);
+       Normalize(nor);
+       length= 0.0f;
 
-                       fac= (float)pow((double)(1.0f - data->dist / data->rad), (double)data->pufffac);
-                       fac *= 0.025f;
-                       if(data->invert)
-                               fac= -fac;
-               }
-               else {
-                       /* compute position as if hair was standing up straight */
-                       VECCOPY(lastco, co);
-                       VECCOPY(co, key->co);
-                       Mat4MulVecfl(mat, co);
-                       length += VecLenf(lastco, co);
+       fac= (float)pow((double)(1.0f - data->dist / data->rad), (double)data->pufffac);
+       fac *= 0.025f;
+       if(data->invert)
+               fac= -fac;
 
-                       VECADDFAC(kco, rootco, nor, length);
+       for(k=1, key++; k<pa->totkey; k++, key++) {
+               /* compute position as if hair was standing up straight */
+               VECCOPY(lastco, co);
+               VECCOPY(co, key->co);
+               Mat4MulVecfl(mat, co);
+               length += VecLenf(lastco, co);
 
-                       /* blend between the current and straight position */
-                       VECSUB(dco, kco, co);
-                       VECADDFAC(co, co, dco, fac);
+               VECADDFAC(kco, rootco, nor, length);
 
-                       VECCOPY(key->co, co);
-                       Mat4MulVecfl(imat, key->co);
-               }
+               /* blend between the current and straight position */
+               VECSUB(dco, kco, co);
+               VECADDFAC(co, co, dco, fac);
+
+               VECCOPY(key->co, co);
+               Mat4MulVecfl(imat, key->co);
        }
 
-       point->flag |= PEP_EDIT_RECALC;
+       pa->flag |= PARS_EDIT_RECALC;
 }
 
-static void brush_smooth_get(PEData *data, float mat[][4], float imat[][4], int point_index, int key_index, PTCacheEditKey *key)
-{      
+static void brush_smooth_get(PEData *data, float mat[][4], float imat[][4], int pa_index, int key_index)
+{
+       ParticleSystem *psys= data->psys;
+       ParticleData *pa= &psys->particles[pa_index];
+       HairKey *key= pa->hair + key_index;
+       
        if(key_index) {
                float dvec[3];
 
@@ -2811,8 +2796,11 @@ static void brush_smooth_get(PEData *data, float mat[][4], float imat[][4], int
        }
 }
 
-static void brush_smooth_do(PEData *data, float mat[][4], float imat[][4], int point_index, int key_index, PTCacheEditKey *key)
+static void brush_smooth_do(PEData *data, float mat[][4], float imat[][4], int pa_index, int key_index)
 {
+       ParticleSystem *psys= data->psys;
+       ParticleData *pa= &psys->particles[pa_index];
+       HairKey *key= pa->hair + key_index;
        float vec[3], dvec[3];
        
        if(key_index) {
@@ -2827,18 +2815,18 @@ static void brush_smooth_do(PEData *data, float mat[][4], float imat[][4], int p
                VECADD(key->co,key->co,dvec);
        }
 
-       (data->edit->points + point_index)->flag |= PEP_EDIT_RECALC;
+       pa->flag |= PARS_EDIT_RECALC;
 }
 
 static void brush_add(PEData *data, short number)
 {
        Scene *scene= data->scene;
        Object *ob= data->ob;
-       PTCacheEdit *edit = data->edit;
-       ParticleSystem *psys= edit->psys;
+       ParticleSystem *psys= data->psys;
        ParticleData *add_pars= MEM_callocN(number*sizeof(ParticleData),"ParticleData add");
        ParticleSystemModifierData *psmd= psys_get_modifier(ob,psys);
        ParticleEditSettings *pset= PE_settings(scene);
+       ParticleEdit *edit= psys->edit;
        int i, k, n= 0, totpart= psys->totpart;
        short mco[2];
        short dmx= 0, dmy= 0;
@@ -2885,20 +2873,19 @@ static void brush_add(PEData *data, short number)
                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");
-               PTCacheEditKey *key;
+               ParticleEditKey *ekey, **key, **new_keys= MEM_callocN(newtotpart*sizeof(ParticleEditKey *),"ParticleEditKey array new");
                HairKey *hkey;
 
                /* save existing elements */
                memcpy(new_pars, psys->particles, totpart * sizeof(ParticleData));
-               memcpy(new_points, edit->points, totpart * sizeof(PTCacheEditPoint));
+               memcpy(new_keys, edit->keys, totpart * sizeof(ParticleEditKey*));
 
                /* change old arrays to new ones */
                if(psys->particles) MEM_freeN(psys->particles);
                psys->particles= new_pars;
 
-               if(edit->points) MEM_freeN(edit->points);
-               edit->points= new_points;
+               if(edit->keys) MEM_freeN(edit->keys);
+               edit->keys= new_keys;
 
                if(edit->mirror_cache) {
                        MEM_freeN(edit->mirror_cache);
@@ -2917,29 +2904,29 @@ static void brush_add(PEData *data, short number)
                        BLI_kdtree_balance(tree);
                }
 
-               edit->totpoint= psys->totpart= newtotpart;
+               psys->totpart= newtotpart;
 
                /* create new elements */
                pa= psys->particles + totpart;
-               point= edit->points + totpart;
+               key= edit->keys + totpart;
 
-               for(i=totpart; i<newtotpart; i++, pa++, point++) {
+               for(i=totpart; i<newtotpart; i++, pa++, key++) {
                        memcpy(pa, add_pars + i - totpart, sizeof(ParticleData));
                        pa->hair= MEM_callocN(pset->totaddkey * sizeof(HairKey), "BakeKey key add");
-                       key= point->keys= MEM_callocN(pset->totaddkey * sizeof(PTCacheEditKey), "PTCacheEditKey add");
-                       point->totkey= pa->totkey= pset->totaddkey;
+                       ekey= *key= MEM_callocN(pset->totaddkey * sizeof(ParticleEditKey), "ParticleEditKey add");
+                       pa->totkey= pset->totaddkey;
 
-                       for(k=0, hkey=pa->hair; k<pa->totkey; k++, hkey++, key++) {
-                               key->co= hkey->co;
-                               key->time= &hkey->time;
+                       for(k=0, hkey=pa->hair; k<pa->totkey; k++, hkey++, ekey++) {
+                               ekey->co= hkey->co;
+                               ekey->time= &hkey->time;
                        }
                        
                        pa->size= 1.0f;
                        initialize_particle(pa,i,ob,psys,psmd);
                        reset_particle(scene, pa,psys,psmd,ob,0.0,1.0,0,0,0);
-                       point->flag |= PEP_EDIT_RECALC;
+                       pa->flag |= PARS_EDIT_RECALC;
                        if(pset->flag & PE_X_MIRROR)
-                               point->flag |= PEP_TAG; /* signal for duplicate */
+                               pa->flag |= PARS_TAG; /* signal for duplicate */
                        
                        framestep= pa->lifetime/(float)(pset->totaddkey-1);
 
@@ -3010,6 +2997,7 @@ static void brush_add(PEData *data, short number)
                                Mat4MulVecfl(imat, hkey->co);
                        }
                }
+               edit->totkeys= psys_count_keys(psys);
 
                if(tree)
                        BLI_kdtree_free(tree);
@@ -3021,12 +3009,25 @@ static void brush_add(PEData *data, short number)
                dm->release(dm);
 }
 
+static void brush_weight(PEData *data, float mat[][4], float imat[][4], int pa_index, int key_index)
+{
+       ParticleSystem *psys= data->psys;
+       ParticleData *pa;
+
+       /* roots have full weight allways */
+       if(key_index) {
+               pa= &psys->particles[pa_index];
+               pa->hair[key_index].weight= data->weightfac;
+               pa->flag |= PARS_EDIT_RECALC;
+       }
+}
+
 /************************* brush edit operator ********************/
 
 typedef struct BrushEdit {
        Scene *scene;
        Object *ob;
-       PTCacheEdit *edit;
+       ParticleSystem *psys;
 
        int first;
        int lastmouse[2];
@@ -3036,8 +3037,8 @@ static int brush_edit_init(bContext *C, wmOperator *op)
 {
        Scene *scene= CTX_data_scene(C);
        Object *ob= CTX_data_active_object(C);
+       ParticleSystem *psys= PE_get_current(scene, ob);
        ParticleEditSettings *pset= PE_settings(scene);
-       PTCacheEdit *edit= PE_get_current(scene, ob);
        ARegion *ar= CTX_wm_region(C);
        BrushEdit *bedit;
 
@@ -3052,7 +3053,7 @@ static int brush_edit_init(bContext *C, wmOperator *op)
 
        bedit->scene= scene;
        bedit->ob= ob;
-       bedit->edit= edit;
+       bedit->psys= psys;
 
        return 1;
 }
@@ -3062,18 +3063,15 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
        BrushEdit *bedit= op->customdata;
        Scene *scene= bedit->scene;
        Object *ob= bedit->ob;
-       PTCacheEdit *edit= bedit->edit;
+       ParticleSystem *psys= bedit->psys;
        ParticleEditSettings *pset= PE_settings(scene);
-       ParticleSystemModifierData *psmd= edit->psys ? psys_get_modifier(ob, edit->psys) : NULL;
+       ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys);
        ParticleBrushData *brush= &pset->brush[pset->brushtype];
        ARegion *ar= CTX_wm_region(C);
-       float vec[3], mousef[2];
+       float vec1[3], vec2[3], mousef[2];
        short mval[2], mvalo[2];
        int flip, mouse[2], dx, dy, removed= 0, selected= 0;
 
-       if(!PE_start_edit(edit))
-               return;
-
        RNA_float_get_array(itemptr, "mouse", mousef);
        mouse[0] = mousef[0];
        mouse[1] = mousef[1];
@@ -3098,7 +3096,7 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
                || bedit->first) {
 
                view3d_operator_needs_opengl(C);
-               selected= (short)count_selected_keys(scene, edit);
+               selected= (short)count_selected_keys(scene, psys);
 
                switch(pset->brushtype) {
                        case PE_BRUSH_COMB:
@@ -3117,8 +3115,10 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
 
                                Mat4Invert(ob->imat, ob->obmat);
 
-                               window_to_3d_delta(ar, vec, dx, dy);
-                               data.dvec= vec;
+                               window_to_3d(ar, vec1, mvalo[0], mvalo[1]);
+                               window_to_3d(ar, vec2, mval[0], mval[1]);
+                               VECSUB(vec1, vec2, vec1);
+                               data.dvec= vec1;
 
                                foreach_mouse_hit_key(&data, brush_comb, selected);
                                break;
@@ -3126,22 +3126,20 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
                        case PE_BRUSH_CUT:
                        {
                                PEData data;
-                               
-                               if(edit->psys && edit->pathcache) {
-                                       PE_set_view3d_data(C, &data);
-                                       data.mval= mval;
-                                       data.rad= (float)brush->size;
-                                       data.cutfac= (float)(brush->strength / 100.0f);
 
-                                       if(selected)
-                                               foreach_selected_point(&data, brush_cut);
-                                       else
-                                               foreach_point(&data, brush_cut);
+                               PE_set_view3d_data(C, &data);
+                               data.mval= mval;
+                               data.rad= (float)brush->size;
+                               data.cutfac= (float)(brush->strength / 100.0f);
 
-                                       removed= remove_tagged_particles(scene, ob, edit->psys);
-                                       if(pset->flag & PE_KEEP_LENGTHS)
-                                               recalc_lengths(edit);
-                               }
+                               if(selected)
+                                       foreach_selected_particle(&data, brush_cut);
+                               else
+                                       PE_foreach_particle(&data, brush_cut);
+
+                               removed= remove_tagged_particles(scene, ob, psys);
+                               if(pset->flag & PE_KEEP_LENGTHS)
+                                       recalc_lengths(psys);
                                break;
                        }
                        case PE_BRUSH_LENGTH:
@@ -3159,50 +3157,61 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
                                else
                                        data.growfac= 1.0f + data.growfac;
 
-                               foreach_mouse_hit_point(&data, brush_length, selected);
+                               foreach_mouse_hit_particle(&data, brush_length, selected);
 
                                if(pset->flag & PE_KEEP_LENGTHS)
-                                       recalc_lengths(edit);
+                                       recalc_lengths(psys);
                                break;
                        }
                        case PE_BRUSH_PUFF:
                        {
                                PEData data;
 
-                               if(edit->psys) {
-                                       PE_set_view3d_data(C, &data);
-                                       data.dm= psmd->dm;
-                                       data.mval= mval;
-                                       data.rad= (float)brush->size;
+                               PE_set_view3d_data(C, &data);
+                               data.dm= psmd->dm;
+                               data.mval= mval;
+                               data.rad= (float)brush->size;
 
-                                       data.pufffac= (float)(brush->strength - 50) / 50.0f;
-                                       if(data.pufffac < 0.0f)
-                                               data.pufffac= 1.0f - 9.0f * data.pufffac;
-                                       else
-                                               data.pufffac= 1.0f - data.pufffac;
+                               data.pufffac= (float)(brush->strength - 50) / 50.0f;
+                               if(data.pufffac < 0.0f)
+                                       data.pufffac= 1.0f - 9.0f * data.pufffac;
+                               else
+                                       data.pufffac= 1.0f - data.pufffac;
 
-                                       data.invert= (brush->invert ^ flip);
-                                       Mat4Invert(ob->imat, ob->obmat);
+                               data.invert= (brush->invert ^ flip);
+                               Mat4Invert(ob->imat, ob->obmat);
 
-                                       foreach_mouse_hit_point(&data, brush_puff, selected);
-                               }
+                               foreach_mouse_hit_particle(&data, brush_puff, selected);
                                break;
                        }
                        case PE_BRUSH_ADD:
                        {
                                PEData data;
 
-                               if(edit->psys && edit->psys->part->from==PART_FROM_FACE) {
+                               if(psys->part->from==PART_FROM_FACE) {
                                        PE_set_view3d_data(C, &data);
                                        data.mval= mval;
 
                                        brush_add(&data, brush->strength);
 
                                        if(pset->flag & PE_KEEP_LENGTHS)
-                                               recalc_lengths(edit);
+                                               recalc_lengths(psys);
                                }
                                break;
                        }
+                       case PE_BRUSH_WEIGHT:
+                       {
+                               PEData data;
+
+                               PE_set_view3d_data(C, &data);
+                               data.mval= mval;
+                               data.rad= (float)brush->size;
+
+                               data.weightfac= (float)(brush->strength / 100.0f);
+
+                               foreach_mouse_hit_key(&data, brush_weight, selected);
+                               break;
+                       }
                        case PE_BRUSH_SMOOTH:
                        {
                                PEData data;
@@ -3229,14 +3238,14 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr)
                        }
                }
                if((pset->flag & PE_KEEP_LENGTHS)==0)
-                       recalc_lengths(edit);
+                       recalc_lengths(psys);
 
                if(pset->brushtype == PE_BRUSH_ADD || removed) {
                        if(pset->brushtype == PE_BRUSH_ADD && (pset->flag & PE_X_MIRROR))
                                PE_mirror_x(scene, ob, 1);
 
-                       update_world_cos(ob,edit);
-                       psys_free_path_cache(NULL, edit);
+                       psys_update_world_cos(ob,psys);
+                       psys_free_path_cache(psys);
                        DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
                }
                else
@@ -3348,157 +3357,104 @@ void PARTICLE_OT_brush_edit(wmOperatorType *ot)
 
 /*********************** undo ***************************/
 
-static void free_PTCacheUndo(PTCacheUndo *undo)
+static void free_ParticleUndo(ParticleUndo *undo)
 {
-       PTCacheEditPoint *point;
+       ParticleData *pa;
        int i;
 
-       for(i=0, point=undo->points; i<undo->totpoint; i++, point++) {
-               if(undo->particles && (undo->particles + i)->hair)
-                       MEM_freeN((undo->particles + i)->hair);
-               if(point->keys)
-                       MEM_freeN(point->keys);
+       for(i=0, pa=undo->particles; i<undo->totpart; i++, pa++) {
+               if(pa->hair)
+                       MEM_freeN(pa->hair);
+               if(undo->keys[i])
+                       MEM_freeN(undo->keys[i]);
        }
-       if(undo->points)
-               MEM_freeN(undo->points);
+       if(undo->keys)
+               MEM_freeN(undo->keys);
 
        if(undo->particles)
                MEM_freeN(undo->particles);
 
-       BKE_ptcache_free_mem(&undo->mem_cache);
+       //if(undo->emitter_cosnos)
+       //      MEM_freeN(undo->emitter_cosnos);
 }
 
-static void make_PTCacheUndo(PTCacheEdit *edit, PTCacheUndo *undo)
+static void make_ParticleUndo(ParticleSystem *psys, ParticleUndo *undo)
 {
-       PTCacheEditPoint *point;
+       ParticleData *pa,*upa;
        int i;
 
-       undo->totpoint= edit->totpoint;
-
-       if(edit->psys) {
-               ParticleData *pa;
-
-               pa= undo->particles= MEM_dupallocN(edit->psys->particles);
-
-               for(i=0; i<edit->totpoint; i++, pa++)
-                       pa->hair= MEM_dupallocN(pa->hair);
-       }
-       else {
-               PTCacheMem *pm;
+       undo->totpart= psys->totpart;
+       undo->totkeys= psys->edit->totkeys;
 
-               BLI_duplicatelist(&undo->mem_cache, &edit->pid.cache->mem_cache);
-               pm = undo->mem_cache.first;
-
-               for(; pm; pm=pm->next) {
-                       for(i=0; i<BPHYS_TOT_DATA; i++)
-                               pm->data[i] = MEM_dupallocN(pm->data[i]);
-               }
-       }
-
-       point= undo->points = MEM_dupallocN(edit->points);
-       undo->totpoint = edit->totpoint;
-
-       for(i=0; i<edit->totpoint; i++, point++) {
-               point->keys= MEM_dupallocN(point->keys);
+       upa= undo->particles= MEM_dupallocN(psys->particles);
+       undo->keys= MEM_dupallocN(psys->edit->keys);
+       
+       for(i=0, pa=psys->particles; i<undo->totpart; i++, pa++, upa++) {
+               upa->hair= MEM_dupallocN(pa->hair);
+               undo->keys[i]= MEM_dupallocN(psys->edit->keys[i]);
                /* no need to update edit key->co & key->time pointers here */
        }
 }
 
-static void get_PTCacheUndo(PTCacheEdit *edit, PTCacheUndo *undo)
+static void get_ParticleUndo(ParticleSystem *psys, ParticleUndo *undo)
 {
-       ParticleSystem *psys = edit->psys;
-       ParticleData *pa;
+       ParticleData *pa, *upa;
+       ParticleEditKey *key;
        HairKey *hkey;
-       POINT_P; KEY_K;
+       int i, k, totpart= psys->totpart;
 
-       LOOP_POINTS {
-               if(psys && psys->particles[p].hair)
-                       MEM_freeN(psys->particles[p].hair);
+       LOOP_PARTICLES(i, pa) {
+               if(pa->hair)
+                       MEM_freeN(pa->hair);
 
-               if(point->keys)
-                       MEM_freeN(point->keys);
+               if(psys->edit->keys[i])
+                       MEM_freeN(psys->edit->keys[i]);
        }
-       if(psys && psys->particles)
+       if(psys->particles)
                MEM_freeN(psys->particles);
-       if(edit->points)
-               MEM_freeN(edit->points);
-       if(edit->mirror_cache) {
-               MEM_freeN(edit->mirror_cache);
-               edit->mirror_cache= NULL;
+       if(psys->edit->keys)
+               MEM_freeN(psys->edit->keys);
+       if(psys->edit->mirror_cache) {
+               MEM_freeN(psys->edit->mirror_cache);
+               psys->edit->mirror_cache= NULL;
        }
 
-       edit->points= MEM_dupallocN(undo->points);
-       edit->totpoint = undo->totpoint;
+       pa= psys->particles= MEM_dupallocN(undo->particles);
+       psys->edit->keys= MEM_dupallocN(undo->keys);
 
-       LOOP_POINTS {
-               point->keys= MEM_dupallocN(point->keys);
-       }
-
-       if(psys) {
-               psys->particles= MEM_dupallocN(undo->particles);
-
-               psys->totpart= undo->totpoint;
-
-               LOOP_POINTS {
-                       pa = psys->particles + p;
-                       hkey= pa->hair = MEM_dupallocN(pa->hair);
-
-                       LOOP_KEYS {
-                               key->co= hkey->co;
-                               key->time= &hkey->time;
-                               hkey++;
-                       }
+       for(i=0,upa=undo->particles; i<undo->totpart; i++, upa++, pa++) {
+               hkey= pa->hair= MEM_dupallocN(upa->hair);
+               key= psys->edit->keys[i]= MEM_dupallocN(undo->keys[i]);
+               for(k=0; k<pa->totkey; k++, hkey++, key++) {
+                       key->co= hkey->co;
+                       key->time= &hkey->time;
                }
        }
-       else {
-               PTCacheMem *pm;
-               int i;
-
-               BKE_ptcache_free_mem(&edit->pid.cache->mem_cache);
-
-               BLI_duplicatelist(&edit->pid.cache->mem_cache, &undo->mem_cache);
-
-               pm = edit->pid.cache->mem_cache.first;
 
-               for(; pm; pm=pm->next) {
-                       for(i=0; i<BPHYS_TOT_DATA; i++)
-                               pm->data[i] = MEM_dupallocN(pm->data[i]);
-
-                       BKE_ptcache_mem_init_pointers(pm);
-
-                       LOOP_POINTS {
-                               LOOP_KEYS {
-                                       if((int)key->ftime == pm->frame) {
-                                               key->co = pm->cur[BPHYS_DATA_LOCATION];
-                                               key->vel = pm->cur[BPHYS_DATA_VELOCITY];
-                                               key->rot = pm->cur[BPHYS_DATA_ROTATION];
-                                               key->time = &key->ftime;
-                                       }
-                               }
-                               BKE_ptcache_mem_incr_pointers(pm);
-                       }
-               }
-       }
+       psys->totpart= undo->totpart;
+       psys->edit->totkeys= undo->totkeys;
 }
 
 void PE_undo_push(Scene *scene, char *str)
 {
-       PTCacheEdit *edit= PE_get_current(scene, OBACT);
-       PTCacheUndo *undo;
+       ParticleSystem *psys= PE_get_current(scene, OBACT);
+       ParticleEdit *edit= 0;
+       ParticleUndo *undo;
        int nr;
 
-       if(!edit) return;
+       if(!PE_can_edit(psys)) return;
+       edit= psys->edit;
 
        /* remove all undos after (also when curundo==NULL) */
        while(edit->undo.last != edit->curundo) {
                undo= edit->undo.last;
                BLI_remlink(&edit->undo, undo);
-               free_PTCacheUndo(undo);
+               free_ParticleUndo(undo);
                MEM_freeN(undo);
        }
 
        /* make new */
-       edit->curundo= undo= MEM_callocN(sizeof(PTCacheUndo), "particle undo file");
+       edit->curundo= undo= MEM_callocN(sizeof(ParticleUndo), "particle undo file");
        strncpy(undo->name, str, 64-1);
        BLI_addtail(&edit->undo, undo);
        
@@ -3512,25 +3468,27 @@ void PE_undo_push(Scene *scene, char *str)
        }
        if(undo) {
                while(edit->undo.first!=undo) {
-                       PTCacheUndo *first= edit->undo.first;
+                       ParticleUndo *first= edit->undo.first;
                        BLI_remlink(&edit->undo, first);
-                       free_PTCacheUndo(first);
+                       free_ParticleUndo(first);
                        MEM_freeN(first);
                }
        }
 
        /* copy  */
-       make_PTCacheUndo(edit,edit->curundo);
+       make_ParticleUndo(psys,edit->curundo);
 }
 
 void PE_undo_step(Scene *scene, int step)
 {      
-       PTCacheEdit *edit= PE_get_current(scene, OBACT);
+       ParticleSystem *psys= PE_get_current(scene, OBACT);
+       ParticleEdit *edit= 0;
 
-       if(!edit) return;
+       if(!PE_can_edit(psys)) return;
+       edit= psys->edit;
 
        if(step==0) {
-               get_PTCacheUndo(edit,edit->curundo);
+               get_ParticleUndo(psys,edit->curundo);
        }
        else if(step==1) {
                
@@ -3538,7 +3496,7 @@ void PE_undo_step(Scene *scene, int step)
                else {
                        if(G.f & G_DEBUG) printf("undo %s\n", edit->curundo->name);
                        edit->curundo= edit->curundo->prev;
-                       get_PTCacheUndo(edit, edit->curundo);
+                       get_ParticleUndo(psys, edit->curundo);
                }
        }
        else {
@@ -3546,19 +3504,18 @@ void PE_undo_step(Scene *scene, int step)
                
                if(edit->curundo==NULL || edit->curundo->next==NULL);
                else {
-                       get_PTCacheUndo(edit, edit->curundo->next);
+                       get_ParticleUndo(psys, edit->curundo->next);
                        edit->curundo= edit->curundo->next;
                        if(G.f & G_DEBUG) printf("redo %s\n", edit->curundo->name);
                }
        }
 
-       PE_update_object(scene, OBACT, 0);
        DAG_object_flush_update(scene, OBACT, OB_RECALC_DATA);
 }
 
-static void PTCacheUndo_number(Scene *scene, PTCacheEdit *edit, int nr)
+static void ParticleUndo_number(Scene *scene, ParticleEdit *edit, int nr)
 {
-       PTCacheUndo *undo;
+       ParticleUndo *undo;
        int a=1;
        
        for(undo= edit->undo.first; undo; undo= undo->next, a++) {
@@ -3568,15 +3525,20 @@ static void PTCacheUndo_number(Scene *scene, PTCacheEdit *edit, int nr)
        PE_undo_step(scene, 0);
 }
 
-static void PTCacheUndo_clear(PTCacheEdit *edit)
+static void ParticleUndo_clear(ParticleSystem *psys)
 {
-       PTCacheUndo *undo;
+       ParticleUndo *undo;
+       ParticleEdit *edit;
+
+       if(psys==0) return;
+
+       edit= psys->edit;
 
        if(edit==0) return;
        
        undo= edit->undo.first;
        while(undo) {
-               free_PTCacheUndo(undo);
+               free_ParticleUndo(undo);
                undo= undo->next;
        }
        BLI_freelistN(&edit->undo);
@@ -3595,13 +3557,15 @@ void PE_redo(Scene *scene)
 
 void PE_undo_menu(Scene *scene, Object *ob)
 {
-       PTCacheEdit *edit= PE_get_current(scene, ob);
-       PTCacheUndo *undo;
+       ParticleSystem *psys= PE_get_current(scene, ob);
+       ParticleEdit *edit= 0;
+       ParticleUndo *undo;
        DynStr *ds;
        short event=0;
        char *menu;
 
-       if(!edit) return;
+       if(!PE_can_edit(psys)) return;
+       edit= psys->edit;
        
        ds= BLI_dynstr_new();
 
@@ -3618,7 +3582,7 @@ void PE_undo_menu(Scene *scene, Object *ob)
 // XXX event= pupmenu_col(menu, 20);
        MEM_freeN(menu);
        
-       if(event>0) PTCacheUndo_number(scene, edit, event);
+       if(event>0) ParticleUndo_number(scene, edit,event);
 }
 
 /************************ utilities ******************************/
@@ -3626,29 +3590,30 @@ void PE_undo_menu(Scene *scene, Object *ob)
 int PE_minmax(Scene *scene, float *min, float *max)
 {
        Object *ob= OBACT;
-       PTCacheEdit *edit= PE_get_current(scene, ob);
-       ParticleSystem *psys = edit->psys;
-       ParticleSystemModifierData *psmd = NULL;
-       POINT_P; KEY_K;
+       ParticleSystem *psys= PE_get_current(scene, ob);
+       ParticleSystemModifierData *psmd;
+       ParticleData *pa;
+       ParticleEditKey *key;
        float co[3], mat[4][4];
-       int ok= 0;
+       int i, k, totpart, ok= 0;
 
-       if(!edit) return ok;
+       if(!PE_can_edit(psys)) return ok;
        
-       if(psys)
-               psmd= psys_get_modifier(ob, psys);
-       else
-               Mat4One(mat);
+       psmd= psys_get_modifier(ob, psys);
+       totpart= psys->totpart;
 
-       LOOP_VISIBLE_POINTS {
-               if(psys)
-                       psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, psys->particles+p, mat);
+       LOOP_PARTICLES(i, pa) {
+               if(pa->flag & PARS_HIDE) continue;
 
-               LOOP_SELECTED_KEYS {
-                       VECCOPY(co, key->co);
-                       Mat4MulVecfl(mat, co);
-                       DO_MINMAX(co, min, max);                
-                       ok= 1;
+               psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, mat);
+
+               LOOP_KEYS(k, key) {
+                       if(key->flag & PEK_SELECT) {
+                               VECCOPY(co, key->co);
+                               Mat4MulVecfl(mat, co);
+                               DO_MINMAX(co, min, max);                
+                               ok= 1;
+                       }
                }
        }
 
@@ -3663,106 +3628,56 @@ int PE_minmax(Scene *scene, float *min, float *max)
 /************************ particle edit toggle operator ************************/
 
 /* initialize needed data for bake edit */
-static void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys)
+static void PE_create_particle_edit(Scene *scene, Object *ob, ParticleSystem *psys)
 {
-       PTCacheEdit *edit= psys ? psys->edit : cache->edit;
-       POINT_P; KEY_K;
-       ParticleData *pa = NULL;
+       ParticleEdit *edit= psys->edit;
+       ParticleData *pa;
+       ParticleEditKey *key;
        HairKey *hkey;
-       int totpoint;
-
-       if(!psys && !cache)
-               return;
+       int i, k, totpart= psys->totpart, alloc=1;
 
-       if(cache && cache->flag & PTCACHE_DISK_CACHE)
+       if((psys->flag & PSYS_EDITED)==0)
                return;
 
-       if(!edit) {
-               totpoint = psys ? psys->totpart : ((PTCacheMem*)cache->mem_cache.first)->totpoint;
-
-               edit= MEM_callocN(sizeof(PTCacheEdit), "PE_create_particle_edit");
-               edit->points=MEM_callocN(totpoint*sizeof(PTCacheEditPoint),"PTCacheEditPoints");
-               edit->totpoint = totpoint;
-
-               if(psys && !cache) {
-                       psys->edit= edit;
-                       edit->psys = psys;
-
-                       psys->free_edit= PE_free_ptcache_edit;
-
-                       edit->pathcache = NULL;
-                       edit->pathcachebufs.first = edit->pathcachebufs.last = NULL;
+       if(edit) {
+               int newtotkeys= psys_count_keys(psys);
 
-                       pa = psys->particles;
-                       LOOP_POINTS {
-                               point->totkey = pa->totkey;
-                               point->keys= MEM_callocN(point->totkey*sizeof(PTCacheEditKey),"ParticleEditKeys");
-                               point->flag |= PEP_EDIT_RECALC;
+               if(newtotkeys == edit->totkeys)
+                       alloc=0;
+       }
 
-                               hkey = pa->hair;
-                               LOOP_KEYS {
-                                       key->co= hkey->co;
-                                       key->time= &hkey->time;
-                                       key->flag= hkey->editflag;
-                                       key->flag |= PEK_USE_WCO;
-                                       hkey++;
-                               }
-                               pa++;
-                       }
+       if(alloc) {
+               if(edit) {
+                       printf("ParticleEdit exists already! Poke jahka!");
+                       PE_free_particle_edit(psys);
                }
-               else {
-                       PTCacheMem *pm;
-                       int totframe=0;
-
-                       cache->edit= edit;
-                       cache->free_edit= PE_free_ptcache_edit;
-                       edit->psys = NULL;
-
-                       for(pm=cache->mem_cache.first; pm; pm=pm->next)
-                               totframe++;
-
-                       for(pm=cache->mem_cache.first; pm; pm=pm->next) {
-                               BKE_ptcache_mem_init_pointers(pm);
-
-                               LOOP_POINTS {
-                                       if(psys) {
-                                               pa = psys->particles + p;
-                                               if((pm->next && pm->next->frame < pa->time)
-                                                       || (pm->prev && pm->prev->frame >= pa->dietime)) {
-                                                               BKE_ptcache_mem_incr_pointers(pm);
-                                                               continue;
-                                                       }
-                                       }
 
-                                       if(!point->totkey) {
-                                               key = point->keys = MEM_callocN(totframe*sizeof(PTCacheEditKey),"ParticleEditKeys");
-                                               point->flag |= PEP_EDIT_RECALC;
-                                       }
-                                       else
-                                               key = point->keys + point->totkey;
+               edit= psys->edit=MEM_callocN(sizeof(ParticleEdit), "PE_create_particle_edit");
+               psys->free_edit= PE_free_particle_edit;
 
-                                       key->co = pm->cur[BPHYS_DATA_LOCATION];
-                                       key->vel = pm->cur[BPHYS_DATA_VELOCITY];
-                                       key->rot = pm->cur[BPHYS_DATA_ROTATION];
-                                       key->ftime = (float)pm->frame;
-                                       key->time = &key->ftime;
-                                       BKE_ptcache_mem_incr_pointers(pm);
+               edit->keys=MEM_callocN(totpart*sizeof(ParticleEditKey*),"ParticleEditKey array");
 
-                                       point->totkey++;
-                               }
+               LOOP_PARTICLES(i, pa) {
+                       key= edit->keys[i]= MEM_callocN(pa->totkey*sizeof(ParticleEditKey),"ParticleEditKeys");
+                       for(k=0, hkey=pa->hair; k<pa->totkey; k++, hkey++, key++) {
+                               key->co= hkey->co;
+                               key->time= &hkey->time;
+                               key->flag= hkey->editflag;
                        }
-                       psys = NULL;
                }
 
+               edit->totkeys= psys_count_keys(psys);
+
                UI_GetThemeColor3ubv(TH_EDGE_SELECT, edit->sel_col);
                UI_GetThemeColor3ubv(TH_WIRE, edit->nosel_col);
+       }
 
-               recalc_lengths(edit);
-               if(psys && !cache)
-                       recalc_emitter_field(ob, psys);
-               PE_update_object(scene, ob, 1);
+       recalc_lengths(psys);
+       recalc_emitter_field(ob, psys);
+       psys_update_world_cos(ob, psys);
 
-               PTCacheUndo_clear(edit);
+       if(alloc) {
+               ParticleUndo_clear(psys);
                PE_undo_push(scene, "Original");
        }
 }
@@ -3775,16 +3690,30 @@ static int particle_edit_toggle_poll(bContext *C)
        if(!scene || !ob || ob->id.lib)
                return 0;
        
-       return (ob->particlesystem.first || modifiers_findByType(ob, eModifierType_Cloth) || modifiers_findByType(ob, eModifierType_Softbody));
+       return (ob->particlesystem.first != NULL);
 }
 
 static int particle_edit_toggle_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, PE_settings(scene)->edittype);
+       ParticleSystem *psys= PE_get_current(scene, ob);
+       
+       if(psys==NULL) {
+               psys= ob->particlesystem.first;
+               psys->flag |= PSYS_CURRENT;
+       }
 
        if(!(ob->mode & OB_MODE_PARTICLE_EDIT)) {
+               if(psys && psys->part->type == PART_HAIR && psys->flag & PSYS_EDITED) {
+                       if(psys_check_enabled(ob, psys)) {
+                               if(psys->edit==NULL)
+                                       PE_create_particle_edit(scene, ob, psys);
+
+                               psys_update_world_cos(ob, psys);
+                       }
+               }
+
                ob->mode |= OB_MODE_PARTICLE_EDIT;
                toggle_particle_cursor(C, 1);
                WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_PARTICLE, NULL);
@@ -3817,65 +3746,112 @@ void PARTICLE_OT_particle_edit_toggle(wmOperatorType *ot)
 
 /************************ set editable operator ************************/
 
-static int clear_edited_exec(bContext *C, wmOperator *op)
+static int set_editable_exec(bContext *C, wmOperator *op)
 {
        Scene *scene= CTX_data_scene(C);
        Object *ob= CTX_data_active_object(C);
-       ParticleSystem *psys = psys_get_current(ob);
+       ParticleSystem *psys= PE_get_current(scene, ob);
        
-       if(psys->edit) {
-               if(psys->edit->edited || 1) { // XXX okee("Lose changes done in particle mode?")) 
-                       PE_free_ptcache_edit(psys->edit);
-
-                       psys->edit = NULL;
-                       psys->free_edit = NULL;
+       if(psys->flag & PSYS_EDITED) {
+               if(1) { // XXX okee("Lose changes done in particle mode?")) {
+                       if(psys->edit)
+                               PE_free_particle_edit(psys);
 
+                       psys->flag &= ~PSYS_EDITED;
                        psys->recalc |= PSYS_RECALC_RESET;
 
-                       psys_reset(psys, PSYS_RESET_DEPSGRAPH);
                        DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
                }
        }
+       else {
+               if(psys_check_enabled(ob, psys)) {
+                       psys->flag |= PSYS_EDITED;
+
+                       if(ob->mode & OB_MODE_PARTICLE_EDIT)
+                               PE_create_particle_edit(scene, ob, psys);
+               }
+               else
+                       BKE_report(op->reports, RPT_ERROR, "Particle system not enabled, skipping set editable");
+       }
 
        return OPERATOR_FINISHED;
 }
 
-void PARTICLE_OT_edited_clear(wmOperatorType *ot)
+void PARTICLE_OT_editable_set(wmOperatorType *ot)
 {
        /* identifiers */
-       ot->name= "Clear Edited";
-       ot->idname= "PARTICLE_OT_edited_clear";
+       ot->name= "Set Editable";
+       ot->idname= "PARTICLE_OT_editable_set";
        
        /* api callbacks */
-       ot->exec= clear_edited_exec;
+       ot->exec= set_editable_exec;
        ot->poll= particle_edit_toggle_poll;
 
        /* flags */
        ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
 }
 
+/*********************** change active **************************/
+
+void PE_change_act(void *ob_v, void *act_v)
+{
+       Scene *scene= NULL; // XXX
+       Object *ob= ob_v;
+       ParticleSystem *psys;
+       short act= *((short*)act_v) - 1;
+
+       if((psys=psys_get_current(ob)))
+               psys->flag &= ~PSYS_CURRENT;
+
+       if(act>=0) {
+               if((psys=BLI_findlink(&ob->particlesystem,act))) {
+                       psys->flag |= PSYS_CURRENT;
+
+                       if(psys_check_enabled(ob, psys)) {
+                               if(ob->mode & OB_MODE_PARTICLE_EDIT && !psys->edit)
+                                       PE_create_particle_edit(scene, ob, psys);
+                               psys_update_world_cos(ob, psys);
+                       }
+               }
+       }
+}
+
+void PE_change_act_psys(Scene *scene, Object *ob, ParticleSystem *psys)
+{
+       ParticleSystem *p;
+       
+       if((p=psys_get_current(ob)))
+               p->flag &= ~PSYS_CURRENT;
+       
+       psys->flag |= PSYS_CURRENT;
+       
+       if(psys_check_enabled(ob, psys)) {
+               if(ob->mode & OB_MODE_PARTICLE_EDIT && !psys->edit)
+                       PE_create_particle_edit(scene, ob, psys);
+
+               psys_update_world_cos(ob, psys);
+       }
+}
+
 /*********************** specials menu **************************/
 
 static int specials_menu_invoke(bContext *C, wmOperator *op, wmEvent *event)
 {
        Scene *scene= CTX_data_scene(C);
        ParticleEditSettings *pset=PE_settings(scene);
-       PTCacheEdit *edit = PE_get_current(scene, CTX_data_active_object(C));
        uiPopupMenu *pup;
        uiLayout *layout;
 
        pup= uiPupMenuBegin(C, "Specials", 0);
        layout= uiPupMenuLayout(pup);
 
-       if(edit->psys) {
-               uiItemO(layout, NULL, 0, "PARTICLE_OT_rekey");
-               if(pset->selectmode & SCE_SELECT_POINT) {
-                       uiItemO(layout, NULL, 0, "PARTICLE_OT_subdivide");
-                       uiItemO(layout, NULL, 0, "PARTICLE_OT_select_first");
-                       uiItemO(layout, NULL, 0, "PARTICLE_OT_select_last");
-               }
-               uiItemO(layout, NULL, 0, "PARTICLE_OT_remove_doubles");
+       uiItemO(layout, NULL, 0, "PARTICLE_OT_rekey");
+       if(pset->selectmode & SCE_SELECT_POINT) {
+               uiItemO(layout, NULL, 0, "PARTICLE_OT_subdivide");
+               uiItemO(layout, NULL, 0, "PARTICLE_OT_select_first");
+               uiItemO(layout, NULL, 0, "PARTICLE_OT_select_last");
        }
+       uiItemO(layout, NULL, 0, "PARTICLE_OT_remove_doubles");
 
        uiPupMenuEnd(C, pup);
 
@@ -3920,7 +3896,7 @@ void ED_operatortypes_particle(void)
        WM_operatortype_append(PARTICLE_OT_specials_menu);
 
        WM_operatortype_append(PARTICLE_OT_particle_edit_toggle);
-       WM_operatortype_append(PARTICLE_OT_edited_clear);
+       WM_operatortype_append(PARTICLE_OT_editable_set);
 }
 
 void ED_keymap_particle(wmWindowManager *wm)