diff options
author | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2018-06-28 15:29:54 +0300 |
---|---|---|
committer | Brecht Van Lommel <brechtvanlommel@gmail.com> | 2018-06-29 15:53:02 +0300 |
commit | a59df21ad8282c20f33a216ba9e3ba739881577d (patch) | |
tree | a38ea5e89859a27068051f6920129e6add62b384 /source/blender/blenkernel | |
parent | ece72c9ec0c706f137ba0bc80af732786ca9990f (diff) |
Fix T55645: broken particle Use Count option for instancing objects.
There is now a manual refresh button on the panel to update the list
of objects in case it changes, and it also gets refreshed when changing
the collection or toggling the use count option.
This is a bit more manual but the previous code of refreshing the
list while evaluating the depsgraph was unreliable.
This also fixes it to take properly take into account visibility, and
to work with linked collections for which index writing was missing.
Diffstat (limited to 'source/blender/blenkernel')
-rw-r--r-- | source/blender/blenkernel/BKE_particle.h | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/library_query.c | 4 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/object_dupli.c | 43 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/particle.c | 107 |
4 files changed, 92 insertions, 63 deletions
diff --git a/source/blender/blenkernel/BKE_particle.h b/source/blender/blenkernel/BKE_particle.h index 11aa67d7f25..4a5be9f0f70 100644 --- a/source/blender/blenkernel/BKE_particle.h +++ b/source/blender/blenkernel/BKE_particle.h @@ -309,6 +309,7 @@ bool psys_in_edit_mode(struct Depsgraph *depsgraph, struct ParticleSystem *psys) bool psys_check_enabled(struct Object *ob, struct ParticleSystem *psys, const bool use_render_params); bool psys_check_edited(struct ParticleSystem *psys); +void psys_find_group_weights(struct ParticleSettings *part); void psys_check_group_weights(struct ParticleSettings *part); int psys_uses_gravity(struct ParticleSimulationData *sim); void BKE_particlesettings_fluid_default_settings(struct ParticleSettings *part); diff --git a/source/blender/blenkernel/intern/library_query.c b/source/blender/blenkernel/intern/library_query.c index f23d8720a65..54b73dad982 100644 --- a/source/blender/blenkernel/intern/library_query.c +++ b/source/blender/blenkernel/intern/library_query.c @@ -807,6 +807,10 @@ void BKE_library_foreach_ID_link(Main *bmain, ID *id, LibraryIDLinkCallback call } } } + + for (ParticleDupliWeight *dw = psett->dupliweights.first; dw; dw = dw->next) { + CALLBACK_INVOKE(dw->ob, IDWALK_CB_NOP); + } break; } diff --git a/source/blender/blenkernel/intern/object_dupli.c b/source/blender/blenkernel/intern/object_dupli.c index 33b65dbe4a3..e288adaf9ad 100644 --- a/source/blender/blenkernel/intern/object_dupli.c +++ b/source/blender/blenkernel/intern/object_dupli.c @@ -836,7 +836,7 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem float tmat[4][4], mat[4][4], pamat[4][4], vec[3], size = 0.0; float (*obmat)[4]; int a, b, hair = 0; - int totpart, totchild, totcollection = 0 /*, pa_num */; + int totpart, totchild; int no_draw_flag = PARS_UNEXIST; @@ -899,15 +899,26 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem } RNG *rng = BLI_rng_new_srandom(31415926u + (unsigned int)psys->seed); - psys_check_group_weights(part); psys->lattice_deform_data = psys_create_lattice_deform_data(&sim); /* gather list of objects or single object */ + int totcollection = 0; + if (part->ren_as == PART_DRAW_GR) { if (part->draw & PART_DRAW_COUNT_GR) { - for (dw = part->dupliweights.first; dw; dw = dw->next) - totcollection += dw->count; + psys_find_group_weights(part); + + for (dw = part->dupliweights.first; dw; dw = dw->next) { + FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN(part->dup_group, object, mode) + { + if (dw->ob == object) { + totcollection += dw->count; + break; + } + } + FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_END; + } } else { FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN(part->dup_group, object, mode) @@ -923,14 +934,20 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem oblist = MEM_callocN((size_t)totcollection * sizeof(Object *), "dupcollection object list"); obcopylist = MEM_callocN((size_t)totcollection * sizeof(Object), "dupcollection copy list"); - if (part->draw & PART_DRAW_COUNT_GR && totcollection) { - dw = part->dupliweights.first; - - for (a = 0; a < totcollection; dw = dw->next) { - for (b = 0; b < dw->count; b++, a++) { - oblist[a] = dw->ob; - obcopylist[a] = *dw->ob; + if (part->draw & PART_DRAW_COUNT_GR) { + a = 0; + for (dw = part->dupliweights.first; dw; dw = dw->next) { + FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN(part->dup_group, object, mode) + { + if (dw->ob == object) { + for (b = 0; b < dw->count; b++, a++) { + oblist[a] = dw->ob; + obcopylist[a] = *dw->ob; + } + break; + } } + FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_END; } } else { @@ -940,10 +957,6 @@ static void make_duplis_particle_system(const DupliContext *ctx, ParticleSystem oblist[a] = object; obcopylist[a] = *object; a++; - - if (a >= totcollection) { - continue; - } } FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_END; } diff --git a/source/blender/blenkernel/intern/particle.c b/source/blender/blenkernel/intern/particle.c index 278a8ab9720..aec4d8b735a 100644 --- a/source/blender/blenkernel/intern/particle.c +++ b/source/blender/blenkernel/intern/particle.c @@ -350,73 +350,84 @@ bool psys_check_edited(ParticleSystem *psys) return (psys->pointcache->edit && psys->pointcache->edit->edited); } +void psys_find_group_weights(ParticleSettings *part) +{ + /* Find object pointers based on index. If the collection is linked from + * another library linking may not have the object pointers available on + * file load, so we have to retrieve them later. See T49273. */ + const ListBase dup_group_objects = BKE_collection_object_cache_get(part->dup_group); + + for (ParticleDupliWeight *dw = part->dupliweights.first; dw; dw = dw->next) { + if (dw->ob == NULL) { + Base *base = BLI_findlink(&dup_group_objects, dw->index); + if (base != NULL) { + dw->ob = base->object; + } + } + } +} + void psys_check_group_weights(ParticleSettings *part) { ParticleDupliWeight *dw, *tdw; - int current = 0; if (part->ren_as != PART_DRAW_GR || !part->dup_group) { BLI_freelistN(&part->dupliweights); return; } - const ListBase dup_group_objects = BKE_collection_object_cache_get(part->dup_group); - if (dup_group_objects.first) { - /* First try to find NULL objects from their index, - * and remove all weights that don't have an object in the group. */ - dw = part->dupliweights.first; - while (dw) { - if (dw->ob == NULL || !BKE_collection_has_object_recursive(part->dup_group, dw->ob)) { - Base *base = BLI_findlink(&dup_group_objects, dw->index); - if (base != NULL) { - dw->ob = base->object; - } - else { - tdw = dw->next; - BLI_freelinkN(&part->dupliweights, dw); - dw = tdw; - } - } - else { - dw = dw->next; - } - } + /* Find object pointers. */ + psys_find_group_weights(part); - /* then add objects in the group to new list */ - FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(part->dup_group, object) - { - dw = part->dupliweights.first; - while (dw && dw->ob != object) { - dw = dw->next; - } - - if (!dw) { - dw = MEM_callocN(sizeof(ParticleDupliWeight), "ParticleDupliWeight"); - dw->ob = object; - dw->count = 1; - BLI_addtail(&part->dupliweights, dw); - } + /* Remove NULL objects, that were removed from the collection. */ + dw = part->dupliweights.first; + while (dw) { + if (dw->ob == NULL || !BKE_collection_has_object_recursive(part->dup_group, dw->ob)) { + tdw = dw->next; + BLI_freelinkN(&part->dupliweights, dw); + dw = tdw; } - FOREACH_COLLECTION_OBJECT_RECURSIVE_END; + else { + dw = dw->next; + } + } + /* Add new objects in the collection. */ + int index = 0; + FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(part->dup_group, object) + { dw = part->dupliweights.first; - for (; dw; dw = dw->next) { - if (dw->flag & PART_DUPLIW_CURRENT) { - current = 1; - break; - } + while (dw && dw->ob != object) { + dw = dw->next; } - if (!current) { - dw = part->dupliweights.first; - if (dw) - dw->flag |= PART_DUPLIW_CURRENT; + if (!dw) { + dw = MEM_callocN(sizeof(ParticleDupliWeight), "ParticleDupliWeight"); + dw->ob = object; + dw->count = 1; + BLI_addtail(&part->dupliweights, dw); } + + dw->index = index++; } - else { - BLI_freelistN(&part->dupliweights); + FOREACH_COLLECTION_OBJECT_RECURSIVE_END; + + /* Ensure there is an element marked as current. */ + int current = 0; + for (dw = part->dupliweights.first; dw; dw = dw->next) { + if (dw->flag & PART_DUPLIW_CURRENT) { + current = 1; + break; + } + } + + if (!current) { + dw = part->dupliweights.first; + if (dw) + dw->flag |= PART_DUPLIW_CURRENT; } } + int psys_uses_gravity(ParticleSimulationData *sim) { return sim->scene->physics_settings.flag & PHYS_GLOBAL_GRAVITY && sim->psys->part && sim->psys->part->effector_weights->global_gravity != 0.0f; |