diff options
-rw-r--r-- | release/scripts/startup/bl_ui/properties_particle.py | 2 | ||||
-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 | ||||
-rw-r--r-- | source/blender/blenloader/intern/readfile.c | 40 | ||||
-rw-r--r-- | source/blender/editors/physics/particle_object.c | 33 | ||||
-rw-r--r-- | source/blender/editors/physics/physics_intern.h | 1 | ||||
-rw-r--r-- | source/blender/editors/physics/physics_ops.c | 1 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_particle.c | 14 |
10 files changed, 146 insertions, 100 deletions
diff --git a/release/scripts/startup/bl_ui/properties_particle.py b/release/scripts/startup/bl_ui/properties_particle.py index fbc053a565f..05538e71faf 100644 --- a/release/scripts/startup/bl_ui/properties_particle.py +++ b/release/scripts/startup/bl_ui/properties_particle.py @@ -1275,6 +1275,8 @@ class PARTICLE_PT_render_collection_use_count(ParticleButtonsPanel, Panel): subsub.operator("particle.dupliob_remove", icon='ZOOMOUT', text="") subsub.operator("particle.dupliob_move_up", icon='TRIA_UP', text="") subsub.operator("particle.dupliob_move_down", icon='TRIA_DOWN', text="") + subsub.separator() + subsub.operator("particle.dupliob_refresh", icon='FILE_REFRESH', text="") weight = part.active_dupliweight if weight: 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; diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c index c94a565216a..79a552a5b86 100644 --- a/source/blender/blenloader/intern/readfile.c +++ b/source/blender/blenloader/intern/readfile.c @@ -4246,40 +4246,8 @@ static void lib_link_particlesettings(FileData *fd, Main *main) } if (part->dupliweights.first && part->dup_group) { - ParticleDupliWeight *dw; - int index_ok = 0; - /* check for old files without indices (all indexes 0) */ - if (BLI_listbase_is_single(&part->dupliweights)) { - /* special case for only one object in the group */ - index_ok = 1; - } - else { - for (dw = part->dupliweights.first; dw; dw = dw->next) { - if (dw->index > 0) { - index_ok = 1; - break; - } - } - } - - if (index_ok) { - /* if we have indexes, let's use them */ - for (dw = part->dupliweights.first; dw; dw = dw->next) { - /* Do not try to restore pointer here, we have to search for group objects in another - * separated step. - * Reason is, the used group may be linked from another library, which has not yet - * been 'lib_linked'. - * Since dw->ob is not considered as an object user (it does not make objet directly linked), - * we may have no valid way to retrieve it yet. - * See T49273. */ - dw->ob = NULL; - } - } - else { - /* otherwise try to get objects from own library (won't work on library linked groups) */ - for (dw = part->dupliweights.first; dw; dw = dw->next) { - dw->ob = newlibadr(fd, part->id.lib, dw->ob); - } + for (ParticleDupliWeight *dw = part->dupliweights.first; dw; dw = dw->next) { + dw->ob = newlibadr(fd, part->id.lib, dw->ob); } } else { @@ -9304,6 +9272,10 @@ static void expand_particlesettings(FileData *fd, Main *mainvar, ParticleSetting } } } + + for (ParticleDupliWeight *dw = part->dupliweights.first; dw; dw = dw->next) { + expand_doit(fd, mainvar, dw->ob); + } } static void expand_collection(FileData *fd, Main *mainvar, Collection *collection) diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c index e531836d744..2f96f4e78e6 100644 --- a/source/blender/editors/physics/particle_object.c +++ b/source/blender/editors/physics/particle_object.c @@ -387,6 +387,35 @@ void PARTICLE_OT_target_move_down(wmOperatorType *ot) ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; } +/************************ refresh dupli objects *********************/ + +static int dupliob_refresh_exec(bContext *C, wmOperator *UNUSED(op)) +{ + PointerRNA ptr = CTX_data_pointer_get_type(C, "particle_system", &RNA_ParticleSystem); + ParticleSystem *psys= ptr.data; + + if (!psys) + return OPERATOR_CANCELLED; + + psys_check_group_weights(psys->part); + DEG_id_tag_update(&psys->part->id, OB_RECALC_DATA | PSYS_RECALC_REDO); + WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, NULL); + + return OPERATOR_FINISHED; +} + +void PARTICLE_OT_dupliob_refresh(wmOperatorType *ot) +{ + ot->name = "Refresh Dupli Objects"; + ot->idname = "PARTICLE_OT_dupliob_refresh"; + ot->description = "Refresh list of dupli objects and their weights"; + + ot->exec = dupliob_refresh_exec; + + /* flags */ + ot->flag = OPTYPE_REGISTER|OPTYPE_UNDO; +} + /************************ move up particle dupliweight operator *********************/ static int dupliob_move_up_exec(bContext *C, wmOperator *UNUSED(op)) @@ -405,6 +434,7 @@ static int dupliob_move_up_exec(bContext *C, wmOperator *UNUSED(op)) BLI_remlink(&part->dupliweights, dw); BLI_insertlinkbefore(&part->dupliweights, dw->prev, dw); + DEG_id_tag_update(&part->id, OB_RECALC_DATA | PSYS_RECALC_REDO); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, NULL); break; } @@ -444,6 +474,7 @@ static int copy_particle_dupliob_exec(bContext *C, wmOperator *UNUSED(op)) dw->flag |= PART_DUPLIW_CURRENT; BLI_addhead(&part->dupliweights, dw); + DEG_id_tag_update(&part->id, OB_RECALC_DATA | PSYS_RECALC_REDO); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, NULL); break; } @@ -490,6 +521,7 @@ static int remove_particle_dupliob_exec(bContext *C, wmOperator *UNUSED(op)) if (dw) dw->flag |= PART_DUPLIW_CURRENT; + DEG_id_tag_update(&part->id, OB_RECALC_DATA | PSYS_RECALC_REDO); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, NULL); return OPERATOR_FINISHED; @@ -527,6 +559,7 @@ static int dupliob_move_down_exec(bContext *C, wmOperator *UNUSED(op)) BLI_remlink(&part->dupliweights, dw); BLI_insertlinkafter(&part->dupliweights, dw->next, dw); + DEG_id_tag_update(&part->id, OB_RECALC_DATA | PSYS_RECALC_REDO); WM_event_add_notifier(C, NC_OBJECT|ND_PARTICLE, NULL); break; } diff --git a/source/blender/editors/physics/physics_intern.h b/source/blender/editors/physics/physics_intern.h index e94f582141b..df688d90e44 100644 --- a/source/blender/editors/physics/physics_intern.h +++ b/source/blender/editors/physics/physics_intern.h @@ -95,6 +95,7 @@ void PARTICLE_OT_dupliob_copy(struct wmOperatorType *ot); void PARTICLE_OT_dupliob_remove(struct wmOperatorType *ot); void PARTICLE_OT_dupliob_move_up(struct wmOperatorType *ot); void PARTICLE_OT_dupliob_move_down(struct wmOperatorType *ot); +void PARTICLE_OT_dupliob_refresh(struct wmOperatorType *ot); /* particle_boids.c */ void BOID_OT_rule_add(struct wmOperatorType *ot); diff --git a/source/blender/editors/physics/physics_ops.c b/source/blender/editors/physics/physics_ops.c index 033777e905e..db64aa8811c 100644 --- a/source/blender/editors/physics/physics_ops.c +++ b/source/blender/editors/physics/physics_ops.c @@ -85,6 +85,7 @@ static void operatortypes_particle(void) WM_operatortype_append(PARTICLE_OT_copy_particle_systems); WM_operatortype_append(PARTICLE_OT_duplicate_particle_system); + WM_operatortype_append(PARTICLE_OT_dupliob_refresh); WM_operatortype_append(PARTICLE_OT_dupliob_copy); WM_operatortype_append(PARTICLE_OT_dupliob_remove); WM_operatortype_append(PARTICLE_OT_dupliob_move_up); diff --git a/source/blender/makesrna/intern/rna_particle.c b/source/blender/makesrna/intern/rna_particle.c index 08bc373b690..b33bf9a47b7 100644 --- a/source/blender/makesrna/intern/rna_particle.c +++ b/source/blender/makesrna/intern/rna_particle.c @@ -607,6 +607,14 @@ static void rna_Particle_redo_dependency(Main *bmain, Scene *scene, PointerRNA * rna_Particle_redo(bmain, scene, ptr); } +static void rna_Particle_redo_count(Main *bmain, Scene *scene, PointerRNA *ptr) +{ + ParticleSettings *part = (ParticleSettings *)ptr->data; + DEG_relations_tag_update(bmain); + psys_check_group_weights(part); + particle_recalc(bmain, scene, ptr, PSYS_RECALC_REDO); +} + static void rna_Particle_reset(Main *bmain, Scene *scene, PointerRNA *ptr) { particle_recalc(bmain, scene, ptr, PSYS_RECALC_RESET); @@ -2320,8 +2328,8 @@ static void rna_def_particle_settings(BlenderRNA *brna) prop = RNA_def_property(srna, "use_group_count", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_COUNT_GR); - RNA_def_property_ui_text(prop, "Use Count", "Use object multiple times in the same group"); - RNA_def_property_update(prop, 0, "rna_Particle_redo"); + RNA_def_property_ui_text(prop, "Use Count", "Use object multiple times in the same collecton"); + RNA_def_property_update(prop, 0, "rna_Particle_redo_count"); prop = RNA_def_property(srna, "use_global_dupli", PROP_BOOLEAN, PROP_NONE); RNA_def_property_boolean_sdna(prop, NULL, "draw", PART_DRAW_GLOBAL_OB); @@ -3085,7 +3093,7 @@ static void rna_def_particle_settings(BlenderRNA *brna) RNA_def_property_struct_type(prop, "Collection"); RNA_def_property_flag(prop, PROP_EDITABLE); RNA_def_property_ui_text(prop, "Dupli Collection", "Show Objects in this collection in place of particles"); - RNA_def_property_update(prop, 0, "rna_Particle_redo_dependency"); + RNA_def_property_update(prop, 0, "rna_Particle_redo_count"); prop = RNA_def_property(srna, "dupli_weights", PROP_COLLECTION, PROP_NONE); RNA_def_property_collection_sdna(prop, NULL, "dupliweights", NULL); |