diff --git a/source/blender/blenkernel/BKE_lib_override.h b/source/blender/blenkernel/BKE_lib_override.h index fb49f60d8b5..786d0b5ba97 100644 --- a/source/blender/blenkernel/BKE_lib_override.h +++ b/source/blender/blenkernel/BKE_lib_override.h @@ -56,7 +56,9 @@ bool BKE_lib_override_library_is_enabled(void); struct IDOverrideLibrary *BKE_lib_override_library_init(struct ID *local_id, struct ID *reference_id); -void BKE_lib_override_library_copy(struct ID *dst_id, const struct ID *src_id); +void BKE_lib_override_library_copy(struct ID *dst_id, + const struct ID *src_id, + const bool do_full_copy); void BKE_lib_override_library_clear(struct IDOverrideLibrary *override, const bool do_id_user); void BKE_lib_override_library_free(struct IDOverrideLibrary **override, const bool do_id_user); diff --git a/source/blender/blenkernel/intern/anim_data.c b/source/blender/blenkernel/intern/anim_data.c index 9ab4e5c028d..cbb34cbee30 100644 --- a/source/blender/blenkernel/intern/anim_data.c +++ b/source/blender/blenkernel/intern/anim_data.c @@ -381,14 +381,15 @@ bool BKE_animdata_copy_id(Main *bmain, ID *id_to, ID *id_from, const int flag) void BKE_animdata_copy_id_action(Main *bmain, ID *id, const bool set_newid) { + const bool is_id_liboverride = ID_IS_OVERRIDE_LIBRARY(id); AnimData *adt = BKE_animdata_from_id(id); if (adt) { - if (adt->action) { + if (adt->action && (!is_id_liboverride || !ID_IS_LINKED(adt->action))) { id_us_min((ID *)adt->action); adt->action = set_newid ? ID_NEW_SET(adt->action, BKE_action_copy(bmain, adt->action)) : BKE_action_copy(bmain, adt->action); } - if (adt->tmpact) { + if (adt->tmpact && (!is_id_liboverride || !ID_IS_LINKED(adt->tmpact))) { id_us_min((ID *)adt->tmpact); adt->tmpact = set_newid ? ID_NEW_SET(adt->tmpact, BKE_action_copy(bmain, adt->tmpact)) : BKE_action_copy(bmain, adt->tmpact); diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c index e8e3e61ced4..1388146eeb7 100644 --- a/source/blender/blenkernel/intern/collection.c +++ b/source/blender/blenkernel/intern/collection.c @@ -314,6 +314,7 @@ static Collection *collection_duplicate_recursive(Main *bmain, Collection *collection_new; bool do_full_process = false; const int object_dupflag = (do_obdata) ? U.dupflag : 0; + const bool is_collection_liboverride = ID_IS_OVERRIDE_LIBRARY(collection_old); if (!do_hierarchy || collection_old->id.newid == NULL) { BKE_id_copy(bmain, &collection_old->id, (ID **)&collection_new); @@ -359,6 +360,12 @@ static Collection *collection_duplicate_recursive(Main *bmain, Object *ob_old = cob->ob; Object *ob_new = (Object *)ob_old->id.newid; + /* If collection is an override, we do not want to duplicate any linked data-block, as that + * would generate a purely local data. */ + if (is_collection_liboverride && ID_IS_LINKED(ob_old)) { + continue; + } + if (ob_new == NULL) { ob_new = BKE_object_duplicate(bmain, ob_old, object_dupflag); ID_NEW_SET(ob_old, ob_new); @@ -430,7 +437,7 @@ Collection *BKE_collection_duplicate(Main *bmain, Collection *collection_new = collection_duplicate_recursive( bmain, parent, collection, do_hierarchy, do_objects, do_obdata); - /* This code will follows into all ID links using an ID tagged with LIB_TAG_NEW.*/ + /* This code will follow into all ID links using an ID tagged with LIB_TAG_NEW.*/ BKE_libblock_relink_to_newid(&collection_new->id); if (do_hierarchy) { diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c index 734fe9ad9ae..3ad429c5f5a 100644 --- a/source/blender/blenkernel/intern/lib_id.c +++ b/source/blender/blenkernel/intern/lib_id.c @@ -64,6 +64,7 @@ #include "BKE_idtype.h" #include "BKE_key.h" #include "BKE_lib_id.h" +#include "BKE_lib_override.h" #include "BKE_lib_query.h" #include "BKE_lib_remap.h" #include "BKE_main.h" @@ -1153,14 +1154,13 @@ void BKE_libblock_copy_ex(Main *bmain, const ID *id, ID **r_newid, const int ori new_id->properties = IDP_CopyProperty_ex(id->properties, copy_data_flag); } - /* XXX Again... We need a way to control what we copy in a much more refined way. - * We cannot always copy this, some internal copying will die on it! */ - /* For now, upper level code will have to do that itself when required. */ -#if 0 - if (id->override != NULL) { - BKE_override_copy(new_id, id); + /* We may need our own flag to control that at some point, but for now 'no main' one should be + * good enough. */ + if ((orig_flag & LIB_ID_CREATE_NO_MAIN) == 0 && id->override_library != NULL) { + /* We do not want to copy existing override rules here, as they would break the proper + * remapping between IDs. Proper overrides rules will be re-generated anyway. */ + BKE_lib_override_library_copy(new_id, id, false); } -#endif if (id_can_have_animdata(new_id)) { IdAdtTemplate *iat = (IdAdtTemplate *)new_id; diff --git a/source/blender/blenkernel/intern/lib_override.c b/source/blender/blenkernel/intern/lib_override.c index 8d1a4e3594c..d16428ccd60 100644 --- a/source/blender/blenkernel/intern/lib_override.c +++ b/source/blender/blenkernel/intern/lib_override.c @@ -92,7 +92,7 @@ IDOverrideLibrary *BKE_lib_override_library_init(ID *local_id, ID *reference_id) if (ancestor_id != NULL && ancestor_id->override_library != NULL) { /* Original ID has a template, use it! */ - BKE_lib_override_library_copy(local_id, ancestor_id); + BKE_lib_override_library_copy(local_id, ancestor_id, true); if (local_id->override_library->reference != reference_id) { id_us_min(local_id->override_library->reference); local_id->override_library->reference = reference_id; @@ -110,8 +110,8 @@ IDOverrideLibrary *BKE_lib_override_library_init(ID *local_id, ID *reference_id) return local_id->override_library; } -/** Deep copy of a whole override from \a src_id to \a dst_id. */ -void BKE_lib_override_library_copy(ID *dst_id, const ID *src_id) +/** Shalow or deep copy of a whole override from \a src_id to \a dst_id. */ +void BKE_lib_override_library_copy(ID *dst_id, const ID *src_id, const bool do_full_copy) { BLI_assert(src_id->override_library != NULL); @@ -138,12 +138,15 @@ void BKE_lib_override_library_copy(ID *dst_id, const ID *src_id) (ID *)src_id; id_us_plus(dst_id->override_library->reference); - BLI_duplicatelist(&dst_id->override_library->properties, &src_id->override_library->properties); - for (IDOverrideLibraryProperty *op_dst = dst_id->override_library->properties.first, - *op_src = src_id->override_library->properties.first; - op_dst; - op_dst = op_dst->next, op_src = op_src->next) { - lib_override_library_property_copy(op_dst, op_src); + if (do_full_copy) { + BLI_duplicatelist(&dst_id->override_library->properties, + &src_id->override_library->properties); + for (IDOverrideLibraryProperty *op_dst = dst_id->override_library->properties.first, + *op_src = src_id->override_library->properties.first; + op_dst; + op_dst = op_dst->next, op_src = op_src->next) { + lib_override_library_property_copy(op_dst, op_src); + } } dst_id->tag &= ~LIB_TAG_OVERRIDE_LIBRARY_REFOK; diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 4505f9e8d57..127c5243c7e 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1763,6 +1763,8 @@ Object *BKE_object_duplicate(Main *bmain, const Object *ob, const int dupflag) Material ***matarar; ID *id; int a, didit; + const bool is_object_liboverride = ID_IS_OVERRIDE_LIBRARY(ob); + Object *obn = BKE_object_copy(bmain, ob); /* 0 == full linked. */ @@ -1790,6 +1792,9 @@ Object *BKE_object_duplicate(Main *bmain, const Object *ob, const int dupflag) for (a = 0; a < obn->totcol; a++) { id = (ID *)obn->mat[a]; if (id) { + if (is_object_liboverride && ID_IS_LINKED(id)) { + continue; + } ID_NEW_REMAP_US(obn->mat[a]) else { @@ -1807,6 +1812,9 @@ Object *BKE_object_duplicate(Main *bmain, const Object *ob, const int dupflag) for (psys = obn->particlesystem.first; psys; psys = psys->next) { id = (ID *)psys->part; if (id) { + if (is_object_liboverride && ID_IS_LINKED(id)) { + continue; + } ID_NEW_REMAP_US(psys->part) else { @@ -1823,179 +1831,181 @@ Object *BKE_object_duplicate(Main *bmain, const Object *ob, const int dupflag) 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: - if (dupflag != 0) { - DEG_id_tag_update(&obn->id, ID_RECALC_GEOMETRY); - if (obn->pose) { - BKE_pose_tag_recalc(bmain, obn->pose); - } - if (dupflag & USER_DUP_ARM) { + if (!is_object_liboverride || !ID_IS_LINKED(id)) { + 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_armature_copy(bmain, obn->data)); - BKE_pose_rebuild(bmain, obn, obn->data, true); + obn->data = ID_NEW_SET(obn->data, BKE_mesh_copy(bmain, obn->data)); 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; + 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); } - 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; + 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); } - id_us_min(id); - } - break; - case OB_LIGHTPROBE: - if (dupflag & USER_DUP_LIGHTPROBE) { - ID_NEW_REMAP_US2(obn->data) - else - { - obn->data = ID_NEW_SET(obn->data, BKE_lightprobe_copy(bmain, obn->data)); - didit = 1; + 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); } - 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; + 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); } - id_us_min(id); - } - break; - case OB_GPENCIL: - if (dupflag & USER_DUP_GPENCIL) { - ID_NEW_REMAP_US2(obn->data) - else - { - obn->data = ID_NEW_SET(obn->data, BKE_gpencil_copy(bmain, obn->data)); - didit = 1; + 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); } - id_us_min(id); - } - break; - case OB_HAIR: - if (dupflag & USER_DUP_HAIR) { - ID_NEW_REMAP_US2(obn->data) - else - { - obn->data = ID_NEW_SET(obn->data, BKE_hair_copy(bmain, obn->data)); - didit = 1; + break; + case OB_ARMATURE: + if (dupflag != 0) { + 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); + } } - id_us_min(id); - } - break; - case OB_POINTCLOUD: - if (dupflag & USER_DUP_POINTCLOUD) { - ID_NEW_REMAP_US2(obn->data) - else - { - obn->data = ID_NEW_SET(obn->data, BKE_pointcloud_copy(bmain, obn->data)); - didit = 1; + 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); } - id_us_min(id); - } - break; - case OB_VOLUME: - if (dupflag & USER_DUP_VOLUME) { - ID_NEW_REMAP_US2(obn->data) - else - { - obn->data = ID_NEW_SET(obn->data, BKE_volume_copy(bmain, obn->data)); - didit = 1; + 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); } - id_us_min(id); - } - break; + break; + case OB_LIGHTPROBE: + if (dupflag & USER_DUP_LIGHTPROBE) { + 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 & USER_DUP_GPENCIL) { + 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; + case OB_HAIR: + if (dupflag & USER_DUP_HAIR) { + ID_NEW_REMAP_US2(obn->data) + else + { + obn->data = ID_NEW_SET(obn->data, BKE_hair_copy(bmain, obn->data)); + didit = 1; + } + id_us_min(id); + } + break; + case OB_POINTCLOUD: + if (dupflag & USER_DUP_POINTCLOUD) { + ID_NEW_REMAP_US2(obn->data) + else + { + obn->data = ID_NEW_SET(obn->data, BKE_pointcloud_copy(bmain, obn->data)); + didit = 1; + } + id_us_min(id); + } + break; + case OB_VOLUME: + if (dupflag & USER_DUP_VOLUME) { + ID_NEW_REMAP_US2(obn->data) + else + { + obn->data = ID_NEW_SET(obn->data, BKE_volume_copy(bmain, obn->data)); + didit = 1; + } + id_us_min(id); + } + break; + } } /* Check if obdata is copied. */ @@ -2020,6 +2030,9 @@ Object *BKE_object_duplicate(Main *bmain, const Object *ob, const int dupflag) for (a = 0; a < obn->totcol; a++) { id = (ID *)(*matarar)[a]; if (id) { + if (is_object_liboverride && ID_IS_LINKED(id)) { + continue; + } ID_NEW_REMAP_US((*matarar)[a]) else {