merged from trunk 20741:20848
[blender-staging.git] / source / blender / blenkernel / intern / particle_system.c
index 31e246f66b9a7ea00837a026f28ede25d7ef55da..596c27a14f511b0575796106caa18a1b3867962b 100644 (file)
 #include "DNA_object_force.h"
 #include "DNA_object_types.h"
 #include "DNA_material_types.h"
-#include "DNA_ipo_types.h"
 #include "DNA_curve_types.h"
 #include "DNA_group_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_texture_types.h"
+#include "DNA_ipo_types.h" // XXX old animation system stuff... to be removed!
 
 #include "BLI_rand.h"
 #include "BLI_jitter.h"
@@ -58,7 +58,6 @@
 #include "BLI_threads.h"
 
 #include "BKE_anim.h"
-#include "BKE_bad_level_calls.h"
 #include "BKE_cdderivedmesh.h"
 #include "BKE_collision.h"
 #include "BKE_displist.h"
@@ -69,7 +68,6 @@
 #include "BKE_DerivedMesh.h"
 #include "BKE_object.h"
 #include "BKE_material.h"
-#include "BKE_ipo.h"
 #include "BKE_softbody.h"
 #include "BKE_depsgraph.h"
 #include "BKE_lattice.h"
 
 #include "PIL_time.h"
 
-#include "BSE_headerbuttons.h"
-
-#include "blendef.h"
-
 #include "RE_shader_ext.h"
 
 /* fluid sim particle import */
 #ifndef DISABLE_ELBEEM
 #include "DNA_object_fluidsim.h"
 #include "LBM_fluidsim.h"
-#include "elbeem.h"
 #include <zlib.h>
 #include <string.h>
 
@@ -225,7 +218,7 @@ static void realloc_particles(Object *ob, ParticleSystem *psys, int new_totpart)
        psys->totpart=totpart;
 }
 
-static int get_psys_child_number(ParticleSystem *psys)
+static int get_psys_child_number(struct Scene *scene, ParticleSystem *psys)
 {
        int nbr;
 
@@ -234,15 +227,15 @@ static int get_psys_child_number(ParticleSystem *psys)
 
        if(psys->renderdata) {
                nbr= psys->part->ren_child_nbr;
-               return get_render_child_particle_number(&G.scene->r, nbr);
+               return get_render_child_particle_number(&scene->r, nbr);
        }
        else
                return psys->part->child_nbr;
 }
 
-static int get_psys_tot_child(ParticleSystem *psys)
+static int get_psys_tot_child(struct Scene *scene, ParticleSystem *psys)
 {
-       return psys->totpart*get_psys_child_number(psys);
+       return psys->totpart*get_psys_child_number(scene, psys);
 }
 
 static void alloc_child_particles(ParticleSystem *psys, int tot)
@@ -938,7 +931,7 @@ static int compare_orig_index(const void *p1, const void *p2)
 /* 6. and we're done!                                                                          */
 
 /* This is to denote functionality that does not yet work with mesh - only derived mesh */
