diff options
author | Dalai Felinto <dfelinto@gmail.com> | 2019-02-26 22:15:30 +0300 |
---|---|---|
committer | Dalai Felinto <dfelinto@gmail.com> | 2019-03-01 17:44:19 +0300 |
commit | e7ea99af1b0d933b9323be39d8b1c6f683bfba52 (patch) | |
tree | 461d23594737af40f62f533dbe357d2264134d1d /source/blender/blenkernel/intern/object.c | |
parent | 619c65a4b3372b45a8d6d7317672c48d248104ca (diff) |
Outliner: Collection - Duplicate Hierarchy, and Duplicate Linked Hierarchy
As per the suggestion on T57064, this introduces two new options to duplicate collections.
We then have:
* Duplicate > Collection (New collection with linked content).
* Duplicate > Hierachy (Duplicate entire hierarchy and make all contents single user).
* Duplicate > Linked Hierarchy (Duplicate entire hierarchy keeping content linked with original).
Development TODO: `single_object_users` can/should use the new functions.
Reviewers: brecht, mont29
Subscribers: pablovazquez, billreynish, JulienKaspar
Differential Revision: https://developer.blender.org/D4394
Diffstat (limited to 'source/blender/blenkernel/intern/object.c')
-rw-r--r-- | source/blender/blenkernel/intern/object.c | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 3c57a5f7086..c4d80fdd5e2 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1427,6 +1427,240 @@ Object *BKE_object_copy(Main *bmain, const Object *ob) return ob_copy; } +Object *BKE_object_duplicate(Main *bmain, const Object *ob, const int dupflag) +{ + Material ***matarar; + ID *id; + int a, didit; + Object *obn = BKE_object_copy(bmain, ob); + + /* 0 == full linked. */ + if (dupflag == 0) { + return obn; + } + +#define ID_NEW_REMAP_US(a) if ( (a)->id.newid) { (a) = (void *)(a)->id.newid; (a)->id.us++; } +#define ID_NEW_REMAP_US2(a) if (((ID *)a)->newid) { (a) = ((ID *)a)->newid; ((ID *)a)->us++; } + + /* duplicates using userflags */ + if (dupflag & USER_DUP_ACT) { + BKE_animdata_copy_id_action(bmain, &obn->id, true); + } + + if (dupflag & USER_DUP_MAT) { + for (a = 0; a < obn->totcol; a++) { + id = (ID *)obn->mat[a]; + if (id) { + ID_NEW_REMAP_US(obn->mat[a]) + else { + obn->mat[a] = ID_NEW_SET(obn->mat[a], BKE_material_copy(bmain, obn->mat[a])); + } + id_us_min(id); + + if (dupflag & USER_DUP_ACT) { + BKE_animdata_copy_id_action(bmain, &obn->mat[a]->id, true); + } + } + } + } + if (dupflag & USER_DUP_PSYS) { + ParticleSystem *psys; + for (psys = obn->particlesystem.first; psys; psys = psys->next) { + id = (ID *) psys->part; + if (id) { + ID_NEW_REMAP_US(psys->part) + else { + psys->part = ID_NEW_SET(psys->part, BKE_particlesettings_copy(bmain, psys->part)); + } + + if (dupflag & USER_DUP_ACT) { + BKE_animdata_copy_id_action(bmain, &psys->part->id, true); + } + + id_us_min(id); + } + } + } + + id = obn->data; + didit = 0; + + switch (obn->type) { + case OB_MESH: + if (dupflag & USER_DUP_MESH) { + ID_NEW_REMAP_US2(obn->data) + else { + obn->data = ID_NEW_SET(obn->data, BKE_mesh_copy(bmain, obn->data)); + didit = 1; + } + id_us_min(id); + } + break; + case OB_CURVE: + if (dupflag & USER_DUP_CURVE) { + ID_NEW_REMAP_US2(obn->data) + else { + obn->data = ID_NEW_SET(obn->data, BKE_curve_copy(bmain, obn->data)); + didit = 1; + } + id_us_min(id); + } + break; + case OB_SURF: + if (dupflag & USER_DUP_SURF) { + ID_NEW_REMAP_US2(obn->data) + else { + obn->data = ID_NEW_SET(obn->data, BKE_curve_copy(bmain, obn->data)); + didit = 1; + } + id_us_min(id); + } + break; + case OB_FONT: + if (dupflag & USER_DUP_FONT) { + ID_NEW_REMAP_US2(obn->data) + else { + obn->data = ID_NEW_SET(obn->data, BKE_curve_copy(bmain, obn->data)); + didit = 1; + } + id_us_min(id); + } + break; + case OB_MBALL: + if (dupflag & USER_DUP_MBALL) { + ID_NEW_REMAP_US2(obn->data) + else { + obn->data = ID_NEW_SET(obn->data, BKE_mball_copy(bmain, obn->data)); + didit = 1; + } + id_us_min(id); + } + break; + case OB_LAMP: + if (dupflag & USER_DUP_LAMP) { + ID_NEW_REMAP_US2(obn->data) + else { + obn->data = ID_NEW_SET(obn->data, BKE_light_copy(bmain, obn->data)); + didit = 1; + } + id_us_min(id); + } + break; + case OB_ARMATURE: + DEG_id_tag_update(&obn->id, ID_RECALC_GEOMETRY); + if (obn->pose) + BKE_pose_tag_recalc(bmain, obn->pose); + if (dupflag & USER_DUP_ARM) { + ID_NEW_REMAP_US2(obn->data) + else { + obn->data = ID_NEW_SET(obn->data, BKE_armature_copy(bmain, obn->data)); + BKE_pose_rebuild(bmain, obn, obn->data, true); + didit = 1; + } + id_us_min(id); + } + break; + case OB_LATTICE: + if (dupflag != 0) { + ID_NEW_REMAP_US2(obn->data) + else { + obn->data = ID_NEW_SET(obn->data, BKE_lattice_copy(bmain, obn->data)); + didit = 1; + } + id_us_min(id); + } + break; + case OB_CAMERA: + if (dupflag != 0) { + ID_NEW_REMAP_US2(obn->data) + else { + obn->data = ID_NEW_SET(obn->data, BKE_camera_copy(bmain, obn->data)); + didit = 1; + } + id_us_min(id); + } + break; + case OB_LIGHTPROBE: + if (dupflag != 0) { + ID_NEW_REMAP_US2(obn->data) + else { + obn->data = ID_NEW_SET(obn->data, BKE_lightprobe_copy(bmain, obn->data)); + didit = 1; + } + id_us_min(id); + } + break; + case OB_SPEAKER: + if (dupflag != 0) { + ID_NEW_REMAP_US2(obn->data) + else { + obn->data = ID_NEW_SET(obn->data, BKE_speaker_copy(bmain, obn->data)); + didit = 1; + } + id_us_min(id); + } + break; + case OB_GPENCIL: + if (dupflag != 0) { + ID_NEW_REMAP_US2(obn->data) + else { + obn->data = ID_NEW_SET(obn->data, BKE_gpencil_copy(bmain, obn->data)); + didit = 1; + } + id_us_min(id); + } + break; + } + + /* Check if obdata is copied. */ + if (didit) { + Key *key = BKE_key_from_object(obn); + + Key *oldkey = BKE_key_from_object(ob); + if (oldkey != NULL) { + ID_NEW_SET(oldkey, key); + } + + if (dupflag & USER_DUP_ACT) { + BKE_animdata_copy_id_action(bmain, (ID *)obn->data, true); + if (key) { + BKE_animdata_copy_id_action(bmain, (ID *)key, true); + } + } + + if (dupflag & USER_DUP_MAT) { + matarar = give_matarar(obn); + if (matarar) { + for (a = 0; a < obn->totcol; a++) { + id = (ID *)(*matarar)[a]; + if (id) { + ID_NEW_REMAP_US((*matarar)[a]) + else { + (*matarar)[a] = ID_NEW_SET((*matarar)[a], BKE_material_copy(bmain, (*matarar)[a])); + } + id_us_min(id); + } + } + } + } + } + +#undef ID_NEW_REMAP_US +#undef ID_NEW_REMAP_US2 + + BKE_libblock_relink_to_newid(&obn->id); + + /* DAG_relations_tag_update(bmain); */ /* caller must do */ + + if (ob->data != NULL) { + DEG_id_tag_update_ex(bmain, (ID *)obn->data, ID_RECALC_EDITORS); + } + + /* BKE_main_id_clear_newpoins(bmain); */ /* Called must do. */ + + return obn; +} + void BKE_object_make_local_ex(Main *bmain, Object *ob, const bool lib_local, const bool clear_proxy) { bool is_local = false, is_lib = false; |