diff options
author | Joseph Eagar <joeedh@gmail.com> | 2009-09-16 21:43:09 +0400 |
---|---|---|
committer | Joseph Eagar <joeedh@gmail.com> | 2009-09-16 21:43:09 +0400 |
commit | deebf4f8f0d79169a0e6c2a391670419b6492bfe (patch) | |
tree | 2a0aaf4042aa78e9d1d835f4544e07c6123e67a9 /source/blender/editors/physics | |
parent | 6b0679a3999d8e5abc60730f523879eadbedcd8f (diff) |
merge with 2.5/trunk at r23271
Diffstat (limited to 'source/blender/editors/physics')
-rw-r--r-- | source/blender/editors/physics/ed_fluidsim.c | 22 | ||||
-rw-r--r-- | source/blender/editors/physics/ed_pointcache.c | 31 | ||||
-rw-r--r-- | source/blender/editors/physics/editparticle.c | 2301 |
3 files changed, 1232 insertions, 1122 deletions
diff --git a/source/blender/editors/physics/ed_fluidsim.c b/source/blender/editors/physics/ed_fluidsim.c index 907d3f99f77..093fa3f0a49 100644 --- a/source/blender/editors/physics/ed_fluidsim.c +++ b/source/blender/editors/physics/ed_fluidsim.c @@ -200,6 +200,28 @@ static void fluidsimPrintChannel(FILE *file, float *channel, int paramsize, char static void fluidsimInitChannel(Scene *scene, float **setchannel, int size, float *time, int *icuIds, float *defaults, Ipo* ipo, int entries) { + + int i, j; + char *cstr = NULL; + float *channel = NULL; + + cstr = "fluidsiminit_channelfloat"; + if(entries>1) cstr = "fluidsiminit_channelvec"; + channel = MEM_callocN( size* (entries+1)* sizeof(float), cstr ); + + /* defaults for now */ + for(j=0; j<entries; j++) { + for(i=1; i<=size; i++) { + channel[(i-1)*(entries+1) + j] = defaults[j]; + } + } + + for(i=1; i<=size; i++) { + channel[(i-1)*(entries+1) + entries] = time[i]; + } + + *setchannel = channel; + #if 0 /* goes away completely */ int i,j; diff --git a/source/blender/editors/physics/ed_pointcache.c b/source/blender/editors/physics/ed_pointcache.c index 917e2b40d72..f2c7b64032f 100644 --- a/source/blender/editors/physics/ed_pointcache.c +++ b/source/blender/editors/physics/ed_pointcache.c @@ -46,6 +46,7 @@ #include "ED_screen.h" #include "ED_physics.h" +#include "ED_particle.h" #include "UI_interface.h" #include "UI_resources.h" @@ -71,6 +72,12 @@ static int ptcache_bake_all_poll(bContext *C) return 1; } +static int ptcache_poll(bContext *C) +{ + PointerRNA ptr= CTX_data_pointer_get_type(C, "PointCache", &RNA_PointCache); + return (ptr.data && ptr.id.data); +} + static int ptcache_bake_all_exec(bContext *C, wmOperator *op) { Scene *scene= CTX_data_scene(C); @@ -184,8 +191,16 @@ static int ptcache_free_bake_exec(bContext *C, wmOperator *op) { PointerRNA ptr= CTX_data_pointer_get_type(C, "PointCache", &RNA_PointCache); PointCache *cache= ptr.data; - - cache->flag &= ~PTCACHE_BAKED; + + if(cache->edit) { + if(!cache->edit->edited || 1) {// XXX okee("Lose changes done in particle mode?")) { + PE_free_ptcache_edit(cache->edit); + cache->edit = NULL; + cache->flag &= ~PTCACHE_BAKED; + } + } + else + cache->flag &= ~PTCACHE_BAKED; return OPERATOR_FINISHED; } @@ -206,12 +221,12 @@ void PTCACHE_OT_bake(wmOperatorType *ot) /* api callbacks */ ot->exec= ptcache_bake_exec; - ot->poll= ptcache_bake_all_poll; + ot->poll= ptcache_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; - RNA_def_boolean(ot->srna, "bake", 1, "Bake", ""); + RNA_def_boolean(ot->srna, "bake", 0, "Bake", ""); } void PTCACHE_OT_free_bake(wmOperatorType *ot) { @@ -221,7 +236,7 @@ void PTCACHE_OT_free_bake(wmOperatorType *ot) /* api callbacks */ ot->exec= ptcache_free_bake_exec; - ot->poll= ptcache_bake_all_poll; + ot->poll= ptcache_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -234,7 +249,7 @@ void PTCACHE_OT_bake_from_cache(wmOperatorType *ot) /* api callbacks */ ot->exec= ptcache_bake_from_cache_exec; - ot->poll= ptcache_bake_all_poll; + ot->poll= ptcache_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -299,7 +314,7 @@ void PTCACHE_OT_add_new(wmOperatorType *ot) /* api callbacks */ ot->exec= ptcache_add_new_exec; - ot->poll= ptcache_bake_all_poll; + ot->poll= ptcache_poll; // ptcache_bake_all_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -312,7 +327,7 @@ void PTCACHE_OT_remove(wmOperatorType *ot) /* api callbacks */ ot->exec= ptcache_remove_exec; - ot->poll= ptcache_bake_all_poll; + ot->poll= ptcache_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; diff --git a/source/blender/editors/physics/editparticle.c b/source/blender/editors/physics/editparticle.c index faf03d1f0e2..212d2047872 100644 --- a/source/blender/editors/physics/editparticle.c +++ b/source/blender/editors/physics/editparticle.c @@ -57,7 +57,8 @@ #include "BKE_particle.h" #include "BKE_report.h" #include "BKE_scene.h" -#include "BKE_utildefines.h" +#include "BKE_utildefines.h" +#include "BKE_pointcache.h" #include "BLI_arithb.h" #include "BLI_blenlib.h" @@ -85,11 +86,23 @@ #include "physics_intern.h" -static void PE_create_particle_edit(Scene *scene, Object *ob, ParticleSystem *psys); -static void ParticleUndo_clear(ParticleSystem *psys); +static void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys); +static void PTCacheUndo_clear(PTCacheEdit *edit); -#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++) +#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 KEY_WCO (key->flag & PEK_USE_WCO ? key->world_co : key->co) /**************************** utilities *******************************/ @@ -97,14 +110,28 @@ static int PE_poll(bContext *C) { Scene *scene= CTX_data_scene(C); Object *ob= CTX_data_active_object(C); - ParticleSystem *psys; + PTCacheEdit *edit; + + if(!scene || !ob) + return 0; + + edit= PE_get_current(scene, ob); + + return (edit && (ob->mode & OB_MODE_PARTICLE_EDIT)); +} + +static int PE_hair_poll(bContext *C) +{ + Scene *scene= CTX_data_scene(C); + Object *ob= CTX_data_active_object(C); + PTCacheEdit *edit; if(!scene || !ob) return 0; - psys= PE_get_current(scene, ob); + edit= PE_get_current(scene, ob); - return (psys && psys->edit && (ob && ob->mode & OB_MODE_PARTICLE_EDIT)); + return (edit && edit->psys && (ob->mode & OB_MODE_PARTICLE_EDIT)); } static int PE_poll_3dview(bContext *C) @@ -113,22 +140,21 @@ static int PE_poll_3dview(bContext *C) CTX_wm_region(C)->regiontype == RGN_TYPE_WINDOW; } -static void PE_free_particle_edit(ParticleSystem *psys) +void PE_free_ptcache_edit(PTCacheEdit *edit) { - ParticleEdit *edit= psys->edit; - int i, totpart= psys->totpart; + POINT_P; if(edit==0) return; - ParticleUndo_clear(psys); + PTCacheUndo_clear(edit); - if(edit->keys) { - for(i=0; i<totpart; i++) { - if(edit->keys[i]) - MEM_freeN(edit->keys[i]); + if(edit->points) { + LOOP_POINTS { + if(point->keys) + MEM_freeN(point->keys); } - MEM_freeN(edit->keys); + MEM_freeN(edit->points); } if(edit->mirror_cache) @@ -144,19 +170,25 @@ static void PE_free_particle_edit(ParticleSystem *psys) edit->emitter_field= 0; } - MEM_freeN(edit); + psys_free_path_cache(NULL, edit); - psys->edit= NULL; - psys->free_edit= NULL; + MEM_freeN(edit); } /************************************************/ /* Edit Mode Helpers */ /************************************************/ -int PE_can_edit(ParticleSystem *psys) +int PE_start_edit(PTCacheEdit *edit) { - return (psys && psys->edit); + if(edit) { + edit->edited = 1; + if(edit->psys) + edit->psys->flag |= PSYS_EDITED; + return 1; + } + + return 0; } ParticleEditSettings *PE_settings(Scene *scene) @@ -165,73 +197,106 @@ ParticleEditSettings *PE_settings(Scene *scene) } /* always gets atleast the first particlesystem even if PSYS_CURRENT flag is not set */ -ParticleSystem *PE_get_current(Scene *scene, Object *ob) +PTCacheEdit *PE_get_current(Scene *scene, Object *ob) { - ParticleSystem *psys; + ParticleEditSettings *pset= PE_settings(scene); + PTCacheEdit *edit = NULL; + ListBase pidlist; + PTCacheID *pid; + + pset->scene = scene; + pset->object = ob; if(ob==NULL) return NULL; - psys= ob->particlesystem.first; - while(psys) { - if(psys->flag & PSYS_CURRENT) - break; - psys=psys->next; - } + BKE_ptcache_ids_from_object(&pidlist, ob); - if(psys==NULL && ob->particlesystem.first) { - psys=ob->particlesystem.first; - psys->flag |= PSYS_CURRENT; + /* in the case of only one editable thing, set pset->edittype accordingly */ + if(pidlist.first && 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; + } } - /* 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); + for(pid=pidlist.first; pid; pid=pid->next) { + if(pset->edittype == PE_TYPE_PARTICLES && pid->type == PTCACHE_TYPE_PARTICLES) { + ParticleSystem *psys = pid->calldata; - return psys; -} - -/* returns -1 if no system has PSYS_CURRENT flag */ -short PE_get_current_num(Object *ob) -{ - short num=0; - ParticleSystem *psys= ob->particlesystem.first; + if(psys->flag & PSYS_CURRENT) { + if(psys->part && psys->part->type == PART_HAIR) { + if(psys->flag & PSYS_HAIR_DYNAMICS && psys->pointcache->flag & PTCACHE_BAKED) { + if(!psys->pointcache->edit) + PE_create_particle_edit(scene, ob, pid->cache, NULL); + edit = pid->cache->edit; + } + else { + 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; + } - while(psys) { - if(psys->flag & PSYS_CURRENT) - return num; - num++; - psys=psys->next; + 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 -1; + if(edit) + edit->pid = *pid; + + BLI_freelistN(&pidlist); + + return edit; } -void PE_hide_keys_time(Scene *scene, ParticleSystem *psys, float cfra) +void PE_hide_keys_time(Scene *scene, PTCacheEdit *edit, float cfra) { - ParticleData *pa; - ParticleEditKey *key; ParticleEditSettings *pset=PE_settings(scene); - int i, k, totpart= psys->totpart; + POINT_P; KEY_K; - 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) + + if(pset->flag & PE_FADE_TIME && pset->selectmode==SCE_SELECT_POINT) { + LOOP_POINTS { + LOOP_KEYS { + if(fabs(cfra-*key->time) < pset->fade_frames) key->flag &= ~PEK_HIDE; else { key->flag |= PEK_HIDE; - key->flag &= ~PEK_SELECT; + //key->flag &= ~PEK_SELECT; } } } } else { - LOOP_PARTICLES(i, pa) { - LOOP_KEYS(k, key) { + LOOP_POINTS { + LOOP_KEYS { key->flag &= ~PEK_HIDE; } } @@ -247,7 +312,7 @@ typedef struct PEData { Scene *scene; Object *ob; DerivedMesh *dm; - ParticleSystem *psys; + PTCacheEdit *edit; short *mval; rcti *rect; @@ -276,7 +341,7 @@ static void PE_set_data(bContext *C, PEData *data) data->scene= CTX_data_scene(C); data->ob= CTX_data_active_object(C); - data->psys= PE_get_current(data->scene, data->ob); + data->edit= PE_get_current(data->scene, data->ob); } static void PE_set_view3d_data(bContext *C, PEData *data) @@ -388,121 +453,103 @@ static int key_inside_test(PEData *data, float co[3]) return key_inside_rect(data, co); } -static int particle_is_selected(ParticleSystem *psys, ParticleData *pa) +static int point_is_selected(PTCacheEditPoint *point) { - ParticleEditKey *key; - int sel, i, k; + KEY_K; + int sel; - if(pa->flag & PARS_HIDE) + if(point->flag & PEP_HIDE) return 0; sel= 0; - i= pa - psys->particles; - LOOP_KEYS(k, key) - if(key->flag & PEK_SELECT) - return 1; + LOOP_SELECTED_KEYS { + return 1; + } return 0; } /*************************** iterators *******************************/ -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); +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); 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); - int i, k, totpart, nearest_pa, nearest_key; + PTCacheEdit *edit= data->edit; + POINT_P; KEY_K; + int nearest_point, nearest_key; float dist= data->rad; /* in path select mode we have no keys */ if(pset->selectmode==SCE_SELECT_PATH) return; - totpart= psys->totpart; - nearest_pa= -1; + nearest_point= -1; nearest_key= -1; - LOOP_PARTICLES(i, pa) { - if(pa->flag & PARS_HIDE) continue; - + LOOP_VISIBLE_POINTS { if(pset->selectmode == SCE_SELECT_END) { /* only do end keys */ - key= edit->keys[i] + pa->totkey-1; + key= point->keys + point->totkey-1; if(nearest) { - if(key_inside_circle(data, dist, key->world_co, &dist)) { - nearest_pa= i; - nearest_key= pa->totkey-1; + if(key_inside_circle(data, dist, KEY_WCO, &dist)) { + nearest_point= p; + nearest_key= point->totkey-1; } } - else if(key_inside_test(data, key->world_co)) - func(data, i, pa->totkey-1); + else if(key_inside_test(data, KEY_WCO)) + func(data, p, point->totkey-1); } else { /* do all keys */ - key= edit->keys[i]; - - LOOP_KEYS(k, key) { - if(key->flag & PEK_HIDE) continue; - + LOOP_VISIBLE_KEYS { if(nearest) { - if(key_inside_circle(data, dist, key->world_co, &dist)) { - nearest_pa= i; + if(key_inside_circle(data, dist, KEY_WCO, &dist)) { + nearest_point= p; nearest_key= k; } } - else if(key_inside_test(data, key->world_co)) - func(data, i, k); + else if(key_inside_test(data, KEY_WCO)) + func(data, p, k); } } } /* do nearest only */ - if(nearest && nearest_pa > -1) - func(data, nearest_pa, nearest_key); + if(nearest && nearest_point > -1) + func(data, nearest_point, nearest_key); } -static void foreach_mouse_hit_particle(PEData *data, ForParticleFunc func, int selected) +static void foreach_mouse_hit_point(PEData *data, ForPointFunc func, int selected) { - ParticleSystem *psys= data->psys; - ParticleData *pa; - ParticleEditKey *key; ParticleEditSettings *pset= PE_settings(data->scene); - int i, k, totpart; - - totpart= psys->totpart; + PTCacheEdit *edit= data->edit; + POINT_P; KEY_K; /* all is selected in path mode */ if(pset->selectmode==SCE_SELECT_PATH) selected=0; - LOOP_PARTICLES(i, pa) { - if(pa->flag & PARS_HIDE) continue; - + LOOP_VISIBLE_POINTS { if(pset->selectmode==SCE_SELECT_END) { /* only do end keys */ - key= psys->edit->keys[i] + pa->totkey-1; + key= point->keys + point->totkey - 1; if(selected==0 || key->flag & PEK_SELECT) - if(key_inside_circle(data, data->rad, key->world_co, &data->dist)) - func(data, i); + if(key_inside_circle(data, data->rad, KEY_WCO, &data->dist)) + func(data, p); } else { /* do all keys */ - LOOP_KEYS(k, key) { - if(key->flag & PEK_HIDE) continue; - + LOOP_VISIBLE_KEYS { if(selected==0 || key->flag & PEK_SELECT) { - if(key_inside_circle(data, data->rad, key->world_co, &data->dist)) { - func(data, i); + if(key_inside_circle(data, data->rad, KEY_WCO, &data->dist)) { + func(data, p); break; } } @@ -513,16 +560,15 @@ static void foreach_mouse_hit_particle(PEData *data, ForParticleFunc func, int s static void foreach_mouse_hit_key(PEData *data, ForKeyMatFunc func, int selected) { - ParticleSystem *psys= data->psys; - ParticleData *pa; - ParticleEditKey *key; - ParticleSystemModifierData *psmd=0; + PTCacheEdit *edit = data->edit; + ParticleSystem *psys = edit->psys; + ParticleSystemModifierData *psmd = NULL; ParticleEditSettings *pset= PE_settings(data->scene); - int i, k, totpart; + POINT_P; KEY_K; float mat[4][4], imat[4][4]; - psmd= psys_get_modifier(data->ob,psys); - totpart= psys->totpart; + if(edit->psys) + psmd= psys_get_modifier(data->ob, edit->psys); /* all is selected in path mode */ if(pset->selectmode==SCE_SELECT_PATH) @@ -531,99 +577,77 @@ static void foreach_mouse_hit_key(PEData *data, ForKeyMatFunc func, int selected Mat4One(imat); Mat4One(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); + LOOP_VISIBLE_POINTS { + if(edit->psys && !(edit->psys->flag & PSYS_GLOBAL_HAIR)) { + psys_mat_hair_to_global(data->ob, psmd->dm, psys->part->from, psys->particles + p, mat); + Mat4Invert(imat,mat); + } if(pset->selectmode==SCE_SELECT_END) { /* only do end keys */ - key= psys->edit->keys[i] + pa->totkey-1; + key= point->keys + point->totkey-1; if(selected==0 || key->flag & PEK_SELECT) - if(key_inside_circle(data, data->rad, key->world_co, &data->dist)) - func(data, mat, imat, i, pa->totkey-1); + if(key_inside_circle(data, data->rad, KEY_WCO, &data->dist)) + func(data, mat, imat, p, point->totkey-1, key); } else { /* do all keys */ - LOOP_KEYS(k, key) { - if(key->flag&PEK_HIDE) continue; - + LOOP_VISIBLE_KEYS { if(selected==0 || key->flag & PEK_SELECT) - if(key_inside_circle(data, data->rad, key->world_co, &data->dist)) - func(data, mat, imat, i, k); + if(key_inside_circle(data, data->rad, KEY_WCO, &data->dist)) + func(data, mat, imat, p, k, key); } } } } -static void foreach_selected_particle(PEData *data, ForParticleFunc func) +static void foreach_selected_point(PEData *data, ForPointFunc func) { - ParticleSystem *psys= data->psys; - ParticleData *pa; - int i, totpart; - - totpart= psys->totpart; + PTCacheEdit *edit = data->edit; + POINT_P; - LOOP_PARTICLES(i, pa) - if(particle_is_selected(psys, pa)) - func(data, i); + LOOP_SELECTED_POINTS { + func(data, p); + } } static void foreach_selected_key(PEData *data, ForKeyFunc func) { - ParticleSystem *psys= data->psys; - ParticleData *pa; - ParticleEditKey *key; - int i, k, totpart; - - totpart= psys->totpart; - - LOOP_PARTICLES(i, pa) { - if(pa->flag & PARS_HIDE) continue; + PTCacheEdit *edit = data->edit; + POINT_P; KEY_K; - key= psys->edit->keys[i]; - - LOOP_KEYS(k, key) - if(key->flag & PEK_SELECT) - func(data, i, k); + LOOP_VISIBLE_POINTS { + LOOP_SELECTED_KEYS { + func(data, p, k); + } } } -void PE_foreach_particle(PEData *data, ForParticleFunc func) +static void foreach_point(PEData *data, ForPointFunc func) { - ParticleSystem *psys= data->psys; - int i, totpart; - - totpart= psys->totpart; + PTCacheEdit *edit = data->edit; + POINT_P; - for(i=0; i<totpart; i++) - func(data, i); + LOOP_POINTS { + func(data, p); + } } -static int count_selected_keys(Scene *scene, ParticleSystem *psys) +static int count_selected_keys(Scene *scene, PTCacheEdit *edit) { - ParticleData *pa; - ParticleEditKey *key; ParticleEditSettings *pset= PE_settings(scene); - int i, k, totpart, sel= 0; - - totpart= psys->totpart; - - LOOP_PARTICLES(i, pa) { - if(pa->flag & PARS_HIDE) continue; - - key= psys->edit->keys[i]; + POINT_P; KEY_K; + int sel= 0; + LOOP_VISIBLE_POINTS { if(pset->selectmode==SCE_SELECT_POINT) { - for(k=0; k<pa->totkey; k++,key++) - if(key->flag & PEK_SELECT) - sel++; + LOOP_SELECTED_KEYS { + sel++; + } } else if(pset->selectmode==SCE_SELECT_END) { - key += pa->totkey-1; - + key = point->keys + point->totkey - 1; if(key->flag & PEK_SELECT) sel++; } @@ -638,13 +662,14 @@ static int count_selected_keys(Scene *scene, ParticleSystem *psys) static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys) { - ParticleEdit *edit; - ParticleData *pa; + PTCacheEdit *edit; ParticleSystemModifierData *psmd; KDTree *tree; KDTreeNearest nearest; + HairKey *key; + PARTICLE_P; float mat[4][4], co[3]; - int i, index, totpart; + int index, totpart; edit= psys->edit; psmd= psys_get_modifier(ob, psys); @@ -653,11 +678,12 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys) tree= BLI_kdtree_new(totpart); /* insert particles into kd tree */ - LOOP_PARTICLES(i, pa) { + LOOP_PARTICLES { + key = pa->hair; psys_mat_hair_to_orco(ob, psmd->dm, psys->part->from, pa, mat); - VECCOPY(co, pa->hair[0].co); + VECCOPY(co, key->co); Mat4MulVecfl(mat, co); - BLI_kdtree_insert(tree, i, co, NULL); + BLI_kdtree_insert(tree, p, co, NULL); } BLI_kdtree_balance(tree); @@ -666,27 +692,28 @@ static void PE_update_mirror_cache(Object *ob, ParticleSystem *psys) if(!edit->mirror_cache) edit->mirror_cache= MEM_callocN(sizeof(int)*totpart, "PE mirror cache"); - LOOP_PARTICLES(i, pa) { + LOOP_PARTICLES { + key = pa->hair; psys_mat_hair_to_orco(ob, psmd->dm, psys->part->from, pa, mat); - VECCOPY(co, pa->hair[0].co); + VECCOPY(co, key->co); Mat4MulVecfl(mat, co); co[0]= -co[0]; index= BLI_kdtree_find_nearest(tree, co, NULL, &nearest); /* this needs a custom threshold still, duplicated for editmode mirror */ - if(index != -1 && index != i && (nearest.dist <= 0.0002f)) - edit->mirror_cache[i]= index; + if(index != -1 && index != p && (nearest.dist <= 0.0002f)) + edit->mirror_cache[p]= index; else - edit->mirror_cache[i]= -1; + edit->mirror_cache[p]= -1; } /* make sure mirrors are in two directions */ - LOOP_PARTICLES(i, pa) { - if(edit->mirror_cache[i]) { - index= edit->mirror_cache[i]; - if(edit->mirror_cache[index] != i) - edit->mirror_cache[i]= -1; + LOOP_PARTICLES { + if(edit->mirror_cache[p]) { + index= edit->mirror_cache[p]; + if(edit->mirror_cache[index] != p) + edit->mirror_cache[p]= -1; } } @@ -696,8 +723,9 @@ 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; - ParticleEditKey *key, *mkey; - ParticleEdit *edit; + PTCacheEditPoint *point, *mpoint; + PTCacheEditKey *key, *mkey; + PTCacheEdit *edit; float mat[4][4], mmat[4][4], immat[4][4]; int i, mi, k; @@ -717,17 +745,20 @@ 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(edit->keys[mi]) MEM_freeN(edit->keys[mi]); + if(mpoint->keys) MEM_freeN(mpoint->keys); mpa->hair= MEM_dupallocN(pa->hair); - edit->keys[mi]= MEM_dupallocN(edit->keys[i]); - mpa->totkey= pa->totkey; + mpoint->keys= MEM_dupallocN(point->keys); + mpoint->totkey= point->totkey; mhkey= mpa->hair; - mkey= edit->keys[mi]; + mkey= mpoint->keys; for(k=0; k<mpa->totkey; k++, mkey++, mhkey++) { mkey->co= mhkey->co; mkey->time= &mhkey->time; @@ -742,8 +773,8 @@ static void PE_mirror_particle(Object *ob, DerivedMesh *dm, ParticleSystem *psys hkey=pa->hair; mhkey=mpa->hair; - key= edit->keys[i]; - mkey= edit->keys[mi]; + key= point->keys; + mkey= mpoint->keys; for(k=0; k<pa->totkey; k++, hkey++, mhkey++, key++, mkey++) { VECCOPY(mhkey->co, hkey->co); Mat4MulVecfl(mat, mhkey->co); @@ -754,199 +785,175 @@ static void PE_mirror_particle(Object *ob, DerivedMesh *dm, ParticleSystem *psys mkey->flag |= PEK_TAG; } - if(pa->flag & PARS_TAG) - mpa->flag |= PARS_TAG; - if(pa->flag & PARS_EDIT_RECALC) - mpa->flag |= PARS_EDIT_RECALC; + if(point->flag & PEP_TAG) + mpoint->flag |= PEP_TAG; + if(point->flag & PEP_EDIT_RECALC) + mpoint->flag |= PEP_EDIT_RECALC; } static void PE_apply_mirror(Object *ob, ParticleSystem *psys) { - ParticleEdit *edit; - ParticleData *pa; + PTCacheEdit *edit; ParticleSystemModifierData *psmd; - int i, totpart; + POINT_P; + + if(!psys) + return; 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_PARTICLES(i, pa) { - if(pa->flag & PARS_EDIT_RECALC) { - PE_mirror_particle(ob, psmd->dm, psys, pa, NULL); + LOOP_POINTS { + if(point->flag & PEP_EDIT_RECALC) { + PE_mirror_particle(ob, psmd->dm, psys, psys->particles + p, NULL); - if(edit->mirror_cache[i] != -1) - psys->particles[edit->mirror_cache[i]].flag &= ~PARS_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); + LOOP_POINTS { + if(point->flag & PEP_EDIT_RECALC) + if(edit->mirror_cache[p] != -1) + edit->points[edit->mirror_cache[p]].flag |= PEP_EDIT_RECALC; + } } /************************************************/ /* Edit Calculation */ /************************************************/ /* tries to stop edited particles from going through the emitter's surface */ -static void pe_deflect_emitter(Scene *scene, Object *ob, ParticleSystem *psys) +static void pe_deflect_emitter(Scene *scene, Object *ob, PTCacheEdit *edit) { - ParticleEdit *edit; - ParticleData *pa; - ParticleEditKey *key; ParticleEditSettings *pset= PE_settings(scene); - ParticleSystemModifierData *psmd= psys_get_modifier(ob,psys); - int i, k, totpart,index; + ParticleSystem *psys; + ParticleSystemModifierData *psmd; + POINT_P; KEY_K; + int index; float *vec, *nor, dvec[3], dot, dist_1st; float hairimat[4][4], hairmat[4][4]; - if(psys==0) - return; - - if((pset->flag & PE_DEFLECT_EMITTER)==0) + if(edit==NULL || edit->psys==NULL || (pset->flag & PE_DEFLECT_EMITTER)==0 || (edit->psys->flag & PSYS_GLOBAL_HAIR)) return; - edit= psys->edit; - totpart= psys->totpart; + psys = edit->psys; + psmd = psys_get_modifier(ob,psys); - 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) { + LOOP_EDITED_POINTS { + psys_mat_hair_to_object(ob, psmd->dm, psys->part->from, psys->particles + p, hairmat); + + LOOP_KEYS { Mat4MulVecfl(hairmat, key->co); } - //} - - //LOOP_PARTICLES(i, pa) { - key=psys->edit->keys[i]+1; - - dist_1st=VecLenf((key-1)->co,key->co); - dist_1st*=0.75f*pset->emitterdist; - 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; + 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; - VecSubf(dvec, key->co, vec); + VecSubf(dvec, key->co, vec); - dot=Inpf(dvec,nor); - VECCOPY(dvec,nor); + dot=Inpf(dvec,nor); + VECCOPY(dvec,nor); - if(dot>0.0f) { - if(dot<dist_1st) { + if(dot>0.0f) { + if(dot<dist_1st) { + Normalize(dvec); + VecMulf(dvec,dist_1st-dot); + VecAddf(key->co,key->co,dvec); + } + } + else { 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(k, key) { + LOOP_KEYS { Mat4MulVecfl(hairimat, key->co); } } } /* force set distances between neighbouring keys */ -void PE_apply_lengths(Scene *scene, ParticleSystem *psys) +void PE_apply_lengths(Scene *scene, PTCacheEdit *edit) { - ParticleEdit *edit; - ParticleData *pa; - ParticleEditKey *key; + ParticleEditSettings *pset=PE_settings(scene); - int i, k, totpart; + POINT_P; KEY_K; float dv1[3]; - if(psys==0) + if(edit==0 || (pset->flag & PE_KEEP_LENGTHS)==0) return; - if((pset->flag & PE_KEEP_LENGTHS)==0) + if(edit->psys && edit->psys->flag & PSYS_GLOBAL_HAIR) 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); + 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); + } } } } /* try to find a nice solution to keep distances between neighbouring keys */ -static void pe_iterate_lengths(Scene *scene, ParticleSystem *psys) +static void pe_iterate_lengths(Scene *scene, PTCacheEdit *edit) { - ParticleEdit *edit; - ParticleData *pa; - ParticleEditKey *key; ParticleEditSettings *pset=PE_settings(scene); - int i, j, k, totpart; + POINT_P; + PTCacheEditKey *key; + int j, k; float tlen; float dv0[3]= {0.0f, 0.0f, 0.0f}; float dv1[3]= {0.0f, 0.0f, 0.0f}; float dv2[3]= {0.0f, 0.0f, 0.0f}; - if(psys==0) + if(edit==0 || (pset->flag & PE_KEEP_LENGTHS)==0) return; - if((pset->flag & PE_KEEP_LENGTHS)==0) + if(edit->psys && edit->psys->flag & PSYS_GLOBAL_HAIR) return; - 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; + LOOP_EDITED_POINTS { + for(j=1; j<point->totkey; j++) { + float mul= 1.0f / (float)point->totkey; if(pset->flag & PE_LOCK_FIRST) { - key= edit->keys[i] + 1; + key= point->keys + 1; k= 1; dv1[0]= dv1[1]= dv1[2]= 0.0; } else { - key= edit->keys[i]; + key= point->keys; k= 0; dv0[0]= dv0[1]= dv0[2]= 0.0; } - for(; k<pa->totkey; k++, key++) { + for(; k<point->totkey; k++, key++) { if(k) { VecSubf(dv0, (key - 1)->co, key->co); tlen= Normalize(dv0); VecMulf(dv0, (mul * (tlen - (key - 1)->length))); } - if(k < pa->totkey - 1) { + if(k < point->totkey - 1) { VecSubf(dv2, (key + 1)->co, key->co); tlen= Normalize(dv2); VecMulf(dv2, mul * (tlen - key->length)); @@ -962,20 +969,16 @@ static void pe_iterate_lengths(Scene *scene, ParticleSystem *psys) } } /* set current distances to be kept between neighbouting keys */ -static void recalc_lengths(ParticleSystem *psys) +static void recalc_lengths(PTCacheEdit *edit) { - ParticleData *pa; - ParticleEditKey *key; - int i, k, totpart; + POINT_P; KEY_K; - if(psys==0) + if(edit==0) return; - totpart= psys->totpart; - - LOOP_PARTICLES(i, pa) { - key= psys->edit->keys[i]; - for(k=0; k<pa->totkey-1; k++, key++) { + LOOP_EDITED_POINTS { + key= point->keys; + for(k=0; k<point->totkey-1; k++, key++) { key->length= VecLenf(key->co, (key + 1)->co); } } @@ -985,7 +988,7 @@ static void recalc_lengths(ParticleSystem *psys) static void recalc_emitter_field(Object *ob, ParticleSystem *psys) { DerivedMesh *dm=psys_get_modifier(ob,psys)->dm; - ParticleEdit *edit= psys->edit; + PTCacheEdit *edit= psys->edit; MFace *mface; MVert *mvert; float *vec, *nor; @@ -1042,74 +1045,146 @@ 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); - ParticleSettings *part= psys->part; - ParticleData *pa; + PTCacheEdit *edit= PE_get_current(scene, ob); HairKey *hkey; - ParticleEditKey *key; - float cfra= CFRA; - int i, k, totpart; - - totpart= psys->totpart; + POINT_P; KEY_K; /* flag all particles to be updated if not using flag */ if(!useflag) - LOOP_PARTICLES(i, pa) - pa->flag |= PARS_EDIT_RECALC; + LOOP_POINTS + point->flag |= PEP_EDIT_RECALC; /* flush edit key flag to hair key flag to preserve selection * on save */ - LOOP_PARTICLES(i, pa) { - key= edit->keys[i]; - - for(k=0, hkey=pa->hair; k<pa->totkey; k++, hkey++, key++) + if(edit->psys) LOOP_POINTS { + hkey = edit->psys->particles[p].hair; + LOOP_KEYS { hkey->editflag= key->flag; + hkey++; + } } - psys_cache_paths(scene, ob, psys, CFRA, 1); + psys_cache_edit_paths(scene, ob, edit, CFRA); - if(part->childtype && (pset->flag & PE_SHOW_CHILD)) - psys_cache_child_paths(scene, ob, psys, cfra, 1); /* disable update flag */ - LOOP_PARTICLES(i, pa) - pa->flag &= ~PARS_EDIT_RECALC; + LOOP_POINTS + point->flag &= ~PEP_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 { + if(!(psys->flag & PSYS_GLOBAL_HAIR)) + psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, psys->particles+p, hairmat); + + LOOP_KEYS { + VECCOPY(key->world_co,key->co); + if(!(psys->flag & PSYS_GLOBAL_HAIR)) + 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); - ParticleSettings *part= psys->part; - ParticleData *pa; - float cfra= CFRA; - int i, totpart= psys->totpart; + PTCacheEdit *edit = PE_get_current(scene, ob); + POINT_P; + + if(!edit) + return; /* flag all particles to be updated if not using flag */ if(!useflag) - LOOP_PARTICLES(i, pa) - pa->flag |= PARS_EDIT_RECALC; + LOOP_POINTS { + point->flag |= PEP_EDIT_RECALC; + } /* do post process on particle edit keys */ - pe_iterate_lengths(scene, psys); - pe_deflect_emitter(scene, ob, psys); - PE_apply_lengths(scene, psys); + pe_iterate_lengths(scene, edit); + pe_deflect_emitter(scene, ob, edit); + PE_apply_lengths(scene, edit); if(pset->flag & PE_X_MIRROR) - PE_apply_mirror(ob,psys); - psys_update_world_cos(ob,psys); - PE_hide_keys_time(scene, psys, cfra); + 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); /* regenerate path caches */ - 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); + psys_cache_edit_paths(scene, ob, edit, CFRA); /* disable update flag */ - LOOP_PARTICLES(i, pa) - pa->flag &= ~PARS_EDIT_RECALC; + LOOP_POINTS { + point->flag &= ~PEP_EDIT_RECALC; + } + + DAG_id_flush_update(&ob->id, OB_RECALC_DATA); } /************************************************/ @@ -1118,48 +1193,44 @@ void PE_update_object(Scene *scene, Object *ob, int useflag) /*-----selection callbacks-----*/ -static void select_key(PEData *data, int pa_index, int key_index) +static void select_key(PEData *data, int point_index, int key_index) { - ParticleSystem *psys= data->psys; - ParticleData *pa= psys->particles + pa_index; - ParticleEditKey *key= psys->edit->keys[pa_index] + key_index; + PTCacheEdit *edit = data->edit; + PTCacheEditPoint *point = edit->points + point_index; + PTCacheEditKey *key = point->keys + key_index; if(data->select) key->flag |= PEK_SELECT; else key->flag &= ~PEK_SELECT; - pa->flag |= PARS_EDIT_RECALC; + point->flag |= PEP_EDIT_RECALC; } -static void select_keys(PEData *data, int pa_index, int key_index) +static void select_keys(PEData *data, int point_index, int key_index) { - ParticleSystem *psys= data->psys; - ParticleData *pa= psys->particles + pa_index; - ParticleEditKey *key= psys->edit->keys[pa_index]; - int k; + PTCacheEdit *edit = data->edit; + PTCacheEditPoint *point = edit->points + point_index; + KEY_K; - for(k=0; k<pa->totkey; k++,key++) { + LOOP_KEYS { if(data->select) key->flag |= PEK_SELECT; else key->flag &= ~PEK_SELECT; } - pa->flag |= PARS_EDIT_RECALC; + point->flag |= PEP_EDIT_RECALC; } -static void toggle_key_select(PEData *data, int pa_index, int key_index) +static void toggle_key_select(PEData *data, int point_index, int key_index) { - ParticleSystem *psys= data->psys; - ParticleData *pa= psys->particles + pa_index; + PTCacheEdit *edit = data->edit; + PTCacheEditPoint *point = edit->points + point_index; + PTCacheEditKey *key = point->keys + key_index; - 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; + key->flag ^= PEK_SELECT; + point->flag |= PEP_EDIT_RECALC; } /************************ de select all operator ************************/ @@ -1168,40 +1239,31 @@ static int de_select_all_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); - ParticleEdit *edit= 0; - ParticleData *pa; - ParticleEditKey *key; - int i, k, totpart, sel= 0; - - edit= psys->edit; - totpart= psys->totpart; + PTCacheEdit *edit= PE_get_current(scene, ob); + POINT_P; KEY_K; + int sel= 0; - 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; - } + LOOP_VISIBLE_POINTS { + LOOP_SELECTED_KEYS { + sel= 1; + key->flag &= ~PEK_SELECT; + point->flag |= PEP_EDIT_RECALC; } } if(sel==0) { - LOOP_PARTICLES(i, pa) { - if(pa->flag & PARS_HIDE) continue; - LOOP_KEYS(k, key) { + LOOP_VISIBLE_POINTS { + LOOP_KEYS { if(!(key->flag & PEK_SELECT)) { key->flag |= PEK_SELECT; - pa->flag |= PARS_EDIT_RECALC; + point->flag |= PEP_EDIT_RECALC; } } } } PE_update_selection(scene, ob, 1); - WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, ob); + WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_SELECT, ob); return OPERATOR_FINISHED; } @@ -1227,26 +1289,17 @@ 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); - ParticleSystem *psys= PE_get_current(scene, ob); - ParticleEdit *edit= 0; - ParticleData *pa; - ParticleEditKey *key; - int i, k, totpart; + PTCacheEdit *edit= PE_get_current(scene, ob); + POINT_P; KEY_K; - if(!PE_can_edit(psys)) + if(!PE_start_edit(edit)) return OPERATOR_CANCELLED; - edit= psys->edit; - totpart= psys->totpart; - if(!extend) { - 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; - } + LOOP_VISIBLE_POINTS { + LOOP_SELECTED_KEYS { + key->flag &= ~PEK_SELECT; + point->flag |= PEP_EDIT_RECALC; } } } @@ -1258,18 +1311,16 @@ int PE_mouse_particles(bContext *C, short *mval, int extend) for_mouse_hit_keys(&data, toggle_key_select, 1); /* nearest only */ PE_update_selection(scene, ob, 1); - WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, data.ob); + WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_SELECT, data.ob); return OPERATOR_FINISHED; } /************************ select first operator ************************/ -static void select_root(PEData *data, int pa_index) +static void select_root(PEData *data, int point_index) { - ParticleSystem *psys= data->psys; - - psys->edit->keys[pa_index]->flag |= PEK_SELECT; + data->edit->points[point_index].keys->flag |= PEK_SELECT; } static int select_first_exec(bContext *C, wmOperator *op) @@ -1277,8 +1328,8 @@ static int select_first_exec(bContext *C, wmOperator *op) PEData data; PE_set_data(C, &data); - PE_foreach_particle(&data, select_root); - WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, data.ob); + foreach_point(&data, select_root); + WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_SELECT, data.ob); return OPERATOR_FINISHED; } @@ -1299,13 +1350,10 @@ void PARTICLE_OT_select_first(wmOperatorType *ot) /************************ select last operator ************************/ -static void select_tip(PEData *data, int pa_index) +static void select_tip(PEData *data, int point_index) { - ParticleSystem *psys= data->psys; - ParticleData *pa= psys->particles + pa_index; - ParticleEditKey *key= psys->edit->keys[pa_index] + pa->totkey-1; - - key->flag |= PEK_SELECT; + PTCacheEditPoint *point = data->edit->points + point_index; + point->keys[point->totkey - 1].flag |= PEK_SELECT; } static int select_last_exec(bContext *C, wmOperator *op) @@ -1313,8 +1361,8 @@ static int select_last_exec(bContext *C, wmOperator *op) PEData data; PE_set_data(C, &data); - PE_foreach_particle(&data, select_tip); - WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, data.ob); + foreach_point(&data, select_tip); + WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_SELECT, data.ob); return OPERATOR_FINISHED; } @@ -1354,7 +1402,7 @@ static int select_linked_exec(bContext *C, wmOperator *op) for_mouse_hit_keys(&data, select_keys, 1); /* nearest only */ PE_update_selection(data.scene, data.ob, 1); - WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, data.ob); + WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_SELECT, data.ob); return OPERATOR_FINISHED; } @@ -1396,10 +1444,10 @@ int PE_border_select(bContext *C, rcti *rect, int select) { Scene *scene= CTX_data_scene(C); Object *ob= CTX_data_active_object(C); - ParticleSystem *psys= PE_get_current(scene, ob); + PTCacheEdit *edit= PE_get_current(scene, ob); PEData data; - if(!PE_can_edit(psys)) + if(!PE_start_edit(edit)) return OPERATOR_CANCELLED; PE_set_view3d_data(C, &data); @@ -1409,7 +1457,7 @@ int PE_border_select(bContext *C, rcti *rect, int select) for_mouse_hit_keys(&data, select_key, 0); PE_update_selection(scene, ob, 1); - WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, ob); + WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_SELECT, ob); return OPERATOR_FINISHED; } @@ -1420,10 +1468,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); - ParticleSystem *psys= PE_get_current(scene, ob); + PTCacheEdit *edit= PE_get_current(scene, ob); PEData data; - if(!PE_can_edit(psys)) + if(!PE_start_edit(edit)) return OPERATOR_FINISHED; PE_set_view3d_data(C, &data); @@ -1434,7 +1482,7 @@ int PE_circle_select(bContext *C, int selecting, short *mval, float rad) for_mouse_hit_keys(&data, select_key, 0); PE_update_selection(scene, ob, 1); - WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, ob); + WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_SELECT, ob); return OPERATOR_FINISHED; } @@ -1446,47 +1494,42 @@ 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_can_edit(psys)) + if(!PE_start_edit(edit)) return OPERATOR_CANCELLED; - psmd= psys_get_modifier(ob, psys); - edit= psys->edit; - totpart= psys->totpart; - - LOOP_PARTICLES(i, pa) { - if(pa->flag & PARS_HIDE) continue; + Mat4One(mat); - psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, mat); + LOOP_VISIBLE_POINTS { + if(edit->psys && !(psys->flag & PSYS_GLOBAL_HAIR)) + psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, psys->particles + p, mat); if(pset->selectmode==SCE_SELECT_POINT) { - LOOP_KEYS(k, key) { + LOOP_KEYS { 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; - pa->flag |= PARS_EDIT_RECALC; + point->flag |= PEP_EDIT_RECALC; } else if(key->flag & PEK_SELECT) { key->flag &= ~PEK_SELECT; - pa->flag |= PARS_EDIT_RECALC; + point->flag |= PEP_EDIT_RECALC; } } } } else if(pset->selectmode==SCE_SELECT_END) { - key= edit->keys[i] + pa->totkey - 1; + key= point->keys + point->totkey - 1; VECCOPY(co, key->co); Mat4MulVecfl(mat, co); @@ -1494,18 +1537,18 @@ 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; - pa->flag |= PARS_EDIT_RECALC; + point->flag |= PEP_EDIT_RECALC; } else if(key->flag & PEK_SELECT) { key->flag &= ~PEK_SELECT; - pa->flag |= PARS_EDIT_RECALC; + point->flag |= PEP_EDIT_RECALC; } } } } PE_update_selection(scene, ob, 1); - WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, ob); + WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_SELECT, ob); return OPERATOR_FINISHED; } @@ -1516,40 +1559,30 @@ static int hide_exec(bContext *C, wmOperator *op) { Object *ob= CTX_data_active_object(C); Scene *scene= CTX_data_scene(C); - ParticleSystem *psys= PE_get_current(scene, ob); - ParticleEdit *edit; - ParticleEditKey *key; - ParticleData *pa; - int i, k, totpart; - - edit= psys->edit; - totpart= psys->totpart; + PTCacheEdit *edit= PE_get_current(scene, ob); + POINT_P; KEY_K; if(RNA_enum_get(op->ptr, "unselected")) { - LOOP_PARTICLES(i, pa) { - if(!particle_is_selected(psys, pa)) { - pa->flag |= PARS_HIDE; - pa->flag |= PARS_EDIT_RECALC; + LOOP_UNSELECTED_POINTS { + point->flag |= PEP_HIDE; + point->flag |= PEP_EDIT_RECALC; - LOOP_KEYS(k, key) - key->flag &= ~PEK_SELECT; - } + LOOP_KEYS + key->flag &= ~PEK_SELECT; } } else { - LOOP_PARTICLES(i, pa) { - if(particle_is_selected(psys, pa)) { - pa->flag |= PARS_HIDE; - pa->flag |= PARS_EDIT_RECALC; + LOOP_SELECTED_POINTS { + point->flag |= PEP_HIDE; + point->flag |= PEP_EDIT_RECALC; - LOOP_KEYS(k, key) - key->flag &= ~PEK_SELECT; - } + LOOP_KEYS + key->flag &= ~PEK_SELECT; } } PE_update_selection(scene, ob, 1); - WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, ob); + WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_SELECT, ob); return OPERATOR_FINISHED; } @@ -1577,27 +1610,21 @@ static int reveal_exec(bContext *C, wmOperator *op) { Object *ob= CTX_data_active_object(C); Scene *scene= CTX_data_scene(C); - ParticleSystem *psys= PE_get_current(scene, ob); - ParticleEdit *edit; - ParticleEditKey *key; - ParticleData *pa; - int i, k, totpart; - - edit= psys->edit; - totpart= psys->totpart; + PTCacheEdit *edit= PE_get_current(scene, ob); + POINT_P; KEY_K; - LOOP_PARTICLES(i, pa) { - if(pa->flag & PARS_HIDE) { - pa->flag &= ~PARS_HIDE; - pa->flag |= PARS_EDIT_RECALC; + LOOP_POINTS { + if(point->flag & PEP_HIDE) { + point->flag &= ~PEP_HIDE; + point->flag |= PEP_EDIT_RECALC; - LOOP_KEYS(k, key) + LOOP_KEYS key->flag |= PEK_SELECT; } } PE_update_selection(scene, ob, 1); - WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, ob); + WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_SELECT, ob); return OPERATOR_FINISHED; } @@ -1618,34 +1645,30 @@ void PARTICLE_OT_reveal(wmOperatorType *ot) /************************ select less operator ************************/ -static void select_less_keys(PEData *data, int pa_index) +static void select_less_keys(PEData *data, int point_index) { - 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; + PTCacheEdit *edit= data->edit; + PTCacheEditPoint *point = edit->points + point_index; + KEY_K; + LOOP_SELECTED_KEYS { if(k==0) { if(((key+1)->flag&PEK_SELECT)==0) - key->flag |= PEK_TO_SELECT; + key->flag |= PEK_TAG; } - else if(k==pa->totkey-1) { + else if(k==point->totkey-1) { if(((key-1)->flag&PEK_SELECT)==0) - key->flag |= PEK_TO_SELECT; + key->flag |= PEK_TAG; } else { if((((key-1)->flag & (key+1)->flag) & PEK_SELECT)==0) - key->flag |= PEK_TO_SELECT; + 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|PEK_SELECT); + LOOP_KEYS { + if(key->flag&PEK_TAG) + key->flag &= ~(PEK_TAG|PEK_SELECT); } } @@ -1654,8 +1677,8 @@ static int select_less_exec(bContext *C, wmOperator *op) PEData data; PE_set_data(C, &data); - PE_foreach_particle(&data, select_less_keys); - WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, data.ob); + foreach_point(&data, select_less_keys); + WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_SELECT, data.ob); return OPERATOR_FINISHED; } @@ -1676,34 +1699,32 @@ void PARTICLE_OT_select_less(wmOperatorType *ot) /************************ select more operator ************************/ -static void select_more_keys(PEData *data, int pa_index) +static void select_more_keys(PEData *data, int point_index) { - ParticleSystem *psys= data->psys; - ParticleEdit *edit= psys->edit; - ParticleData *pa= &psys->particles[pa_index]; - ParticleEditKey *key; - int k; + PTCacheEdit *edit= data->edit; + PTCacheEditPoint *point = edit->points + point_index; + KEY_K; - for(k=0,key=edit->keys[pa_index]; k<pa->totkey; k++,key++) { + LOOP_KEYS { if(key->flag & PEK_SELECT) continue; if(k==0) { if((key+1)->flag&PEK_SELECT) - key->flag |= PEK_TO_SELECT; + key->flag |= PEK_TAG; } - else if(k==pa->totkey-1) { + else if(k==point->totkey-1) { if((key-1)->flag&PEK_SELECT) - key->flag |= PEK_TO_SELECT; + key->flag |= PEK_TAG; } else { if(((key-1)->flag | (key+1)->flag) & PEK_SELECT) - key->flag |= PEK_TO_SELECT; + 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; + LOOP_KEYS { + if(key->flag&PEK_TAG) { + key->flag &= ~PEK_TAG; key->flag |= PEK_SELECT; } } @@ -1714,8 +1735,8 @@ static int select_more_exec(bContext *C, wmOperator *op) PEData data; PE_set_data(C, &data); - PE_foreach_particle(&data, select_more_keys); - WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, data.ob); + foreach_point(&data, select_more_keys); + WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_SELECT, data.ob); return OPERATOR_FINISHED; } @@ -1738,12 +1759,13 @@ void PARTICLE_OT_select_more(wmOperatorType *ot) static void rekey_particle(PEData *data, int pa_index) { - ParticleSystem *psys= data->psys; - ParticleData *pa= &psys->particles[pa_index]; - ParticleEdit *edit= psys->edit; + PTCacheEdit *edit= data->edit; + ParticleSystem *psys= edit->psys; + ParticleData *pa= psys->particles + pa_index; + PTCacheEditPoint *point = edit->points + pa_index; ParticleKey state; - HairKey *key, *new_keys; - ParticleEditKey *ekey; + HairKey *key, *new_keys, *okey; + PTCacheEditKey *ekey; float dval, sta, end; int k; @@ -1751,12 +1773,13 @@ static void rekey_particle(PEData *data, int pa_index) key= new_keys= MEM_callocN(data->totrekey * sizeof(HairKey),"Hair re-key keys"); + okey = pa->hair; /* root and tip stay the same */ - VECCOPY(key->co, pa->hair->co); - VECCOPY((key + data->totrekey - 1)->co, (pa->hair + pa->totkey - 1)->co); + VECCOPY(key->co, okey->co); + VECCOPY((key + data->totrekey - 1)->co, (okey + pa->totkey - 1)->co); - sta= key->time= pa->hair->time; - end= (key + data->totrekey - 1)->time= (pa->hair + pa->totkey - 1)->time; + sta= key->time= okey->time; + end= (key + data->totrekey - 1)->time= (okey + pa->totkey - 1)->time; dval= (end - sta) / (float)(data->totrekey - 1); /* interpolate new keys from old ones */ @@ -1772,19 +1795,22 @@ static void rekey_particle(PEData *data, int pa_index) MEM_freeN(pa->hair); pa->hair= new_keys; - pa->totkey=data->totrekey; + point->totkey=pa->totkey=data->totrekey; - 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"); + + if(point->keys) + MEM_freeN(point->keys); + ekey= point->keys= MEM_callocN(pa->totkey * sizeof(PTCacheEditKey),"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; + if(!(psys->flag & PSYS_GLOBAL_HAIR)) + ekey->flag |= PEK_USE_WCO; } pa->flag &= ~PARS_REKEY; - pa->flag |= PARS_EDIT_RECALC; + point->flag |= PEP_EDIT_RECALC; } static int rekey_exec(bContext *C, wmOperator *op) @@ -1796,13 +1822,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_particle(&data, rekey_particle); - - data.psys->edit->totkeys= psys_count_keys(data.psys); - recalc_lengths(data.psys); + foreach_selected_point(&data, rekey_particle); + recalc_lengths(data.edit); PE_update_object(data.scene, data.ob, 1); - WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, data.ob); + WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_DATA, data.ob); return OPERATOR_FINISHED; } @@ -1827,19 +1851,19 @@ void PARTICLE_OT_rekey(wmOperatorType *ot) static void rekey_particle_to_time(Scene *scene, Object *ob, int pa_index, float path_time) { - ParticleSystem *psys= PE_get_current(scene, ob); - ParticleEdit *edit=0; + PTCacheEdit *edit= PE_get_current(scene, ob); + ParticleSystem *psys; ParticleData *pa; ParticleKey state; HairKey *new_keys, *key; - ParticleEditKey *ekey; + PTCacheEditKey *ekey; int k; - if(psys==0) return; + if(!edit || !edit->psys) return; - edit= psys->edit; + psys = edit->psys; - pa= &psys->particles[pa_index]; + pa= psys->particles + pa_index; pa->flag |= PARS_REKEY; @@ -1858,7 +1882,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->keys[pa_index]; k<pa->totkey; k++, key++, ekey++) { + for(k=0, key=pa->hair, ekey=edit->points[pa_index].keys; k<pa->totkey; k++, key++, ekey++) { ekey->co= key->co; ekey->time= &key->time; } @@ -1870,10 +1894,11 @@ 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) { - ParticleEdit *edit= psys->edit; + PTCacheEdit *edit = psys->edit; ParticleEditSettings *pset= PE_settings(scene); ParticleData *pa, *npa=0, *new_pars=0; - ParticleEditKey **key, **nkey=0, **new_keys=0; + POINT_P; + PTCacheEditPoint *npoint=0, *new_points=0; ParticleSystemModifierData *psmd; int i, totpart, new_totpart= psys->totpart, removed= 0; @@ -1882,55 +1907,51 @@ static int remove_tagged_particles(Scene *scene, Object *ob, ParticleSystem *psy psmd= psys_get_modifier(ob, psys); totpart= psys->totpart; - LOOP_PARTICLES(i, pa) - if(pa->flag & PARS_TAG) - PE_mirror_particle(ob, psmd->dm, psys, pa, NULL); + LOOP_TAGGED_POINTS { + PE_mirror_particle(ob, psmd->dm, psys, psys->particles + p, NULL); + } } - for(i=0, pa=psys->particles; i<psys->totpart; i++, pa++) { - if(pa->flag & PARS_TAG) { - new_totpart--; - removed++; - } + LOOP_TAGGED_POINTS { + new_totpart--; + removed++; } if(new_totpart != psys->totpart) { if(new_totpart) { npa= new_pars= MEM_callocN(new_totpart * sizeof(ParticleData), "ParticleData array"); - nkey= new_keys= MEM_callocN(new_totpart * sizeof(ParticleEditKey *), "ParticleEditKey array"); + npoint= new_points= MEM_callocN(new_totpart * sizeof(PTCacheEditPoint), "PTCacheEditKey array"); } pa= psys->particles; - key= edit->keys; - for(i=0; i<psys->totpart; i++, pa++, key++) { - if(pa->flag & PARS_TAG) { - if(*key) - MEM_freeN(*key); + point= edit->points; + for(i=0; i<psys->totpart; i++, pa++, point++) { + if(point->flag & PEP_TAG) { + if(point->keys) + MEM_freeN(point->keys); if(pa->hair) MEM_freeN(pa->hair); } else { memcpy(npa, pa, sizeof(ParticleData)); - memcpy(nkey, key, sizeof(ParticleEditKey*)); + memcpy(npoint, point, sizeof(PTCacheEditPoint)); npa++; - nkey++; + npoint++; } } if(psys->particles) MEM_freeN(psys->particles); psys->particles= new_pars; - if(edit->keys) MEM_freeN(edit->keys); - edit->keys= new_keys; + if(edit->points) MEM_freeN(edit->points); + edit->points= new_points; if(edit->mirror_cache) { MEM_freeN(edit->mirror_cache); edit->mirror_cache= NULL; } - psys->totpart= new_totpart; - - edit->totkeys= psys_count_keys(psys); + edit->totpoint= psys->totpart= new_totpart; } return removed; @@ -1938,84 +1959,82 @@ static int remove_tagged_particles(Scene *scene, Object *ob, ParticleSystem *psy static void remove_tagged_keys(Scene *scene, Object *ob, ParticleSystem *psys) { - ParticleEdit *edit= psys->edit; + PTCacheEdit *edit= psys->edit; ParticleEditSettings *pset= PE_settings(scene); ParticleData *pa; - HairKey *key, *nkey, *new_keys=0; - ParticleEditKey *ekey; + HairKey *hkey, *nhkey, *new_hkeys=0; + POINT_P; KEY_K; 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_PARTICLES(i, pa) { - LOOP_KEYS(k,ekey) { - if(ekey->flag & PEK_TAG) { - PE_mirror_particle(ob, psmd->dm, psys, pa, NULL); - break; - } + LOOP_POINTS { + LOOP_TAGGED_KEYS { + PE_mirror_particle(ob, psmd->dm, psys, psys->particles + p, NULL); + break; } } } - LOOP_PARTICLES(i, pa) { - new_totkey= pa->totkey; - LOOP_KEYS(k,ekey) { - if(ekey->flag & PEK_TAG) - new_totkey--; + LOOP_POINTS { + new_totkey= point->totkey; + LOOP_TAGGED_KEYS { + new_totkey--; } /* we can't have elements with less than two keys*/ if(new_totkey < 2) - pa->flag |= PARS_TAG; + point->flag |= PEP_TAG; } remove_tagged_particles(scene, ob, psys); - totpart= psys->totpart; - - LOOP_PARTICLES(i, pa) { + LOOP_POINTS { + pa = psys->particles + p; new_totkey= pa->totkey; - LOOP_KEYS(k,ekey) { - if(ekey->flag & PEK_TAG) - new_totkey--; + + LOOP_TAGGED_KEYS { + new_totkey--; } + if(new_totkey != pa->totkey) { - key= pa->hair; - nkey= new_keys= MEM_callocN(new_totkey*sizeof(HairKey), "HairKeys"); + hkey= pa->hair; + nhkey= new_hkeys= MEM_callocN(new_totkey*sizeof(HairKey), "HairKeys"); - for(k=0, ekey=edit->keys[i]; k<new_totkey; k++, key++, nkey++, ekey++) { - while(ekey->flag & PEK_TAG && key < pa->hair + pa->totkey) { + LOOP_KEYS { + while(key->flag & PEK_TAG && hkey < pa->hair + pa->totkey) { key++; - ekey++; + hkey++; } - if(key < pa->hair + pa->totkey) { - VECCOPY(nkey->co, key->co); - nkey->time= key->time; - nkey->weight= key->weight; + if(hkey < pa->hair + pa->totkey) { + VECCOPY(nhkey->co, hkey->co); + nhkey->time= hkey->time; + nhkey->weight= hkey->weight; } + hkey++; + nhkey++; } if(pa->hair) MEM_freeN(pa->hair); - pa->hair= new_keys; + pa->hair= new_hkeys; - pa->totkey=new_totkey; + point->totkey= pa->totkey= new_totkey; - if(edit->keys[i]) - MEM_freeN(edit->keys[i]); - ekey= edit->keys[i]= MEM_callocN(new_totkey*sizeof(ParticleEditKey), "particle edit keys"); + if(point->keys) + MEM_freeN(point->keys); + key= point->keys= MEM_callocN(new_totkey*sizeof(PTCacheEditKey), "particle edit keys"); - for(k=0, key=pa->hair; k<pa->totkey; k++, key++, ekey++) { - ekey->co= key->co; - ekey->time= &key->time; + hkey = pa->hair; + LOOP_KEYS { + key->co= hkey->co; + key->time= &hkey->time; + hkey++; } } } - - edit->totkeys= psys_count_keys(psys); } /************************ subdivide opertor *********************/ @@ -2023,19 +2042,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) { - ParticleSystem *psys= data->psys; - ParticleEdit *edit= psys->edit; - ParticleData *pa= &psys->particles[pa_index]; - + PTCacheEdit *edit= data->edit; + ParticleSystem *psys= edit->psys; + ParticleData *pa= psys->particles + pa_index; + PTCacheEditPoint *point = edit->points + pa_index; ParticleKey state; HairKey *key, *nkey, *new_keys; - ParticleEditKey *ekey, *nekey, *new_ekeys; + PTCacheEditKey *ekey, *nekey, *new_ekeys; int k; short totnewkey=0; float endtime; - for(k=0, ekey=edit->keys[pa_index]; k<pa->totkey-1; k++,ekey++) { + for(k=0, ekey=point->keys; k<pa->totkey-1; k++,ekey++) { if(ekey->flag&PEK_SELECT && (ekey+1)->flag&PEK_SELECT) totnewkey++; } @@ -2045,13 +2064,15 @@ 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(ParticleEditKey)),"Hair subdivide edit keys"); - endtime= pa->hair[pa->totkey-1].time; + nekey= new_ekeys= MEM_callocN((pa->totkey+totnewkey)*(sizeof(PTCacheEditKey)),"Hair subdivide edit keys"); + + key = pa->hair; + endtime= key[pa->totkey-1].time; - for(k=0, key=pa->hair, ekey=edit->keys[pa_index]; k<pa->totkey-1; k++, key++, ekey++) { + for(k=0, ekey=point->keys; k<pa->totkey-1; k++, key++, ekey++) { memcpy(nkey,key,sizeof(HairKey)); - memcpy(nekey,ekey,sizeof(ParticleEditKey)); + memcpy(nekey,ekey,sizeof(PTCacheEditKey)); nekey->co= nkey->co; nekey->time= &nkey->time; @@ -2068,6 +2089,8 @@ static void subdivide_particle(PEData *data, int pa_index) nekey->co= nkey->co; nekey->time= &nkey->time; nekey->flag |= PEK_SELECT; + if(!(psys->flag & PSYS_GLOBAL_HAIR)) + nekey->flag |= PEK_USE_WCO; nekey++; nkey++; @@ -2075,7 +2098,7 @@ static void subdivide_particle(PEData *data, int pa_index) } /*tip still not copied*/ memcpy(nkey,key,sizeof(HairKey)); - memcpy(nekey,ekey,sizeof(ParticleEditKey)); + memcpy(nekey,ekey,sizeof(PTCacheEditKey)); nekey->co= nkey->co; nekey->time= &nkey->time; @@ -2084,13 +2107,12 @@ static void subdivide_particle(PEData *data, int pa_index) MEM_freeN(pa->hair); pa->hair= new_keys; - if(edit->keys[pa_index]) - MEM_freeN(edit->keys[pa_index]); + if(point->keys) + MEM_freeN(point->keys); + point->keys= new_ekeys; - edit->keys[pa_index]= new_ekeys; - - pa->totkey += totnewkey; - pa->flag |= PARS_EDIT_RECALC; + point->totkey = pa->totkey = pa->totkey + totnewkey; + point->flag |= PEP_EDIT_RECALC; pa->flag &= ~PARS_REKEY; } @@ -2099,15 +2121,11 @@ static int subdivide_exec(bContext *C, wmOperator *op) PEData data; PE_set_data(C, &data); - PE_foreach_particle(&data, subdivide_particle); - - data.psys->edit->totkeys= psys_count_keys(data.psys); + foreach_point(&data, subdivide_particle); - recalc_lengths(data.psys); - psys_update_world_cos(data.ob, 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); + WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_DATA, data.ob); return OPERATOR_FINISHED; } @@ -2132,15 +2150,18 @@ 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); - ParticleData *pa; - ParticleEdit *edit; + PTCacheEdit *edit= PE_get_current(scene, ob); + ParticleSystem *psys = edit->psys; ParticleSystemModifierData *psmd; KDTree *tree; KDTreeNearest nearest[10]; + POINT_P; float mat[4][4], co[3], threshold= RNA_float_get(op->ptr, "threshold"); - int i, n, totn, removed, totpart, flag, totremoved; + int n, totn, removed, flag, totremoved; + + if(psys->flag & PSYS_GLOBAL_HAIR) + return OPERATOR_CANCELLED; edit= psys->edit; psmd= psys_get_modifier(ob, psys); @@ -2149,37 +2170,32 @@ static int remove_doubles_exec(bContext *C, wmOperator *op) do { removed= 0; - totpart= psys->totpart; - tree=BLI_kdtree_new(totpart); + tree=BLI_kdtree_new(psys->totpart); /* insert particles into kd tree */ - 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); - } + 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); } BLI_kdtree_balance(tree); /* tag particles to be removed */ - 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); + 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); - 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 > i && nearest[n].dist < threshold) { - if(!(pa->flag & PARS_TAG)) { - pa->flag |= PARS_TAG; - removed++; - } + 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++; } } } @@ -2200,9 +2216,9 @@ static int remove_doubles_exec(bContext *C, wmOperator *op) BKE_reportf(op->reports, RPT_INFO, "Remove %d double particles.", totremoved); - 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); + PE_update_object(scene, ob, 0); + DAG_id_flush_update(&ob->id, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_DATA, ob); return OPERATOR_FINISHED; } @@ -2347,16 +2363,16 @@ static EnumPropertyItem delete_type_items[]= { static void set_delete_particle(PEData *data, int pa_index) { - ParticleSystem *psys= data->psys; + PTCacheEdit *edit= data->edit; - psys->particles[pa_index].flag |= PARS_TAG; + edit->points[pa_index].flag |= PEP_TAG; } static void set_delete_particle_key(PEData *data, int pa_index, int key_index) { - ParticleSystem *psys= data->psys; + PTCacheEdit *edit= data->edit; - psys->edit->keys[pa_index][key_index].flag |= PEK_TAG; + edit->points[pa_index].keys[key_index].flag |= PEK_TAG; } static int delete_exec(bContext *C, wmOperator *op) @@ -2368,17 +2384,19 @@ 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.psys); - recalc_lengths(data.psys); + remove_tagged_keys(data.scene, data.ob, data.edit->psys); + recalc_lengths(data.edit); } else if(type == DEL_PARTICLE) { - foreach_selected_particle(&data, set_delete_particle); - remove_tagged_particles(data.scene, data.ob, data.psys); - recalc_lengths(data.psys); + foreach_selected_point(&data, set_delete_particle); + remove_tagged_particles(data.scene, data.ob, data.edit->psys); + recalc_lengths(data.edit); } - DAG_object_flush_update(data.scene, data.ob, OB_RECALC_DATA); - WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_DATA, data.ob); + PE_update_object(data.scene, data.ob, 0); + + DAG_id_flush_update(&data.ob->id, OB_RECALC_DATA); + WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_DATA, data.ob); return OPERATOR_FINISHED; } @@ -2392,7 +2410,7 @@ void PARTICLE_OT_delete(wmOperatorType *ot) /* api callbacks */ ot->exec= delete_exec; ot->invoke= WM_menu_invoke; - ot->poll= PE_poll; + ot->poll= PE_hair_poll; /* flags */ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO; @@ -2407,15 +2425,18 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged) { Mesh *me= (Mesh*)(ob->data); ParticleSystemModifierData *psmd; - ParticleSystem *psys= PE_get_current(scene, ob); - ParticleEdit *edit; + PTCacheEdit *edit= PE_get_current(scene, ob); + ParticleSystem *psys = edit->psys; ParticleData *pa, *newpa, *new_pars; - ParticleEditKey *ekey, **newkey, **key, **new_keys; + PTCacheEditPoint *newpoint, *new_points; + POINT_P; KEY_K; HairKey *hkey; int *mirrorfaces; - int i, k, rotation, totpart, newtotpart; + int rotation, totpart, newtotpart; + + if(psys->flag & PSYS_GLOBAL_HAIR) + return; - edit= psys->edit; psmd= psys_get_modifier(ob, psys); mirrorfaces= mesh_get_x_mirror_faces(ob, NULL); @@ -2425,29 +2446,28 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged) totpart= psys->totpart; newtotpart= psys->totpart; - LOOP_PARTICLES(i, pa) { - if(pa->flag & PARS_HIDE) continue; - + LOOP_VISIBLE_POINTS { + pa = psys->particles + p; if(!tagged) { - if(particle_is_selected(psys, pa)) { - if(edit->mirror_cache[i] != -1) { + if(point_is_selected(point)) { + if(edit->mirror_cache[p] != -1) { /* already has a mirror, don't need to duplicate */ PE_mirror_particle(ob, psmd->dm, psys, pa, NULL); continue; } else - pa->flag |= PARS_TAG; + point->flag |= PEP_TAG; } } - if((pa->flag & PARS_TAG) && mirrorfaces[pa->num*2] != -1) + if((point->flag & PEP_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_keys= MEM_callocN(newtotpart*sizeof(ParticleEditKey*), "ParticleEditKey new"); + new_points= MEM_callocN(newtotpart*sizeof(PTCacheEditPoint), "PTCacheEditPoint new"); if(psys->particles) { memcpy(new_pars, psys->particles, totpart*sizeof(ParticleData)); @@ -2455,36 +2475,34 @@ static void PE_mirror_x(Scene *scene, Object *ob, int tagged) } psys->particles= new_pars; - if(edit->keys) { - memcpy(new_keys, edit->keys, totpart*sizeof(ParticleEditKey*)); - MEM_freeN(edit->keys); + if(edit->points) { + memcpy(new_points, edit->points, totpart*sizeof(PTCacheEditPoint)); + MEM_freeN(edit->points); } - edit->keys= new_keys; + edit->points= new_points; if(edit->mirror_cache) { MEM_freeN(edit->mirror_cache); edit->mirror_cache= NULL; } - psys->totpart= newtotpart; + edit->totpoint= psys->totpart= newtotpart; /* create new elements */ - pa= psys->particles; newpa= psys->particles + totpart; - key= edit->keys; - newkey= edit->keys + totpart; + newpoint= edit->points + totpart; - for(i=0; i<totpart; i++, pa++, key++) { - if(pa->flag & PARS_HIDE) continue; + LOOP_VISIBLE_POINTS { + pa = psys->particles + p; - if(!(pa->flag & PARS_TAG) || mirrorfaces[pa->num*2] == -1) + if(!(point->flag & PEP_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(*key) *newkey= MEM_dupallocN(*key); + if(point->keys) newpoint->keys= MEM_dupallocN(point->keys); /* rotate weights according to vertex index rotation */ rotation= mirrorfaces[pa->num*2+1]; @@ -2503,24 +2521,23 @@ 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 */ - ekey= *newkey; - for(k=0, hkey=newpa->hair; k<newpa->totkey; k++, hkey++, ekey++) { - ekey->co= hkey->co; - ekey->time= &hkey->time; + key= newpoint->keys; + for(k=0, hkey=newpa->hair; k<newpa->totkey; k++, hkey++, key++) { + key->co= hkey->co; + key->time= &hkey->time; } /* map key positions as mirror over x axis */ PE_mirror_particle(ob, psmd->dm, psys, pa, newpa); newpa++; - newkey++; + newpoint++; } - - edit->totkeys= psys_count_keys(psys); } - for(pa=psys->particles, i=0; i<psys->totpart; i++, pa++) - pa->flag &= ~PARS_TAG; + LOOP_POINTS { + point->flag &= ~PEP_TAG; + } MEM_freeN(mirrorfaces); } @@ -2529,13 +2546,13 @@ static int mirror_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); + PTCacheEdit *edit= PE_get_current(scene, ob); PE_mirror_x(scene, ob, 0); - 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); + update_world_cos(ob, edit); + WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_DATA, ob); + DAG_id_flush_update(&ob->id, OB_RECALC_DATA); return OPERATOR_FINISHED; } @@ -2560,7 +2577,6 @@ 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", ""}, @@ -2593,14 +2609,46 @@ 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 Edit Type"; + ot->idname= "PARTICLE_OT_edit_type_set"; + + /* api callbacks */ + ot->exec= set_edit_mode_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 pa_index, int key_index) +static void brush_comb(PEData *data, float mat[][4], float imat[][4], int point_index, int key_index, PTCacheEditKey *key) { - 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; @@ -2612,19 +2660,19 @@ static void brush_comb(PEData *data, float mat[][4], float imat[][4], int pa_ind VecMulf(cvec, fac); VECADD(key->co, key->co, cvec); - pa->flag |= PARS_EDIT_RECALC; + (data->edit->points + point_index)->flag |= PEP_EDIT_RECALC; } static void brush_cut(PEData *data, int pa_index) { - ParticleSystem *psys= data->psys; + PTCacheEdit *edit = data->edit; ARegion *ar= data->vc.ar; Object *ob= data->ob; - ParticleData *pa= &psys->particles[pa_index]; - ParticleCacheKey *key= psys->pathcache[pa_index]; + ParticleEditSettings *pset= PE_settings(data->scene); + ParticleCacheKey *key= edit->pathcache[pa_index]; float rad2, cut_time= 1.0; float x0, x1, v0, v1, o0, o1, xo0, xo1, d, dv; - int k, cut, keys= (int)pow(2.0, (double)psys->part->draw_step); + int k, cut, keys= (int)pow(2.0, (double)pset->draw_step); short vertco[2]; /* blunt scissors */ @@ -2699,93 +2747,97 @@ static void brush_cut(PEData *data, int pa_index) if(cut) { if(cut_time < 0.0f) { - pa->flag |= PARS_TAG; + edit->points[pa_index].flag |= PEP_TAG; } else { rekey_particle_to_time(data->scene, ob, pa_index, cut_time); - pa->flag |= PARS_EDIT_RECALC; + edit->points[pa_index].flag |= PEP_EDIT_RECALC; } } } -static void brush_length(PEData *data, int pa_index) +static void brush_length(PEData *data, int point_index) { - ParticleSystem *psys= data->psys; - ParticleData *pa= &psys->particles[pa_index]; - HairKey *key; + PTCacheEdit *edit= data->edit; + PTCacheEditPoint *point = edit->points + point_index; + KEY_K; float dvec[3],pvec[3]; - int k; - - 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); + 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); + } } - pa->flag |= PARS_EDIT_RECALC; + point->flag |= PEP_EDIT_RECALC; } -static void brush_puff(PEData *data, int pa_index) +static void brush_puff(PEData *data, int point_index) { - ParticleSystem *psys= data->psys; - ParticleData *pa= &psys->particles[pa_index]; - ParticleEdit *edit= psys->edit; - HairKey *key; + PTCacheEdit *edit = data->edit; + ParticleSystem *psys = edit->psys; + PTCacheEditPoint *point = edit->points + point_index; + KEY_K; float mat[4][4], imat[4][4]; float lastco[3], rootco[3], co[3], nor[3], kco[3], dco[3], fac, length; - int k; - psys_mat_hair_to_global(data->ob, data->dm, psys->part->from, pa, mat); - Mat4Invert(imat,mat); - - /* find root coordinate and normal on emitter */ - key= pa->hair; - VECCOPY(co, key->co); - Mat4MulVecfl(mat, co); + if(psys && !(psys->flag & PSYS_GLOBAL_HAIR)) { + 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); + } - pa_index= BLI_kdtree_find_nearest(edit->emitter_field, co, NULL, NULL); - if(pa_index == -1) return; + LOOP_KEYS { + if(k==0) { + /* find root coordinate and normal on emitter */ + VECCOPY(co, key->co); + Mat4MulVecfl(mat, co); - VECCOPY(rootco, co); - VecCopyf(nor, &psys->edit->emitter_cosnos[pa_index*6+3]); - Normalize(nor); - length= 0.0f; + point_index= BLI_kdtree_find_nearest(edit->emitter_field, co, NULL, NULL); + if(point_index == -1) return; - fac= (float)pow((double)(1.0f - data->dist / data->rad), (double)data->pufffac); - fac *= 0.025f; - if(data->invert) - fac= -fac; + VECCOPY(rootco, co); + VecCopyf(nor, &edit->emitter_cosnos[point_index*6+3]); + Normalize(nor); + length= 0.0f; - 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); + 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); - VECADDFAC(kco, rootco, nor, length); + VECADDFAC(kco, rootco, nor, length); - /* blend between the current and straight position */ - VECSUB(dco, kco, co); - VECADDFAC(co, co, dco, fac); + /* blend between the current and straight position */ + VECSUB(dco, kco, co); + VECADDFAC(co, co, dco, fac); - VECCOPY(key->co, co); - Mat4MulVecfl(imat, key->co); + VECCOPY(key->co, co); + Mat4MulVecfl(imat, key->co); + } } - pa->flag |= PARS_EDIT_RECALC; + point->flag |= PEP_EDIT_RECALC; } -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; - +static void brush_smooth_get(PEData *data, float mat[][4], float imat[][4], int point_index, int key_index, PTCacheEditKey *key) +{ if(key_index) { float dvec[3]; @@ -2796,11 +2848,8 @@ 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 pa_index, int key_index) +static void brush_smooth_do(PEData *data, float mat[][4], float imat[][4], int point_index, int key_index, PTCacheEditKey *key) { - ParticleSystem *psys= data->psys; - ParticleData *pa= &psys->particles[pa_index]; - HairKey *key= pa->hair + key_index; float vec[3], dvec[3]; if(key_index) { @@ -2815,18 +2864,18 @@ static void brush_smooth_do(PEData *data, float mat[][4], float imat[][4], int p VECADD(key->co,key->co,dvec); } - pa->flag |= PARS_EDIT_RECALC; + (data->edit->points + point_index)->flag |= PEP_EDIT_RECALC; } static void brush_add(PEData *data, short number) { Scene *scene= data->scene; Object *ob= data->ob; - ParticleSystem *psys= data->psys; + PTCacheEdit *edit = data->edit; + ParticleSystem *psys= edit->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; @@ -2837,6 +2886,9 @@ static void brush_add(PEData *data, short number) DerivedMesh *dm=0; Mat4Invert(imat,ob->obmat); + if(psys->flag & PSYS_GLOBAL_HAIR) + return; + BLI_srandom(psys->seed+data->mval[0]+data->mval[1]); /* painting onto the deformed mesh, could be an option? */ @@ -2873,19 +2925,20 @@ 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"); - ParticleEditKey *ekey, **key, **new_keys= MEM_callocN(newtotpart*sizeof(ParticleEditKey *),"ParticleEditKey array new"); + PTCacheEditPoint *point, *new_points= MEM_callocN(newtotpart*sizeof(PTCacheEditPoint),"PTCacheEditPoint array new"); + PTCacheEditKey *key; HairKey *hkey; /* save existing elements */ memcpy(new_pars, psys->particles, totpart * sizeof(ParticleData)); - memcpy(new_keys, edit->keys, totpart * sizeof(ParticleEditKey*)); + memcpy(new_points, edit->points, totpart * sizeof(PTCacheEditPoint)); /* change old arrays to new ones */ if(psys->particles) MEM_freeN(psys->particles); psys->particles= new_pars; - if(edit->keys) MEM_freeN(edit->keys); - edit->keys= new_keys; + if(edit->points) MEM_freeN(edit->points); + edit->points= new_points; if(edit->mirror_cache) { MEM_freeN(edit->mirror_cache); @@ -2904,29 +2957,29 @@ static void brush_add(PEData *data, short number) BLI_kdtree_balance(tree); } - psys->totpart= newtotpart; + edit->totpoint= psys->totpart= newtotpart; /* create new elements */ pa= psys->particles + totpart; - key= edit->keys + totpart; + point= edit->points + totpart; - for(i=totpart; i<newtotpart; i++, pa++, key++) { + for(i=totpart; i<newtotpart; i++, pa++, point++) { memcpy(pa, add_pars + i - totpart, sizeof(ParticleData)); pa->hair= MEM_callocN(pset->totaddkey * sizeof(HairKey), "BakeKey key add"); - ekey= *key= MEM_callocN(pset->totaddkey * sizeof(ParticleEditKey), "ParticleEditKey add"); - pa->totkey= pset->totaddkey; + key= point->keys= MEM_callocN(pset->totaddkey * sizeof(PTCacheEditKey), "PTCacheEditKey add"); + point->totkey= pa->totkey= pset->totaddkey; - for(k=0, hkey=pa->hair; k<pa->totkey; k++, hkey++, ekey++) { - ekey->co= hkey->co; - ekey->time= &hkey->time; + for(k=0, hkey=pa->hair; k<pa->totkey; k++, hkey++, key++) { + key->co= hkey->co; + key->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); - pa->flag |= PARS_EDIT_RECALC; + point->flag |= PEP_EDIT_RECALC; if(pset->flag & PE_X_MIRROR) - pa->flag |= PARS_TAG; /* signal for duplicate */ + point->flag |= PEP_TAG; /* signal for duplicate */ framestep= pa->lifetime/(float)(pset->totaddkey-1); @@ -2956,7 +3009,7 @@ static void brush_add(PEData *data, short number) weight[w] /= totw; for(k=0; k<pset->totaddkey; k++) { - hkey= pa->hair + k; + hkey= (HairKey*)pa->hair + k; hkey->time= pa->time + k * framestep; key[0].time= hkey->time/ 100.0f; @@ -2980,15 +3033,15 @@ static void brush_add(PEData *data, short number) if(k==0) VECSUB(co1, pa->state.co, key[0].co); - VECADD(pa->hair[k].co, key[0].co, co1); + VECADD(hkey->co, key[0].co, co1); - pa->hair[k].time= key[0].time; + hkey->time= key[0].time; } } else { for(k=0, hkey=pa->hair; k<pset->totaddkey; k++, hkey++) { VECADDFAC(hkey->co, pa->state.co, pa->state.vel, k * framestep * timestep); - pa->hair[k].time += k * framestep; + hkey->time += k * framestep; } } for(k=0, hkey=pa->hair; k<pset->totaddkey; k++, hkey++) { @@ -2997,7 +3050,6 @@ static void brush_add(PEData *data, short number) Mat4MulVecfl(imat, hkey->co); } } - edit->totkeys= psys_count_keys(psys); if(tree) BLI_kdtree_free(tree); @@ -3009,25 +3061,12 @@ 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; - ParticleSystem *psys; + PTCacheEdit *edit; int first; int lastmouse[2]; @@ -3037,8 +3076,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; @@ -3053,7 +3092,7 @@ static int brush_edit_init(bContext *C, wmOperator *op) bedit->scene= scene; bedit->ob= ob; - bedit->psys= psys; + bedit->edit= edit; return 1; } @@ -3063,14 +3102,18 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) BrushEdit *bedit= op->customdata; Scene *scene= bedit->scene; Object *ob= bedit->ob; - ParticleSystem *psys= bedit->psys; + PTCacheEdit *edit= bedit->edit; ParticleEditSettings *pset= PE_settings(scene); - ParticleSystemModifierData *psmd= psys_get_modifier(ob, psys); + ParticleSystemModifierData *psmd= edit->psys ? psys_get_modifier(ob, edit->psys) : NULL; ParticleBrushData *brush= &pset->brush[pset->brushtype]; ARegion *ar= CTX_wm_region(C); - float vec1[3], vec2[3], mousef[2]; + float vec[3], mousef[2]; short mval[2], mvalo[2]; int flip, mouse[2], dx, dy, removed= 0, selected= 0; + int lock_root = pset->flag & PE_LOCK_FIRST; + + if(!PE_start_edit(edit)) + return; RNA_float_get_array(itemptr, "mouse", mousef); mouse[0] = mousef[0]; @@ -3091,12 +3134,16 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) mvalo[0]= bedit->lastmouse[0]; mvalo[1]= bedit->lastmouse[1]; + /* disable locking temporatily for disconnected hair */ + if(edit->psys && edit->psys->flag & PSYS_GLOBAL_HAIR) + pset->flag &= ~PE_LOCK_FIRST; + if(((pset->brushtype == PE_BRUSH_ADD) ? (sqrt(dx * dx + dy * dy) > pset->brush[PE_BRUSH_ADD].step) : (dx != 0 || dy != 0)) || bedit->first) { view3d_operator_needs_opengl(C); - selected= (short)count_selected_keys(scene, psys); + selected= (short)count_selected_keys(scene, edit); switch(pset->brushtype) { case PE_BRUSH_COMB: @@ -3115,10 +3162,8 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) Mat4Invert(ob->imat, ob->obmat); - 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; + window_to_3d_delta(ar, vec, dx, dy); + data.dvec= vec; foreach_mouse_hit_key(&data, brush_comb, selected); break; @@ -3126,20 +3171,22 @@ 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); - 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_particle(&data, brush_cut); - else - PE_foreach_particle(&data, brush_cut); + if(selected) + foreach_selected_point(&data, brush_cut); + else + foreach_point(&data, brush_cut); - removed= remove_tagged_particles(scene, ob, psys); - if(pset->flag & PE_KEEP_LENGTHS) - recalc_lengths(psys); + removed= remove_tagged_particles(scene, ob, edit->psys); + if(pset->flag & PE_KEEP_LENGTHS) + recalc_lengths(edit); + } break; } case PE_BRUSH_LENGTH: @@ -3157,61 +3204,50 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) else data.growfac= 1.0f + data.growfac; - foreach_mouse_hit_particle(&data, brush_length, selected); + foreach_mouse_hit_point(&data, brush_length, selected); if(pset->flag & PE_KEEP_LENGTHS) - recalc_lengths(psys); + recalc_lengths(edit); break; } case PE_BRUSH_PUFF: { PEData data; - PE_set_view3d_data(C, &data); - data.dm= psmd->dm; - data.mval= mval; - data.rad= (float)brush->size; + if(edit->psys) { + 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_particle(&data, brush_puff, selected); + foreach_mouse_hit_point(&data, brush_puff, selected); + } break; } case PE_BRUSH_ADD: { PEData data; - if(psys->part->from==PART_FROM_FACE) { + if(edit->psys && edit->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(psys); + recalc_lengths(edit); } 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; @@ -3238,25 +3274,27 @@ static void brush_edit_apply(bContext *C, wmOperator *op, PointerRNA *itemptr) } } if((pset->flag & PE_KEEP_LENGTHS)==0) - recalc_lengths(psys); + recalc_lengths(edit); if(pset->brushtype == PE_BRUSH_ADD || removed) { if(pset->brushtype == PE_BRUSH_ADD && (pset->flag & PE_X_MIRROR)) PE_mirror_x(scene, ob, 1); - psys_update_world_cos(ob,psys); - psys_free_path_cache(psys); - DAG_object_flush_update(scene, ob, OB_RECALC_DATA); + update_world_cos(ob,edit); + psys_free_path_cache(NULL, edit); + DAG_id_flush_update(&ob->id, OB_RECALC_DATA); } else PE_update_object(scene, ob, 1); - WM_event_add_notifier(C, NC_OBJECT|ND_GEOM_SELECT, ob); + WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE_SELECT, ob); bedit->lastmouse[0]= mouse[0]; bedit->lastmouse[1]= mouse[1]; bedit->first= 0; } + + pset->flag |= lock_root; } static void brush_edit_exit(bContext *C, wmOperator *op) @@ -3357,104 +3395,161 @@ void PARTICLE_OT_brush_edit(wmOperatorType *ot) /*********************** undo ***************************/ -static void free_ParticleUndo(ParticleUndo *undo) +static void free_PTCacheUndo(PTCacheUndo *undo) { - ParticleData *pa; + PTCacheEditPoint *point; int i; - 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]); + 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); } - if(undo->keys) - MEM_freeN(undo->keys); + if(undo->points) + MEM_freeN(undo->points); if(undo->particles) MEM_freeN(undo->particles); - //if(undo->emitter_cosnos) - // MEM_freeN(undo->emitter_cosnos); + BKE_ptcache_free_mem(&undo->mem_cache); } -static void make_ParticleUndo(ParticleSystem *psys, ParticleUndo *undo) +static void make_PTCacheUndo(PTCacheEdit *edit, PTCacheUndo *undo) { - ParticleData *pa,*upa; + PTCacheEditPoint *point; int i; - undo->totpart= psys->totpart; - undo->totkeys= psys->edit->totkeys; + undo->totpoint= edit->totpoint; - 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]); + 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); + + undo->psys_flag = edit->psys->flag; + } + else { + PTCacheMem *pm; + + 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); /* no need to update edit key->co & key->time pointers here */ } } -static void get_ParticleUndo(ParticleSystem *psys, ParticleUndo *undo) +static void get_PTCacheUndo(PTCacheEdit *edit, PTCacheUndo *undo) { - ParticleData *pa, *upa; - ParticleEditKey *key; + ParticleSystem *psys = edit->psys; + ParticleData *pa; HairKey *hkey; - int i, k, totpart= psys->totpart; + POINT_P; KEY_K; - LOOP_PARTICLES(i, pa) { - if(pa->hair) - MEM_freeN(pa->hair); + LOOP_POINTS { + if(psys && psys->particles[p].hair) + MEM_freeN(psys->particles[p].hair); - if(psys->edit->keys[i]) - MEM_freeN(psys->edit->keys[i]); + if(point->keys) + MEM_freeN(point->keys); } - if(psys->particles) + if(psys && psys->particles) MEM_freeN(psys->particles); - 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; + if(edit->points) + MEM_freeN(edit->points); + if(edit->mirror_cache) { + MEM_freeN(edit->mirror_cache); + edit->mirror_cache= NULL; } - pa= psys->particles= MEM_dupallocN(undo->particles); - psys->edit->keys= MEM_dupallocN(undo->keys); + edit->points= MEM_dupallocN(undo->points); + edit->totpoint = undo->totpoint; + + LOOP_POINTS { + point->keys= MEM_dupallocN(point->keys); + } + + if(psys) { + psys->particles= MEM_dupallocN(undo->particles); + + psys->totpart= undo->totpoint; - 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; + LOOP_POINTS { + pa = psys->particles + p; + hkey= pa->hair = MEM_dupallocN(pa->hair); + + LOOP_KEYS { + key->co= hkey->co; + key->time= &hkey->time; + hkey++; + } } + + psys->flag = undo->psys_flag; } + else { + PTCacheMem *pm; + int i; + + BKE_ptcache_free_mem(&edit->pid.cache->mem_cache); + + BLI_duplicatelist(&edit->pid.cache->mem_cache, &undo->mem_cache); - psys->totpart= undo->totpart; - psys->edit->totkeys= undo->totkeys; + 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); + } + } + } } void PE_undo_push(Scene *scene, char *str) { - ParticleSystem *psys= PE_get_current(scene, OBACT); - ParticleEdit *edit= 0; - ParticleUndo *undo; + PTCacheEdit *edit= PE_get_current(scene, OBACT); + PTCacheUndo *undo; int nr; - if(!PE_can_edit(psys)) return; - edit= psys->edit; + if(!edit) return; /* remove all undos after (also when curundo==NULL) */ while(edit->undo.last != edit->curundo) { undo= edit->undo.last; BLI_remlink(&edit->undo, undo); - free_ParticleUndo(undo); + free_PTCacheUndo(undo); MEM_freeN(undo); } /* make new */ - edit->curundo= undo= MEM_callocN(sizeof(ParticleUndo), "particle undo file"); + edit->curundo= undo= MEM_callocN(sizeof(PTCacheUndo), "particle undo file"); strncpy(undo->name, str, 64-1); BLI_addtail(&edit->undo, undo); @@ -3468,27 +3563,25 @@ void PE_undo_push(Scene *scene, char *str) } if(undo) { while(edit->undo.first!=undo) { - ParticleUndo *first= edit->undo.first; + PTCacheUndo *first= edit->undo.first; BLI_remlink(&edit->undo, first); - free_ParticleUndo(first); + free_PTCacheUndo(first); MEM_freeN(first); } } /* copy */ - make_ParticleUndo(psys,edit->curundo); + make_PTCacheUndo(edit,edit->curundo); } void PE_undo_step(Scene *scene, int step) { - ParticleSystem *psys= PE_get_current(scene, OBACT); - ParticleEdit *edit= 0; + PTCacheEdit *edit= PE_get_current(scene, OBACT); - if(!PE_can_edit(psys)) return; - edit= psys->edit; + if(!edit) return; if(step==0) { - get_ParticleUndo(psys,edit->curundo); + get_PTCacheUndo(edit,edit->curundo); } else if(step==1) { @@ -3496,7 +3589,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_ParticleUndo(psys, edit->curundo); + get_PTCacheUndo(edit, edit->curundo); } } else { @@ -3504,18 +3597,19 @@ void PE_undo_step(Scene *scene, int step) if(edit->curundo==NULL || edit->curundo->next==NULL); else { - get_ParticleUndo(psys, edit->curundo->next); + get_PTCacheUndo(edit, edit->curundo->next); edit->curundo= edit->curundo->next; if(G.f & G_DEBUG) printf("redo %s\n", edit->curundo->name); } } - DAG_object_flush_update(scene, OBACT, OB_RECALC_DATA); + PE_update_object(scene, OBACT, 0); + DAG_id_flush_update(&OBACT->id, OB_RECALC_DATA); } -static void ParticleUndo_number(Scene *scene, ParticleEdit *edit, int nr) +static void PTCacheUndo_number(Scene *scene, PTCacheEdit *edit, int nr) { - ParticleUndo *undo; + PTCacheUndo *undo; int a=1; for(undo= edit->undo.first; undo; undo= undo->next, a++) { @@ -3525,20 +3619,15 @@ static void ParticleUndo_number(Scene *scene, ParticleEdit *edit, int nr) PE_undo_step(scene, 0); } -static void ParticleUndo_clear(ParticleSystem *psys) +static void PTCacheUndo_clear(PTCacheEdit *edit) { - ParticleUndo *undo; - ParticleEdit *edit; - - if(psys==0) return; - - edit= psys->edit; + PTCacheUndo *undo; if(edit==0) return; undo= edit->undo.first; while(undo) { - free_ParticleUndo(undo); + free_PTCacheUndo(undo); undo= undo->next; } BLI_freelistN(&edit->undo); @@ -3557,15 +3646,13 @@ void PE_redo(Scene *scene) void PE_undo_menu(Scene *scene, Object *ob) { - ParticleSystem *psys= PE_get_current(scene, ob); - ParticleEdit *edit= 0; - ParticleUndo *undo; + PTCacheEdit *edit= PE_get_current(scene, ob); + PTCacheUndo *undo; DynStr *ds; short event=0; char *menu; - if(!PE_can_edit(psys)) return; - edit= psys->edit; + if(!edit) return; ds= BLI_dynstr_new(); @@ -3582,7 +3669,7 @@ void PE_undo_menu(Scene *scene, Object *ob) // XXX event= pupmenu_col(menu, 20); MEM_freeN(menu); - if(event>0) ParticleUndo_number(scene, edit,event); + if(event>0) PTCacheUndo_number(scene, edit, event); } /************************ utilities ******************************/ @@ -3590,30 +3677,29 @@ void PE_undo_menu(Scene *scene, Object *ob) int PE_minmax(Scene *scene, float *min, float *max) { Object *ob= OBACT; - ParticleSystem *psys= PE_get_current(scene, ob); - ParticleSystemModifierData *psmd; - ParticleData *pa; - ParticleEditKey *key; + PTCacheEdit *edit= PE_get_current(scene, ob); + ParticleSystem *psys = edit->psys; + ParticleSystemModifierData *psmd = NULL; + POINT_P; KEY_K; float co[3], mat[4][4]; - int i, k, totpart, ok= 0; + int ok= 0; - if(!PE_can_edit(psys)) return ok; + if(!edit) return ok; - psmd= psys_get_modifier(ob, psys); - totpart= psys->totpart; - - LOOP_PARTICLES(i, pa) { - if(pa->flag & PARS_HIDE) continue; + if(psys) + psmd= psys_get_modifier(ob, psys); + else + Mat4One(mat); - psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, mat); + LOOP_VISIBLE_POINTS { + if(psys) + psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, psys->particles+p, mat); - LOOP_KEYS(k, key) { - if(key->flag & PEK_SELECT) { - VECCOPY(co, key->co); - Mat4MulVecfl(mat, co); - DO_MINMAX(co, min, max); - ok= 1; - } + LOOP_SELECTED_KEYS { + VECCOPY(co, key->co); + Mat4MulVecfl(mat, co); + DO_MINMAX(co, min, max); + ok= 1; } } @@ -3628,56 +3714,107 @@ 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, ParticleSystem *psys) +static void PE_create_particle_edit(Scene *scene, Object *ob, PointCache *cache, ParticleSystem *psys) { - ParticleEdit *edit= psys->edit; - ParticleData *pa; - ParticleEditKey *key; + PTCacheEdit *edit= psys ? psys->edit : cache->edit; + POINT_P; KEY_K; + ParticleData *pa = NULL; HairKey *hkey; - int i, k, totpart= psys->totpart, alloc=1; + int totpoint; - if((psys->flag & PSYS_EDITED)==0) + if(!psys && !cache) return; - if(edit) { - int newtotkeys= psys_count_keys(psys); + if(cache && cache->flag & PTCACHE_DISK_CACHE) + return; - if(newtotkeys == edit->totkeys) - alloc=0; - } + if(!edit) { + totpoint = psys ? psys->totpart : ((PTCacheMem*)cache->mem_cache.first)->totpoint; - if(alloc) { - if(edit) { - printf("ParticleEdit exists already! Poke jahka!"); - PE_free_particle_edit(psys); - } + edit= MEM_callocN(sizeof(PTCacheEdit), "PE_create_particle_edit"); + edit->points=MEM_callocN(totpoint*sizeof(PTCacheEditPoint),"PTCacheEditPoints"); + edit->totpoint = totpoint; - edit= psys->edit=MEM_callocN(sizeof(ParticleEdit), "PE_create_particle_edit"); - psys->free_edit= PE_free_particle_edit; + if(psys && !cache) { + psys->edit= edit; + edit->psys = psys; - edit->keys=MEM_callocN(totpart*sizeof(ParticleEditKey*),"ParticleEditKey array"); + psys->free_edit= PE_free_ptcache_edit; - 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; + edit->pathcache = NULL; + edit->pathcachebufs.first = edit->pathcachebufs.last = NULL; + + pa = psys->particles; + LOOP_POINTS { + point->totkey = pa->totkey; + point->keys= MEM_callocN(point->totkey*sizeof(PTCacheEditKey),"ParticleEditKeys"); + point->flag |= PEP_EDIT_RECALC; + + hkey = pa->hair; + LOOP_KEYS { + key->co= hkey->co; + key->time= &hkey->time; + key->flag= hkey->editflag; + if(!(psys->flag & PSYS_GLOBAL_HAIR)) + key->flag |= PEK_USE_WCO; + hkey++; + } + pa++; } } + 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->totkeys= psys_count_keys(psys); + 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); + + point->totkey++; + } + } + psys = NULL; + } UI_GetThemeColor3ubv(TH_EDGE_SELECT, edit->sel_col); UI_GetThemeColor3ubv(TH_WIRE, edit->nosel_col); - } - recalc_lengths(psys); - recalc_emitter_field(ob, psys); - psys_update_world_cos(ob, psys); + recalc_lengths(edit); + if(psys && !cache) + recalc_emitter_field(ob, psys); + PE_update_object(scene, ob, 1); - if(alloc) { - ParticleUndo_clear(psys); + PTCacheUndo_clear(edit); PE_undo_push(scene, "Original"); } } @@ -3690,30 +3827,14 @@ static int particle_edit_toggle_poll(bContext *C) if(!scene || !ob || ob->id.lib) return 0; - return (ob->particlesystem.first != NULL); + return (ob->particlesystem.first || modifiers_findByType(ob, eModifierType_Cloth) || modifiers_findByType(ob, eModifierType_Softbody)); } static int particle_edit_toggle_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); - - 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); @@ -3724,7 +3845,7 @@ static int particle_edit_toggle_exec(bContext *C, wmOperator *op) WM_event_add_notifier(C, NC_SCENE|ND_MODE|NS_MODE_OBJECT, NULL); } - DAG_object_flush_update(scene, ob, OB_RECALC_DATA); + DAG_id_flush_update(&ob->id, OB_RECALC_DATA); return OPERATOR_FINISHED; } @@ -3746,99 +3867,51 @@ void PARTICLE_OT_particle_edit_toggle(wmOperatorType *ot) /************************ set editable operator ************************/ -static int set_editable_exec(bContext *C, wmOperator *op) +static int clear_edited_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); + ParticleSystem *psys = psys_get_current(ob); - if(psys->flag & PSYS_EDITED) { - if(1) { // XXX okee("Lose changes done in particle mode?")) { - if(psys->edit) - PE_free_particle_edit(psys); + if(psys->edit) { + if(psys->edit->edited || 1) { // XXX okee("Lose changes done in particle mode?")) + PE_free_ptcache_edit(psys->edit); - psys->flag &= ~PSYS_EDITED; - psys->recalc |= PSYS_RECALC_RESET; + psys->edit = NULL; + psys->free_edit = NULL; - DAG_object_flush_update(scene, ob, OB_RECALC_DATA); - } - } - else { - if(psys_check_enabled(ob, psys)) { - psys->flag |= PSYS_EDITED; + psys->recalc |= PSYS_RECALC_RESET; + psys->flag &= ~PSYS_GLOBAL_HAIR; + psys->flag &= ~PSYS_EDITED; - if(ob->mode & OB_MODE_PARTICLE_EDIT) - PE_create_particle_edit(scene, ob, psys); + psys_reset(psys, PSYS_RESET_DEPSGRAPH); + DAG_id_flush_update(&ob->id, OB_RECALC_DATA); } - else - BKE_report(op->reports, RPT_ERROR, "Particle system not enabled, skipping set editable"); } return OPERATOR_FINISHED; } -void PARTICLE_OT_editable_set(wmOperatorType *ot) +void PARTICLE_OT_edited_clear(wmOperatorType *ot) { /* identifiers */ - ot->name= "Set Editable"; - ot->idname= "PARTICLE_OT_editable_set"; + ot->name= "Clear Edited"; + ot->idname= "PARTICLE_OT_edited_clear"; /* api callbacks */ - ot->exec= set_editable_exec; + ot->exec= clear_edited_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; @@ -3866,7 +3939,7 @@ void PARTICLE_OT_specials_menu(wmOperatorType *ot) /* api callbacks */ ot->invoke= specials_menu_invoke; - ot->poll= PE_poll; + ot->poll= PE_hair_poll; } /**************************** registration **********************************/ @@ -3896,7 +3969,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_editable_set); + WM_operatortype_append(PARTICLE_OT_edited_clear); } void ED_keymap_particle(wmWindowManager *wm) |