diff options
Diffstat (limited to 'source/blender/blenkernel/intern/particle.c')
-rw-r--r-- | source/blender/blenkernel/intern/particle.c | 548 |
1 files changed, 504 insertions, 44 deletions
diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 7b8ee7343ee..0b331fb88d2 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -21,6 +21,9 @@ * \ingroup bke */ +/* Allow using deprecated functionality for .blend file I/O. */ +#define DNA_DEPRECATED_ALLOW + #include <math.h> #include <stdlib.h> #include <string.h> @@ -29,6 +32,7 @@ #include "DNA_defaults.h" +#include "DNA_cloth_types.h" #include "DNA_collection_types.h" #include "DNA_curve_types.h" #include "DNA_dynamicpaint_types.h" @@ -52,6 +56,7 @@ #include "BLT_translation.h" +#include "BKE_anim_data.h" #include "BKE_anim_path.h" #include "BKE_boids.h" #include "BKE_cloth.h" @@ -78,7 +83,9 @@ #include "DEG_depsgraph_build.h" #include "DEG_depsgraph_query.h" -#include "RE_render_ext.h" +#include "RE_texture.h" + +#include "BLO_read_write.h" #include "particle_private.h" @@ -206,6 +213,279 @@ static void particle_settings_foreach_id(ID *id, LibraryForeachIDData *data) } } +static void write_boid_state(BlendWriter *writer, BoidState *state) +{ + BLO_write_struct(writer, BoidState, state); + + LISTBASE_FOREACH (BoidRule *, rule, &state->rules) { + switch (rule->type) { + case eBoidRuleType_Goal: + case eBoidRuleType_Avoid: + BLO_write_struct(writer, BoidRuleGoalAvoid, rule); + break; + case eBoidRuleType_AvoidCollision: + BLO_write_struct(writer, BoidRuleAvoidCollision, rule); + break; + case eBoidRuleType_FollowLeader: + BLO_write_struct(writer, BoidRuleFollowLeader, rule); + break; + case eBoidRuleType_AverageSpeed: + BLO_write_struct(writer, BoidRuleAverageSpeed, rule); + break; + case eBoidRuleType_Fight: + BLO_write_struct(writer, BoidRuleFight, rule); + break; + default: + BLO_write_struct(writer, BoidRule, rule); + break; + } + } +#if 0 + BoidCondition *cond = state->conditions.first; + for (; cond; cond = cond->next) { + BLO_write_struct(writer, BoidCondition, cond); + } +#endif +} + +static void particle_settings_blend_write(BlendWriter *writer, ID *id, const void *id_address) +{ + ParticleSettings *part = (ParticleSettings *)id; + if (part->id.us > 0 || BLO_write_is_undo(writer)) { + /* write LibData */ + BLO_write_id_struct(writer, ParticleSettings, id_address, &part->id); + BKE_id_blend_write(writer, &part->id); + + if (part->adt) { + BKE_animdata_blend_write(writer, part->adt); + } + BLO_write_struct(writer, PartDeflect, part->pd); + BLO_write_struct(writer, PartDeflect, part->pd2); + BLO_write_struct(writer, EffectorWeights, part->effector_weights); + + if (part->clumpcurve) { + BKE_curvemapping_blend_write(writer, part->clumpcurve); + } + if (part->roughcurve) { + BKE_curvemapping_blend_write(writer, part->roughcurve); + } + if (part->twistcurve) { + BKE_curvemapping_blend_write(writer, part->twistcurve); + } + + LISTBASE_FOREACH (ParticleDupliWeight *, dw, &part->instance_weights) { + /* update indices, but only if dw->ob is set (can be NULL after loading e.g.) */ + if (dw->ob != NULL) { + dw->index = 0; + if (part->instance_collection) { /* can be NULL if lining fails or set to None */ + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (part->instance_collection, object) { + if (object == dw->ob) { + break; + } + dw->index++; + } + FOREACH_COLLECTION_OBJECT_RECURSIVE_END; + } + } + BLO_write_struct(writer, ParticleDupliWeight, dw); + } + + if (part->boids && part->phystype == PART_PHYS_BOIDS) { + BLO_write_struct(writer, BoidSettings, part->boids); + + LISTBASE_FOREACH (BoidState *, state, &part->boids->states) { + write_boid_state(writer, state); + } + } + if (part->fluid && part->phystype == PART_PHYS_FLUID) { + BLO_write_struct(writer, SPHFluidSettings, part->fluid); + } + + for (int a = 0; a < MAX_MTEX; a++) { + if (part->mtex[a]) { + BLO_write_struct(writer, MTex, part->mtex[a]); + } + } + } +} + +void BKE_particle_partdeflect_blend_read_data(BlendDataReader *UNUSED(reader), PartDeflect *pd) +{ + if (pd) { + pd->rng = NULL; + } +} + +static void particle_settings_blend_read_data(BlendDataReader *reader, ID *id) +{ + ParticleSettings *part = (ParticleSettings *)id; + BLO_read_data_address(reader, &part->adt); + BLO_read_data_address(reader, &part->pd); + BLO_read_data_address(reader, &part->pd2); + + BKE_animdata_blend_read_data(reader, part->adt); + BKE_particle_partdeflect_blend_read_data(reader, part->pd); + BKE_particle_partdeflect_blend_read_data(reader, part->pd2); + + BLO_read_data_address(reader, &part->clumpcurve); + if (part->clumpcurve) { + BKE_curvemapping_blend_read(reader, part->clumpcurve); + } + BLO_read_data_address(reader, &part->roughcurve); + if (part->roughcurve) { + BKE_curvemapping_blend_read(reader, part->roughcurve); + } + BLO_read_data_address(reader, &part->twistcurve); + if (part->twistcurve) { + BKE_curvemapping_blend_read(reader, part->twistcurve); + } + + BLO_read_data_address(reader, &part->effector_weights); + if (!part->effector_weights) { + part->effector_weights = BKE_effector_add_weights(part->force_group); + } + + BLO_read_list(reader, &part->instance_weights); + + BLO_read_data_address(reader, &part->boids); + BLO_read_data_address(reader, &part->fluid); + + if (part->boids) { + BLO_read_list(reader, &part->boids->states); + + LISTBASE_FOREACH (BoidState *, state, &part->boids->states) { + BLO_read_list(reader, &state->rules); + BLO_read_list(reader, &state->conditions); + BLO_read_list(reader, &state->actions); + } + } + for (int a = 0; a < MAX_MTEX; a++) { + BLO_read_data_address(reader, &part->mtex[a]); + } + + /* Protect against integer overflow vulnerability. */ + CLAMP(part->trail_count, 1, 100000); +} + +void BKE_particle_partdeflect_blend_read_lib(BlendLibReader *reader, ID *id, PartDeflect *pd) +{ + if (pd && pd->tex) { + BLO_read_id_address(reader, id->lib, &pd->tex); + } + if (pd && pd->f_source) { + BLO_read_id_address(reader, id->lib, &pd->f_source); + } +} + +static void particle_settings_blend_read_lib(BlendLibReader *reader, ID *id) +{ + ParticleSettings *part = (ParticleSettings *)id; + BLO_read_id_address( + reader, part->id.lib, &part->ipo); /* XXX deprecated - old animation system */ + + BLO_read_id_address(reader, part->id.lib, &part->instance_object); + BLO_read_id_address(reader, part->id.lib, &part->instance_collection); + BLO_read_id_address(reader, part->id.lib, &part->force_group); + BLO_read_id_address(reader, part->id.lib, &part->bb_ob); + BLO_read_id_address(reader, part->id.lib, &part->collision_group); + + BKE_particle_partdeflect_blend_read_lib(reader, &part->id, part->pd); + BKE_particle_partdeflect_blend_read_lib(reader, &part->id, part->pd2); + + if (part->effector_weights) { + BLO_read_id_address(reader, part->id.lib, &part->effector_weights->group); + } + else { + part->effector_weights = BKE_effector_add_weights(part->force_group); + } + + if (part->instance_weights.first && part->instance_collection) { + LISTBASE_FOREACH (ParticleDupliWeight *, dw, &part->instance_weights) { + BLO_read_id_address(reader, part->id.lib, &dw->ob); + } + } + else { + BLI_listbase_clear(&part->instance_weights); + } + + if (part->boids) { + LISTBASE_FOREACH (BoidState *, state, &part->boids->states) { + LISTBASE_FOREACH (BoidRule *, rule, &state->rules) { + switch (rule->type) { + case eBoidRuleType_Goal: + case eBoidRuleType_Avoid: { + BoidRuleGoalAvoid *brga = (BoidRuleGoalAvoid *)rule; + BLO_read_id_address(reader, part->id.lib, &brga->ob); + break; + } + case eBoidRuleType_FollowLeader: { + BoidRuleFollowLeader *brfl = (BoidRuleFollowLeader *)rule; + BLO_read_id_address(reader, part->id.lib, &brfl->ob); + break; + } + } + } + } + } + + for (int a = 0; a < MAX_MTEX; a++) { + MTex *mtex = part->mtex[a]; + if (mtex) { + BLO_read_id_address(reader, part->id.lib, &mtex->tex); + BLO_read_id_address(reader, part->id.lib, &mtex->object); + } + } +} + +static void particle_settings_blend_read_expand(BlendExpander *expander, ID *id) +{ + ParticleSettings *part = (ParticleSettings *)id; + BLO_expand(expander, part->instance_object); + BLO_expand(expander, part->instance_collection); + BLO_expand(expander, part->force_group); + BLO_expand(expander, part->bb_ob); + BLO_expand(expander, part->collision_group); + + for (int a = 0; a < MAX_MTEX; a++) { + if (part->mtex[a]) { + BLO_expand(expander, part->mtex[a]->tex); + BLO_expand(expander, part->mtex[a]->object); + } + } + + if (part->effector_weights) { + BLO_expand(expander, part->effector_weights->group); + } + + if (part->pd) { + BLO_expand(expander, part->pd->tex); + BLO_expand(expander, part->pd->f_source); + } + if (part->pd2) { + BLO_expand(expander, part->pd2->tex); + BLO_expand(expander, part->pd2->f_source); + } + + if (part->boids) { + LISTBASE_FOREACH (BoidState *, state, &part->boids->states) { + LISTBASE_FOREACH (BoidRule *, rule, &state->rules) { + if (rule->type == eBoidRuleType_Avoid) { + BoidRuleGoalAvoid *gabr = (BoidRuleGoalAvoid *)rule; + BLO_expand(expander, gabr->ob); + } + else if (rule->type == eBoidRuleType_FollowLeader) { + BoidRuleFollowLeader *flbr = (BoidRuleFollowLeader *)rule; + BLO_expand(expander, flbr->ob); + } + } + } + } + + LISTBASE_FOREACH (ParticleDupliWeight *, dw, &part->instance_weights) { + BLO_expand(expander, dw->ob); + } +} + IDTypeInfo IDType_ID_PA = { .id_code = ID_PA, .id_filter = FILTER_ID_PA, @@ -223,17 +503,19 @@ IDTypeInfo IDType_ID_PA = { .foreach_id = particle_settings_foreach_id, .foreach_cache = NULL, - .blend_write = NULL, - .blend_read_data = NULL, - .blend_read_lib = NULL, - .blend_read_expand = NULL, + .blend_write = particle_settings_blend_write, + .blend_read_data = particle_settings_blend_read_data, + .blend_read_lib = particle_settings_blend_read_lib, + .blend_read_expand = particle_settings_blend_read_expand, + + .blend_read_undo_preserve = NULL, }; unsigned int PSYS_FRAND_SEED_OFFSET[PSYS_FRAND_COUNT]; unsigned int PSYS_FRAND_SEED_MULTIPLIER[PSYS_FRAND_COUNT]; float PSYS_FRAND_BASE[PSYS_FRAND_COUNT]; -void psys_init_rng(void) +void BKE_particle_init_rng(void) { RNG *rng = BLI_rng_new_srandom(5831); /* arbitrary */ for (int i = 0; i < PSYS_FRAND_COUNT; i++) { @@ -917,7 +1199,7 @@ static float interpolate_particle_value( value += w[3] * v4; } - CLAMP(value, 0.f, 1.f); + CLAMP(value, 0.0f, 1.0f); return value; } @@ -1146,7 +1428,7 @@ static void do_particle_interpolation(ParticleSystem *psys, PTCacheEditPoint *point = pind->epoint; ParticleKey keys[4]; int point_vel = (point && point->keys->vel); - float real_t, dfra, keytime, invdt = 1.f; + float real_t, dfra, keytime, invdt = 1.0f; /* billboards wont fill in all of these, so start cleared */ memset(keys, 0, sizeof(keys)); @@ -1316,7 +1598,7 @@ static void do_particle_interpolation(ParticleSystem *psys, /* Convert velocity to time-step size. */ if (pind->keyed || pind->cache || point_vel) { - invdt = dfra * 0.04f * (psys ? psys->part->timetweak : 1.f); + invdt = dfra * 0.04f * (psys ? psys->part->timetweak : 1.0f); mul_v3_fl(keys[1].vel, invdt); mul_v3_fl(keys[2].vel, invdt); interp_qt_qtqt(result->rot, keys[1].rot, keys[2].rot, keytime); @@ -1335,7 +1617,7 @@ static void do_particle_interpolation(ParticleSystem *psys, /* the velocity needs to be converted back from cubic interpolation */ if (pind->keyed || pind->cache || point_vel) { - mul_v3_fl(result->vel, 1.f / invdt); + mul_v3_fl(result->vel, 1.0f / invdt); } } @@ -2200,7 +2482,7 @@ int do_guides(Depsgraph *depsgraph, pd->kink_freq, pd->kink_shape, pd->kink_amp, - 0.f, + 0.0f, pd->kink, pd->kink_axis, 0, @@ -2550,12 +2832,12 @@ static void psys_thread_create_path(ParticleTask *task, if (ctx->between) { ParticleData *pa = psys->particles + cpa->pa[0]; int w, needupdate; - float foffset, wsum = 0.f; + float foffset, wsum = 0.0f; float co[3]; float p_min = part->parting_min; float p_max = part->parting_max; /* Virtual parents don't work nicely with parting. */ - float p_fac = part->parents > 0.f ? 0.f : part->parting_fac; + float p_fac = part->parents > 0.0f ? 0.0f : part->parting_fac; if (ctx->editupdate) { needupdate = 0; @@ -2583,15 +2865,15 @@ static void psys_thread_create_path(ParticleTask *task, } else { key[w] = pcache[0]; - weight[w] = 0.f; + weight[w] = 0.0f; } } /* modify weights to create parting */ - if (p_fac > 0.f) { + if (p_fac > 0.0f) { const ParticleCacheKey *key_0_last = pcache_key_segment_endpoint_safe(key[0]); for (w = 0; w < 4; w++) { - if (w && (weight[w] > 0.f)) { + if (w && (weight[w] > 0.0f)) { const ParticleCacheKey *key_w_last = pcache_key_segment_endpoint_safe(key[w]); float d; if (part->flag & PART_CHILD_LONG_HAIR) { @@ -2600,7 +2882,7 @@ static void psys_thread_create_path(ParticleTask *task, float d1 = len_v3v3(key[0]->co, key[w]->co); float d2 = len_v3v3(key_0_last->co, key_w_last->co); - d = d1 > 0.f ? d2 / d1 - 1.f : 10000.f; + d = d1 > 0.0f ? d2 / d1 - 1.0f : 10000.0f; } else { float v1[3], v2[3]; @@ -2616,13 +2898,13 @@ static void psys_thread_create_path(ParticleTask *task, d = (d - p_min) / (p_max - p_min); } else { - d = (d - p_min) <= 0.f ? 0.f : 1.f; + d = (d - p_min) <= 0.0f ? 0.0f : 1.0f; } - CLAMP(d, 0.f, 1.f); + CLAMP(d, 0.0f, 1.0f); - if (d > 0.f) { - weight[w] *= (1.f - d); + if (d > 0.0f) { + weight[w] *= (1.0f - d); } } wsum += weight[w]; @@ -3059,7 +3341,7 @@ void psys_cache_paths(ParticleSimulationData *sim, float cfra, const bool use_re LOOP_PARTICLES { if (!psys->totchild) { - psys_get_texture(sim, pa, &ptex, PAMAP_LENGTH, 0.f); + psys_get_texture(sim, pa, &ptex, PAMAP_LENGTH, 0.0f); pa_length = ptex.length * (1.0f - part->randlength * psys_frand(psys, psys->seed + p)); if (vg_length) { pa_length *= psys_particle_value_from_verts(psmd->mesh_final, part->from, pa, vg_length); @@ -3716,19 +3998,25 @@ void object_remove_particle_system(Main *bmain, Scene *UNUSED(scene), Object *ob if (psys->part->type == PART_FLUID_FLIP) { fmd->domain->particle_type &= ~FLUID_DOMAIN_PARTICLE_FLIP; } - if (psys->part->type == PART_FLUID_SPRAY || psys->part->type == PART_FLUID_SPRAYFOAM || - psys->part->type == PART_FLUID_SPRAYBUBBLE || - psys->part->type == PART_FLUID_SPRAYFOAMBUBBLE) { + if (ELEM(psys->part->type, + PART_FLUID_SPRAY, + PART_FLUID_SPRAYFOAM, + PART_FLUID_SPRAYBUBBLE, + PART_FLUID_SPRAYFOAMBUBBLE)) { fmd->domain->particle_type &= ~FLUID_DOMAIN_PARTICLE_SPRAY; } - if (psys->part->type == PART_FLUID_FOAM || psys->part->type == PART_FLUID_SPRAYFOAM || - psys->part->type == PART_FLUID_FOAMBUBBLE || - psys->part->type == PART_FLUID_SPRAYFOAMBUBBLE) { + if (ELEM(psys->part->type, + PART_FLUID_FOAM, + PART_FLUID_SPRAYFOAM, + PART_FLUID_FOAMBUBBLE, + PART_FLUID_SPRAYFOAMBUBBLE)) { fmd->domain->particle_type &= ~FLUID_DOMAIN_PARTICLE_FOAM; } - if (psys->part->type == PART_FLUID_BUBBLE || psys->part->type == PART_FLUID_FOAMBUBBLE || - psys->part->type == PART_FLUID_SPRAYBUBBLE || - psys->part->type == PART_FLUID_SPRAYFOAMBUBBLE) { + if (ELEM(psys->part->type, + PART_FLUID_BUBBLE, + PART_FLUID_FOAMBUBBLE, + PART_FLUID_SPRAYBUBBLE, + PART_FLUID_SPRAYFOAMBUBBLE)) { fmd->domain->particle_type &= ~FLUID_DOMAIN_PARTICLE_BUBBLE; } if (psys->part->type == PART_FLUID_TRACER) { @@ -3736,9 +4024,11 @@ void object_remove_particle_system(Main *bmain, Scene *UNUSED(scene), Object *ob } /* Disable combined export if combined particle system was deleted. */ - if (psys->part->type == PART_FLUID_SPRAYFOAM || psys->part->type == PART_FLUID_SPRAYBUBBLE || - psys->part->type == PART_FLUID_FOAMBUBBLE || - psys->part->type == PART_FLUID_SPRAYFOAMBUBBLE) { + if (ELEM(psys->part->type, + PART_FLUID_SPRAYFOAM, + PART_FLUID_SPRAYBUBBLE, + PART_FLUID_FOAMBUBBLE, + PART_FLUID_SPRAYFOAMBUBBLE)) { fmd->domain->sndparticle_combined_export = SNDPARTICLE_COMBINED_EXPORT_OFF; } } @@ -3992,9 +4282,9 @@ static void get_cpa_texture(Mesh *mesh, break; case TEXCO_PARTICLE: /* texture coordinates in range [-1, 1] */ - texvec[0] = 2.f * (cfra - par->time) / (par->dietime - par->time) - 1.f; - texvec[1] = 0.f; - texvec[2] = 0.f; + texvec[0] = 2.0f * (cfra - par->time) / (par->dietime - par->time) - 1.0f; + texvec[1] = 0.0f; + texvec[2] = 0.0f; break; } @@ -4102,14 +4392,15 @@ void psys_get_texture( break; case TEXCO_PARTICLE: /* texture coordinates in range [-1, 1] */ - texvec[0] = 2.f * (cfra - pa->time) / (pa->dietime - pa->time) - 1.f; + texvec[0] = 2.0f * (cfra - pa->time) / (pa->dietime - pa->time) - 1.0f; if (sim->psys->totpart > 0) { - texvec[1] = 2.f * (float)(pa - sim->psys->particles) / (float)sim->psys->totpart - 1.f; + texvec[1] = 2.0f * (float)(pa - sim->psys->particles) / (float)sim->psys->totpart - + 1.0f; } else { texvec[1] = 0.0f; } - texvec[2] = 0.f; + texvec[2] = 0.0f; break; } @@ -4654,8 +4945,8 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta else { float dfra, frs_sec = sim->scene->r.frs_sec; /* let's interpolate to try to be as accurate as possible */ - if (pa->state.time + 2.f >= state->time && pa->prev_state.time - 2.f <= state->time) { - if (pa->prev_state.time >= pa->state.time || pa->prev_state.time < 0.f) { + if (pa->state.time + 2.0f >= state->time && pa->prev_state.time - 2.0f <= state->time) { + if (pa->prev_state.time >= pa->state.time || pa->prev_state.time < 0.0f) { /* prev_state is wrong so let's not use it, * this can happen at frames 1, 0 or particle birth. */ dfra = state->time - pa->state.time; @@ -4682,13 +4973,13 @@ int psys_get_particle_state(ParticleSimulationData *sim, int p, ParticleKey *sta psys_interpolate_particle(-1, keys, keytime, state, 1); /* convert back to real velocity */ - mul_v3_fl(state->vel, 1.f / (dfra * timestep)); + mul_v3_fl(state->vel, 1.0f / (dfra * timestep)); interp_v3_v3v3(state->ave, keys[1].ave, keys[2].ave, keytime); interp_qt_qtqt(state->rot, keys[1].rot, keys[2].rot, keytime); } } - else if (pa->state.time + 1.f >= state->time && pa->state.time - 1.f <= state->time) { + else if (pa->state.time + 1.0f >= state->time && pa->state.time - 1.0f <= state->time) { /* linear interpolation using only pa->state */ dfra = state->time - pa->state.time; @@ -4949,3 +5240,172 @@ void BKE_particle_batch_cache_free(ParticleSystem *psys) BKE_particle_batch_cache_free_cb(psys); } } + +void BKE_particle_system_blend_write(BlendWriter *writer, ListBase *particles) +{ + LISTBASE_FOREACH (ParticleSystem *, psys, particles) { + BLO_write_struct(writer, ParticleSystem, psys); + + if (psys->particles) { + BLO_write_struct_array(writer, ParticleData, psys->totpart, psys->particles); + + if (psys->particles->hair) { + ParticleData *pa = psys->particles; + + for (int a = 0; a < psys->totpart; a++, pa++) { + BLO_write_struct_array(writer, HairKey, pa->totkey, pa->hair); + } + } + + if (psys->particles->boid && (psys->part->phystype == PART_PHYS_BOIDS)) { + BLO_write_struct_array(writer, BoidParticle, psys->totpart, psys->particles->boid); + } + + if (psys->part->fluid && (psys->part->phystype == PART_PHYS_FLUID) && + (psys->part->fluid->flag & SPH_VISCOELASTIC_SPRINGS)) { + BLO_write_struct_array( + writer, ParticleSpring, psys->tot_fluidsprings, psys->fluid_springs); + } + } + LISTBASE_FOREACH (ParticleTarget *, pt, &psys->targets) { + BLO_write_struct(writer, ParticleTarget, pt); + } + + if (psys->child) { + BLO_write_struct_array(writer, ChildParticle, psys->totchild, psys->child); + } + + if (psys->clmd) { + BLO_write_struct(writer, ClothModifierData, psys->clmd); + BLO_write_struct(writer, ClothSimSettings, psys->clmd->sim_parms); + BLO_write_struct(writer, ClothCollSettings, psys->clmd->coll_parms); + } + + BKE_ptcache_blend_write(writer, &psys->ptcaches); + } +} + +void BKE_particle_system_blend_read_data(BlendDataReader *reader, ListBase *particles) +{ + ParticleData *pa; + int a; + + LISTBASE_FOREACH (ParticleSystem *, psys, particles) { + BLO_read_data_address(reader, &psys->particles); + + if (psys->particles && psys->particles->hair) { + for (a = 0, pa = psys->particles; a < psys->totpart; a++, pa++) { + BLO_read_data_address(reader, &pa->hair); + } + } + + if (psys->particles && psys->particles->keys) { + for (a = 0, pa = psys->particles; a < psys->totpart; a++, pa++) { + pa->keys = NULL; + pa->totkey = 0; + } + + psys->flag &= ~PSYS_KEYED; + } + + if (psys->particles && psys->particles->boid) { + pa = psys->particles; + BLO_read_data_address(reader, &pa->boid); + + /* This is purely runtime data, but still can be an issue if left dangling. */ + pa->boid->ground = NULL; + + for (a = 1, pa++; a < psys->totpart; a++, pa++) { + pa->boid = (pa - 1)->boid + 1; + pa->boid->ground = NULL; + } + } + else if (psys->particles) { + for (a = 0, pa = psys->particles; a < psys->totpart; a++, pa++) { + pa->boid = NULL; + } + } + + BLO_read_data_address(reader, &psys->fluid_springs); + + BLO_read_data_address(reader, &psys->child); + psys->effectors = NULL; + + BLO_read_list(reader, &psys->targets); + + psys->edit = NULL; + psys->free_edit = NULL; + psys->pathcache = NULL; + psys->childcache = NULL; + BLI_listbase_clear(&psys->pathcachebufs); + BLI_listbase_clear(&psys->childcachebufs); + psys->pdd = NULL; + + if (psys->clmd) { + BLO_read_data_address(reader, &psys->clmd); + psys->clmd->clothObject = NULL; + psys->clmd->hairdata = NULL; + + BLO_read_data_address(reader, &psys->clmd->sim_parms); + BLO_read_data_address(reader, &psys->clmd->coll_parms); + + if (psys->clmd->sim_parms) { + psys->clmd->sim_parms->effector_weights = NULL; + if (psys->clmd->sim_parms->presets > 10) { + psys->clmd->sim_parms->presets = 0; + } + } + + psys->hair_in_mesh = psys->hair_out_mesh = NULL; + psys->clmd->solver_result = NULL; + } + + BKE_ptcache_blend_read_data(reader, &psys->ptcaches, &psys->pointcache, 0); + if (psys->clmd) { + psys->clmd->point_cache = psys->pointcache; + } + + psys->tree = NULL; + psys->bvhtree = NULL; + + psys->orig_psys = NULL; + psys->batch_cache = NULL; + } +} + +void BKE_particle_system_blend_read_lib(BlendLibReader *reader, + Object *ob, + ID *id, + ListBase *particles) +{ + LISTBASE_FOREACH_MUTABLE (ParticleSystem *, psys, particles) { + + BLO_read_id_address(reader, id->lib, &psys->part); + if (psys->part) { + LISTBASE_FOREACH (ParticleTarget *, pt, &psys->targets) { + BLO_read_id_address(reader, id->lib, &pt->ob); + } + + BLO_read_id_address(reader, id->lib, &psys->parent); + BLO_read_id_address(reader, id->lib, &psys->target_ob); + + if (psys->clmd) { + /* XXX - from reading existing code this seems correct but intended usage of + * pointcache /w cloth should be added in 'ParticleSystem' - campbell */ + psys->clmd->point_cache = psys->pointcache; + psys->clmd->ptcaches.first = psys->clmd->ptcaches.last = NULL; + BLO_read_id_address(reader, id->lib, &psys->clmd->coll_parms->group); + psys->clmd->modifier.error = NULL; + } + } + else { + /* particle modifier must be removed before particle system */ + ParticleSystemModifierData *psmd = psys_get_modifier(ob, psys); + BLI_remlink(&ob->modifiers, psmd); + BKE_modifier_free((ModifierData *)psmd); + + BLI_remlink(particles, psys); + MEM_freeN(psys); + } + } +} |