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:
authorLukas Tönne <lukas.toenne@gmail.com>2015-01-16 13:07:00 +0300
committerLukas Tönne <lukas.toenne@gmail.com>2015-01-20 11:30:11 +0300
commit6d65107656f0ac23ff7b8c2f7927e417400438f8 (patch)
tree56065b217f9d2d64cb7d2c75bffaa65c9f319fa5 /source/blender
parent04226e324ee7d761d8a77dfdca4abc3933864f15 (diff)
Make removal of existing particle systems on copying optional.
This will be most useful when copying individual particle systems one-by-one (to be implemented).
Diffstat (limited to 'source/blender')
-rw-r--r--source/blender/blenkernel/BKE_object.h1
-rw-r--r--source/blender/blenkernel/intern/object.c4
-rw-r--r--source/blender/editors/physics/particle_object.c81
3 files changed, 65 insertions, 21 deletions
diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h
index 1bdbc339f21..0ea460d1a60 100644
--- a/source/blender/blenkernel/BKE_object.h
+++ b/source/blender/blenkernel/BKE_object.h
@@ -57,6 +57,7 @@ void BKE_object_workob_calc_parent(struct Scene *scene, struct Object *ob, struc
void BKE_object_transform_copy(struct Object *ob_tar, const struct Object *ob_src);
struct SoftBody *copy_softbody(struct SoftBody *sb, bool copy_caches);
struct BulletSoftBody *copy_bulletsoftbody(struct BulletSoftBody *sb);
+struct ParticleSystem *BKE_object_copy_particlesystem(struct ParticleSystem *psys);
void BKE_object_copy_particlesystems(struct Object *obn, struct Object *ob);
void BKE_object_copy_softbody(struct Object *obn, struct Object *ob);
void BKE_object_free_particlesystems(struct Object *ob);
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c
index bf0aa4536dc..fa0ad32f62d 100644
--- a/source/blender/blenkernel/intern/object.c
+++ b/source/blender/blenkernel/intern/object.c
@@ -1234,7 +1234,7 @@ BulletSoftBody *copy_bulletsoftbody(BulletSoftBody *bsb)
return bsbn;
}
-static ParticleSystem *copy_particlesystem(ParticleSystem *psys)
+ParticleSystem *BKE_object_copy_particlesystem(ParticleSystem *psys)
{
ParticleSystem *psysn;
ParticleData *pa;
@@ -1314,7 +1314,7 @@ void BKE_object_copy_particlesystems(Object *obn, Object *ob)
BLI_listbase_clear(&obn->particlesystem);
for (psys = ob->particlesystem.first; psys; psys = psys->next) {
- npsys = copy_particlesystem(psys);
+ npsys = BKE_object_copy_particlesystem(psys);
BLI_addtail(&obn->particlesystem, npsys);
diff --git a/source/blender/editors/physics/particle_object.c b/source/blender/editors/physics/particle_object.c
index b4a7b97d87c..81dd1dfc292 100644
--- a/source/blender/editors/physics/particle_object.c
+++ b/source/blender/editors/physics/particle_object.c
@@ -966,22 +966,15 @@ static void copy_particle_edit(Scene *scene, Object *ob, ParticleSystem *psys, P
PE_undo_push(scene, "Original");
}
-static bool copy_particle_systems_to_object(Scene *scene, Object *ob_from, Object *ob_to, int space)
+static void remove_particle_systems_from_object(Object *ob_to)
{
ModifierData *md, *md_next;
- ParticleSystem *psys, *psys_from;
- DerivedMesh *final_dm;
- CustomDataMask cdmask;
- int i;
if (ob_to->type != OB_MESH)
- return false;
+ return;
if (!ob_to->data || ((ID *)ob_to->data)->lib)
- return false;
+ return;
- /* XXX in theory it could be nice to not delete existing particle systems,
- * but the current code for copying assumes that the target object list is empty ...
- */
for (md = ob_to->modifiers.first; md; md = md_next) {
md_next = md->next;
@@ -993,26 +986,65 @@ static bool copy_particle_systems_to_object(Scene *scene, Object *ob_from, Objec
modifier_free(md);
}
}
+
BKE_object_free_particlesystems(ob_to);
+}
+
+static bool copy_particle_systems_to_object(Scene *scene, Object *ob_from, Object *ob_to, int space)
+{
+ ModifierData *md;
+ ParticleSystem *psys_start, *psys, *psys_from;
+ ParticleSystem **tmp_psys;
+ DerivedMesh *final_dm;
+ CustomDataMask cdmask;
+ int i, totpsys;
- BKE_object_copy_particlesystems(ob_to, ob_from);
+ if (ob_to->type != OB_MESH)
+ return false;
+ if (!ob_to->data || ((ID *)ob_to->data)->lib)
+ return false;
/* For remapping we need a valid DM.
- * Because the modifier is appended at the end it's safe to use
- * the final DM of the object without particles
+ * Because the modifiers are appended at the end it's safe to use
+ * the final DM of the object without particles.
+ * However, when evaluating the DM all the particle modifiers must be valid,
+ * i.e. have the psys assigned already.
+ * To break this hen/egg problem we create all psys separately first (to collect required customdata masks),
+ * then create the DM, then add them to the object and make the psys modifiers ...
*/
+ totpsys = BLI_listbase_count(&ob_from->particlesystem);
+ tmp_psys = MEM_mallocN(sizeof(ParticleSystem*) * totpsys, "temporary particle system array");
+
cdmask = 0;
- for (psys = ob_to->particlesystem.first; psys; psys = psys->next, ++i) {
+ for (psys_from = ob_from->particlesystem.first, i = 0; psys_from; psys_from = psys_from->next, ++i) {
+ psys = BKE_object_copy_particlesystem(psys_from);
+ tmp_psys[i] = psys;
+
+ if (psys_start == NULL)
+ psys_start = psys;
+
cdmask |= psys_emitter_customdata_mask(psys);
}
+ /* to iterate source and target psys in sync,
+ * we need to know where the newly added psys start
+ */
+ psys_start = totpsys > 0 ? tmp_psys[0] : NULL;
+
+ /* get the DM (psys and their modifiers have not been appended yet) */
final_dm = mesh_get_derived_final(scene, ob_to, cdmask);
- for (psys = ob_to->particlesystem.first, psys_from = ob_from->particlesystem.first, i = 0;
- psys;
- psys = psys->next, psys_from = psys_from->next, ++i) {
+ /* now append psys to the object and make modifiers */
+ for (i = 0, psys_from = ob_from->particlesystem.first;
+ i < totpsys;
+ ++i, psys_from = psys_from->next) {
ParticleSystemModifierData *psmd;
+ psys = tmp_psys[i];
+
+ /* append to the object */
+ BLI_addtail(&ob_to->particlesystem, psys);
+
/* add a particle system modifier for each system */
md = modifier_new(eModifierType_ParticleSystem);
psmd = (ParticleSystemModifierData *)md;
@@ -1030,11 +1062,12 @@ static bool copy_particle_systems_to_object(Scene *scene, Object *ob_from, Objec
if (psys_from->edit)
copy_particle_edit(scene, ob_to, psys, psys_from);
}
+ MEM_freeN(tmp_psys);
/* note: do this after creating DM copies for all the particle system modifiers,
* the remapping otherwise makes final_dm invalid!
*/
- for (psys = ob_to->particlesystem.first, psys_from = ob_from->particlesystem.first, i = 0;
+ for (psys = psys_start, psys_from = ob_from->particlesystem.first, i = 0;
psys;
psys = psys->next, psys_from = psys_from->next, ++i) {
@@ -1084,6 +1117,7 @@ static int copy_particle_systems_exec(bContext *C, wmOperator *op)
Object *ob_from = ED_object_active_context(C);
Scene *scene = CTX_data_scene(C);
const int space = RNA_enum_get(op->ptr, "space");
+ const bool remove_target_particles = RNA_boolean_get(op->ptr, "remove_target_particles");
int changed_tot = 0;
int fail = 0;
@@ -1091,10 +1125,18 @@ static int copy_particle_systems_exec(bContext *C, wmOperator *op)
CTX_DATA_BEGIN (C, Object *, ob_to, selected_editable_objects)
{
if (ob_from != ob_to) {
+ bool changed = false;
+ if (remove_target_particles) {
+ remove_particle_systems_from_object(ob_to);
+ changed = true;
+ }
if (copy_particle_systems_to_object(scene, ob_from, ob_to, space))
- changed_tot++;
+ changed = true;
else
fail++;
+
+ if (changed)
+ changed_tot++;
}
}
CTX_DATA_END;
@@ -1127,4 +1169,5 @@ void PARTICLE_OT_copy_particle_systems(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
RNA_def_enum(ot->srna, "space", space_items, PAR_COPY_SPACE_OBJECT, "Space", "Space transform for copying from one object to another");
+ RNA_def_boolean(ot->srna, "remove_target_particles", true, "Remove Target Particles", "Remove particle systems on the target objects");
}