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:
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_particle.h1
-rw-r--r--source/blender/blenkernel/intern/library_query.c4
-rw-r--r--source/blender/blenkernel/intern/object_dupli.c43
-rw-r--r--source/blender/blenkernel/intern/particle.c107
-rw-r--r--source/blender/blenloader/intern/readfile.c40
-rw-r--r--source/blender/editors/physics/particle_object.c33
-rw-r--r--source/blender/editors/physics/physics_intern.h1
-rw-r--r--source/blender/editors/physics/physics_ops.c1
-rw-r--r--source/blender/makesrna/intern/rna_particle.c14
9 files changed, 144 insertions, 100 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;
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);