Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJanne Karhu <jhkarh@gmail.com>2009-07-13 03:38:47 +0400
committerJanne Karhu <jhkarh@gmail.com>2009-07-13 03:38:47 +0400
commit6fb0181b50461b529bb960950870de941711041e (patch)
tree8c730990b1860c48d4535cd9d0b03560cbe578b8 /source/blender
parent5f8f2fc33a2f2fd363be16a36d14fa3b3f1ad78a (diff)
Keyed physics refresh:
- Keyed targets in one list instead of "chaining", this opens up many more possibilities than before and is much less obscure. - Better keyed timing possibilities (time & duration in frames). - Looping over keyed targets list. Other changes: - New child setting "length" with threshold (great for guard & underfur with a single particle system) - Modularization of path interpolation code. - Cleared "animateable" flags from many particle settings that shouldn't be animateable. Fixes: - Keyed particles weren't copied properly (ancient bug). - Hair rotations depended on global z-axis for root rotation so downward facing strands could flip rotation randomly. Now initial hair rotation is derived from face dependent hair matrix. (This caused for example ugly flipping of child strands on some cases). - Children from faces weren't calculated straight after activating them. - Multiple disk cache fixes: * Disk cache didn't work correctly with frame steps. * Conversion from memory cache to disk cache didn't work with cloth. * Disk cache crashed on some frames trying to close an already closed cache file. * Trails didn't work with disk cached particles. - Child rough effects were effected by emitter object loc/rot making them next to useless with animation, why didn't anybody tell me this!! - Lots of random code cleanup.
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_particle.h5
-rw-r--r--source/blender/blenkernel/intern/depsgraph.c15
-rw-r--r--source/blender/blenkernel/intern/object.c26
-rw-r--r--source/blender/blenkernel/intern/particle.c669
-rw-r--r--source/blender/blenkernel/intern/particle_system.c279
-rw-r--r--source/blender/blenkernel/intern/pointcache.c36
-rw-r--r--source/blender/blenloader/intern/readfile.c13
-rw-r--r--source/blender/blenloader/intern/writefile.c5
-rw-r--r--source/blender/editors/space_buttons/buttons_intern.h4
-rw-r--r--source/blender/editors/space_buttons/buttons_ops.c204
-rw-r--r--source/blender/editors/space_buttons/space_buttons.c4
-rw-r--r--source/blender/editors/space_view3d/drawobject.c32
-rw-r--r--source/blender/makesdna/DNA_particle_types.h38
-rw-r--r--source/blender/makesrna/RNA_access.h1
-rw-r--r--source/blender/makesrna/intern/rna_particle.c325
-rw-r--r--source/blender/render/intern/source/convertblender.c20
16 files changed, 1044 insertions, 632 deletions
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h
index aa24706077d..bb0b905b8e3 100644
--- a/source/blender/blenkernel/BKE_particle.h
+++ b/source/blender/blenkernel/BKE_particle.h
@@ -260,7 +260,6 @@ void psys_flush_particle_settings(struct Scene *scene, struct ParticleSettings *
void make_local_particlesettings(struct ParticleSettings *part);
struct LinkNode *psys_using_settings(struct Scene *scene, struct ParticleSettings *part, int flush_update);
-void psys_changed_type(struct ParticleSystem *psys);
void psys_reset(struct ParticleSystem *psys, int mode);
void psys_find_parents(struct Object *ob, struct ParticleSystemModifierData *psmd, struct ParticleSystem *psys);
@@ -289,12 +288,14 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa,
void psys_make_billboard(ParticleBillboardData *bb, float xvec[3], float yvec[3], float zvec[3], float center[3]);
/* particle_system.c */
-int psys_count_keyed_targets(struct Object *ob, struct ParticleSystem *psys);
+void psys_count_keyed_targets(struct Object *ob, struct ParticleSystem *psys);
void psys_get_reactor_target(struct Object *ob, struct ParticleSystem *psys, struct Object **target_ob, struct ParticleSystem **target_psys);
void psys_init_effectors(struct Scene *scene, struct Object *obsrc, struct Group *group, struct ParticleSystem *psys);
void psys_end_effectors(struct ParticleSystem *psys);
+void psys_make_temp_pointcache(struct Object *ob, struct ParticleSystem *psys);
+void psys_end_temp_pointcache(struct ParticleSystem *psys);
void psys_get_pointcache_start_end(struct Scene *scene, struct ParticleSystem *psys, int *sfra, int *efra);
void particle_system_update(struct Scene *scene, struct Object *ob, struct ParticleSystem *psys);
diff --git a/source/blender/blenkernel/intern/depsgraph.c b/source/blender/blenkernel/intern/depsgraph.c
index de036e25d82..f52eec34cc7 100644
--- a/source/blender/blenkernel/intern/depsgraph.c
+++ b/source/blender/blenkernel/intern/depsgraph.c
@@ -562,10 +562,17 @@ static void build_dag_object(DagForest *dag, DagNode *scenenode, Scene *scene, O
if(!psys_check_enabled(ob, psys))
continue;
- if(part->phystype==PART_PHYS_KEYED && psys->keyed_ob &&
- BLI_findlink(&psys->keyed_ob->particlesystem,psys->keyed_psys-1)) {
- node2 = dag_get_node(dag, psys->keyed_ob);
- dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA, "Particle Keyed Physics");
+ if(part->phystype==PART_PHYS_KEYED) {
+ KeyedParticleTarget *kpt = psys->keyed_targets.first;
+
+ for(; kpt; kpt=kpt->next) {
+ if(kpt->ob && BLI_findlink(&kpt->ob->particlesystem, kpt->psys-1)) {
+ node2 = dag_get_node(dag, kpt->ob);
+ dag_add_relation(dag, node2, node, DAG_RL_DATA_DATA|DAG_RL_OB_DATA, "Particle Keyed Physics");
+ }
+ else
+ break;
+ }
}
if(part->ren_as == PART_DRAW_OB && part->dup_ob) {
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index 6490ff3c724..7d6a83d7900 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -427,17 +427,14 @@ void unlink_object(Scene *scene, Object *ob)
if(obt->particlesystem.first) {
ParticleSystem *tpsys= obt->particlesystem.first;
for(; tpsys; tpsys=tpsys->next) {
- if(tpsys->keyed_ob==ob) {
- ParticleSystem *psys= BLI_findlink(&ob->particlesystem,tpsys->keyed_psys-1);
-
- if(psys && psys->keyed_ob) {
- tpsys->keyed_ob= psys->keyed_ob;
- tpsys->keyed_psys= psys->keyed_psys;
+ KeyedParticleTarget *kpt = tpsys->keyed_targets.first;
+ for(; kpt; kpt=kpt->next) {
+ if(kpt->ob==ob) {
+ BLI_remlink(&tpsys->keyed_targets, kpt);
+ MEM_freeN(kpt);
+ obt->recalc |= OB_RECALC_DATA;
+ break;
}
- else
- tpsys->keyed_ob= NULL;
-
- obt->recalc |= OB_RECALC_DATA;
}
if(tpsys->target_ob==ob) {
@@ -1050,18 +1047,23 @@ ParticleSystem *copy_particlesystem(ParticleSystem *psys)
psysn= MEM_dupallocN(psys);
psysn->particles= MEM_dupallocN(psys->particles);
psysn->child= MEM_dupallocN(psys->child);
+ if(psysn->particles->keys)
+ psysn->particles->keys = MEM_dupallocN(psys->particles->keys);
for(a=0, pa=psysn->particles; a<psysn->totpart; a++, pa++) {
if(pa->hair)
pa->hair= MEM_dupallocN(pa->hair);
- if(pa->keys)
- pa->keys= MEM_dupallocN(pa->keys);
+ if(a)
+ pa->keys= (pa-1)->keys + (pa-1)->totkey;
}
if(psys->soft) {
psysn->soft= copy_softbody(psys->soft);
psysn->soft->particles = psysn;
}
+
+ if(psys->keyed_targets.first)
+ BLI_duplicatelist(&psysn->keyed_targets, &psys->keyed_targets);
psysn->pathcache= NULL;
psysn->childcache= NULL;
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c
index 4488f8cdffd..cefeafcdd50 100644
--- a/source/blender/blenkernel/intern/particle.c
+++ b/source/blender/blenkernel/intern/particle.c
@@ -84,7 +84,8 @@ static void get_cpa_texture(DerivedMesh *dm, Material *ma, int face_index,
static void get_child_modifier_parameters(ParticleSettings *part, ParticleThreadContext *ctx,
ChildParticle *cpa, short cpa_from, int cpa_num, float *cpa_fuv, float *orco, ParticleTexture *ptex);
static void do_child_modifiers(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSettings *part,
- ParticleTexture *ptex, ParticleKey *par, float *par_rot, ChildParticle *cpa, float *orco, ParticleKey *state, float t);
+ ParticleTexture *ptex, ParticleKey *par, float *par_rot, ChildParticle *cpa,
+ float *orco, float mat[4][4], ParticleKey *state, float t);
/* few helpers for countall etc. */
int count_particles(ParticleSystem *psys){
@@ -478,10 +479,16 @@ void psys_free(Object *ob, ParticleSystem * psys)
if(psys->pointcache)
BKE_ptcache_free(psys->pointcache);
+ if(psys->keyed_targets.first)
+ BLI_freelistN(&psys->keyed_targets);
+
MEM_freeN(psys);
}
}
+/************************************************/
+/* Rendering */
+/************************************************/
/* these functions move away particle data and bring it back after
* rendering, to make different render settings possible without
* removing the previous data. this should be solved properly once */
@@ -889,7 +896,7 @@ int psys_render_simplify_params(ParticleSystem *psys, ChildParticle *cpa, float
}
/************************************************/
-/* Interpolated Particles */
+/* Interpolation */
/************************************************/
static float interpolate_particle_value(float v1, float v2, float v3, float v4, float *w, int four)
{
@@ -938,6 +945,214 @@ void psys_interpolate_particle(short type, ParticleKey keys[4], float dt, Partic
+typedef struct ParticleInterpolationData {
+ ParticleKey *kkey[2];
+ HairKey *hkey[2];
+ BodyPoint *bp[2];
+ SoftBody *soft;
+ int keyed, cached;
+ float birthtime, dietime;
+} ParticleInterpolationData;
+/* Assumes pointcache->mem_cache exists, so for disk cached particles call psys_make_temp_pointcache() before use */
+static void get_pointcache_keys_for_time(Object *ob, ParticleSystem *psys, int index, float t, ParticleKey *key1, ParticleKey *key2)
+{
+ PointCache *cache = psys->pointcache;
+ static PTCacheMem *pm = NULL; /* not thread safe */
+
+ if(index < 0) { /* initialize */
+ pm = cache->mem_cache.first;
+
+ if(pm)
+ pm = pm->next;
+ }
+ else {
+ if(pm) {
+ while(pm && pm->next && (float)pm->frame < t)
+ pm = pm->next;
+
+ copy_particle_key(key2, ((ParticleKey *)pm->data) + index, 1);
+ copy_particle_key(key1, ((ParticleKey *)(pm->prev)->data) + index, 1);
+ }
+ else if(cache->mem_cache.first) {
+ PTCacheMem *pm2 = cache->mem_cache.first;
+ copy_particle_key(key2, ((ParticleKey *)pm2->data) + index, 1);
+ copy_particle_key(key1, ((ParticleKey *)pm2->data) + index, 1);
+ }
+ }
+}
+static void init_particle_interpolation(Object *ob, ParticleSystem *psys, ParticleData *pa, ParticleInterpolationData *pind)
+{
+
+ if(pind->keyed) {
+ pind->kkey[0] = pa->keys;
+
+ if(pa->totkey > 1)
+ pind->kkey[1] = pa->keys + 1;
+ else
+ pind->kkey[1] = NULL;
+
+ pind->birthtime = pa->keys->time;
+ pind->dietime = (pa->keys + pa->totkey - 1)->time;
+ }
+ else if(pind->cached) {
+ get_pointcache_keys_for_time(ob, psys, -1, 0.0f, NULL, NULL);
+
+ pind->birthtime = pa->time;
+ pind->dietime = pa->dietime;
+ }
+ else {
+ pind->hkey[0] = pa->hair;
+ pind->hkey[1] = pa->hair + 1;
+
+ pind->birthtime = pa->hair->time;
+ pind->dietime = (pa->hair + pa->totkey - 1)->time;
+ }
+
+ if(pind->soft) {
+ pind->bp[0] = pind->soft->bpoint + pa->bpi;
+ pind->bp[1] = pind->soft->bpoint + pa->bpi + 1;
+ }
+}
+static void hair_to_particle(ParticleKey *key, HairKey *hkey)
+{
+ VECCOPY(key->co, hkey->co);
+ key->time = hkey->time;
+}
+static void bp_to_particle(ParticleKey *key, BodyPoint *bp, HairKey *hkey)
+{
+ VECCOPY(key->co, bp->pos);
+ key->time = hkey->time;
+}
+
+static void do_particle_interpolation(ParticleSystem *psys, int p, ParticleData *pa, float t, float frs_sec, ParticleInterpolationData *pind, ParticleKey *result)
+{
+ ParticleKey keys[4];
+ float real_t, dfra, keytime;
+
+ /* interpret timing and find keys */
+ if(pind->keyed) {
+ /* we have only one key, so let's use that */
+ if(pind->kkey[1]==NULL) {
+ copy_particle_key(result, pind->kkey[0], 1);
+ return;
+ }
+
+ if(result->time < 0.0f)
+ real_t = -result->time;
+ else
+ real_t = pind->kkey[0]->time + t * (pind->kkey[0][pa->totkey-1].time - pind->kkey[0]->time);
+
+ if(psys->part->phystype==PART_PHYS_KEYED && psys->flag & PSYS_KEYED_TIMING) {
+ KeyedParticleTarget *kpt = psys->keyed_targets.first;
+
+ kpt=kpt->next;
+
+ while(kpt && pa->time + kpt->time < real_t)
+ kpt= kpt->next;
+
+ if(kpt) {
+ kpt=kpt->prev;
+
+ if(pa->time + kpt->time + kpt->duration > real_t)
+ real_t = pa->time + kpt->time;
+ }
+ else
+ real_t = pa->time + ((KeyedParticleTarget*)psys->keyed_targets.last)->time;
+ }
+
+ CLAMP(real_t, pa->time, pa->dietime);
+
+ while(pind->kkey[1]->time < real_t)
+ pind->kkey[1]++;
+
+ pind->kkey[0] = pind->kkey[1] - 1;
+ }
+ else if(pind->cached) {
+ if(result->time < 0.0f) /* flag for time in frames */
+ real_t = -result->time;
+ else
+ real_t = pa->time + t * (pa->dietime - pa->time);
+ }
+ else {
+ if(result->time < 0.0f)
+ real_t = -result->time;
+ else
+ real_t = pind->hkey[0]->time + t * (pind->hkey[0][pa->totkey-1].time - pind->hkey[0]->time);
+
+ while(pind->hkey[1]->time < real_t) {
+ pind->hkey[1]++;
+ pind->bp[1]++;
+ }
+
+ pind->hkey[0] = pind->hkey[1] - 1;
+ }
+
+ /* set actual interpolation keys */
+ if(pind->soft) {
+ pind->bp[0] = pind->bp[1] - 1;
+ bp_to_particle(keys + 1, pind->bp[0], pind->hkey[0]);
+ bp_to_particle(keys + 2, pind->bp[1], pind->hkey[1]);
+ }
+ else if(pind->keyed) {
+ memcpy(keys + 1, pind->kkey[0], sizeof(ParticleKey));
+ memcpy(keys + 2, pind->kkey[1], sizeof(ParticleKey));
+ }
+ else if(pind->cached) {
+ get_pointcache_keys_for_time(NULL, psys, p, real_t, keys+1, keys+2);
+ }
+ else {
+ hair_to_particle(keys + 1, pind->hkey[0]);
+ hair_to_particle(keys + 2, pind->hkey[1]);
+ }
+
+ /* set secondary interpolation keys for hair */
+ if(!pind->keyed && !pind->cached) {
+ if(pind->soft) {
+ if(pind->hkey[0] != pa->hair)
+ bp_to_particle(keys, pind->bp[0] - 1, pind->hkey[0] - 1);
+ else
+ bp_to_particle(keys, pind->bp[0], pind->hkey[0]);
+ }
+ else {
+ if(pind->hkey[0] != pa->hair)
+ hair_to_particle(keys, pind->hkey[0] - 1);
+ else
+ hair_to_particle(keys, pind->hkey[0]);
+ }
+
+ if(pind->soft) {
+ if(pind->hkey[1] != pa->hair + pa->totkey - 1)
+ bp_to_particle(keys + 3, pind->bp[1] + 1, pind->hkey[1] + 1);
+ else
+ bp_to_particle(keys + 3, pind->bp[1], pind->hkey[1]);
+ }
+ else {
+ if(pind->hkey[1] != pa->hair + pa->totkey - 1)
+ hair_to_particle(keys + 3, pind->hkey[1] + 1);
+ else
+ hair_to_particle(keys + 3, pind->hkey[1]);
+ }
+ }
+
+ dfra = keys[2].time - keys[1].time;
+ keytime = (real_t - keys[1].time) / dfra;
+
+ /* convert velocity to timestep size */
+ if(pind->keyed || pind->cached){
+ VecMulf(keys[1].vel, dfra / frs_sec);
+ VecMulf(keys[2].vel, dfra / frs_sec);
+ QuatInterpol(result->rot,keys[1].rot,keys[2].rot,keytime);
+ }
+
+ /* now we should have in chronologiacl order k1<=k2<=t<=k3<=k4 with keytime between [0,1]->[k2,k3] (k1 & k4 used for cardinal & bspline interpolation)*/
+ psys_interpolate_particle((pind->keyed || pind->cached) ? -1 /* signal for cubic interpolation */
+ : ((psys->part->flag & PART_HAIR_BSPLINE) ? KEY_BSPLINE : KEY_CARDINAL)
+ ,keys, keytime, result, 1);
+
+ /* the velocity needs to be converted back from cubic interpolation */
+ if(pind->keyed || pind->cached)
+ VecMulf(result->vel, frs_sec / dfra);
+}
/************************************************/
/* Particles on a dm */
/************************************************/
@@ -1438,16 +1653,6 @@ void psys_particle_on_emitter(ParticleSystemModifierData *psmd, int from, int in
/************************************************/
/* Path Cache */
/************************************************/
-static void hair_to_particle(ParticleKey *key, HairKey *hkey)
-{
- VECCOPY(key->co, hkey->co);
- key->time = hkey->time;
-}
-static void bp_to_particle(ParticleKey *key, BodyPoint *bp, HairKey *hkey)
-{
- VECCOPY(key->co, bp->pos);
- key->time = hkey->time;
-}
static float vert_weight(MDeformVert *dvert, int group)
{
MDeformWeight *dw;
@@ -1734,7 +1939,7 @@ int do_guide(Scene *scene, ParticleKey *state, int pa_num, float time, ListBase
}
return 0;
}
-static void do_rough(float *loc, float t, float fac, float size, float thres, ParticleKey *state)
+static void do_rough(float *loc, float mat[4][4], float t, float fac, float size, float thres, ParticleKey *state)
{
float rough[3];
float rco[3];
@@ -1747,32 +1952,24 @@ static void do_rough(float *loc, float t, float fac, float size, float thres, Pa
rough[0]=-1.0f+2.0f*BLI_gTurbulence(size, rco[0], rco[1], rco[2], 2,0,2);
rough[1]=-1.0f+2.0f*BLI_gTurbulence(size, rco[1], rco[2], rco[0], 2,0,2);
rough[2]=-1.0f+2.0f*BLI_gTurbulence(size, rco[2], rco[0], rco[1], 2,0,2);
- VECADDFAC(state->co,state->co,rough,fac);
+
+ VECADDFAC(state->co,state->co,mat[0],fac*rough[0]);
+ VECADDFAC(state->co,state->co,mat[1],fac*rough[1]);
+ VECADDFAC(state->co,state->co,mat[2],fac*rough[2]);
}
-static void do_rough_end(float *loc, float t, float fac, float shape, ParticleKey *state, ParticleKey *par)
+static void do_rough_end(float *loc, float mat[4][4], float t, float fac, float shape, ParticleKey *state)
{
- float rough[3], rnor[3];
+ float rough[2];
float roughfac;
roughfac=fac*(float)pow((double)t,shape);
VECCOPY(rough,loc);
rough[0]=-1.0f+2.0f*rough[0];
rough[1]=-1.0f+2.0f*rough[1];
- rough[2]=-1.0f+2.0f*rough[2];
VecMulf(rough,roughfac);
-
- if(par){
- VECCOPY(rnor,par->vel);
- }
- else{
- VECCOPY(rnor,state->vel);
- }
- Normalize(rnor);
- Projf(rnor,rough,rnor);
- VECSUB(rough,rough,rnor);
-
- VECADD(state->co,state->co,rough);
+ VECADDFAC(state->co,state->co,mat[0],rough[0]);
+ VECADDFAC(state->co,state->co,mat[1],rough[1]);
}
static void do_path_effectors(Scene *scene, Object *ob, ParticleSystem *psys, int i, ParticleCacheKey *ca, int k, int steps, float *rootco, float effector, float dfra, float cfra, float *length, float *vec)
{
@@ -2007,7 +2204,7 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa,
ParticleData *pa=NULL;
ParticleTexture ptex;
float *cpa_fuv=0, *par_rot=0;
- float co[3], orco[3], ornor[3], t, cpa_1st[3], dvec[3];
+ float co[3], orco[3], ornor[3], hairmat[4][4], t, cpa_1st[3], dvec[3];
float branch_begin, branch_end, branch_prob, rough_rand;
float length, max_length = 1.0f, cur_length = 0.0f;
float eff_length, eff_vec[3];
@@ -2065,8 +2262,6 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa,
cpa_num = cpa->num;
foffset= cpa->foffset;
- if(part->childtype == PART_CHILD_FACES)
- foffset = -(2.0f + part->childspread);
cpa_fuv = cpa->fuv;
cpa_from = PART_FROM_FACE;
@@ -2078,6 +2273,10 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa,
Mat4MulVecfl(ob->obmat,cpa_1st);
}
+ pa = psys->particles + cpa->parent;
+
+ psys_mat_hair_to_global(ob, ctx->psmd->dm, psys->part->from, pa, hairmat);
+
pa=0;
}
else{
@@ -2099,6 +2298,8 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa,
cpa_fuv=pa->fuv;
psys_particle_on_emitter(ctx->psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa_fuv,pa->foffset,co,ornor,0,0,orco,0);
+
+ psys_mat_hair_to_global(ob, ctx->psmd->dm, psys->part->from, pa, hairmat);
}
keys->steps = ctx->steps;
@@ -2190,7 +2391,7 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa,
}
/* apply different deformations to the child path */
- do_child_modifiers(ctx->scene, ob, psys, part, &ptex, (ParticleKey *)par, par_rot, cpa, orco, (ParticleKey *)state, t);
+ do_child_modifiers(ctx->scene, ob, psys, part, &ptex, (ParticleKey *)par, par_rot, cpa, orco, hairmat, (ParticleKey *)state, t);
/* TODO: better branching */
//if(part->flag & PART_BRANCHING && ctx->between == 0 && part->flag & PART_ANIM_BRANCHING)
@@ -2247,20 +2448,12 @@ void psys_thread_create_path(ParticleThread *thread, struct ChildParticle *cpa,
/* check if path needs to be cut before actual end of data points */
if(k){
VECSUB(dvec,state->co,(state-1)->co);
- if(part->flag&PART_ABS_LENGTH)
- length=VecLength(dvec);
- else
- length=1.0f/(float)ctx->steps;
-
+ length=1.0f/(float)ctx->steps;
k=check_path_length(k,keys,state,max_length,&cur_length,length,dvec);
}
else{
/* initialize length calculation */
- if(part->flag&PART_ABS_LENGTH)
- max_length= part->abslength*ptex.length;
- else
- max_length= ptex.length;
-
+ max_length= ptex.length;
cur_length= 0.0f;
}
@@ -2353,36 +2546,6 @@ void psys_cache_child_paths(Scene *scene, Object *ob, ParticleSystem *psys, floa
psys_threads_free(pthreads);
}
-static void get_pointcache_keys_for_time(ParticleSystem *psys, int index, float t, ParticleKey *key1, ParticleKey *key2)
-{
- PointCache *cache = psys->pointcache;
- static PTCacheMem *pm = NULL;
-
- if(cache->flag & PTCACHE_DISK_CACHE) {
- /* TODO */
- }
- else {
- if(index < 0) { /* initialize */
- pm = cache->mem_cache.first;
- if(pm)
- pm = pm->next;
- }
- else {
- if(pm) {
- while(pm && pm->next && (float)pm->frame < t)
- pm = pm->next;
-
- copy_particle_key(key2, ((ParticleKey *)pm->data) + index, 1);
- copy_particle_key(key1, ((ParticleKey *)(pm->prev)->data) + index, 1);
- }
- else if(cache->mem_cache.first) {
- pm = cache->mem_cache.first;
- copy_particle_key(key2, ((ParticleKey *)pm->data) + index, 1);
- copy_particle_key(key1, ((ParticleKey *)pm->data) + index, 1);
- }
- }
- }
-}
/* Calculates paths ready for drawing/rendering. */
/* -Usefull for making use of opengl vertex arrays for super fast strand drawing. */
/* -Makes child strands possible and creates them too into the cache. */
@@ -2395,7 +2558,7 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
ParticleSettings *part = psys->part;
ParticleData *pa;
- ParticleKey keys[4], result, *kkey[2] = {NULL, NULL};
+ ParticleKey result, *kkey[2] = {NULL, NULL};
HairKey *hkey[2] = {NULL, NULL};
ParticleEdit *edit = 0;
@@ -2405,11 +2568,14 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
BodyPoint *bp[2] = {NULL, NULL};
Material *ma;
+
+ ParticleInterpolationData pind;
float birthtime = 0.0, dietime = 0.0;
float t, time = 0.0, keytime = 0.0, dfra = 1.0, frs_sec = scene->r.frs_sec;
float col[4] = {0.5f, 0.5f, 0.5f, 1.0f};
float prev_tangent[3], hairmat[4][4];
+ float rotmat[3][3];
int k,i;
int steps = (int)pow(2.0, (double)psys->part->draw_step);
int totpart = psys->totpart;
@@ -2492,7 +2658,6 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
else memset(cache[i], 0, sizeof(*cache[i])*(steps+1));
if(!edit && !psys->totchild) {
- //pa_length = part->length * (1.0f - part->randlength*pa->r_ave[0]);
pa_length = 1.0f - part->randlength * 0.5 * (1.0f + pa->r_ave[0]);
if(vg_length)
pa_length *= psys_particle_value_from_verts(psmd->dm,part->from,pa,vg_length);
@@ -2504,38 +2669,27 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
ekey = edit->keys[i];
/*--get the first data points--*/
- if(keyed) {
- kkey[0] = pa->keys;
- kkey[1] = kkey[0] + 1;
+ pind.keyed = keyed;
+ pind.cached = baked;
+ pind.soft = soft;
+ init_particle_interpolation(ob, psys, pa, &pind);
- birthtime = kkey[0]->time;
- dietime = kkey[0][pa->totkey-1].time;
- }
- else if(baked) {
- get_pointcache_keys_for_time(psys, -1, 0.0f, NULL, NULL);
-
- birthtime = pa->time;
- dietime = pa->dietime;
- }
- else {
- hkey[0] = pa->hair;
- hkey[1] = hkey[0] + 1;
- birthtime = hkey[0]->time;
- dietime = hkey[0][pa->totkey-1].time;
-
- psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat);
- }
+ /* hairmat is needed for for non-hair particle too so we get proper rotations */
+ psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat);
+ VECCOPY(rotmat[0], hairmat[2]);
+ VECCOPY(rotmat[1], hairmat[1]);
+ VECCOPY(rotmat[2], hairmat[0]);
if(!edit) {
if(part->draw & PART_ABS_PATH_TIME) {
- birthtime = MAX2(birthtime, part->path_start);
- dietime = MIN2(dietime, part->path_end);
+ birthtime = MAX2(pind.birthtime, part->path_start);
+ dietime = MIN2(pind.dietime, part->path_end);
}
else {
- float tb = birthtime;
- birthtime = tb + part->path_start * (dietime - tb);
- dietime = tb + part->path_end * (dietime - tb);
+ float tb = pind.birthtime;
+ birthtime = tb + part->path_start * (pind.dietime - tb);
+ dietime = tb + part->path_end * (pind.dietime - tb);
}
if(birthtime >= dietime) {
@@ -2546,101 +2700,18 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
dietime = birthtime + pa_length * (dietime - birthtime);
}
- if(soft){
- bp[0] = soft->bpoint + pa->bpi;
- bp[1] = bp[0] + 1;
- }
-
/*--interpolate actual path from data points--*/
for(k=0, ca=cache[i]; k<=steps; k++, ca++){
time = (float)k / (float)steps;
t = birthtime + time * (dietime - birthtime);
- if(keyed) {
- while(kkey[1]->time < t) {
- kkey[1]++;
- }
+ result.time = -t;
- kkey[0] = kkey[1] - 1;
- }
- else if(baked) {
- get_pointcache_keys_for_time(psys, i, t, keys+1, keys+2);
- }
- else {
- while(hkey[1]->time < t) {
- hkey[1]++;
- bp[1]++;
- }
-
- hkey[0] = hkey[1] - 1;
- }
+ do_particle_interpolation(psys, i, pa, t, frs_sec, &pind, &result);
- if(soft) {
- bp[0] = bp[1] - 1;
- bp_to_particle(keys + 1, bp[0], hkey[0]);
- bp_to_particle(keys + 2, bp[1], hkey[1]);
- }
- else if(keyed) {
- memcpy(keys + 1, kkey[0], sizeof(ParticleKey));
- memcpy(keys + 2, kkey[1], sizeof(ParticleKey));
- }
- else if(baked)
- ; /* keys already set */
- else {
- hair_to_particle(keys + 1, hkey[0]);
- hair_to_particle(keys + 2, hkey[1]);
- }
-
-
- if(!keyed && !baked) {
- if(soft) {
- if(hkey[0] != pa->hair)
- bp_to_particle(keys, bp[0] - 1, hkey[0] - 1);
- else
- bp_to_particle(keys, bp[0], hkey[0]);
- }
- else {
- if(hkey[0] != pa->hair)
- hair_to_particle(keys, hkey[0] - 1);
- else
- hair_to_particle(keys, hkey[0]);
- }
-
- if(soft) {
- if(hkey[1] != pa->hair + pa->totkey - 1)
- bp_to_particle(keys + 3, bp[1] + 1, hkey[1] + 1);
- else
- bp_to_particle(keys + 3, bp[1], hkey[1]);
- }
- else {
- if(hkey[1] != pa->hair + pa->totkey - 1)
- hair_to_particle(keys + 3, hkey[1] + 1);
- else
- hair_to_particle(keys + 3, hkey[1]);
- }
- }
-
- dfra = keys[2].time - keys[1].time;
-
- keytime = (t - keys[1].time) / dfra;
-
- /* convert velocity to timestep size */
- if(keyed || baked){
- VecMulf(keys[1].vel, dfra / frs_sec);
- VecMulf(keys[2].vel, dfra / frs_sec);
- }
-
- /* now we should have in chronologiacl order k1<=k2<=t<=k3<=k4 with keytime between [0,1]->[k2,k3] (k1 & k4 used for cardinal & bspline interpolation)*/
- psys_interpolate_particle((keyed || baked) ? -1 /* signal for cubic interpolation */
- : ((psys->part->flag & PART_HAIR_BSPLINE) ? KEY_BSPLINE : KEY_CARDINAL)
- ,keys, keytime, &result, 0);
-
- /* the velocity needs to be converted back from cubic interpolation */
- if(keyed || baked){
- VecMulf(result.vel, frs_sec / dfra);
- }
- else if(soft==NULL) { /* softbody and keyed are allready in global space */
+ /* keyed, baked and softbody are allready in global space */
+ if(!keyed && !baked && !soft) {
Mat4MulVecfl(hairmat, result.co);
}
@@ -2678,8 +2749,9 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
VECCOPY(ca->col, col);
}
}
+
- /*--modify paths--*/
+ /*--modify paths and calculate rotation & velocity--*/
VecSubf(vec,(cache[i]+1)->co,cache[i]->co);
length = VecLength(vec);
@@ -2708,12 +2780,18 @@ void psys_cache_paths(Scene *scene, Object *ob, ParticleSystem *psys, float cfra
float cosangle, angle, tangent[3], normal[3], q[4];
if(k == 1) {
+ /* calculate initial tangent for incremental rotations */
VECSUB(tangent, ca->co, (ca - 1)->co);
-
- vectoquat(tangent, OB_POSX, OB_POSZ, (ca-1)->rot);
-
VECCOPY(prev_tangent, tangent);
Normalize(prev_tangent);
+
+ /* First rotation is based on emitting face orientation. */
+ /* This is way better than having flipping rotations resulting */
+ /* from using a global axis as a rotation pole (vec_to_quat()). */
+ /* It's not an ideal solution though since it disregards the */
+ /* initial tangent, but taking that in to account will allow */
+ /* the possibility of flipping again. -jahka */
+ Mat3ToQuat_is_ok(rotmat, (ca-1)->rot);
}
else {
VECSUB(tangent, ca->co, (ca - 1)->co);
@@ -2780,15 +2858,6 @@ void copy_particle_key(ParticleKey *to, ParticleKey *from, int time){
memcpy(to,from,sizeof(ParticleKey));
to->time=to_time;
}
- /*
- VECCOPY(to->co,from->co);
- VECCOPY(to->vel,from->vel);
- QUATCOPY(to->rot,from->rot);
- if(time)
- to->time=from->time;
- to->flag=from->flag;
- to->sbw=from->sbw;
- */
}
void psys_get_from_key(ParticleKey *key, float *loc, float *vel, float *rot, float *time){
if(loc) VECCOPY(loc,key->co);
@@ -3017,8 +3086,6 @@ static void default_particle_settings(ParticleSettings *part)
part->totpart= 1000;
part->grid_res= 10;
part->timetweak= 1.0;
- part->keyed_time= 0.5;
- //part->userjit;
part->integrator= PART_INT_MIDPOINT;
part->phystype= PART_PHYS_NEWTON;
@@ -3032,7 +3099,6 @@ static void default_particle_settings(ParticleSettings *part)
part->reactevent= PART_EVENT_DEATH;
part->disp=100;
part->from= PART_FROM_FACE;
- part->length= 1.0;
part->nbetween= 4;
part->boidneighbours= 5;
@@ -3059,10 +3125,15 @@ static void default_particle_settings(ParticleSettings *part)
part->rough2_size=1.0;
part->rough_end_shape=1.0;
+ part->clength=1.0f;
+ part->clength_thres=0.0f;
+
part->draw_line[0]=0.5;
part->path_start = 0.0f;
part->path_end = 1.0f;
+ part->keyed_loops = 1;
+
part->banking=1.0;
part->max_bank=1.0;
@@ -3480,7 +3551,7 @@ float psys_get_child_size(ParticleSystem *psys, ChildParticle *cpa, float cfra,
}
static void get_child_modifier_parameters(ParticleSettings *part, ParticleThreadContext *ctx, ChildParticle *cpa, short cpa_from, int cpa_num, float *cpa_fuv, float *orco, ParticleTexture *ptex)
{
- ptex->length=part->length*(1.0f - part->randlength*cpa->rand[0]);
+ ptex->length= 1.0f - part->randlength*cpa->rand[0];
ptex->clump=1.0;
ptex->kink=1.0;
ptex->rough1= 1.0;
@@ -3489,6 +3560,8 @@ static void get_child_modifier_parameters(ParticleSettings *part, ParticleThread
ptex->exist= 1.0;
ptex->effector= 1.0;
+ ptex->length*= part->clength_thres < cpa->rand[1] ? part->clength : 1.0f;
+
get_cpa_texture(ctx->dm,ctx->ma,cpa_num,cpa_fuv,orco,ptex,
MAP_PA_DENS|MAP_PA_LENGTH|MAP_PA_CLUMP|MAP_PA_KINK|MAP_PA_ROUGH);
@@ -3511,7 +3584,7 @@ static void get_child_modifier_parameters(ParticleSettings *part, ParticleThread
if(ctx->vg_effector)
ptex->effector*=psys_interpolate_value_from_verts(ctx->dm,cpa_from,cpa_num,cpa_fuv,ctx->vg_effector);
}
-static void do_child_modifiers(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSettings *part, ParticleTexture *ptex, ParticleKey *par, float *par_rot, ChildParticle *cpa, float *orco, ParticleKey *state, float t)
+static void do_child_modifiers(Scene *scene, Object *ob, ParticleSystem *psys, ParticleSettings *part, ParticleTexture *ptex, ParticleKey *par, float *par_rot, ChildParticle *cpa, float *orco, float mat[4][4], ParticleKey *state, float t)
{
int guided = 0;
@@ -3528,13 +3601,13 @@ static void do_child_modifiers(Scene *scene, Object *ob, ParticleSystem *psys, P
}
if(part->rough1 != 0.0 && ptex->rough1 != 0.0)
- do_rough(orco, t, ptex->rough1*part->rough1, part->rough1_size, 0.0, state);
+ do_rough(orco, mat, t, ptex->rough1*part->rough1, part->rough1_size, 0.0, state);
if(part->rough2 != 0.0 && ptex->rough2 != 0.0)
- do_rough(cpa->rand, t, ptex->rough2*part->rough2, part->rough2_size, part->rough2_thres, state);
+ do_rough(cpa->rand, mat, t, ptex->rough2*part->rough2, part->rough2_size, part->rough2_thres, state);
if(part->rough_end != 0.0 && ptex->roughe != 0.0)
- do_rough_end(cpa->rand, t, ptex->roughe*part->rough_end, part->rough_end_shape, state, par);
+ do_rough_end(cpa->rand, mat, t, ptex->roughe*part->rough_end, part->rough_end_shape, state);
}
/* get's hair (or keyed) particles state at the "path time" specified in state->time */
void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, int p, ParticleKey *state, int vel)
@@ -3549,8 +3622,9 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i
HairKey *hkey[2] = {NULL, NULL};
ParticleKey *par=0, keys[4], tstate;
ParticleThreadContext ctx; /* fake thread context for child modifiers */
+ ParticleInterpolationData pind;
- float t, real_t, dfra, keytime, frs_sec = scene->r.frs_sec;
+ float t, frs_sec = scene->r.frs_sec;
float co[3], orco[3];
float hairmat[4][4];
int totparent = 0;
@@ -3558,7 +3632,7 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i
int totchild = psys->totchild;
short between = 0, edit = 0;
- int keyed = psys->flag & PSYS_KEYED;
+ int keyed = part->phystype & PART_PHYS_KEYED && psys->flag & PSYS_KEYED;
int cached = !keyed && part->type != PART_HAIR;
float *cpa_fuv; int cpa_num; short cpa_from;
@@ -3580,88 +3654,14 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i
key_from_object(pa->stick_ob,state);
return;
}
-
- if(keyed) {
- kkey[0] = pa->keys;
- kkey[1] = kkey[0] + 1;
- if(state->time < 0.0f)
- real_t = -state->time;
- else
- real_t = kkey[0]->time + t * (kkey[0][pa->totkey-1].time - kkey[0]->time);
- }
- else if(cached) {
- get_pointcache_keys_for_time(psys, -1, 0.0f, NULL, NULL);
- }
- else {
- hkey[0] = pa->hair;
- hkey[1] = pa->hair + 1;
-
- if(state->time < 0.0f)
- real_t = -state->time;
- else
- real_t = hkey[0]->time + t * (hkey[0][pa->totkey-1].time - hkey[0]->time);
- }
-
- if(keyed) {
- while(kkey[1]->time < real_t) {
- kkey[1]++;
- }
- kkey[0] = kkey[1] - 1;
-
- memcpy(keys + 1, kkey[0], sizeof(ParticleKey));
- memcpy(keys + 2, kkey[1], sizeof(ParticleKey));
- }
- else if(cached) {
- if(state->time < 0.0f) /* flag for time in frames */
- real_t = -state->time;
- else
- real_t = pa->time + t * (pa->dietime - pa->time);
-
- get_pointcache_keys_for_time(psys, p, real_t, keys+1, keys+2);
- }
- else {
- while(hkey[1]->time < real_t)
- hkey[1]++;
-
- hkey[0] = hkey[1] - 1;
-
- hair_to_particle(keys + 1, hkey[0]);
- hair_to_particle(keys + 2, hkey[1]);
- }
+ pind.keyed = keyed;
+ pind.cached = cached;
+ pind.soft = NULL;
+ init_particle_interpolation(ob, psys, pa, &pind);
+ do_particle_interpolation(psys, p, pa, t, frs_sec, &pind, state);
if(!keyed && !cached) {
- if(hkey[0] != pa->hair)
- hair_to_particle(keys, hkey[0] - 1);
- else
- hair_to_particle(keys, hkey[0]);
-
- if(hkey[1] != pa->hair + pa->totkey - 1)
- hair_to_particle(keys + 3, hkey[1] + 1);
- else
- hair_to_particle(keys + 3, hkey[1]);
- }
-
- dfra = keys[2].time - keys[1].time;
-
- keytime = (real_t - keys[1].time) / dfra;
-
- /* convert velocity to timestep size */
- if(keyed || cached){
- VecMulf(keys[1].vel, dfra / frs_sec);
- VecMulf(keys[2].vel, dfra / frs_sec);
- QuatInterpol(state->rot,keys[1].rot,keys[2].rot,keytime);
- }
-
- psys_interpolate_particle((keyed || cached) ? -1 /* signal for cubic interpolation */
- : ((psys->part->flag & PART_HAIR_BSPLINE) ? KEY_BSPLINE : KEY_CARDINAL)
- ,keys, keytime, state, 1);
-
- /* the velocity needs to be converted back from cubic interpolation */
- if(keyed || cached){
- VecMulf(state->vel, frs_sec / dfra);
- }
- else {
if((pa->flag & PARS_REKEY)==0) {
psys_mat_hair_to_global(ob, psmd->dm, part->from, pa, hairmat);
Mat4MulVecfl(hairmat, state->co);
@@ -3709,8 +3709,6 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i
cpa_num=cpa->num;
foffset= cpa->foffset;
- if(part->childtype == PART_CHILD_FACES)
- foffset = -(2.0f + part->childspread);
cpa_fuv = cpa->fuv;
cpa_from = PART_FROM_FACE;
@@ -3721,11 +3719,14 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i
//Mat4MulVecfl(ob->obmat,cpa_1st);
+ pa = psys->particles + cpa->parent;
+
+ psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat);
+
pa=0;
}
else{
/* get the parent state */
-
keys->time = state->time;
psys_get_particle_on_path(scene, ob, psys, cpa->parent, keys,1);
@@ -3737,6 +3738,8 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i
cpa_fuv=pa->fuv;
psys_particle_on_emitter(psmd,cpa_from,cpa_num,DMCACHE_ISCHILD,cpa_fuv,pa->foffset,co,0,0,0,orco,0);
+
+ psys_mat_hair_to_global(ob, psmd->dm, psys->part->from, pa, hairmat);
}
/* correct child ipo timing */
@@ -3785,7 +3788,7 @@ void psys_get_particle_on_path(Scene *scene, Object *ob, ParticleSystem *psys, i
copy_particle_key(&tstate, state, 1);
/* apply different deformations to the child path */
- do_child_modifiers(scene, ob, psys, part, &ptex, par, par->rot, cpa, orco, state, t);
+ do_child_modifiers(scene, ob, psys, part, &ptex, par, par->rot, cpa, orco, hairmat, state, t);
/* try to estimate correct velocity */
if(vel){
@@ -3856,7 +3859,7 @@ int psys_get_particle_state(struct Scene *scene, Object *ob, ParticleSystem *psy
state->time= (cfra-(part->sta+(part->end-part->sta)*cpa->rand[0]))/(part->lifetime*cpa->rand[1]);
}
else
- state->time= (cfra-pa->time)/(pa->dietime-pa->time);
+ state->time= -cfra;
psys_get_particle_on_path(scene, ob, psys, p, state,1);
return 1;
@@ -3893,57 +3896,55 @@ int psys_get_particle_state(struct Scene *scene, Object *ob, ParticleSystem *psy
calc_latt_deform(psys->lattice, state->co,1.0f);
}
else{
- if (pa) { /* TODO PARTICLE - should this ever be NULL? - Campbell */
- if(pa->state.time==state->time || ELEM(part->phystype,PART_PHYS_NO,PART_PHYS_KEYED))
- copy_particle_key(state, &pa->state, 1);
- else if(pa->prev_state.time==state->time)
- copy_particle_key(state, &pa->prev_state, 1);
- else {
- /* let's interpolate to try to be as accurate as possible */
- if(pa->state.time + 1.0f > state->time && pa->prev_state.time - 1.0f < state->time) {
- ParticleKey keys[4];
- float dfra, keytime, frs_sec = scene->r.frs_sec;
+ if(pa->state.time==state->time || ELEM(part->phystype,PART_PHYS_NO,PART_PHYS_KEYED))
+ copy_particle_key(state, &pa->state, 1);
+ else if(pa->prev_state.time==state->time)
+ copy_particle_key(state, &pa->prev_state, 1);
+ else {
+ /* let's interpolate to try to be as accurate as possible */
+ if(pa->state.time + 1.0f > state->time && pa->prev_state.time - 1.0f < state->time) {
+ ParticleKey keys[4];
+ float dfra, keytime, frs_sec = scene->r.frs_sec;
- if(pa->prev_state.time >= pa->state.time) {
- /* prev_state is wrong so let's not use it, this can happen at frame 1 or particle birth */
- copy_particle_key(state, &pa->state, 1);
+ if(pa->prev_state.time >= pa->state.time) {
+ /* prev_state is wrong so let's not use it, this can happen at frame 1 or particle birth */
+ copy_particle_key(state, &pa->state, 1);
- VECADDFAC(state->co, state->co, state->vel, (state->time-pa->state.time)/frs_sec);
- }
- else {
- copy_particle_key(keys+1, &pa->prev_state, 1);
- copy_particle_key(keys+2, &pa->state, 1);
+ VECADDFAC(state->co, state->co, state->vel, (state->time-pa->state.time)/frs_sec);
+ }
+ else {
+ copy_particle_key(keys+1, &pa->prev_state, 1);
+ copy_particle_key(keys+2, &pa->state, 1);
- dfra = keys[2].time - keys[1].time;
+ dfra = keys[2].time - keys[1].time;
- keytime = (state->time - keys[1].time) / dfra;
+ keytime = (state->time - keys[1].time) / dfra;
- /* convert velocity to timestep size */
- VecMulf(keys[1].vel, dfra / frs_sec);
- VecMulf(keys[2].vel, dfra / frs_sec);
-
- psys_interpolate_particle(-1, keys, keytime, state, 1);
-
- /* convert back to real velocity */
- VecMulf(state->vel, frs_sec / dfra);
+ /* convert velocity to timestep size */
+ VecMulf(keys[1].vel, dfra / frs_sec);
+ VecMulf(keys[2].vel, dfra / frs_sec);
+
+ psys_interpolate_particle(-1, keys, keytime, state, 1);
+
+ /* convert back to real velocity */
+ VecMulf(state->vel, frs_sec / dfra);
- VecLerpf(state->ave, keys[1].ave, keys[2].ave, keytime);
- QuatInterpol(state->rot, keys[1].rot, keys[2].rot, keytime);
- }
- }
- else {
- /* extrapolating over big ranges is not accurate so let's just give something close to reasonable back */
- copy_particle_key(state, &pa->state, 0);
+ VecLerpf(state->ave, keys[1].ave, keys[2].ave, keytime);
+ QuatInterpol(state->rot, keys[1].rot, keys[2].rot, keytime);
}
}
-
- if(pa->alive==PARS_DEAD && part->flag&PART_STICKY && pa->flag&PARS_STICKY && pa->stick_ob){
- key_from_object(pa->stick_ob,state);
+ else {
+ /* extrapolating over big ranges is not accurate so let's just give something close to reasonable back */
+ copy_particle_key(state, &pa->state, 0);
}
+ }
- if(psys->lattice)
- calc_latt_deform(psys->lattice, state->co,1.0f);
+ if(pa->alive==PARS_DEAD && part->flag&PART_STICKY && pa->flag&PARS_STICKY && pa->stick_ob){
+ key_from_object(pa->stick_ob,state);
}
+
+ if(psys->lattice)
+ calc_latt_deform(psys->lattice, state->co,1.0f);
}
return 1;
diff --git a/source/blender/blenkernel/intern/particle_system.c b/source/blender/blenkernel/intern/particle_system.c
index 07e0e82a86d..56ca3e8e22b 100644
--- a/source/blender/blenkernel/intern/particle_system.c
+++ b/source/blender/blenkernel/intern/particle_system.c
@@ -111,10 +111,7 @@ static int get_current_display_percentage(ParticleSystem *psys)
return 100;
if(part->phystype==PART_PHYS_KEYED){
- if(psys->flag & PSYS_FIRST_KEYED)
- return psys->part->disp;
- else
- return 100;
+ return psys->part->disp;
}
else
return psys->part->disp;
@@ -199,7 +196,7 @@ static void realloc_particles(Object *ob, ParticleSystem *psys, int new_totpart)
if(psys->particles->keys)
MEM_freeN(psys->particles->keys);
- for(i=0, pa=psys->particles; i<psys->totpart; i++, pa++)
+ for(i=0, pa=newpars; i<totsaved; i++, pa++)
if(pa->keys) {
pa->keys= NULL;
pa->totkey= 0;
@@ -1976,64 +1973,59 @@ static void reset_all_particles(Scene *scene, Object *ob, ParticleSystem *psys,
/************************************************/
/* Keyed particles */
/************************************************/
-/* a bit of an unintuitive function :) counts objects in a keyed chain and returns 1 if some of them were selected (used in drawing) */
-int psys_count_keyed_targets(Object *ob, ParticleSystem *psys)
+/* Counts valid keyed targets */
+void psys_count_keyed_targets(Object *ob, ParticleSystem *psys)
{
- ParticleSystem *kpsys=psys,*tpsys;
- ParticleSettings *tpart;
- Object *kob=ob,*tob;
- int select=ob->flag&SELECT;
- short totkeyed=0;
- Base *base;
-
- ListBase lb;
- lb.first=lb.last=0;
-
- tob=psys->keyed_ob;
- while(tob){
- if((tpsys=BLI_findlink(&tob->particlesystem,kpsys->keyed_psys-1))){
- tpart=tpsys->part;
-
- if(tpart->phystype==PART_PHYS_KEYED){
- if(lb.first){
- for(base=lb.first;base;base=base->next){
- if(tob==base->object){
- fprintf(stderr,"Error: loop in keyed chain!\n");
- BLI_freelistN(&lb);
- return select;
- }
- }
- }
- base=MEM_callocN(sizeof(Base), "keyed base");
- base->object=tob;
- BLI_addtail(&lb,base);
-
- if(tob->flag&SELECT)
- select++;
- kob=tob;
- kpsys=tpsys;
- tob=tpsys->keyed_ob;
- totkeyed++;
+ ParticleSystem *kpsys;
+ KeyedParticleTarget *kpt = psys->keyed_targets.first;
+ int psys_num = BLI_findindex(&ob->particlesystem, psys);
+ int keys_valid = 1;
+ psys->totkeyed = 0;
+
+ for(; kpt; kpt=kpt->next) {
+ kpsys = NULL;
+ if(kpt->ob==ob || kpt->ob==NULL) {
+ if(kpt->psys >= psys_num)
+ kpsys = BLI_findlink(&ob->particlesystem, kpt->psys-1);
+
+ if(kpsys && kpsys->totpart) {
+ kpt->flag |= KEYED_TARGET_VALID;
+ psys->totkeyed += keys_valid;
+ if(psys->flag & PSYS_KEYED_TIMING && kpt->duration != 0.0f)
+ psys->totkeyed += 1;
}
- else{
- tob=0;
- totkeyed++;
+ else {
+ kpt->flag &= ~KEYED_TARGET_VALID;
+ keys_valid = 0;
+ }
+ }
+ else {
+ if(kpt->ob)
+ kpsys = BLI_findlink(&kpt->ob->particlesystem, kpt->psys-1);
+
+ if(kpsys && kpsys->totpart) {
+ kpt->flag |= KEYED_TARGET_VALID;
+ psys->totkeyed += keys_valid;
+ if(psys->flag & PSYS_KEYED_TIMING && kpt->duration != 0.0f)
+ psys->totkeyed += 1;
+ }
+ else {
+ kpt->flag &= ~KEYED_TARGET_VALID;
+ keys_valid = 0;
}
}
- else
- tob=0;
}
- psys->totkeyed=totkeyed;
- BLI_freelistN(&lb);
- return select;
+
+ psys->totkeyed *= psys->flag & PSYS_KEYED_TIMING ? 1 : psys->part->keyed_loops;
}
static void set_keyed_keys(Scene *scene, Object *ob, ParticleSystem *psys)
{
Object *kob = ob;
ParticleSystem *kpsys = psys;
+ KeyedParticleTarget *kpt;
ParticleData *pa;
- int totpart = psys->totpart, i, k, totkeys = psys->totkeyed + 1;
+ int totpart = psys->totpart, i, k, totkeys = psys->totkeyed;
float prevtime, nexttime, keyedtime;
/* no proper targets so let's clear and bail out */
@@ -2046,7 +2038,7 @@ static void set_keyed_keys(Scene *scene, Object *ob, ParticleSystem *psys)
if(totpart && psys->particles->totkey != totkeys) {
free_keyed_keys(psys);
- psys->particles->keys = MEM_callocN(psys->totpart*totkeys*sizeof(ParticleKey), "Keyed keys");
+ psys->particles->keys = MEM_callocN(totpart*totkeys*sizeof(ParticleKey), "Keyed keys");
psys->particles->totkey = totkeys;
for(i=1, pa=psys->particles+1; i<totpart; i++,pa++){
@@ -2057,32 +2049,36 @@ static void set_keyed_keys(Scene *scene, Object *ob, ParticleSystem *psys)
psys->flag &= ~PSYS_KEYED;
+
+ kpt = psys->keyed_targets.first;
for(k=0; k<totkeys; k++) {
+ if(kpt->ob)
+ kpsys = BLI_findlink(&kpt->ob->particlesystem, kpt->psys - 1);
+ else
+ kpsys = BLI_findlink(&ob->particlesystem, kpt->psys - 1);
+
for(i=0,pa=psys->particles; i<totpart; i++, pa++) {
(pa->keys + k)->time = -1.0; /* use current time */
- if(kpsys->totpart > 0)
- psys_get_particle_state(scene, kob, kpsys, i%kpsys->totpart, pa->keys + k, 1);
+ psys_get_particle_state(scene, kpt->ob, kpsys, i%kpsys->totpart, pa->keys + k, 1);
- if(k==0)
- pa->keys->time = pa->time;
- else if(k==totkeys-1)
- (pa->keys + k)->time = pa->time + pa->lifetime;
- else{
- if(psys->flag & PSYS_KEYED_TIME){
- prevtime = (pa->keys + k - 1)->time;
- nexttime = pa->time + pa->lifetime;
- keyedtime = kpsys->part->keyed_time;
- (pa->keys + k)->time = (1.0f - keyedtime) * prevtime + keyedtime * nexttime;
+ if(psys->flag & PSYS_KEYED_TIMING){
+ (pa->keys+k)->time = pa->time + kpt->time;
+ if(kpt->duration != 0.0f && k+1 < totkeys) {
+ copy_particle_key(pa->keys+k+1, pa->keys+k, 1);
+ (pa->keys+k+1)->time = pa->time + kpt->time + kpt->duration;
}
- else
- (pa->keys+k)->time = pa->time + (float)k / (float)(totkeys - 1) * pa->lifetime;
}
+ else if(totkeys > 1)
+ (pa->keys+k)->time = pa->time + (float)k / (float)(totkeys - 1) * pa->lifetime;
+ else
+ pa->keys->time = pa->time;
}
- if(kpsys->keyed_ob){
- kob = kpsys->keyed_ob;
- kpsys = BLI_findlink(&kob->particlesystem, kpsys->keyed_psys - 1);
- }
+
+ if(psys->flag & PSYS_KEYED_TIMING && kpt->duration!=0.0f)
+ k++;
+
+ kpt = (kpt->next && kpt->next->flag & KEYED_TARGET_VALID) ? kpt = kpt->next : psys->keyed_targets.first;
}
psys->flag |= PSYS_KEYED;
@@ -2198,6 +2194,60 @@ void psys_get_reactor_target(Object *ob, ParticleSystem *psys, Object **target_o
/************************************************/
/* Point Cache */
/************************************************/
+void psys_make_temp_pointcache(Object *ob, ParticleSystem *psys)
+{
+ PointCache *cache = psys->pointcache;
+ PTCacheFile *pf = NULL;
+ PTCacheMem *pm = NULL;
+ PTCacheID pid;
+ int cfra, sfra = cache->startframe, efra = cache->endframe;
+ int totelem = psys->totpart;
+ int float_count = sizeof(ParticleKey) / sizeof(float);
+ int tot = totelem * float_count;
+
+ if((cache->flag & PTCACHE_DISK_CACHE)==0 || cache->mem_cache.first)
+ return;
+
+ BKE_ptcache_id_from_particles(&pid, ob, psys);
+
+ for(cfra=sfra; cfra <= efra; cfra++) {
+ pf = BKE_ptcache_file_open(&pid, PTCACHE_FILE_READ, cfra);
+
+ if(pf) {
+ pm = MEM_callocN(sizeof(PTCacheMem), "Pointcache temp mem");
+ pm->data = MEM_callocN(sizeof(float)*tot, "Pointcache temp mem data");
+
+ if(fread(pm->data, sizeof(float), tot, pf->fp)!= tot) {
+ printf("Error reading from disk cache\n");
+
+ MEM_freeN(pm->data);
+ MEM_freeN(pm);
+ BKE_ptcache_file_close(pf);
+ return;
+ }
+
+ pm->frame = cfra;
+ pm->totpoint = totelem;
+
+ BLI_addtail(&cache->mem_cache, pm);
+
+ BKE_ptcache_file_close(pf);
+ }
+ }
+}
+void psys_clear_temp_pointcache(ParticleSystem *psys)
+{
+ PTCacheMem *pm = psys->pointcache->mem_cache.first;
+
+ if((psys->pointcache->flag & PTCACHE_DISK_CACHE)==0)
+ return;
+
+ for(; pm; pm=pm->next) {
+ MEM_freeN(pm->data);
+ }
+
+ BLI_freelistN(&psys->pointcache->mem_cache);
+}
void psys_get_pointcache_start_end(Scene *scene, ParticleSystem *psys, int *sfra, int *efra)
{
ParticleSettings *part = psys->part;
@@ -3912,61 +3962,6 @@ static void boid_body(Scene *scene, BoidVecFunc *bvf, ParticleData *pa, Particle
if(part->flag & PART_BOIDS_2D){
pa->state.vel[2]=0.0;
pa->state.co[2]=part->groundz;
-
- if(psys->keyed_ob && (psys->keyed_ob->type == OB_MESH)){
- Object *zob=psys->keyed_ob;
- int min_face;
- float co1[3],co2[3],min_d=2.0,min_w[4],imat[4][4];
- VECCOPY(co1,pa->state.co);
- VECCOPY(co2,pa->state.co);
-
- co1[2]=1000.0f;
- co2[2]=-1000.0f;
-
- Mat4Invert(imat,zob->obmat);
- Mat4MulVecfl(imat,co1);
- Mat4MulVecfl(imat,co2);
-
- if(psys_intersect_dm(scene,zob,0,0,co1,co2,&min_d,&min_face,min_w,0,0,0,0)){
- DerivedMesh *dm;
- MFace *mface;
- MVert *mvert;
- float loc[3],nor[3],q1[4];
-
- psys_disable_all(zob);
- dm=mesh_get_derived_final(scene, zob, 0);
- psys_enable_all(zob);
-
- mface=dm->getFaceDataArray(dm,CD_MFACE);
- mface+=min_face;
- mvert=dm->getVertDataArray(dm,CD_MVERT);
-
- /* get deflection point & normal */
- psys_interpolate_face(mvert,mface,0,0,min_w,loc,nor,0,0,0,0);
-
- Mat4MulVecfl(zob->obmat,loc);
- Mat4Mul3Vecfl(zob->obmat,nor);
-
- Normalize(nor);
-
- VECCOPY(pa->state.co,loc);
-
- zvec[2]=1.0;
-
- Crossf(loc,zvec,nor);
-
- bank=VecLength(loc);
- if(bank>0.0){
- bank=saasin(bank);
-
- VecRotToQuat(loc,bank,q);
-
- QUATCOPY(q1,pa->state.rot);
-
- QuatMul(pa->state.rot,q,q1);
- }
- }
- }
}
length=bvf->Length(pa->state.vel);
@@ -4238,7 +4233,7 @@ static void psys_update_path_cache(Scene *scene, Object *ob, ParticleSystemModif
if((psys->part->childtype && psys->totchild != get_psys_tot_child(scene, psys)) || psys->recalc&PSYS_RECALC_RESET)
alloc=1;
- if(alloc || psys->recalc&PSYS_RECALC_RESET || (psys->vgroup[PSYS_VG_DENSITY] && (G.f & G_WEIGHTPAINT)))
+ if(alloc || psys->recalc&PSYS_RECALC_CHILD || (psys->vgroup[PSYS_VG_DENSITY] && (G.f & G_WEIGHTPAINT)))
distr=1;
if(distr){
@@ -4416,12 +4411,15 @@ static void cached_step(Scene *scene, Object *ob, ParticleSystemModifierData *ps
MEM_freeN(vg_size);
}
-void psys_changed_type(ParticleSystem *psys)
+static void psys_changed_type(Object *ob, ParticleSystem *psys)
{
ParticleSettings *part;
+ PTCacheID pid;
part= psys->part;
+ BKE_ptcache_id_from_particles(&pid, ob, psys);
+
/* system type has changed so set sensible defaults and clear non applicable flags */
if(part->from == PART_FROM_PARTICLE) {
if(part->type != PART_REACTOR)
@@ -4430,7 +4428,7 @@ void psys_changed_type(ParticleSystem *psys)
part->distr = PART_DISTR_JIT;
}
- if(psys->part->phystype != PART_PHYS_KEYED)
+ if(part->phystype != PART_PHYS_KEYED)
psys->flag &= ~PSYS_KEYED;
if(part->type == PART_HAIR) {
@@ -4442,6 +4440,8 @@ void psys_changed_type(ParticleSystem *psys)
CLAMP(part->path_start, 0.0f, 100.0f);
CLAMP(part->path_end, 0.0f, 100.0f);
+
+ BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, 0);
}
else {
free_hair(psys, 1);
@@ -4454,7 +4454,18 @@ void psys_changed_type(ParticleSystem *psys)
psys_reset(psys, PSYS_RESET_ALL);
}
-
+void psys_changed_physics(Object *ob, ParticleSystem *psys)
+{
+ if(ELEM(psys->part->phystype, PART_PHYS_NO, PART_PHYS_KEYED)) {
+ PTCacheID pid;
+ BKE_ptcache_id_from_particles(&pid, ob, psys);
+ BKE_ptcache_id_clear(&pid, PTCACHE_CLEAR_ALL, 0);
+ }
+ else {
+ free_keyed_keys(psys);
+ psys->flag &= ~PSYS_KEYED;
+ }
+}
static void particles_fluid_step(Scene *scene, Object *ob, ParticleSystem *psys, int cfra)
{
if(psys->particles){
@@ -4588,6 +4599,8 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
BKE_ptcache_id_from_particles(&pid, ob, psys);
BKE_ptcache_id_time(&pid, scene, 0.0f, &startframe, &endframe, NULL);
+ psys_clear_temp_pointcache(psys);
+
/* update ipo's */
#if 0 // XXX old animation system
if((part->flag & PART_ABS_TIME) && part->ipo) {
@@ -4736,7 +4749,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
if(usecache && psys->cfra == startframe && (cache->flag & PTCACHE_OUTDATED || cache->last_exact==0))
write_particles_to_cache(ob, psys, startframe);
- if(part->phystype==PART_PHYS_KEYED && psys->flag&PSYS_FIRST_KEYED)
+ if(part->phystype==PART_PHYS_KEYED)
psys_count_keyed_targets(ob,psys);
/* initialize vertex groups */
@@ -4783,7 +4796,7 @@ static void system_step(Scene *scene, Object *ob, ParticleSystem *psys, Particle
write_particles_to_cache(ob, psys, framenr);
/* for keyed particles the path is allways known so it can be drawn */
- if(part->phystype==PART_PHYS_KEYED && psys->flag&PSYS_FIRST_KEYED){
+ if(part->phystype==PART_PHYS_KEYED) {
set_keyed_keys(scene, ob, psys);
psys_update_path_cache(scene, ob, psmd, psys,(int)cfra);
}
@@ -4866,7 +4879,9 @@ void particle_system_update(Scene *scene, Object *ob, ParticleSystem *psys)
return;
if(psys->recalc & PSYS_RECALC_TYPE)
- psys_changed_type(psys);
+ psys_changed_type(ob, psys);
+ else if(psys->recalc & PSYS_RECALC_PHYS)
+ psys_changed_physics(ob, psys);
/* (re-)create hair */
if(psys->part->type==PART_HAIR && hair_needs_recalc(psys)) {
diff --git a/source/blender/blenkernel/intern/pointcache.c b/source/blender/blenkernel/intern/pointcache.c
index 2fe46be7a89..6107510fa47 100644
--- a/source/blender/blenkernel/intern/pointcache.c
+++ b/source/blender/blenkernel/intern/pointcache.c
@@ -315,8 +315,10 @@ static int ptcache_pid_totelem(PTCacheID *pid)
ParticleSystem *psys = pid->data;
return psys->totpart;
}
- else if(pid->type==PTCACHE_TYPE_CLOTH)
- return 0; // TODO
+ else if(pid->type==PTCACHE_TYPE_CLOTH) {
+ ClothModifierData *clmd = pid->data;
+ return clmd->clothObject->numverts;
+ }
return 0;
}
@@ -429,6 +431,7 @@ int BKE_ptcache_read_cache(PTCacheReader *reader)
if(pf) {
BKE_ptcache_file_close(pf);
+ pf = NULL;
MEM_freeN(data);
}
@@ -523,7 +526,9 @@ int BKE_ptcache_read_cache(PTCacheReader *reader)
if(pf) {
BKE_ptcache_file_close(pf);
+ pf = NULL;
BKE_ptcache_file_close(pf2);
+ pf2 = NULL;
MEM_freeN(data1);
MEM_freeN(data2);
}
@@ -567,10 +572,13 @@ int BKE_ptcache_read_cache(PTCacheReader *reader)
if(pf) {
BKE_ptcache_file_close(pf);
+ pf = NULL;
MEM_freeN(data);
}
- if(pf2)
+ if(pf2) {
BKE_ptcache_file_close(pf2);
+ pf = NULL;
+ }
ret = PTCACHE_READ_OLD;
}
@@ -602,13 +610,15 @@ int BKE_ptcache_write_cache(PTCacheWriter *writer)
PTCacheFile *pf= NULL;
int elemsize = ptcache_pid_elemsize(writer->pid);
int i, incr = elemsize / sizeof(float);
- int add = 0, overwrite = 0, ocfra;
+ int add = 0, overwrite = 0;
float temp[14];
if(writer->totelem == 0 || writer->cfra <= 0)
return 0;
if(cache->flag & PTCACHE_DISK_CACHE) {
+ int cfra = cache->endframe;
+
/* allways start from scratch on the first frame */
if(writer->cfra == cache->startframe) {
BKE_ptcache_id_clear(writer->pid, PTCACHE_CLEAR_ALL, writer->cfra);
@@ -616,7 +626,7 @@ int BKE_ptcache_write_cache(PTCacheWriter *writer)
add = 1;
}
else {
- int cfra = cache->endframe;
+ int ocfra;
/* find last cached frame */
while(cfra > cache->startframe && !BKE_ptcache_id_exist(writer->pid, cfra))
cfra--;
@@ -626,7 +636,7 @@ int BKE_ptcache_write_cache(PTCacheWriter *writer)
while(ocfra > cache->startframe && !BKE_ptcache_id_exist(writer->pid, ocfra))
ocfra--;
- if(writer->cfra > cfra) {
+ if(cfra >= cache->startframe && writer->cfra > cfra) {
if(ocfra >= cache->startframe && cfra - ocfra < cache->step)
overwrite = 1;
else
@@ -636,7 +646,7 @@ int BKE_ptcache_write_cache(PTCacheWriter *writer)
if(add || overwrite) {
if(overwrite)
- BKE_ptcache_id_clear(writer->pid, PTCACHE_CLEAR_FRAME, ocfra);
+ BKE_ptcache_id_clear(writer->pid, PTCACHE_CLEAR_FRAME, cfra);
pf = BKE_ptcache_file_open(writer->pid, PTCACHE_FILE_WRITE, writer->cfra);
if(!pf)
@@ -665,7 +675,7 @@ int BKE_ptcache_write_cache(PTCacheWriter *writer)
pm2 = cache->mem_cache.last;
if(pm2 && writer->cfra > pm2->frame) {
- if(pm2 && pm2->prev && pm2->frame - pm2->prev->frame < cache->step)
+ if(pm2->prev && pm2->frame - pm2->prev->frame < cache->step)
overwrite = 1;
else
add = 1;
@@ -1102,6 +1112,10 @@ PointCache *BKE_ptcache_copy(PointCache *cache)
ncache= MEM_dupallocN(cache);
+ /* hmm, should these be copied over instead? */
+ ncache->mem_cache.first = NULL;
+ ncache->mem_cache.last = NULL;
+
ncache->flag= 0;
ncache->simframe= 0;
@@ -1211,8 +1225,9 @@ void BKE_ptcache_make_cache(PTCacheBaker* baker)
cache = pid->cache;
if((cache->flag & PTCACHE_BAKED)==0) {
if(pid->type==PTCACHE_TYPE_PARTICLES) {
- /* skip hair particles */
- if(((ParticleSystem*)pid->data)->part->type == PART_HAIR)
+ ParticleSystem *psys = (ParticleSystem*)pid->data;
+ /* skip hair & keyed particles */
+ if(psys->part->type == PART_HAIR || psys->part->phystype == PART_PHYS_KEYED)
continue;
psys_get_pointcache_start_end(scene, pid->data, &cache->startframe, &cache->endframe);
@@ -1310,6 +1325,7 @@ void BKE_ptcache_toggle_disk_cache(PTCacheID *pid) {
if (!G.relbase_valid){
cache->flag &= ~PTCACHE_DISK_CACHE;
+ printf("File must be saved before using disk cache!\n");
return;
}
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 479fa760423..c2b19a804ee 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -2968,6 +2968,9 @@ static void direct_link_pointcache(FileData *fd, PointCache *cache)
for(; pm; pm=pm->next)
pm->data = newdataadr(fd, pm->data);
}
+ else
+ cache->mem_cache.first = cache->mem_cache.last = NULL;
+
cache->flag &= ~(PTCACHE_SIMULATION_VALID|PTCACHE_BAKE_EDIT_ACTIVE);
cache->simframe= 0;
}
@@ -3011,12 +3014,18 @@ static void lib_link_particlesystems(FileData *fd, Object *ob, ID *id, ListBase
psys->part = newlibadr_us(fd, id->lib, psys->part);
if(psys->part) {
+ KeyedParticleTarget *kpt = psys->keyed_targets.first;
+
+ for(; kpt; kpt=kpt->next)
+ kpt->ob=newlibadr(fd, id->lib, kpt->ob);
+
psys->target_ob = newlibadr(fd, id->lib, psys->target_ob);
- psys->keyed_ob = newlibadr(fd, id->lib, psys->keyed_ob);
for(a=0,pa=psys->particles; a<psys->totpart; a++,pa++){
pa->stick_ob=newlibadr(fd, id->lib, pa->stick_ob);
}
+
+
}
else {
/* particle modifier must be removed before particle system */
@@ -3066,6 +3075,8 @@ static void direct_link_particlesystems(FileData *fd, ListBase *particles)
direct_link_pointcache(fd, sb->pointcache);
}
+ link_list(fd, &psys->keyed_targets);
+
psys->edit = 0;
psys->free_edit = NULL;
psys->pathcache = 0;
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c
index 4b52da83019..65a4a355717 100644
--- a/source/blender/blenloader/intern/writefile.c
+++ b/source/blender/blenloader/intern/writefile.c
@@ -589,6 +589,7 @@ static void write_particlesettings(WriteData *wd, ListBase *idbase)
static void write_particlesystems(WriteData *wd, ListBase *particles)
{
ParticleSystem *psys= particles->first;
+ KeyedParticleTarget *kpt;
int a;
for(; psys; psys=psys->next) {
@@ -604,6 +605,10 @@ static void write_particlesystems(WriteData *wd, ListBase *particles)
writestruct(wd, DATA, "HairKey", pa->totkey, pa->hair);
}
}
+ kpt = psys->keyed_targets.first;
+ for(; kpt; kpt=kpt->next)
+ writestruct(wd, DATA, "KeyedParticleTarget", 1, kpt);
+
if(psys->child) writestruct(wd, DATA, "ChildParticle", psys->totchild ,psys->child);
writestruct(wd, DATA, "SoftBody", 1, psys->soft);
if(psys->soft) write_pointcaches(wd, psys->soft->pointcache, PTCACHE_WRITE_PSYS);
diff --git a/source/blender/editors/space_buttons/buttons_intern.h b/source/blender/editors/space_buttons/buttons_intern.h
index 65c2976d57c..f16a232f26d 100644
--- a/source/blender/editors/space_buttons/buttons_intern.h
+++ b/source/blender/editors/space_buttons/buttons_intern.h
@@ -75,6 +75,10 @@ void OBJECT_OT_particle_system_add(struct wmOperatorType *ot);
void OBJECT_OT_particle_system_remove(struct wmOperatorType *ot);
void PARTICLE_OT_new(struct wmOperatorType *ot);
+void PARTICLE_OT_new_keyed_target(struct wmOperatorType *ot);
+void PARTICLE_OT_remove_keyed_target(struct wmOperatorType *ot);
+void PARTICLE_OT_keyed_target_move_up(struct wmOperatorType *ot);
+void PARTICLE_OT_keyed_target_move_down(struct wmOperatorType *ot);
#endif /* ED_BUTTONS_INTERN_H */
diff --git a/source/blender/editors/space_buttons/buttons_ops.c b/source/blender/editors/space_buttons/buttons_ops.c
index 66b380ab413..6fb52c61131 100644
--- a/source/blender/editors/space_buttons/buttons_ops.c
+++ b/source/blender/editors/space_buttons/buttons_ops.c
@@ -49,6 +49,7 @@
#include "BKE_world.h"
#include "BLI_editVert.h"
+#include "BLI_listbase.h"
#include "RNA_access.h"
@@ -473,33 +474,32 @@ static int new_particle_settings_exec(bContext *C, wmOperator *op)
{
Scene *scene = CTX_data_scene(C);
Main *bmain= CTX_data_main(C);
- ParticleSettings *part= CTX_data_pointer_get_type(C, "particle_settings", &RNA_ParticleSettings).data;
+ ParticleSystem *psys;
+ ParticleSettings *part = NULL;
Object *ob;
PointerRNA ptr;
+ ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
+
+ psys = ptr.data;
+
/* add or copy particle setting */
- if(part)
- part= psys_copy_settings(part);
+ if(psys->part)
+ part= psys_copy_settings(psys->part);
else
part= psys_new_settings("PSys", bmain);
- /* attempt to assign to material slot */
- ptr= CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
+ ob= ptr.id.data;
- if(ptr.data) {
- ParticleSystem *psys = (ParticleSystem*)ptr.data;
- ob= ptr.id.data;
-
- if(psys->part)
- psys->part->id.us--;
+ if(psys->part)
+ psys->part->id.us--;
- psys->part = part;
+ psys->part = part;
- DAG_scene_sort(scene);
- DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+ DAG_scene_sort(scene);
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
- WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
- }
+ WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
return OPERATOR_FINISHED;
}
@@ -517,3 +517,175 @@ void PARTICLE_OT_new(wmOperatorType *ot)
ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
}
+/********************** keyed particle target operators *********************/
+
+static int new_keyed_particle_target_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
+ ParticleSystem *psys= ptr.data;
+ Object *ob = ptr.id.data;
+
+ KeyedParticleTarget *kpt;
+
+ if(!psys)
+ return OPERATOR_CANCELLED;
+
+ kpt = psys->keyed_targets.first;
+ for(; kpt; kpt=kpt->next)
+ kpt->flag &= ~KEYED_TARGET_CURRENT;
+
+ kpt = MEM_callocN(sizeof(KeyedParticleTarget), "keyed particle target");
+
+ kpt->flag |= KEYED_TARGET_CURRENT;
+ kpt->psys = 1;
+
+ BLI_addtail(&psys->keyed_targets, kpt);
+
+ DAG_scene_sort(scene);
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void PARTICLE_OT_new_keyed_target(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "New Keyed Particle Target";
+ ot->idname= "PARTICLE_OT_new_keyed_target";
+
+ /* api callbacks */
+ ot->exec= new_keyed_particle_target_exec;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+static int remove_keyed_particle_target_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene = CTX_data_scene(C);
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
+ ParticleSystem *psys= ptr.data;
+ Object *ob = ptr.id.data;
+
+ KeyedParticleTarget *kpt;
+
+ if(!psys)
+ return OPERATOR_CANCELLED;
+
+ kpt = psys->keyed_targets.first;
+ for(; kpt; kpt=kpt->next) {
+ if(kpt->flag & KEYED_TARGET_CURRENT) {
+ BLI_remlink(&psys->keyed_targets, kpt);
+ MEM_freeN(kpt);
+ break;
+ }
+
+ }
+ kpt = psys->keyed_targets.last;
+
+ if(kpt)
+ kpt->flag |= KEYED_TARGET_CURRENT;
+
+ DAG_scene_sort(scene);
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+
+ WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
+
+ return OPERATOR_FINISHED;
+}
+
+void PARTICLE_OT_remove_keyed_target(wmOperatorType *ot)
+{
+ /* identifiers */
+ ot->name= "Remove Keyed Particle Target";
+ ot->idname= "PARTICLE_OT_remove_keyed_target";
+
+ /* api callbacks */
+ ot->exec= remove_keyed_particle_target_exec;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/************************ move up modifier operator *********************/
+
+static int keyed_target_move_up_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
+ ParticleSystem *psys= ptr.data;
+ Object *ob = ptr.id.data;
+ KeyedParticleTarget *kpt;
+
+ if(!psys)
+ return OPERATOR_CANCELLED;
+
+ kpt = psys->keyed_targets.first;
+ for(; kpt; kpt=kpt->next) {
+ if(kpt->flag & KEYED_TARGET_CURRENT && kpt->prev) {
+ BLI_remlink(&psys->keyed_targets, kpt);
+ BLI_insertlink(&psys->keyed_targets, kpt->prev->prev, kpt);
+
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
+ break;
+ }
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void PARTICLE_OT_keyed_target_move_up(wmOperatorType *ot)
+{
+ ot->name= "Move Up Keyed Target";
+ ot->description= "Move keyed particle target up in the list.";
+ ot->idname= "PARTICLE_OT_keyed_target_move_up";
+
+ ot->exec= keyed_target_move_up_exec;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
+/************************ move down modifier operator *********************/
+
+static int keyed_target_move_down_exec(bContext *C, wmOperator *op)
+{
+ Scene *scene= CTX_data_scene(C);
+ PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem);
+ ParticleSystem *psys= ptr.data;
+ Object *ob = ptr.id.data;
+ KeyedParticleTarget *kpt;
+
+ if(!psys)
+ return OPERATOR_CANCELLED;
+ kpt = psys->keyed_targets.first;
+ for(; kpt; kpt=kpt->next) {
+ if(kpt->flag & KEYED_TARGET_CURRENT && kpt->next) {
+ BLI_remlink(&psys->keyed_targets, kpt);
+ BLI_insertlink(&psys->keyed_targets, kpt->next, kpt);
+
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+ WM_event_add_notifier(C, NC_OBJECT|ND_DRAW, ob);
+ break;
+ }
+ }
+
+ return OPERATOR_FINISHED;
+}
+
+void PARTICLE_OT_keyed_target_move_down(wmOperatorType *ot)
+{
+ ot->name= "Move Down Keyed Target";
+ ot->description= "Move keyed particle target down in the list.";
+ ot->idname= "PARTICLE_OT_keyed_target_move_down";
+
+ ot->exec= keyed_target_move_down_exec;
+
+ /* flags */
+ ot->flag= OPTYPE_REGISTER|OPTYPE_UNDO;
+}
+
diff --git a/source/blender/editors/space_buttons/space_buttons.c b/source/blender/editors/space_buttons/space_buttons.c
index f7be323a4c5..6cdb4dbf93d 100644
--- a/source/blender/editors/space_buttons/space_buttons.c
+++ b/source/blender/editors/space_buttons/space_buttons.c
@@ -224,6 +224,10 @@ void buttons_operatortypes(void)
WM_operatortype_append(OBJECT_OT_particle_system_remove);
WM_operatortype_append(PARTICLE_OT_new);
+ WM_operatortype_append(PARTICLE_OT_new_keyed_target);
+ WM_operatortype_append(PARTICLE_OT_remove_keyed_target);
+ WM_operatortype_append(PARTICLE_OT_keyed_target_move_up);
+ WM_operatortype_append(PARTICLE_OT_keyed_target_move_down);
}
void buttons_keymap(struct wmWindowManager *wm)
diff --git a/source/blender/editors/space_view3d/drawobject.c b/source/blender/editors/space_view3d/drawobject.c
index e8749537f5e..f83a0b9686e 100644
--- a/source/blender/editors/space_view3d/drawobject.c
+++ b/source/blender/editors/space_view3d/drawobject.c
@@ -3161,15 +3161,11 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
/* 2. */
if(part->phystype==PART_PHYS_KEYED){
- if(psys->flag & PSYS_FIRST_KEYED){
- if(psys->flag&PSYS_KEYED){
- select=psys_count_keyed_targets(ob,psys);
- if(psys->totkeyed==0)
- return;
- }
+ if(psys->flag&PSYS_KEYED){
+ psys_count_keyed_targets(ob,psys);
+ if(psys->totkeyed==0)
+ return;
}
- else
- return;
}
if(select){
@@ -3226,8 +3222,8 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
else
draw_as = part->draw_as;
- if(part->flag&PART_GLOB_TIME)
- cfra=bsystem_time(scene, 0, (float)CFRA, 0.0f);
+ //if(part->flag&PART_GLOB_TIME)
+ cfra=bsystem_time(scene, 0, (float)CFRA, 0.0f);
if(draw_as==PART_DRAW_PATH && psys->pathcache==NULL)
draw_as=PART_DRAW_DOT;
@@ -3306,8 +3302,10 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
if(draw_as && draw_as!=PART_DRAW_PATH) {
int tot_vec_size = (totpart + totchild) * 3 * sizeof(float);
- if(part->draw_as == PART_DRAW_REND && part->trail_count > 1)
+ if(part->draw_as == PART_DRAW_REND && part->trail_count > 1) {
tot_vec_size *= part->trail_count;
+ psys_make_temp_pointcache(ob, psys);
+ }
if(draw_as!=PART_DRAW_CIRC) {
switch(draw_as) {
@@ -3361,8 +3359,8 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
pa_dietime = pa->dietime;
pa_size=pa->size;
- if((part->flag&PART_ABS_TIME)==0){
-#if 0 // XXX old animation system
+#if 0 // XXX old animation system
+ if((part->flag&PART_ABS_TIME)==0){
if(ma && ma->ipo){
IpoCurve *icu;
@@ -3389,8 +3387,8 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
pa_size = icu->curval;
}
}
-#endif // XXX old animation system
}
+#endif // XXX old animation system
r_tilt = 1.0f + pa->r_ave[0];
r_length = 0.5f * (1.0f + pa->r_ave[1]);
@@ -3400,9 +3398,9 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
pa_time=psys_get_child_time(psys,cpa,cfra,&pa_birthtime,&pa_dietime);
+#if 0 // XXX old animation system
if((part->flag&PART_ABS_TIME)==0) {
if(ma && ma->ipo){
-#if 0 // XXX old animation system
IpoCurve *icu;
/* correction for lifetime */
@@ -3416,9 +3414,9 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
else if(icu->adrcode == MA_COL_B)
ma_b = icu->curval;
}
-#endif // XXX old animation system
}
}
+#endif // XXX old animation system
pa_size=psys_get_child_size(psys,cpa,cfra,0);
@@ -3444,7 +3442,7 @@ static void draw_new_particle_system(Scene *scene, View3D *v3d, RegionView3D *rv
else if(ct < 0.0f || ct > 1.0f)
continue;
- state.time = (part->draw & PART_ABS_PATH_TIME) ? -ct : ct;
+ state.time = (part->draw & PART_ABS_PATH_TIME) ? -ct : -(pa_birthtime + ct * (pa_dietime - pa_birthtime));
psys_get_particle_on_path(scene,ob,psys,a,&state,need_v);
if(psys->parent)
diff --git a/source/blender/makesdna/DNA_particle_types.h b/source/blender/makesdna/DNA_particle_types.h
index c793362c223..0b3309bfc0c 100644
--- a/source/blender/makesdna/DNA_particle_types.h
+++ b/source/blender/makesdna/DNA_particle_types.h
@@ -61,6 +61,14 @@ typedef struct ChildParticle {
float rand[3];
} ChildParticle;
+typedef struct KeyedParticleTarget {
+ struct KeyedParticleTarget *next, *prev;
+ struct Object *ob;
+ int psys;
+ short flag, rt;
+ float time, duration;
+} KeyedParticleTarget;
+
/* Everything that's non dynamic for a particle: */
typedef struct ParticleData {
struct Object *stick_ob;/* object that particle sticks to when dead */
@@ -131,7 +139,7 @@ typedef struct ParticleSettings {
/* general values */
float sta, end, lifetime, randlife;
- float timetweak, jitfac, keyed_time, eff_hair;
+ float timetweak, jitfac, eff_hair;
int totpart, userjit, grid_res;
/* initial velocity factors */
@@ -142,11 +150,11 @@ typedef struct ParticleSettings {
/* global physical properties */
float acc[3], dragfac, brownfac, dampfac;
/* length */
- float length, abslength, randlength;
+ float randlength;
/* children */
int child_nbr, ren_child_nbr;
float parents, childsize, childrandsize;
- float childrad, childflat, childspread;
+ float childrad, childflat, rt;
/* clumping */
float clumpfac, clumppow;
/* kink */
@@ -155,12 +163,16 @@ typedef struct ParticleSettings {
float rough1, rough1_size;
float rough2, rough2_size, rough2_thres;
float rough_end, rough_end_shape;
+ /* length */
+ float clength, clength_thres;
/* branching */
float branch_thres;
/* drawing stuff */
float draw_line[2];
float path_start, path_end;
int trail_count;
+ /* keyed particles */
+ int keyed_loops;
/* boids */
float max_vel, max_lat_acc, max_tan_acc;
@@ -195,17 +207,18 @@ typedef struct ParticleSystem{ /* note, make sure all (runtime) are NULL's in
struct SoftBody *soft; /* hair softbody */
struct Object *target_ob;
- struct Object *keyed_ob;
struct Object *lattice;
struct Object *parent; /* particles from global space -> parent space */
struct ListBase effectors, reactevents; /* runtime */
+
+ struct ListBase keyed_targets;
float imat[4][4]; /* used for duplicators */
float cfra;
int seed;
int flag, totpart, totchild, totcached, totchildcache, rt;
- short recalc, target_psys, keyed_psys, totkeyed, softflag, bakespace;
+ short recalc, target_psys, totkeyed, softflag, bakespace, rt2;
char bb_uvname[3][32]; /* billboard uv name */
@@ -255,10 +268,10 @@ typedef struct ParticleSystem{ /* note, make sure all (runtime) are NULL's in
#define PART_ROT_DYN (1<<14) /* dynamic rotation */
#define PART_SIZEMASS (1<<16)
-#define PART_ABS_LENGTH (1<<15)
+//#define PART_KEYED_TIMING (1<<15)
-#define PART_ABS_TIME (1<<17)
-#define PART_GLOB_TIME (1<<18)
+//#define PART_ABS_TIME (1<<17)
+//#define PART_GLOB_TIME (1<<18)
#define PART_BOIDS_2D (1<<19)
@@ -396,14 +409,15 @@ typedef struct ParticleSystem{ /* note, make sure all (runtime) are NULL's in
#define PSYS_RECALC_RESET 2 /* reset everything including pointcache */
#define PSYS_RECALC_TYPE 4 /* handle system type change */
#define PSYS_RECALC_CHILD 16 /* only child settings changed */
+#define PSYS_RECALC_PHYS 32 /* physics type changed */
/* psys->flag */
#define PSYS_CURRENT 1
//#define PSYS_BAKING 2
//#define PSYS_BAKE_UI 4
-#define PSYS_KEYED_TIME 8
+#define PSYS_KEYED_TIMING 8
#define PSYS_ENABLED 16 /* deprecated */
-#define PSYS_FIRST_KEYED 32
+//#define PSYS_FIRST_KEYED 32
#define PSYS_DRAWING 64
//#define PSYS_SOFT_BAKE 128
#define PSYS_DELETE 256 /* remove particlesystem as soon as possible */
@@ -458,6 +472,10 @@ typedef struct ParticleSystem{ /* note, make sure all (runtime) are NULL's in
#define BOID_GOAL 6
#define BOID_LEVEL 7
+/* psys->keyed_targets->flag */
+#define KEYED_TARGET_CURRENT 1
+#define KEYED_TARGET_VALID 2
+
//#define PSYS_INTER_CUBIC 0
//#define PSYS_INTER_LINEAR 1
diff --git a/source/blender/makesrna/RNA_access.h b/source/blender/makesrna/RNA_access.h
index 3631d83310a..ed1a8052acd 100644
--- a/source/blender/makesrna/RNA_access.h
+++ b/source/blender/makesrna/RNA_access.h
@@ -221,6 +221,7 @@ extern StructRNA RNA_Key;
extern StructRNA RNA_KeyboardSensor;
extern StructRNA RNA_KeyingSet;
extern StructRNA RNA_KeyingSetPath;
+extern StructRNA RNA_KeyedParticleTarget;
extern StructRNA RNA_KinematicConstraint;
extern StructRNA RNA_Lamp;
extern StructRNA RNA_LampSkySettings;
diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c
index 98ed12afd5a..39411752792 100644
--- a/source/blender/makesrna/intern/rna_particle.c
+++ b/source/blender/makesrna/intern/rna_particle.c
@@ -140,6 +140,35 @@ static void rna_Particle_reset(bContext *C, PointerRNA *ptr)
}
}
+static void rna_Particle_keyed_reset(bContext *C, PointerRNA *ptr)
+{
+ Scene *scene = CTX_data_scene(C);
+
+ if(ptr->type==&RNA_KeyedParticleTarget) {
+ Object *ob = (Object*)ptr->id.data;
+ ParticleSystem *psys = psys_get_current(ob);
+
+ psys->recalc = PSYS_RECALC_RESET;
+
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+ DAG_scene_sort(scene);
+ }
+}
+
+static void rna_Particle_keyed_redo(bContext *C, PointerRNA *ptr)
+{
+ Scene *scene = CTX_data_scene(C);
+
+ if(ptr->type==&RNA_KeyedParticleTarget) {
+ Object *ob = (Object*)ptr->id.data;
+ ParticleSystem *psys = psys_get_current(ob);
+
+ psys->recalc = PSYS_RECALC_REDO;
+
+ DAG_object_flush_update(scene, ob, OB_RECALC_DATA);
+ }
+}
+
static void rna_Particle_change_type(bContext *C, PointerRNA *ptr)
{
Scene *scene = CTX_data_scene(C);
@@ -161,6 +190,13 @@ static void rna_Particle_change_type(bContext *C, PointerRNA *ptr)
}
}
+static void rna_Particle_change_physics(bContext *C, PointerRNA *ptr)
+{
+ Scene *scene = CTX_data_scene(C);
+ ParticleSettings *part = ptr->id.data;
+ psys_flush_particle_settings(scene, part, PSYS_RECALC_RESET|PSYS_RECALC_PHYS);
+}
+
static void rna_Particle_redo_child(bContext *C, PointerRNA *ptr)
{
Scene *scene = CTX_data_scene(C);
@@ -299,6 +335,97 @@ static void rna_ParticleSystem_name_get(PointerRNA *ptr, char *str)
strcpy(str, "");
}
+static PointerRNA rna_ParticleSystem_active_keyed_target_get(PointerRNA *ptr)
+{
+ ParticleSystem *psys= (ParticleSystem*)ptr->data;
+ KeyedParticleTarget *kpt = psys->keyed_targets.first;
+
+ for(; kpt; kpt=kpt->next) {
+ if(kpt->flag & KEYED_TARGET_CURRENT)
+ return rna_pointer_inherit_refine(ptr, &RNA_KeyedParticleTarget, kpt);
+ }
+ return rna_pointer_inherit_refine(ptr, &RNA_KeyedParticleTarget, NULL);
+}
+static void rna_ParticleSystem_active_keyed_target_index_range(PointerRNA *ptr, int *min, int *max)
+{
+ ParticleSystem *psys= (ParticleSystem*)ptr->data;
+ *min= 0;
+ *max= BLI_countlist(&psys->keyed_targets)-1;
+ *max= MAX2(0, *max);
+}
+
+static int rna_ParticleSystem_active_keyed_target_index_get(PointerRNA *ptr)
+{
+ ParticleSystem *psys= (ParticleSystem*)ptr->data;
+ KeyedParticleTarget *kpt = psys->keyed_targets.first;
+ int i=0;
+
+ for(; kpt; kpt=kpt->next, i++)
+ if(kpt->flag & KEYED_TARGET_CURRENT)
+ return i;
+
+ return 0;
+}
+
+static void rna_ParticleSystem_active_keyed_target_index_set(struct PointerRNA *ptr, int value)
+{
+ ParticleSystem *psys= (ParticleSystem*)ptr->data;
+ KeyedParticleTarget *kpt = psys->keyed_targets.first;
+ int i=0;
+
+ for(; kpt; kpt=kpt->next, i++) {
+ if(i==value)
+ kpt->flag |= KEYED_TARGET_CURRENT;
+ else
+ kpt->flag &= ~KEYED_TARGET_CURRENT;
+ }
+}
+static int rna_KeyedParticleTarget_name_length(PointerRNA *ptr)
+{
+ KeyedParticleTarget *kpt= ptr->data;
+
+ if(kpt->flag & KEYED_TARGET_VALID) {
+ if(kpt->ob)
+ return strlen(kpt->ob->id.name+2) + 4;
+ else
+ return 20;
+ }
+ else
+ return 15;
+
+ return 0;
+}
+
+static void rna_KeyedParticleTarget_name_get(PointerRNA *ptr, char *str)
+{
+ KeyedParticleTarget *kpt= ptr->data;
+
+ if(kpt->flag & KEYED_TARGET_VALID) {
+ if(kpt->ob)
+ sprintf(str, "%s: %i", kpt->ob->id.name+2, kpt->psys);
+ else
+ sprintf(str, "Particle System: %i", kpt->psys);
+
+ }
+ else
+ strcpy(str, "Invalid target!");
+}
+
+static EnumPropertyItem from_items[] = {
+ {PART_FROM_VERT, "VERT", 0, "Vertexes", ""},
+ {PART_FROM_FACE, "FACE", 0, "Faces", ""},
+ {PART_FROM_VOLUME, "VOLUME", 0, "Volume", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
+static EnumPropertyItem reactor_from_items[] = {
+ {PART_FROM_VERT, "VERT", 0, "Vertexes", ""},
+ {PART_FROM_FACE, "FACE", 0, "Faces", ""},
+ {PART_FROM_VOLUME, "VOLUME", 0, "Volume", ""},
+ {PART_FROM_PARTICLE, "PARTICLE", 0, "Particle", ""},
+ {0, NULL, 0, NULL, NULL}
+};
+
static EnumPropertyItem *rna_Particle_from_itemf(bContext *C, PointerRNA *ptr, int *free)
{
ParticleSettings *part = ptr->id.data;
@@ -660,16 +787,19 @@ static void rna_def_particle_settings(BlenderRNA *brna)
/* flag */
prop= RNA_def_property(srna, "react_start_end", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_REACT_STA_END);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATEABLE);
RNA_def_property_ui_text(prop, "Start/End", "Give birth to unreacted particles eventually.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
prop= RNA_def_property(srna, "react_multiple", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_REACT_MULTIPLE);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATEABLE);
RNA_def_property_ui_text(prop, "Multi React", "React multiple times.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
prop= RNA_def_property(srna, "loop", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_LOOP);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATEABLE);
RNA_def_property_ui_text(prop, "Loop", "Loop particle lives.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
@@ -690,54 +820,46 @@ static void rna_def_particle_settings(BlenderRNA *brna)
prop= RNA_def_property(srna, "trand", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_TRAND);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATEABLE);
RNA_def_property_ui_text(prop, "Random", "Emit in random order of elements");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
prop= RNA_def_property(srna, "even_distribution", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_EDISTR);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATEABLE);
RNA_def_property_ui_text(prop, "Even Distribution", "Use even distribution from faces based on face areas or edge lengths.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
prop= RNA_def_property(srna, "sticky", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_STICKY);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATEABLE);
RNA_def_property_ui_text(prop, "Sticky", "Particles stick to collided objects if they die in the collision.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
prop= RNA_def_property(srna, "die_on_collision", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_DIE_ON_COL);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATEABLE);
RNA_def_property_ui_text(prop, "Die on hit", "Particles die when they collide with a deflector object.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
prop= RNA_def_property(srna, "size_deflect", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_SIZE_DEFL);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATEABLE);
RNA_def_property_ui_text(prop, "Size Deflect", "Use particle's size in deflection.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
prop= RNA_def_property(srna, "rotation_dynamic", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_ROT_DYN);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATEABLE);
RNA_def_property_ui_text(prop, "Dynamic", "Sets rotation to dynamic/constant");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
prop= RNA_def_property(srna, "sizemass", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_SIZEMASS);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATEABLE);
RNA_def_property_ui_text(prop, "Mass from Size", "Multiply mass with particle size.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
- prop= RNA_def_property(srna, "abs_length", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_ABS_LENGTH);
- RNA_def_property_ui_text(prop, "Abs Length", "Use maximum length for children");
- RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo");
-
- //prop= RNA_def_property(srna, "absolute_time", PROP_BOOLEAN, PROP_NONE);
- //RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_ABS_TIME);
- //RNA_def_property_ui_text(prop, "Absolute Time", "Set all ipos that work on particles to be calculated in absolute/relative time.");
- //RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
-
- //prop= RNA_def_property(srna, "global_time", PROP_BOOLEAN, PROP_NONE);
- //RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_GLOB_TIME);
- //RNA_def_property_ui_text(prop, "Global Time", "Set all ipos that work on particles to be calculated in global/object time.");
- //RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
-
prop= RNA_def_property(srna, "boids_2d", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "flag", PART_BOIDS_2D);
RNA_def_property_ui_text(prop, "Boids 2D", "Constrain boids to a surface");
@@ -796,18 +918,21 @@ static void rna_def_particle_settings(BlenderRNA *brna)
prop= RNA_def_property(srna, "type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_items(prop, type_items);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATEABLE);
RNA_def_property_ui_text(prop, "Type", "");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_change_type");
prop= RNA_def_property(srna, "emit_from", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "from");
RNA_def_property_enum_items(prop, part_reactor_from_items);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATEABLE);
RNA_def_property_enum_funcs(prop, NULL, NULL, "rna_Particle_from_itemf");
RNA_def_property_ui_text(prop, "Emit From", "Where to emit particles from");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
prop= RNA_def_property(srna, "distribution", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "distr");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATEABLE);
RNA_def_property_enum_items(prop, dist_items);
RNA_def_property_ui_text(prop, "Distribution", "How to distribute particles on selected element");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
@@ -815,24 +940,28 @@ static void rna_def_particle_settings(BlenderRNA *brna)
/* physics modes */
prop= RNA_def_property(srna, "physics_type", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "phystype");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATEABLE);
RNA_def_property_enum_items(prop, phys_type_items);
RNA_def_property_ui_text(prop, "Physics Type", "Particle physics type");
- RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
+ RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_change_physics");
prop= RNA_def_property(srna, "rotation_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "rotmode");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATEABLE);
RNA_def_property_enum_items(prop, rot_mode_items);
RNA_def_property_ui_text(prop, "Rotation", "Particles initial rotation");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
prop= RNA_def_property(srna, "angular_velocity_mode", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "avemode");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATEABLE);
RNA_def_property_enum_items(prop, ave_mode_items);
RNA_def_property_ui_text(prop, "Angular Velocity Mode", "Particle angular velocity mode.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
prop= RNA_def_property(srna, "react_event", PROP_ENUM, PROP_NONE);
RNA_def_property_enum_sdna(prop, NULL, "reactevent");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATEABLE);
RNA_def_property_enum_items(prop, react_event_items);
RNA_def_property_ui_text(prop, "React On", "The event of target particles to react on.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
@@ -843,11 +972,6 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Velocity", "Show particle velocity");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo");
- //prop= RNA_def_property(srna, "draw_path_length", PROP_BOOLEAN, PROP_NONE);
- //RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_PATH_LEN);
- //RNA_def_property_ui_text(prop, "Path length", "Draw path length");
- //RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo");
-
prop= RNA_def_property(srna, "show_size", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_SIZE);
RNA_def_property_ui_text(prop, "Size", "Show particle size");
@@ -936,7 +1060,7 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_enum_sdna(prop, NULL, "childtype");
RNA_def_property_enum_items(prop, child_type_items);
RNA_def_property_ui_text(prop, "Children From", "Create child particles");
- RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo");
+ RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo_child");
prop= RNA_def_property(srna, "draw_step", PROP_INT, PROP_NONE);
RNA_def_property_range(prop, 0, 7);
@@ -1091,12 +1215,15 @@ static void rna_def_particle_settings(BlenderRNA *brna)
prop= RNA_def_property(srna, "start", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "sta");//optional if prop names are the same
RNA_def_property_range(prop, MINAFRAMEF, MAXFRAMEF);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATEABLE);
RNA_def_property_float_funcs(prop, NULL, "rna_PartSettings_start_set", NULL);
RNA_def_property_ui_text(prop, "Start", "Frame # to start emitting particles.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
prop= RNA_def_property(srna, "end", PROP_FLOAT, PROP_NONE);
RNA_def_property_range(prop, MINAFRAMEF, MAXFRAMEF);
+
+ RNA_def_property_clear_flag(prop, PROP_ANIMATEABLE);
RNA_def_property_float_funcs(prop, NULL, "rna_PartSettings_end_set", NULL);
RNA_def_property_ui_text(prop, "End", "Frame # to stop emitting particles.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
@@ -1119,38 +1246,35 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
prop= RNA_def_property(srna, "jitter_factor", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATEABLE);
RNA_def_property_float_sdna(prop, NULL, "jitfac");
RNA_def_property_range(prop, 0.0f, 2.0f);
RNA_def_property_ui_text(prop, "Amount", "Amount of jitter applied to the sampling.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
- prop= RNA_def_property(srna, "keyed_time", PROP_FLOAT, PROP_NONE);
- RNA_def_property_range(prop, 0.0f, 1.0f);
- RNA_def_property_ui_text(prop, "Time", "Keyed key time relative to remaining particle life.");
- RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
-
prop= RNA_def_property(srna, "effect_hair", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "eff_hair");
RNA_def_property_range(prop, 0.0f, 1.0f);
RNA_def_property_ui_text(prop, "Stiffnes", "Hair stiffness for effectors");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo");
- //float rt; TODO:find where rt is used - can't find it in UI
-
prop= RNA_def_property(srna, "amount", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "totpart");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATEABLE);
RNA_def_property_range(prop, 0, 100000);
RNA_def_property_ui_text(prop, "Amount", "Total number of particles.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
prop= RNA_def_property(srna, "userjit", PROP_INT, PROP_UNSIGNED);//TODO: can we get a better name for userjit?
RNA_def_property_int_sdna(prop, NULL, "userjit");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATEABLE);
RNA_def_property_range(prop, 0, 1000);
RNA_def_property_ui_text(prop, "P/F", "Emission locations / face (0 = automatic).");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
prop= RNA_def_property(srna, "grid_resolution", PROP_INT, PROP_UNSIGNED);
RNA_def_property_int_sdna(prop, NULL, "grid_res");
+ RNA_def_property_clear_flag(prop, PROP_ANIMATEABLE);
RNA_def_property_range(prop, 1, 100);
RNA_def_property_ui_text(prop, "Resolution", "The resolution of the particle grid.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
@@ -1273,19 +1397,7 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Damp", "Specify the amount of damping");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
- /* length */
- //TODO: is this readonly?
- prop= RNA_def_property(srna, "length", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "length");
-// RNA_def_property_range(prop, 0.0f, upperLimitf);//TODO: limits
- RNA_def_property_ui_text(prop, "Length", "");
-
- prop= RNA_def_property(srna, "absolute_length", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "abslength");
- RNA_def_property_range(prop, 0.0f, 10000.0f);
- RNA_def_property_ui_text(prop, "Max Length", "Absolute maximum path length for children, in blender units.");
- RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo");
-
+ /* random length */
prop= RNA_def_property(srna, "random_length", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "randlength");
RNA_def_property_range(prop, 0.0f, 1.0f);
@@ -1334,13 +1446,6 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Child Roundness", "Roundness of children around parent.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo_child");
- //TODO: is this readonly?
- prop= RNA_def_property(srna, "child_spread", PROP_FLOAT, PROP_NONE);
- RNA_def_property_float_sdna(prop, NULL, "childspread");
-// RNA_def_property_range(prop, 0.0f, upperLimitf); TODO: limits
- RNA_def_property_ui_text(prop, "Child Spread", "");
- RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo_child");
-
/* clumping */
prop= RNA_def_property(srna, "clump_factor", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "clumpfac");
@@ -1414,6 +1519,18 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Shape", "Shape of end point rough");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo_child");
+ prop= RNA_def_property(srna, "child_length", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "clength");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Length", "Length of child paths");
+ RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo_child");
+
+ prop= RNA_def_property(srna, "child_length_thres", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "clength_thres");
+ RNA_def_property_range(prop, 0.0f, 1.0f);
+ RNA_def_property_ui_text(prop, "Threshold", "Amount of particles left untouched by child path length.");
+ RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo_child");
+
/* branching */
prop= RNA_def_property(srna, "branch_threshold", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "branch_thres");
@@ -1451,7 +1568,14 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_range(prop, 1.0f, 100.0f);
RNA_def_property_ui_text(prop, "Trail Count", "Number of trail particles.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo");
-
+
+ /* keyed particles */
+ prop= RNA_def_property(srna, "keyed_loops", PROP_INT, PROP_NONE);
+ RNA_def_property_int_sdna(prop, NULL, "keyed_loops");
+ RNA_def_property_range(prop, 1.0f, 100.0f);
+ RNA_def_property_ui_text(prop, "Loop count", "Number of times the keys are looped.");
+ RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo");
+
/* boids */
prop= RNA_def_property(srna, "max_velocity", PROP_FLOAT, PROP_NONE);
RNA_def_property_float_sdna(prop, NULL, "max_vel");
@@ -1494,14 +1618,6 @@ static void rna_def_particle_settings(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Ground Z", "Default Z value");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
- /*TODO: not sure how to deal with this
- prop= RNA_def_property(srna, "boid_factor", PROP_FLOAT, PROP_VECTOR);
- RNA_def_property_float_sdna(prop, NULL, "boidfac");
- RNA_def_property_ui_text(prop, "Boid Factor", "");
-
- //char boidrule[8];
- */
-
prop= RNA_def_property(srna, "dupli_group", PROP_POINTER, PROP_NONE);
RNA_def_property_pointer_sdna(prop, NULL, "dup_group");
RNA_def_property_struct_type(prop, "Group");
@@ -1537,6 +1653,52 @@ static void rna_def_particle_settings(BlenderRNA *brna)
// struct PartDeflect *pd2;
}
+static void rna_def_keyed_particle_target(BlenderRNA *brna)
+{
+ StructRNA *srna;
+ PropertyRNA *prop;
+
+ srna = RNA_def_struct(brna, "KeyedParticleTarget", NULL);
+ RNA_def_struct_ui_text(srna, "Keyed Particle Target", "Target particle system for keyed particles.");
+
+ prop= RNA_def_property(srna, "name", PROP_STRING, PROP_NONE);
+ RNA_def_property_string_funcs(prop, "rna_KeyedParticleTarget_name_get", "rna_KeyedParticleTarget_name_length", NULL);
+ RNA_def_property_ui_text(prop, "Name", "Keyed particle target name.");
+ RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+ RNA_def_struct_name_property(srna, prop);
+
+ prop= RNA_def_property(srna, "object", PROP_POINTER, PROP_NONE);
+ RNA_def_property_pointer_sdna(prop, NULL, "ob");
+ RNA_def_property_flag(prop, PROP_EDITABLE);
+ RNA_def_property_ui_text(prop, "Target Object", "The object that has the target particle system (empty if same object).");
+ RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_keyed_reset");
+
+ prop= RNA_def_property(srna, "system", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_sdna(prop, NULL, "psys");
+ RNA_def_property_range(prop, 1, INT_MAX);
+ RNA_def_property_ui_text(prop, "Target Particle System", "The index of particle system on the target object.");
+ RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_keyed_reset");
+
+ prop= RNA_def_property(srna, "time", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "time");
+ RNA_def_property_range(prop, 0.0, 30000.0f); //TODO: replace 30000 with MAXFRAMEF when available in 2.5
+ RNA_def_property_ui_text(prop, "Time", "");
+ RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_keyed_redo");
+
+ prop= RNA_def_property(srna, "duration", PROP_FLOAT, PROP_NONE);
+ RNA_def_property_float_sdna(prop, NULL, "duration");
+ RNA_def_property_range(prop, 0.0, 30000.0f); //TODO: replace 30000 with MAXFRAMEF when available in 2.5
+ RNA_def_property_ui_text(prop, "Duration", "");
+ RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_keyed_redo");
+
+ prop= RNA_def_property(srna, "valid", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", KEYED_TARGET_VALID);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATEABLE);
+ RNA_def_property_ui_text(prop, "Valid", "Keyed particles target is valid.");
+
+
+
+}
static void rna_def_particle_system(BlenderRNA *brna)
{
StructRNA *srna;
@@ -1604,34 +1766,33 @@ static void rna_def_particle_system(BlenderRNA *brna)
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
/* boids */
- prop= RNA_def_property(srna, "boids_surface_object", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "keyed_ob");
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Boids Surface Object", "For boids physics systems, constrain boids to this object's surface.");
- RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
+ //prop= RNA_def_property(srna, "boids_surface_object", PROP_POINTER, PROP_NONE);
+ //RNA_def_property_pointer_sdna(prop, NULL, "keyed_ob");
+ //RNA_def_property_flag(prop, PROP_EDITABLE);
+ //RNA_def_property_ui_text(prop, "Boids Surface Object", "For boids physics systems, constrain boids to this object's surface.");
+ //RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
/* keyed */
- prop= RNA_def_property(srna, "keyed_object", PROP_POINTER, PROP_NONE);
- RNA_def_property_pointer_sdna(prop, NULL, "keyed_ob");
- RNA_def_property_flag(prop, PROP_EDITABLE);
- RNA_def_property_ui_text(prop, "Keyed Object", "For keyed physics systems, the object that has the target particle system.");
- RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
+ prop= RNA_def_property(srna, "keyed_timing", PROP_BOOLEAN, PROP_NONE);
+ RNA_def_property_boolean_sdna(prop, NULL, "flag", PSYS_KEYED_TIMING);
+ RNA_def_property_clear_flag(prop, PROP_ANIMATEABLE);
+ RNA_def_property_ui_text(prop, "Keyed timing", "Use key times");
+ RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo");
- prop= RNA_def_property(srna, "keyed_particle_system", PROP_INT, PROP_UNSIGNED);
- RNA_def_property_int_sdna(prop, NULL, "keyed_psys");
- RNA_def_property_range(prop, 1, INT_MAX);
- RNA_def_property_ui_text(prop, "Keyed Particle System", "For keyed physics systems, index of particle system on the keyed object.");
- RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
+ prop= RNA_def_property(srna, "keyed_targets", PROP_COLLECTION, PROP_NONE);
+ RNA_def_property_collection_sdna(prop, NULL, "keyed_targets", NULL);
+ RNA_def_property_struct_type(prop, "KeyedParticleTarget");
+ RNA_def_property_ui_text(prop, "Keyed Targets", "Target particle systems for keyed particles");
- prop= RNA_def_property(srna, "keyed_first", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PSYS_FIRST_KEYED);
- RNA_def_property_ui_text(prop, "Keyed First", "Set the system to be the starting point of keyed particles");
- RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
+ prop= RNA_def_property(srna, "active_keyed_target", PROP_POINTER, PROP_NONE);
+ RNA_def_property_struct_type(prop, "KeyedParticleTarget");
+ RNA_def_property_pointer_funcs(prop, "rna_ParticleSystem_active_keyed_target_get", NULL, NULL);
+ RNA_def_property_ui_text(prop, "Active Particle System", "Active particle system being displayed");
+
+ prop= RNA_def_property(srna, "active_keyed_target_index", PROP_INT, PROP_UNSIGNED);
+ RNA_def_property_int_funcs(prop, "rna_ParticleSystem_active_keyed_target_index_get", "rna_ParticleSystem_active_keyed_target_index_set", "rna_ParticleSystem_active_keyed_target_index_range");
+ RNA_def_property_ui_text(prop, "Active Particle System Index", "Index of active particle system slot.");
- prop= RNA_def_property(srna, "keyed_timed", PROP_BOOLEAN, PROP_NONE);
- RNA_def_property_boolean_sdna(prop, NULL, "flag", PSYS_KEYED_TIME);
- RNA_def_property_ui_text(prop, "Keyed Timed", "Use intermediate key times for keyed particles (setting for starting point only).");
- RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_reset");
/* billboard */
prop= RNA_def_property(srna, "billboard_normal_uv", PROP_STRING, PROP_NONE);
@@ -1782,7 +1943,6 @@ static void rna_def_particle_system(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_ui_text(prop, "Parent", "Use this object's coordinate system instead of global coordinate system.");
RNA_def_property_update(prop, NC_OBJECT|ND_PARTICLE, "rna_Particle_redo");
-
}
void RNA_def_particle(BlenderRNA *brna)
@@ -1791,6 +1951,7 @@ void RNA_def_particle(BlenderRNA *brna)
rna_def_particle_key(brna);
rna_def_child_particle(brna);
rna_def_particle(brna);
+ rna_def_keyed_particle_target(brna);
rna_def_particle_system(brna);
rna_def_particle_settings(brna);
}
diff --git a/source/blender/render/intern/source/convertblender.c b/source/blender/render/intern/source/convertblender.c
index 74686511b21..1d6d98bebdf 100644
--- a/source/blender/render/intern/source/convertblender.c
+++ b/source/blender/render/intern/source/convertblender.c
@@ -1513,12 +1513,8 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
return 1;
/* 2. start initialising things */
- if(part->phystype==PART_PHYS_KEYED){
- if(psys->flag & PSYS_FIRST_KEYED)
- psys_count_keyed_targets(ob,psys);
- else
- return 1;
- }
+ if(part->phystype==PART_PHYS_KEYED)
+ psys_count_keyed_targets(ob,psys);
/* last possibility to bail out! */
psmd= psys_get_modifier(ob,psys);
@@ -1606,10 +1602,10 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
calc_ipo(part->ipo, cfra);
execute_ipo((ID *)part, part->ipo);
}
-#endif // XXX old animation system
if(part->flag & PART_GLOB_TIME)
- cfra = bsystem_time(re->scene, 0, (float)re->scene->r.cfra, 0.0);
+#endif // XXX old animation system
+ cfra = bsystem_time(re->scene, 0, (float)re->scene->r.cfra, 0.0);
/* 2.4 setup reactors */
if(part->type == PART_REACTOR){
@@ -1707,8 +1703,8 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
pa_time=(cfra-pa->time)/pa->lifetime;
pa_birthtime = pa->time;
pa_dietime = pa->dietime;
- if((part->flag&PART_ABS_TIME) == 0){
#if 0 // XXX old animation system
+ if((part->flag&PART_ABS_TIME) == 0){
if(ma->ipo) {
/* correction for lifetime */
calc_ipo(ma->ipo, 100.0f * pa_time);
@@ -1719,8 +1715,8 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
calc_ipo(part->ipo, 100.0f*pa_time);
execute_ipo((ID *)part, part->ipo);
}
-#endif // XXX old animation system
}
+#endif // XXX old animation system
hasize = ma->hasize;
@@ -1767,8 +1763,8 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
pa_time = psys_get_child_time(psys, cpa, cfra, &pa_birthtime, &pa_dietime);
- if((part->flag & PART_ABS_TIME) == 0) {
#if 0 // XXX old animation system
+ if((part->flag & PART_ABS_TIME) == 0) {
if(ma->ipo){
/* correction for lifetime */
calc_ipo(ma->ipo, 100.0f * pa_time);
@@ -1779,8 +1775,8 @@ static int render_new_particle_system(Render *re, ObjectRen *obr, ParticleSystem
calc_ipo(part->ipo, 100.0f * pa_time);
execute_ipo((ID *)part, part->ipo);
}
-#endif // XXX old animation system
}
+#endif // XXX old animation system
pa_size = psys_get_child_size(psys, cpa, cfra, &pa_time);