-int psys_threads_init_distribution(ParticleThread *threads, DerivedMesh *finaldm, int from)
+int psys_threads_init_distribution(ParticleThread *threads, Scene *scene, DerivedMesh *finaldm, int from)
 {
        ParticleThreadContext *ctx= threads[0].ctx;
        Object *ob= ctx->ob;
@@ -969,7 +962,7 @@ int psys_threads_init_distribution(ParticleThread *threads, DerivedMesh *finaldm
                return 0;
 
        if (!finaldm->deformedOnly && !CustomData_has_layer( &finaldm->faceData, CD_ORIGINDEX ) ) {
-               error("Can't paint with the current modifier stack, disable destructive modifiers");
+// XXX         error("Can't paint with the current modifier stack, disable destructive modifiers");
                return 0;
        }
 
@@ -991,7 +984,7 @@ int psys_threads_init_distribution(ParticleThread *threads, DerivedMesh *finaldm
 
                        BLI_kdtree_balance(tree);
 
-                       totpart=get_psys_tot_child(psys);
+                       totpart=get_psys_tot_child(scene, psys);
                        cfrom=from=PART_FROM_FACE;
 
                        if(part->flag&PART_CHILD_SEAMS){
@@ -1040,9 +1033,9 @@ int psys_threads_init_distribution(ParticleThread *threads, DerivedMesh *finaldm
                }
                else{
                        /* no need to figure out distribution */
-                       int child_nbr= get_psys_child_number(psys);
+                       int child_nbr= get_psys_child_number(scene, psys);
 
-                       totpart= get_psys_tot_child(psys);
+                       totpart= get_psys_tot_child(scene, psys);
                        alloc_child_particles(psys, totpart);
                        cpa=psys->child;
                        for(i=0; i<child_nbr; i++){
@@ -1389,16 +1382,16 @@ int psys_threads_init_distribution(ParticleThread *threads, DerivedMesh *finaldm
        return 1;
 }
 
-static void distribute_particles_on_dm(DerivedMesh *finaldm, Object *ob, ParticleSystem *psys, int from)
+static void distribute_particles_on_dm(DerivedMesh *finaldm, Scene *scene, Object *ob, ParticleSystem *psys, int from)
 {
        ListBase threads;
        ParticleThread *pthreads;
        ParticleThreadContext *ctx;
        int i, totthread;
 
-       pthreads= psys_threads_create(ob, psys);
+       pthreads= psys_threads_create(scene, ob, psys);
 
-       if(!psys_threads_init_distribution(pthreads, finaldm, from)) {
+       if(!psys_threads_init_distribution(pthreads, scene, finaldm, from)) {
                psys_threads_free(pthreads);
                return;
        }
@@ -1438,7 +1431,7 @@ static void distribute_particles_on_shape(Object *ob, ParticleSystem *psys, int
                pa->num= -1;
        }
 }
-static void distribute_particles(Object *ob, ParticleSystem *psys, int from)
+static void distribute_particles(Scene *scene, Object *ob, ParticleSystem *psys, int from)
 {
        ParticleSystemModifierData *psmd=0;
        int distr_error=0;
@@ -1446,7 +1439,7 @@ static void distribute_particles(Object *ob, ParticleSystem *psys, int from)
 
        if(psmd){
                if(psmd->dm)
-                       distribute_particles_on_dm(psmd->dm,ob,psys,from);
+                       distribute_particles_on_dm(psmd->dm, scene, ob, psys, from);
                else
                        distr_error=1;
        }
@@ -1468,20 +1461,21 @@ static void distribute_particles(Object *ob, ParticleSystem *psys, int from)
 }
 
 /* threaded child particle distribution and path caching */
-ParticleThread *psys_threads_create(struct Object *ob, struct ParticleSystem *psys)
+ParticleThread *psys_threads_create(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys)
 {
        ParticleThread *threads;
        ParticleThreadContext *ctx;
        int i, totthread;
 
-       if(G.scene->r.mode & R_FIXED_THREADS)
-               totthread= G.scene->r.threads;
+       if(scene->r.mode & R_FIXED_THREADS)
+               totthread= scene->r.threads;
        else
                totthread= BLI_system_thread_count();
        
        threads= MEM_callocN(sizeof(ParticleThread)*totthread, "ParticleThread");
        ctx= MEM_callocN(sizeof(ParticleThreadContext), "ParticleThreadContext");
 
+       ctx->scene= scene;
        ctx->ob= ob;
        ctx->psys= psys;
        ctx->psmd= psys_get_modifier(ob, psys);
@@ -1519,8 +1513,8 @@ void psys_threads_free(ParticleThread *threads)
                MEM_freeN(ctx->vg_roughe);
 
        if(ctx->psys->lattice){
-               end_latt_deform();
-               ctx->psys->lattice=0;
+               end_latt_deform(ctx->psys->lattice);
+               ctx->psys->lattice= NULL;
        }
 
        /* distribution */
@@ -1551,7 +1545,7 @@ void initialize_particle(ParticleData *pa, int p, Object *ob, ParticleSystem *ps
        ParticleSettings *part;
        ParticleTexture ptex;
        Material *ma=0;
-       IpoCurve *icu=0;
+       //IpoCurve *icu=0; // XXX old animation system
        int totpart;
        float rand,length;
 
@@ -1574,9 +1568,9 @@ void initialize_particle(ParticleData *pa, int p, Object *ob, ParticleSystem *ps
        pa->lifetime= part->lifetime*ptex.life;
 
        if(part->type==PART_HAIR)
-               pa->time=0.0f;
+               pa->time= 0.0f;
        else if(part->type==PART_REACTOR && (part->flag&PART_REACT_STA_END)==0)
-               pa->time=MAXFRAMEF;
+               pa->time= 300000.0f;    /* max frame */
        else{
                //icu=find_ipocurve(psys->part->ipo,PART_EMIT_TIME);
                //if(icu){
@@ -1592,13 +1586,15 @@ void initialize_particle(ParticleData *pa, int p, Object *ob, ParticleSystem *ps
                pa->lifetime=100.0f;
        }
        else{
+#if 0 // XXX old animation system
                icu=find_ipocurve(psys->part->ipo,PART_EMIT_LIFE);
                if(icu){
                        calc_icu(icu,100*ptex.time);
                        pa->lifetime*=icu->curval;
                }
+#endif // XXX old animation system
 
-       /* need to get every rand even if we don't use them so that randoms don't affect eachother */
+       /* need to get every rand even if we don't use them so that randoms don't affect each other */
                rand= BLI_frand();
                if(part->randlife!=0.0)
                        pa->lifetime*= 1.0f - part->randlife*rand;
@@ -1649,7 +1645,7 @@ void initialize_particle(ParticleData *pa, int p, Object *ob, ParticleSystem *ps
 }
 static void initialize_all_particles(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd)
 {
-       IpoCurve *icu=0;
+       //IpoCurve *icu=0; // XXX old animation system
        ParticleData *pa;
        int p, totpart=psys->totpart;
 
@@ -1657,6 +1653,7 @@ static void initialize_all_particles(Object *ob, ParticleSystem *psys, ParticleS
                initialize_particle(pa,p,ob,psys,psmd);
        
        if(psys->part->type != PART_FLUID) {
+#if 0 // XXX old animation system
                icu=find_ipocurve(psys->part->ipo,PART_EMIT_FREQ);
                if(icu){
                        float time=psys->part->sta, end=psys->part->end;
@@ -1665,6 +1662,7 @@ static void initialize_all_particles(Object *ob, ParticleSystem *psys, ParticleS
                        p=0;
                        pa=psys->particles;
 
+
                        calc_icu(icu,time);
                        v1=icu->curval;
                        if(v1<0.0f) v1=0.0f;
@@ -1705,16 +1703,17 @@ static void initialize_all_particles(Object *ob, ParticleSystem *psys, ParticleS
                                pa->flag |= PARS_UNEXIST;
                        }
                }
+#endif // XXX old animation system
        }
 }
 /* sets particle to the emitter surface with initial velocity & rotation */
-void reset_particle(ParticleData *pa, ParticleSystem *psys, ParticleSystemModifierData *psmd, Object *ob,
+void reset_particle(Scene *scene, ParticleData *pa, ParticleSystem *psys, ParticleSystemModifierData *psmd, Object *ob,
                                        float dtime, float cfra, float *vg_vel, float *vg_tan, float *vg_rot)
 {
        ParticleSettings *part;
        ParticleTexture ptex;
        ParticleKey state;
-       IpoCurve *icu=0;
+       //IpoCurve *icu=0; // XXX old animation system
        float fac, phasefac, nor[3]={0,0,0},loc[3],tloc[3],vel[3]={0.0,0.0,0.0},rot[4],q2[4];
        float r_vel[3],r_ave[3],r_rot[4],p_vel[3]={0.0,0.0,0.0};
        float x_vec[3]={1.0,0.0,0.0}, utan[3]={0.0,1.0,0.0}, vtan[3]={0.0,0.0,1.0}, rot_vec[3]={0.0,0.0,0.0};
@@ -1738,7 +1737,7 @@ void reset_particle(ParticleData *pa, ParticleSystem *psys, ParticleSystemModifi
                if(pa->num == -1)
                        memset(&state, 0, sizeof(state));
                else
-                       psys_get_particle_state(tob,tpsys,pa->num,&state,1);
+                       psys_get_particle_state(scene, tob,tpsys,pa->num,&state,1);
                psys_get_from_key(&state,loc,nor,rot,0);
 
                QuatMulVecf(rot,vtan);
@@ -1759,7 +1758,7 @@ void reset_particle(ParticleData *pa, ParticleSystem *psys, ParticleSystemModifi
        else{
                /* get precise emitter matrix if particle is born */
                if(part->type!=PART_HAIR && pa->time < cfra && pa->time >= psys->cfra)
-                       where_is_object_time(ob,pa->time);
+                       where_is_object_time(scene, ob,pa->time);
 
                /* get birth location from object               */
                psys_particle_on_emitter(psmd,part->from,pa->num, pa->num_dmcache, pa->fuv,pa->foffset,loc,nor,utan,vtan,0,0);
@@ -1859,11 +1858,13 @@ void reset_particle(ParticleData *pa, ParticleSystem *psys, ParticleSystemModifi
        if(part->partfac!=0.0)
                VECADDFAC(vel,vel,p_vel,part->partfac);
 
+#if 0 // XXX old animation system
        icu=find_ipocurve(psys->part->ipo,PART_EMIT_VEL);
        if(icu){
                calc_icu(icu,100*((pa->time-part->sta)/(part->end-part->sta)));
                ptex.ivel*=icu->curval;
        }
+#endif // XXX old animation system
 
        VecMulf(vel,ptex.ivel);
        
@@ -1933,11 +1934,13 @@ void reset_particle(ParticleData *pa, ParticleSystem *psys, ParticleSystemModifi
                Normalize(pa->state.ave);
                VecMulf(pa->state.ave,part->avefac);
 
+#if 0 // XXX old animation system
                icu=find_ipocurve(psys->part->ipo,PART_EMIT_AVE);
                if(icu){
                        calc_icu(icu,100*((pa->time-part->sta)/(part->end-part->sta)));
                        VecMulf(pa->state.ave,icu->curval);
                }
+#endif // XXX old animation system
        }
 
        pa->dietime = pa->time + pa->lifetime;
@@ -1950,7 +1953,7 @@ void reset_particle(ParticleData *pa, ParticleSystem *psys, ParticleSystemModifi
        pa->stick_ob = 0;
        pa->flag &= ~PARS_STICKY;
 }
-static void reset_all_particles(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float dtime, float cfra, int from)
+static void reset_all_particles(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float dtime, float cfra, int from)
 {
        ParticleData *pa;
        int p, totpart=psys->totpart;
@@ -1959,7 +1962,7 @@ static void reset_all_particles(Object *ob, ParticleSystem *psys, ParticleSystem
        float *vg_rot=psys_cache_vgroup(psmd->dm,psys,PSYS_VG_ROT);
        
        for(p=from, pa=psys->particles+from; p<totpart; p++, pa++)
-               reset_particle(pa, psys, psmd, ob, dtime, cfra, vg_vel, vg_tan, vg_rot);
+               reset_particle(scene, pa, psys, psmd, ob, dtime, cfra, vg_vel, vg_tan, vg_rot);
 
        if(vg_vel)
                MEM_freeN(vg_vel);
@@ -2019,7 +2022,7 @@ int psys_count_keyed_targets(Object *ob, ParticleSystem *psys)
        return select;
 }
 
-static void set_keyed_keys(Object *ob, ParticleSystem *psys)
+static void set_keyed_keys(Scene *scene, Object *ob, ParticleSystem *psys)
 {
        Object *kob = ob;
        ParticleSystem *kpsys = psys;
@@ -2053,7 +2056,7 @@ static void set_keyed_keys(Object *ob, ParticleSystem *psys)
                        (pa->keys + k)->time = -1.0; /* use current time */
 
                        if(kpsys->totpart > 0)
-                               psys_get_particle_state(kob, kpsys, i%kpsys->totpart, pa->keys + k, 1);
+                               psys_get_particle_state(scene, kob, kpsys, i%kpsys->totpart, pa->keys + k, 1);
 
                        if(k==0)
                                pa->keys->time = pa->time;
@@ -2317,7 +2320,7 @@ static void do_texture_effector(Tex *tex, short mode, short is_2d, float nabla,
 
        VecAddf(field,field,mag_vec);
 }
-static void add_to_effectors(ListBase *lb, Object *ob, Object *obsrc, ParticleSystem *psys)
+static void add_to_effectors(ListBase *lb, Scene *scene, Object *ob, Object *obsrc, ParticleSystem *psys)
 {
        ParticleEffectorCache *ec;
        PartDeflect *pd= ob->pd;
@@ -2329,7 +2332,7 @@ static void add_to_effectors(ListBase *lb, Object *ob, Object *obsrc, ParticleSy
                                Curve *cu= ob->data;
                                if(cu->flag & CU_PATH) {
                                        if(cu->path==NULL || cu->path->data==NULL)
-                                               makeDispListCurveTypes(ob, 0);
+                                               makeDispListCurveTypes(scene, ob, 0);
                                        if(cu->path && cu->path->data) {
                                                type |= PSYS_EC_EFFECTOR;
                                        }
@@ -2400,7 +2403,7 @@ static void add_to_effectors(ListBase *lb, Object *ob, Object *obsrc, ParticleSy
        }
 }
 
-static void psys_init_effectors_recurs(Object *ob, Object *obsrc, ParticleSystem *psys, ListBase *listb, int level)
+static void psys_init_effectors_recurs(Scene *scene, Object *ob, Object *obsrc, ParticleSystem *psys, ListBase *listb, int level)
 {
        Group *group;
        GroupObject *go;
@@ -2410,17 +2413,17 @@ static void psys_init_effectors_recurs(Object *ob, Object *obsrc, ParticleSystem
 
        if(ob->lay & layer) {
                if(ob->pd || ob->particlesystem.first)
-                       add_to_effectors(listb, ob, obsrc, psys);
+                       add_to_effectors(listb, scene, ob, obsrc, psys);
 
                if(ob->dup_group) {
                        group= ob->dup_group;
                        for(go= group->gobject.first; go; go= go->next)
-                               psys_init_effectors_recurs(go->ob, obsrc, psys, listb, level+1);
+                               psys_init_effectors_recurs(scene, go->ob, obsrc, psys, listb, level+1);
                }
        }
 }
 
-void psys_init_effectors(Object *obsrc, Group *group, ParticleSystem *psys)
+void psys_init_effectors(Scene *scene, Object *obsrc, Group *group, ParticleSystem *psys)
 {
        ListBase *listb= &psys->effectors;
        Base *base;
@@ -2431,11 +2434,11 @@ void psys_init_effectors(Object *obsrc, Group *group, ParticleSystem *psys)
                GroupObject *go;
                
                for(go= group->gobject.first; go; go= go->next)
-                       psys_init_effectors_recurs(go->ob, obsrc, psys, listb, 0);
+                       psys_init_effectors_recurs(scene, go->ob, obsrc, psys, listb, 0);
        }
        else {
-               for(base = G.scene->base.first; base; base= base->next)
-                       psys_init_effectors_recurs(base->object, obsrc, psys, listb, 0);
+               for(base = scene->base.first; base; base= base->next)
+                       psys_init_effectors_recurs(scene, base->object, obsrc, psys, listb, 0);
        }
 }
 
@@ -2471,7 +2474,7 @@ void psys_end_effectors(ParticleSystem *psys)
        }
 }
 
-static void precalc_effectors(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra)
+static void precalc_effectors(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra)
 {
        ListBase *lb=&psys->effectors;
        ParticleEffectorCache *ec;
@@ -2535,7 +2538,7 @@ static void precalc_effectors(Object *ob, ParticleSystem *psys, ParticleSystemMo
                                        ec->tree=tree;
 
                                        for(p=0, epa=epsys->particles; p<totepart; p++,epa++)
-                                               if(epa->alive==PARS_ALIVE && psys_get_particle_state(eob,epsys,p,&state,0))
+                                               if(epa->alive==PARS_ALIVE && psys_get_particle_state(scene, eob,epsys,p,&state,0))
                                                        BLI_kdtree_insert(tree, p, state.co, NULL);
 
                                        BLI_kdtree_balance(tree);
@@ -2553,7 +2556,7 @@ static void precalc_effectors(Object *ob, ParticleSystem *psys, ParticleSystemMo
 
 
 /* calculate forces that all effectors apply to a particle*/
-void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, ParticleSystem *psys, float *rootco, float *force_field, float *vel,float framestep, float cfra)
+void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Scene *scene, Object *ob, ParticleSystem *psys, float *rootco, float *force_field, float *vel,float framestep, float cfra)
 {
        Object *eob;
        ParticleSystem *epsys;
@@ -2587,7 +2590,7 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P
                        if(ec->type & PSYS_EC_EFFECTOR){
                                pd=eob->pd;
                                if(psys->part->type!=PART_HAIR && psys->part->integrator)
-                                       where_is_object_time(eob,cfra);
+                                       where_is_object_time(scene, eob,cfra);
 
                                if(pd && pd->flag&PFIELD_SURFACE) {
                                        surmd = (SurfaceModifierData *)modifiers_findByType ( eob, eModifierType_Surface );
@@ -2628,7 +2631,7 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P
                                                                        pd->flag & PFIELD_TEX_OBJECT, (pd->flag & PFIELD_TEX_ROOTCO) ? rootco : state->co, eob->obmat,
                                                                        pd->f_strength, falloff, force_field);
                                } else {
-                                       do_physical_effector(eob, state->co, pd->forcefield,pd->f_strength,distance,
+                                       do_physical_effector(scene, eob, state->co, pd->forcefield,pd->f_strength,distance,
                                                                                falloff,0.0,pd->f_damp,eob->obmat[2],vec_to_part,
                                                                                state->vel,force_field,pd->flag&PFIELD_PLANAR,ec->rng,pd->f_noise,charge,pa->size);
                                }
@@ -2652,7 +2655,7 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P
                                        p=0;
                                }
 
-                               epsys->lattice=psys_get_lattice(ob,psys);
+                               epsys->lattice= psys_get_lattice(scene, ob, psys);
 
                                for(; p<totepart; p++){
                                        /* particle skips itself as effector */
@@ -2660,7 +2663,7 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P
 
                                        epa = epsys->particles + p;
                                        estate.time=cfra;
-                                       if(psys_get_particle_state(eob,epsys,p,&estate,0)){
+                                       if(psys_get_particle_state(scene, eob,epsys,p,&estate,0)){
                                                VECSUB(vec_to_part, state->co, estate.co);
                                                distance = VecLength(vec_to_part);
                                                
@@ -2672,22 +2675,22 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P
                                                        if(falloff<=0.0f)
                                                                ;       /* don't do anything */
                                                        else
-                                                               do_physical_effector(eob, state->co, pd->forcefield,pd->f_strength,distance,
+                                                               do_physical_effector(scene, eob, state->co, pd->forcefield,pd->f_strength,distance,
                                                                falloff,epart->size,pd->f_damp,estate.vel,vec_to_part,
                                                                state->vel,force_field,0, ec->rng, pd->f_noise,charge,pa->size);
                                                }
                                        }
                                        else if(pd && pd->forcefield==PFIELD_HARMONIC && cfra-framestep <= epa->dietime && cfra>epa->dietime){
                                                /* first step after key release */
-                                               psys_get_particle_state(eob,epsys,p,&estate,1);
+                                               psys_get_particle_state(scene, eob,epsys,p,&estate,1);
                                                VECADD(vel,vel,estate.vel);
                                                /* TODO: add rotation handling here too */
                                        }
                                }
 
                                if(epsys->lattice){
-                                       end_latt_deform();
-                                       epsys->lattice=0;
+                                       end_latt_deform(epsys->lattice);
+                                       epsys->lattice= NULL;
                                }
                        }
                }
@@ -2698,7 +2701,7 @@ void do_effectors(int pa_no, ParticleData *pa, ParticleKey *state, Object *ob, P
 /*                     Newtonian physics                                       */
 /************************************************/
 /* gathers all forces that effect particles and calculates a new state for the particle */
-static void apply_particle_forces(int pa_no, ParticleData *pa, Object *ob, ParticleSystem *psys, ParticleSettings *part, float timestep, float dfra, float cfra)
+static void apply_particle_forces(Scene *scene, int pa_no, ParticleData *pa, Object *ob, ParticleSystem *psys, ParticleSettings *part, float timestep, float dfra, float cfra)
 {
        ParticleKey states[5], tkey;
        float force[3],tvel[3],dx[4][3],dv[4][3];
@@ -2730,7 +2733,7 @@ static void apply_particle_forces(int pa_no, ParticleData *pa, Object *ob, Parti
                tvel[0]=tvel[1]=tvel[2]=0.0;
                /* add effectors */
                if(part->type != PART_HAIR)
-                       do_effectors(pa_no,pa,states+i,ob,psys,states->co,force,tvel,dfra,fra);
+                       do_effectors(pa_no,pa,states+i,scene, ob, psys,states->co,force,tvel,dfra,fra);
 
                /* calculate air-particle interaction */
                if(part->dragfac!=0.0f){
@@ -2834,7 +2837,7 @@ static void apply_particle_forces(int pa_no, ParticleData *pa, Object *ob, Parti
        tkey.time=pa->state.time;
 
        if(part->type != PART_HAIR) {
-               if(do_guide(&tkey,pa_no,time,&psys->effectors)) {
+               if(do_guide(scene, &tkey, pa_no, time, &psys->effectors)) {
                        VECCOPY(pa->state.co,tkey.co);
                        /* guides don't produce valid velocity */
                        VECSUB(pa->state.vel,tkey.co,pa->prev_state.co);
@@ -2899,7 +2902,7 @@ static void intersect_dm_quad_weights(float *v1, float *v2, float *v3, float *v4
 }
 
 /* check intersection with a derivedmesh */
-int psys_intersect_dm(Object *ob, DerivedMesh *dm, float *vert_cos, float *co1, float* co2, float *min_d, int *min_face, float *min_w,
+int psys_intersect_dm(Scene *scene, Object *ob, DerivedMesh *dm, float *vert_cos, float *co1, float* co2, float *min_d, int *min_face, float *min_w,
                                                  float *face_minmax, float *pa_minmax, float radius, float *ipoint)
 {
        MFace *mface=0;
@@ -2911,9 +2914,9 @@ int psys_intersect_dm(Object *ob, DerivedMesh *dm, float *vert_cos, float *co1,
        if(dm==0){
                psys_disable_all(ob);
 
-               dm=mesh_get_derived_final(ob,0);
+               dm=mesh_get_derived_final(scene, ob, 0);
                if(dm==0)
-                       dm=mesh_get_derived_deform(ob,0);
+                       dm=mesh_get_derived_deform(scene, ob, 0);
 
                psys_enable_all(ob);
 
@@ -3111,7 +3114,7 @@ static void particle_intersect_face(void *userdata, int index, const BVHTreeRay
 /* angular momentum <-> linear momentum and swept sphere - mesh collisions */
 /* 1. check for all possible deflectors for closest intersection on particle path */
 /* 2. if deflection was found kill the particle or calculate new coordinates */
-static void deflect_particle(Object *pob, ParticleSystemModifierData *psmd, ParticleSystem *psys, ParticleSettings *part, ParticleData *pa, int p, float timestep, float dfra, float cfra){
+static void deflect_particle(Scene *scene, Object *pob, ParticleSystemModifierData *psmd, ParticleSystem *psys, ParticleSettings *part, ParticleData *pa, int p, float timestep, float dfra, float cfra){
        Object *ob = NULL;
        ListBase *lb=&psys->effectors;
        ParticleEffectorCache *ec;
@@ -3144,7 +3147,7 @@ static void deflect_particle(Object *pob, ParticleSystemModifierData *psmd, Part
                                ob= ec->ob;
 
                                if(part->type!=PART_HAIR)
-                                       where_is_object_time(ob,cfra);
+                                       where_is_object_time(scene, ob,cfra);
 
                                /* particles should not collide with emitter at birth */
                                if(ob==pob && pa->time < cfra && pa->time >= psys->cfra)
@@ -3316,7 +3319,7 @@ static void deflect_particle(Object *pob, ParticleSystemModifierData *psmd, Part
 /************************************************/
 /*                     Boid physics                                            */
 /************************************************/
-static int boid_see_mesh(ListBase *lb, Object *pob, ParticleSystem *psys, float *vec1, float *vec2, float *loc, float *nor, float cfra)
+static int boid_see_mesh(ListBase *lb, Scene *scene, Object *pob, ParticleSystem *psys, float *vec1, float *vec2, float *loc, float *nor, float cfra)
 {
        Object *ob, *min_ob;
        DerivedMesh *dm;
@@ -3337,7 +3340,7 @@ static int boid_see_mesh(ListBase *lb, Object *pob, ParticleSystem *psys, float
                                ob= ec->ob;
 
                                if(psys->part->type!=PART_HAIR)
-                                       where_is_object_time(ob,cfra);
+                                       where_is_object_time(scene, ob,cfra);
 
                                if(ob==pob)
                                        dm=psmd->dm;
@@ -3355,7 +3358,7 @@ static int boid_see_mesh(ListBase *lb, Object *pob, ParticleSystem *psys, float
                                        Mat4MulVecfl(imat,co2);
                                }
 
-                               if(psys_intersect_dm(ob,dm,ec->vert_cos,co1,co2,&min_d,&min_face,min_w,ec->face_minmax,0,0,0))
+                               if(psys_intersect_dm(scene,ob,dm,ec->vert_cos,co1,co2,&min_d,&min_face,min_w,ec->face_minmax,0,0,0))
                                        min_ob=ob;
                        }
                }
@@ -3368,9 +3371,9 @@ static int boid_see_mesh(ListBase *lb, Object *pob, ParticleSystem *psys, float
                        else{
                                psys_disable_all(ob);
 
-                               dm=mesh_get_derived_final(ob,0);
+                               dm=mesh_get_derived_final(scene, ob, 0);
                                if(dm==0)
-                                       dm=mesh_get_derived_deform(ob,0);
+                                       dm=mesh_get_derived_deform(scene, ob, 0);
 
                                psys_enable_all(ob);
                        }
@@ -3473,7 +3476,7 @@ static int add_boid_acc(BoidVecFunc *bvf, float lat_max, float tan_max, float *l
        }
 }
 /* determines the acceleration that the boid tries to acchieve */
-static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleSystem *psys, ParticleSettings *part, KDTree *tree, float timestep, float cfra, float *acc)
+static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Scene *scene, Object *ob, ParticleSystem *psys, ParticleSettings *part, KDTree *tree, float timestep, float cfra, float *acc)
 {
        ParticleData *pars=psys->particles;
        KDTreeNearest ptn[MAX_BOIDNEIGHBOURS+1];
@@ -3507,7 +3510,7 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS
                                bvf->Copyf(dvec,pa->prev_state.vel);
                                bvf->Mulf(dvec,5.0f);
                                bvf->Addf(dvec,dvec,pa->prev_state.co);
-                               if(boid_see_mesh(&psys->effectors,ob,psys,pa->prev_state.co,dvec,ob_co,ob_nor,cfra)){
+                               if(boid_see_mesh(&psys->effectors,scene, ob,psys,pa->prev_state.co,dvec,ob_co,ob_nor,cfra)){
                                        float probelen = bvf->Length(dvec);
                                        float proj;
                                        float oblen;
@@ -3573,7 +3576,7 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS
                                                                count=BLI_kdtree_find_n_nearest(ec->tree,epart->boidneighbours,pa->prev_state.co,NULL,ptn2);
                                                                for(p=0; p<count; p++){
                                                                        state.time=-1.0;
-                                                                       if(psys_get_particle_state(eob,epsys,ptn2[p].index,&state,0)){
+                                                                       if(psys_get_particle_state(scene, eob,epsys,ptn2[p].index,&state,0)){
                                                                                VECSUB(dvec, state.co, pa->prev_state.co);
 
                                                                                distance = Normalize(dvec);
@@ -3720,7 +3723,7 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS
                                                                count=BLI_kdtree_find_n_nearest(ec->tree,epart->boidneighbours,pa->prev_state.co,NULL,ptn2);
                                                                for(p=0; p<count; p++){
                                                                        state.time=-1.0;
-                                                                       if(psys_get_particle_state(eob,epsys,ptn2[p].index,&state,0)){
+                                                                       if(psys_get_particle_state(scene, eob,epsys,ptn2[p].index,&state,0)){
                                                                                VECSUB(dvec, state.co, pa->prev_state.co);
 
                                                                                distance = Normalize(dvec);
@@ -3753,7 +3756,7 @@ static void boid_brain(BoidVecFunc *bvf, ParticleData *pa, Object *ob, ParticleS
        }
 }
 /* tries to realize the wanted acceleration */
-static void boid_body(BoidVecFunc *bvf, ParticleData *pa, ParticleSystem *psys, ParticleSettings *part, float timestep, float *acc)
+static void boid_body(Scene *scene, BoidVecFunc *bvf, ParticleData *pa, ParticleSystem *psys, ParticleSettings *part, float timestep, float *acc)
 {
        float dvec[3], bvec[3], length, max_vel=part->max_vel;
        float q2[4], q[4];
@@ -3880,14 +3883,14 @@ static void boid_body(BoidVecFunc *bvf, ParticleData *pa, ParticleSystem *psys,
                        Mat4MulVecfl(imat,co1);
                        Mat4MulVecfl(imat,co2);
 
-                       if(psys_intersect_dm(zob,0,0,co1,co2,&min_d,&min_face,min_w,0,0,0,0)){
+                       if(psys_intersect_dm(scene,zob,0,0,co1,co2,&min_d,&min_face,min_w,0,0,0,0)){
                                DerivedMesh *dm;
                                MFace *mface;
                                MVert *mvert;
                                float loc[3],nor[3],q1[4];
 
                                psys_disable_all(zob);
-                               dm=mesh_get_derived_final(zob,0);
+                               dm=mesh_get_derived_final(scene, zob, 0);
                                psys_enable_all(zob);
 
                                mface=dm->getFaceDataArray(dm,CD_MFACE);
@@ -3929,7 +3932,7 @@ static void boid_body(BoidVecFunc *bvf, ParticleData *pa, ParticleSystem *psys,
 /************************************************/
 /*                     Hair                                                            */
 /************************************************/
-static void save_hair(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra){
+static void save_hair(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra){
        ParticleData *pa;
        HairKey *key;
        int totpart;
@@ -3937,7 +3940,7 @@ static void save_hair(Object *ob, ParticleSystem *psys, ParticleSystemModifierDa
 
        Mat4Invert(ob->imat,ob->obmat);
        
-       psys->lattice=psys_get_lattice(ob,psys);
+       psys->lattice= psys_get_lattice(scene, ob, psys);
 
        if(psys->totpart==0) return;
 
@@ -3977,19 +3980,19 @@ static void save_hair(Object *ob, ParticleSystem *psys, ParticleSystemModifierDa
 /*                     System Core                                                     */
 /************************************************/
 /* unbaked particles are calculated dynamically */
-static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra,
+static void dynamics_step(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra,
                                                  float *vg_vel, float *vg_tan, float *vg_rot, float *vg_size)
 {
        ParticleData *pa;
        ParticleSettings *part=psys->part;
        KDTree *tree=0;
        BoidVecFunc bvf;
-       IpoCurve *icu_esize=find_ipocurve(part->ipo,PART_EMIT_SIZE);
+       IpoCurve *icu_esize= NULL; //=find_ipocurve(part->ipo,PART_EMIT_SIZE); // XXX old animation system
        Material *ma=give_current_material(ob,part->omat);
        float timestep;
        int p, totpart;
        /* current time */
-       float ctime, ipotime;
+       float ctime, ipotime; // XXX old animation system
        /* frame & time changes */
        float dfra, dtime, pa_dtime, pa_dfra=0.0;
        float birthtime, dietime;
@@ -4002,12 +4005,14 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi
        timestep=psys_get_timestep(part);
        dtime= dfra*timestep;
        ctime= cfra*timestep;
-       ipotime= cfra;
+       ipotime= cfra; // XXX old animation system
 
+#if 0 // XXX old animation system
        if(part->flag&PART_ABS_TIME && part->ipo){
                calc_ipo(part->ipo, cfra);
                execute_ipo((ID *)part, part->ipo);
        }
+#endif // XXX old animation system
 
        if(dfra<0.0){
                float *vg_size=0;
@@ -4018,14 +4023,16 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi
                        if(pa->flag & PARS_UNEXIST) continue;
 
                        /* set correct ipo timing */
+#if 0 // XXX old animation system
                        if((part->flag&PART_ABS_TIME)==0 && part->ipo){
                                ipotime=100.0f*(cfra-pa->time)/pa->lifetime;
                                calc_ipo(part->ipo, ipotime);
                                execute_ipo((ID *)part, part->ipo);
                        }
+#endif // XXX old animation system
                        pa->size=psys_get_size(ob,ma,psmd,icu_esize,psys,part,pa,vg_size);
 
-                       reset_particle(pa,psys,psmd,ob,dtime,cfra,vg_vel,vg_tan,vg_rot);
+                       reset_particle(scene, pa,psys,psmd,ob,dtime,cfra,vg_vel,vg_tan,vg_rot);
 
                        if(cfra>pa->time && part->flag & PART_LOOP && part->type!=PART_HAIR){
                                pa->loop=(short)((cfra-pa->time)/pa->lifetime);
@@ -4055,10 +4062,10 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi
                if(psys->effectors.first)
                        psys_end_effectors(psys);
 
-               psys_init_effectors(ob,part->eff_group,psys);
+               psys_init_effectors(scene, ob, part->eff_group, psys);
                
                if(psys->effectors.first)
-                       precalc_effectors(ob,psys,psmd,cfra);
+                       precalc_effectors(scene, ob,psys,psmd,cfra);
 
                if(part->phystype==PART_PHYS_BOIDS){
                        /* create particle tree for fast inter-particle comparisons */
@@ -4080,11 +4087,13 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi
                        copy_particle_key(&pa->prev_state,&pa->state,1);
                        
                        /* set correct ipo timing */
+#if 0 // XXX old animation system
                        if((part->flag&PART_ABS_TIME)==0 && part->ipo){
                                ipotime=100.0f*(cfra-pa->time)/pa->lifetime;
                                calc_ipo(part->ipo, ipotime);
                                execute_ipo((ID *)part, part->ipo);
                        }
+#endif // XXX old animation system
                        pa->size=psys_get_size(ob,ma,psmd,icu_esize,psys,part,pa,vg_size);
 
                        /* reactions can change birth time so they need to be checked first */
@@ -4099,7 +4108,7 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi
                                || pa->alive==PARS_KILLED
                                || ELEM(part->phystype,PART_PHYS_NO,PART_PHYS_KEYED)
                                || birthtime >= cfra){
-                               reset_particle(pa,psys,psmd,ob,dtime,cfra,vg_vel,vg_tan,vg_rot);
+                               reset_particle(scene, pa,psys,psmd,ob,dtime,cfra,vg_vel,vg_tan,vg_rot);
                        }
 
                        pa_dfra = dfra;
@@ -4126,10 +4135,10 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi
                                switch(part->phystype){
                                        case PART_PHYS_NEWTON:
                                                /* do global forces & effectors */
-                                               apply_particle_forces(p,pa,ob,psys,part,timestep,pa_dfra,cfra);
+                                               apply_particle_forces(scene, p, pa, ob, psys, part, timestep,pa_dfra,cfra);
                        
                                                /* deflection */
-                                               deflect_particle(ob,psmd,psys,part,pa,p,timestep,pa_dfra,cfra);
+                                               deflect_particle(scene, ob,psmd,psys,part,pa,p,timestep,pa_dfra,cfra);
 
                                                /* rotations */
                                                rotate_particle(part,pa,pa_dfra,timestep);
@@ -4137,9 +4146,9 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi
                                        case PART_PHYS_BOIDS:
                                        {
                                                float acc[3];
-                                               boid_brain(&bvf,pa,ob,psys,part,tree,timestep,cfra,acc);
+                                               boid_brain(&bvf, pa, scene, ob, psys, part, tree, timestep,cfra,acc);
                                                if(pa->alive != PARS_DYING)
-                                                       boid_body(&bvf,pa,psys,part,timestep,acc);
+                                                       boid_body(scene, &bvf,pa,psys,part,timestep,acc);
                                                break;
                                        }
                                }
@@ -4149,7 +4158,7 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi
 
                                        if(part->flag & PART_LOOP && part->type!=PART_HAIR){
                                                pa->loop++;
-                                               reset_particle(pa,psys,psmd,ob,0.0,cfra,vg_vel,vg_tan,vg_rot);
+                                               reset_particle(scene, pa,psys,psmd,ob,0.0,cfra,vg_vel,vg_tan,vg_rot);
                                                pa->alive=PARS_ALIVE;
                                        }
                                        else{
@@ -4175,26 +4184,26 @@ static void dynamics_step(Object *ob, ParticleSystem *psys, ParticleSystemModifi
 }
 
 /* check if path cache or children need updating and do it if needed */
-static void psys_update_path_cache(Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra)
+static void psys_update_path_cache(Scene *scene, Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra)
 {
        ParticleSettings *part=psys->part;
-       ParticleEditSettings *pset=&G.scene->toolsettings->particle;
+       ParticleEditSettings *pset=&scene->toolsettings->particle;
        int distr=0,alloc=0;
 
-       if((psys->part->childtype && psys->totchild != get_psys_tot_child(psys)) || psys->recalc&PSYS_ALLOC)
+       if((psys->part->childtype && psys->totchild != get_psys_tot_child(scene, psys)) || psys->recalc&PSYS_RECALC_RESET)
                alloc=1;
 
-       if(alloc || psys->recalc&PSYS_DISTR || (psys->vgroup[PSYS_VG_DENSITY] && (G.f & G_WEIGHTPAINT)))
+       if(alloc || psys->recalc&PSYS_RECALC_RESET || (psys->vgroup[PSYS_VG_DENSITY] && (G.f & G_WEIGHTPAINT)))
                distr=1;
 
        if(distr){
                if(alloc)
                        realloc_particles(ob,psys,psys->totpart);
 
-               if(get_psys_tot_child(psys)) {
+               if(get_psys_tot_child(scene, psys)) {
                        /* don't generate children while computing the hair keys */
                        if(!(psys->part->type == PART_HAIR) || (psys->flag & PSYS_HAIR_DONE)) {
-                               distribute_particles(ob,psys,PART_FROM_CHILD);
+                               distribute_particles(scene, ob, psys, PART_FROM_CHILD);
 
                                if(part->from!=PART_FROM_PARTICLE && part->childtype==PART_CHILD_FACES && part->parents!=0.0)
                                        psys_find_parents(ob,psmd,psys);
@@ -4202,22 +4211,47 @@ static void psys_update_path_cache(Object *ob, ParticleSystemModifierData *psmd,
                }
        }
 
-       if((part->type==PART_HAIR || psys->flag&PSYS_KEYED) && (psys_in_edit_mode(psys)
-               || (part->type==PART_HAIR || part->draw_as==PART_DRAW_PATH))){
-               psys_cache_paths(ob, psys, cfra, 0);
+       if((part->type==PART_HAIR || psys->flag&PSYS_KEYED) && ( psys_in_edit_mode(scene, psys) || (part->type==PART_HAIR 
+               || (part->ren_as == PART_DRAW_PATH && (part->draw_as == PART_DRAW_REND || psys->renderdata))))){
+
+               psys_cache_paths(scene, ob, psys, cfra, 0);
 
                /* for render, child particle paths are computed on the fly */
                if(part->childtype) {
-                       if(((psys->totchild!=0)) || (psys_in_edit_mode(psys) && (pset->flag&PE_SHOW_CHILD)))
+                       if(((psys->totchild!=0)) || (psys_in_edit_mode(scene, psys) && (pset->flag&PE_SHOW_CHILD)))
                                if(!(psys->part->type == PART_HAIR) || (psys->flag & PSYS_HAIR_DONE))
-                                       psys_cache_child_paths(ob, psys, cfra, 0);
+                                       psys_cache_child_paths(scene, ob, psys, cfra, 0);
                }
        }
        else if(psys->pathcache)
                psys_free_path_cache(psys);
 }
 
-static void hair_step(Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra)
+/* calculate and store key locations in world coordinates */
+void psys_update_world_cos(Object *ob, ParticleSystem *psys)
+{
+       ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys);
+       ParticleData *pa;
+       ParticleEditKey *key;
+       int i, k, totpart;
+       float hairmat[4][4];
+
+       if(psys==0 || psys->edit==0)
+               return;
+
+       totpart= psys->totpart;
+
+       for(i=0, pa=psys->particles; i<totpart; i++, pa++) {
+               psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat);
+
+               for(k=0, key=psys->edit->keys[i]; k<pa->totkey; k++, key++) {
+                       VECCOPY(key->world_co,key->co);
+                       Mat4MulVecfl(hairmat, key->world_co);
+               }
+       }
+}
+
+static void hair_step(Scene *scene, Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra)
 {
        ParticleSettings *part = psys->part;
        ParticleData *pa;
@@ -4231,33 +4265,33 @@ static void hair_step(Object *ob, ParticleSystemModifierData *psmd, ParticleSyst
                        pa->flag &= ~PARS_NO_DISP;
        }
 
-       if(psys->recalc & PSYS_DISTR)
+       if(psys->recalc & PSYS_RECALC_RESET)
                /* need this for changing subsurf levels */
                psys_calc_dmcache(ob, psmd->dm, psys);
 
        if(psys->effectors.first)
                psys_end_effectors(psys);
 
-       psys_init_effectors(ob,part->eff_group,psys);
+       psys_init_effectors(scene, ob, part->eff_group, psys);
        if(psys->effectors.first)
-               precalc_effectors(ob,psys,psmd,cfra);
+               precalc_effectors(scene, ob,psys,psmd,cfra);
                
-       if(psys_in_edit_mode(psys))
-               PE_recalc_world_cos(ob, psys);
+       if(psys_in_edit_mode(scene, psys))
+               psys_update_world_cos(ob, psys);
 
-       psys_update_path_cache(ob,psmd,psys,cfra);
+       psys_update_path_cache(scene, ob,psmd,psys,cfra);
 }
 
 /* updates cached particles' alive & other flags etc..*/
-static void cached_step(Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra)
+static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *psmd, ParticleSystem *psys, float cfra)
 {
        ParticleSettings *part=psys->part;
        ParticleData *pa;
        ParticleKey state;
-       IpoCurve *icu_esize=find_ipocurve(part->ipo,PART_EMIT_SIZE);
+       IpoCurve *icu_esize= NULL; //=find_ipocurve(part->ipo,PART_EMIT_SIZE); // XXX old animation system
        Material *ma=give_current_material(ob,part->omat);
        int p;
-       float ipotime=cfra, disp, birthtime, dietime, *vg_size= NULL;
+       float disp, birthtime, dietime, *vg_size= NULL; // XXX ipotime=cfra
 
        if(part->from!=PART_FROM_PARTICLE)
                vg_size= psys_cache_vgroup(psmd->dm,psys,PSYS_VG_SIZE);
@@ -4266,22 +4300,24 @@ static void cached_step(Object *ob, ParticleSystemModifierData *psmd, ParticleSy
                psys_end_effectors(psys);
        
        //if(part->flag & (PART_BAKED_GUIDES+PART_BAKED_DEATHS)){
-               psys_init_effectors(ob,part->eff_group,psys);
+               psys_init_effectors(scene, ob, part->eff_group, psys);
                if(psys->effectors.first)
-                       precalc_effectors(ob,psys,psmd,cfra);
+                       precalc_effectors(scene, ob,psys,psmd,cfra);
        //}
        
        disp= (float)get_current_display_percentage(psys)/50.0f-1.0f;
 
        for(p=0, pa=psys->particles; p<psys->totpart; p++,pa++){
+#if 0 // XXX old animation system
                if((part->flag&PART_ABS_TIME)==0 && part->ipo){
                        ipotime=100.0f*(cfra-pa->time)/pa->lifetime;
                        calc_ipo(part->ipo, ipotime);
                        execute_ipo((ID *)part, part->ipo);
                }
+#endif // XXX old animation system
                pa->size= psys_get_size(ob,ma,psmd,icu_esize,psys,part,pa,vg_size);
 
-               psys->lattice=psys_get_lattice(ob,psys);
+               psys->lattice= psys_get_lattice(scene, ob, psys);
 
                if(part->flag & PART_LOOP && part->type!=PART_HAIR)
                        pa->loop = (short)((cfra - pa->time) / pa->lifetime);
@@ -4297,7 +4333,7 @@ static void cached_step(Object *ob, ParticleSystemModifierData *psmd, ParticleSy
                else if(dietime <= cfra){
                        if(dietime > psys->cfra){
                                state.time = pa->dietime;
-                               psys_get_particle_state(ob,psys,p,&state,1);
+                               psys_get_particle_state(scene, ob,psys,p,&state,1);
                                push_reaction(ob,psys,p,PART_EVENT_DEATH,&state);
                        }
                        pa->alive = PARS_DEAD;
@@ -4305,14 +4341,14 @@ static void cached_step(Object *ob, ParticleSystemModifierData *psmd, ParticleSy
                else{
                        pa->alive = PARS_ALIVE;
                        state.time = cfra;
-                       psys_get_particle_state(ob,psys,p,&state,1);
+                       psys_get_particle_state(scene, ob,psys,p,&state,1);
                        state.time = cfra;
                        push_reaction(ob,psys,p,PART_EVENT_NEAR,&state);
                }
 
                if(psys->lattice){
-                       end_latt_deform();
-                       psys->lattice=0;
+                       end_latt_deform(psys->lattice);
+                       psys->lattice= NULL;
                }
 
                if(pa->r_rot[0] > disp)
@@ -4322,9 +4358,9 @@ static void cached_step(Object *ob, ParticleSystemModifierData *psmd, ParticleSy
        }
 
        /* make sure that children are up to date */
-       if(psys->part->childtype && psys->totchild != get_psys_tot_child(psys)) {
+       if(psys->part->childtype && psys->totchild != get_psys_tot_child(scene, psys)) {
                realloc_particles(ob, psys, psys->totpart);
-               distribute_particles(ob, psys, PART_FROM_CHILD);
+               distribute_particles(scene, ob, psys, PART_FROM_CHILD);
        }
 
        if(vg_size)
@@ -4349,23 +4385,21 @@ void psys_changed_type(ParticleSystem *psys)
                psys->flag &= ~PSYS_KEYED;
 
        if(part->type == PART_HAIR) {
-               part->draw_as = PART_DRAW_PATH;
-               part->rotfrom = PART_ROT_IINCR;
-       }
-       else {
-               free_hair(psys, 1);
+               if(ELEM4(part->ren_as, PART_DRAW_NOT, PART_DRAW_PATH, PART_DRAW_OB, PART_DRAW_GR)==0)
+                       part->ren_as = PART_DRAW_PATH;
 
-               if(part->draw_as == PART_DRAW_PATH)
-                       if(psys->part->phystype != PART_PHYS_KEYED)
-                               part->draw_as = PART_DRAW_DOT;
+               if(ELEM3(part->draw_as, PART_DRAW_NOT, PART_DRAW_REND, PART_DRAW_PATH)==0)
+                       part->draw_as = PART_DRAW_REND;
        }
+       else
+               free_hair(psys, 1);
 
        psys->softflag= 0;
 
        psys_reset(psys, PSYS_RESET_ALL);
 }
 
-static void particles_fluid_step(Object *ob, ParticleSystem *psys, int cfra)
+static void particles_fluid_step(Scene *scene, Object *ob, ParticleSystem *psys, int cfra)
 {      
        if(psys->particles){
                MEM_freeN(psys->particles);
@@ -4386,13 +4420,13 @@ static void particles_fluid_step(Object *ob, ParticleSystem *psys, int cfra)
                        char *suffix2 = ".gz";
                        char filename[256];
                        char debugStrBuffer[256];
-                       int  curFrame = G.scene->r.cfra -1; // warning - sync with derived mesh fsmesh loading
+                       int  curFrame = scene->r.cfra -1; // warning - sync with derived mesh fsmesh loading
                        int  p, j, numFileParts, totpart;
                        int readMask, activeParts = 0, fileParts = 0;
                        gzFile gzf;
        
-                       if(ob==G.obedit) // off...
-                               return;
+// XXX                 if(ob==G.obedit) // off...
+//                             return;
        
                        // ok, start loading
                        strcpy(filename, fss->surfdataPath);
@@ -4404,7 +4438,7 @@ static void particles_fluid_step(Object *ob, ParticleSystem *psys, int cfra)
                        gzf = gzopen(filename, "rb");
                        if (!gzf) {
                                snprintf(debugStrBuffer,256,"readFsPartData::error - Unable to open file for reading '%s' \n", filename); 
-                               //elbeemDebugOut(debugStrBuffer);
+                               // XXX bad level call elbeemDebugOut(debugStrBuffer);
                                return;
                        }
        
@@ -4414,7 +4448,7 @@ static void particles_fluid_step(Object *ob, ParticleSystem *psys, int cfra)
                        
                        part->totpart= totpart;
                        part->sta=part->end = 1.0f;
-                       part->lifetime = G.scene->r.efra + 1;
+                       part->lifetime = scene->r.efra + 1;
        
                        /* initialize particles */
                        realloc_particles(ob, psys, part->totpart);
@@ -4464,7 +4498,9 @@ static void particles_fluid_step(Object *ob, ParticleSystem *psys, int cfra)
        
                        totpart = psys->totpart = activeParts;
                        snprintf(debugStrBuffer,256,"readFsPartData::done - particles:%d, active:%d, file:%d, mask:%d  \n", psys->totpart,activeParts,fileParts,readMask);
-                       elbeemDebugOut(debugStrBuffer);
+                       // bad level call
+                       // XXX elbeemDebugOut(debugStrBuffer);
+                       
                } // fluid sim particles done
        }
        #endif // DISABLE_ELBEEM
@@ -4472,7 +4508,7 @@ static void particles_fluid_step(Object *ob, ParticleSystem *psys, int cfra)
 
 /* Calculates the next state for all particles of the system */
 /* In particles code most fra-ending are frames, time-ending are fra*timestep (seconds)*/
-static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra)
+static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSystemModifierData *psmd, float cfra)
 {
        ParticleSettings *part;
        ParticleData *pa;
@@ -4486,28 +4522,30 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier
        part= psys->part;
        cache= psys->pointcache;
 
-       framenr= (int)CFRA;
+       framenr= (int)scene->r.cfra;
        framedelta= framenr - cache->simframe;
 
        BKE_ptcache_id_from_particles(&pid, ob, psys);
-       BKE_ptcache_id_time(&pid, 0.0f, &startframe, &endframe, NULL);
+       BKE_ptcache_id_time(&pid, scene, 0.0f, &startframe, &endframe, NULL);
 
        /* update ipo's */
+#if 0 // XXX old animation system
        if((part->flag & PART_ABS_TIME) && part->ipo) {
                calc_ipo(part->ipo, cfra);
                execute_ipo((ID *)part, part->ipo);
        }
+#endif // XXX old animation system
 
        /* hair if it's already done is handled separate */
        if(part->type == PART_HAIR && (psys->flag & PSYS_HAIR_DONE)) {
-               hair_step(ob, psmd, psys, cfra);
+               hair_step(scene, ob, psmd, psys, cfra);
                psys->cfra = cfra;
                psys->recalc = 0;
                return;
        }
        /* fluid is also handled separate */
        else if(part->type == PART_FLUID) {
-               particles_fluid_step(ob, psys, framenr);
+               particles_fluid_step(scene, ob, psys, framenr);
                psys->cfra = cfra;
                psys->recalc = 0;
                return;
@@ -4542,7 +4580,7 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier
                totpart = part->grid_res*part->grid_res*part->grid_res;
        else
                totpart = psys->part->totpart;
-       totchild = get_psys_tot_child(psys);
+       totchild = get_psys_tot_child(scene, psys);
 
        if(oldtotpart != totpart || (psys->part->childtype && oldtotchild != totchild)) {
                only_children_changed = (oldtotpart == totpart);
@@ -4552,7 +4590,7 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier
                init= 1;
        }
 
-       if(psys->recalc & PSYS_DISTR) {
+       if(psys->recalc & PSYS_RECALC_RESET) {
                distr= 1;
                init= 1;
        }
@@ -4562,20 +4600,22 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier
                        if(alloc)
                                realloc_particles(ob, psys, totpart);
 
-                       distribute_particles(ob, psys, part->from);
+                       distribute_particles(scene, ob, psys, part->from);
 
                        if((psys->part->type == PART_HAIR) && !(psys->flag & PSYS_HAIR_DONE))
                        /* don't generate children while growing hair - waste of time */
                                psys_free_children(psys);
-                       else if(get_psys_tot_child(psys))
-                               distribute_particles(ob, psys, PART_FROM_CHILD);
+                       else if(get_psys_tot_child(scene, psys))
+                               distribute_particles(scene, ob, psys, PART_FROM_CHILD);
                }
 
                if(only_children_changed==0) {
+                       free_keyed_keys(psys);
+
                        initialize_all_particles(ob, psys, psmd);
 
                        if(alloc)
-                               reset_all_particles(ob, psys, psmd, 0.0, cfra, oldtotpart);
+                               reset_all_particles(scene, ob, psys, psmd, 0.0, cfra, oldtotpart);
                }
 
                /* flag for possible explode modifiers after this system */
@@ -4587,15 +4627,15 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier
                if(get_particles_from_cache(ob, psys, framenr)) {
                        if(part->phystype==PART_PHYS_KEYED && psys->flag&PSYS_FIRST_KEYED) {
                                psys_count_keyed_targets(ob,psys);
-                               set_keyed_keys(ob, psys);
+                               set_keyed_keys(scene, ob, psys);
                        }
 
-                       cached_step(ob,psmd,psys,cfra);
+                       cached_step(scene, ob, psmd, psys, cfra);
                        psys->cfra=cfra;
                        psys->recalc = 0;
 
                        if(part->phystype==PART_PHYS_KEYED && psys->flag&PSYS_FIRST_KEYED) {
-                               psys_update_path_cache(ob,psmd,psys,framenr);
+                               psys_update_path_cache(scene, ob, psmd, psys, framenr);
                        }
 
                        cache->simframe= framenr;
@@ -4657,7 +4697,7 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier
 
                for(dframe=-totframesback; dframe<=0; dframe++) {
                        /* ok now we're all set so let's go */
-                       dynamics_step(ob,psys,psmd,cfra+dframe,vg_vel,vg_tan,vg_rot,vg_size);
+                       dynamics_step(scene, ob, psys, psmd, cfra+dframe, vg_vel, vg_tan, vg_rot, vg_size);
                        psys->cfra = cfra+dframe;
                }
        }
@@ -4674,8 +4714,8 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier
 
        /* for keyed particles the path is allways known so it can be drawn */
        if(part->phystype==PART_PHYS_KEYED && psys->flag&PSYS_FIRST_KEYED){
-               set_keyed_keys(ob, psys);
-               psys_update_path_cache(ob,psmd,psys,(int)cfra);
+               set_keyed_keys(scene, ob, psys);
+               psys_update_path_cache(scene, ob, psmd, psys,(int)cfra);
        }
        else if(psys->pathcache)
                psys_free_path_cache(psys);
@@ -4687,12 +4727,12 @@ static void system_step(Object *ob, ParticleSystem *psys, ParticleSystemModifier
        if(vg_size) MEM_freeN(vg_size);
 
        if(psys->lattice){
-               end_latt_deform();
-               psys->lattice=0;
+               end_latt_deform(psys->lattice);
+               psys->lattice= NULL;
        }
 }
 
-static void psys_to_softbody(Object *ob, ParticleSystem *psys)
+static void psys_to_softbody(Scene *scene, Object *ob, ParticleSystem *psys)
 {
        SoftBody *sb;
        short softflag; 
@@ -4712,7 +4752,7 @@ static void psys_to_softbody(Object *ob, ParticleSystem *psys)
        ob->softflag= psys->softflag;
 
        /* do softbody */
-       sbObjectStep(ob, (float)G.scene->r.cfra, NULL, psys_count_keys(psys));
+       sbObjectStep(scene, ob, (float)scene->r.cfra, NULL, psys_count_keys(psys));
 
        /* return things back to normal */
        psys->soft= ob->soft;
@@ -4725,8 +4765,8 @@ static void psys_to_softbody(Object *ob, ParticleSystem *psys)
 static int hair_needs_recalc(ParticleSystem *psys)
 {
        if((psys->flag & PSYS_EDITED)==0 &&
-               ((psys->flag & PSYS_HAIR_DONE)==0 || psys->recalc & PSYS_RECALC_HAIR)) {
-               psys->recalc &= ~PSYS_RECALC_HAIR;
+               ((psys->flag & PSYS_HAIR_DONE)==0 || psys->recalc & PSYS_RECALC_REDO)) {
+               psys->recalc &= ~PSYS_RECALC_REDO;
                return 1;
        }
 
@@ -4734,7 +4774,7 @@ static int hair_needs_recalc(ParticleSystem *psys)
 }
 
 /* main particle update call, checks that things are ok on the large scale before actual particle calculations */
-void particle_system_update(Object *ob, ParticleSystem *psys)
+void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys)
 {
        ParticleSystemModifierData *psmd;
        float cfra;
@@ -4742,7 +4782,7 @@ void particle_system_update(Object *ob, ParticleSystem *psys)
        if(!psys_check_enabled(ob, psys))
                return;
 
-       cfra= bsystem_time(ob, CFRA, 0.0f);
+       cfra= bsystem_time(scene, ob, (float)scene->r.cfra, 0.0f);
        psmd= psys_get_modifier(ob, psys);
 
        /* system was already updated from modifier stack */
@@ -4756,6 +4796,9 @@ void particle_system_update(Object *ob, ParticleSystem *psys)
        if(!psmd->dm)
                return;
 
+       if(psys->recalc & PSYS_RECALC_TYPE)
+               psys_changed_type(psys);
+
        /* (re-)create hair */
        if(psys->part->type==PART_HAIR && hair_needs_recalc(psys)) {
                float hcfra=0.0f;
@@ -4768,8 +4811,8 @@ void particle_system_update(Object *ob, ParticleSystem *psys)
 
                for(i=0; i<=psys->part->hair_step; i++){
                        hcfra=100.0f*(float)i/(float)psys->part->hair_step;
-                       system_step(ob, psys, psmd, hcfra);
-                       save_hair(ob, psys, psmd, hcfra);
+                       system_step(scene, ob, psys, psmd, hcfra);
+                       save_hair(scene, ob, psys, psmd, hcfra);
                }
 
                psys->flag |= PSYS_HAIR_DONE;
@@ -4777,10 +4820,10 @@ void particle_system_update(Object *ob, ParticleSystem *psys)
 
        /* handle softbody hair */
        if(psys->part->type==PART_HAIR && psys->soft)
-               psys_to_softbody(ob, psys);
+               psys_to_softbody(scene, ob, psys);
 
        /* the main particle system step */
-       system_step(ob, psys, psmd, cfra);
+       system_step(scene, ob, psys, psmd, cfra);
 
        /* save matrix for duplicators */
        Mat4Invert(psys->imat, ob->obmat);