diff options
author | Bastien Montagne <bastien@blender.org> | 2020-07-09 16:33:34 +0300 |
---|---|---|
committer | Bastien Montagne <bastien@blender.org> | 2020-07-09 18:56:05 +0300 |
commit | 7b1c406b5431ce65d84ddb5f2c53977c25c18373 (patch) | |
tree | d10874f81e0ca717dc288ae2071bc127c6da990a /source | |
parent | 78b629a98f0c7c5c2c8f3b6b6d1081646cbe6fde (diff) |
Implement T77959: Never duplicate linked data during deep-copy.
Note that this behavior is enforced on user level for now, but on code
side it is controlled with a flag, which should make it easy to refine
that behavior if needed.
Only exception is when we duplicate a linked ID directly (then we assume
user wants a local deep-copy of that linked data, and we always also
duplicate linked sub-data-blocks).
Note that this commit also slightly refactor the handling of actions of
animdata, by simplifying `BKE_animdata_copy_id_action()` and adding an
explicit new `BKE_animdata_duplicate_id_action()` to be used during ID
duplication (deep copy).
This also allows us to get rid of the special case for liboverrides.
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/BKE_anim_data.h | 6 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_lib_id.h | 1 | ||||
-rw-r--r-- | source/blender/blenkernel/BKE_object.h | 2 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/anim_data.c | 27 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/collection.c | 33 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/lib_id.c | 54 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/object.c | 55 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/scene.c | 19 | ||||
-rw-r--r-- | source/blender/editors/object/object_relations.c | 12 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_userdef_types.h | 2 |
10 files changed, 119 insertions, 92 deletions
diff --git a/source/blender/blenkernel/BKE_anim_data.h b/source/blender/blenkernel/BKE_anim_data.h index 5aeaf4405f5..48e95740b9d 100644 --- a/source/blender/blenkernel/BKE_anim_data.h +++ b/source/blender/blenkernel/BKE_anim_data.h @@ -71,7 +71,11 @@ bool BKE_animdata_copy_id(struct Main *bmain, const int flag); /* Copy AnimData Actions */ -void BKE_animdata_copy_id_action(struct Main *bmain, struct ID *id, const bool set_newid); +void BKE_animdata_copy_id_action(struct Main *bmain, struct ID *id); + +void BKE_animdata_duplicate_id_action(struct Main *bmain, + struct ID *id, + const uint duplicate_flags); /* Merge copies of data from source AnimData block */ typedef enum eAnimData_MergeCopy_Modes { diff --git a/source/blender/blenkernel/BKE_lib_id.h b/source/blender/blenkernel/BKE_lib_id.h index bc72afdd08d..76bae6fa909 100644 --- a/source/blender/blenkernel/BKE_lib_id.h +++ b/source/blender/blenkernel/BKE_lib_id.h @@ -229,7 +229,6 @@ bool BKE_id_copy(struct Main *bmain, const struct ID *id, struct ID **newid); bool BKE_id_copy_ex(struct Main *bmain, const struct ID *id, struct ID **r_newid, const int flag); struct ID *BKE_id_copy_for_duplicate(struct Main *bmain, struct ID *id, - const bool is_owner_id_liboverride, const uint duplicate_flags); void BKE_lib_id_swap(struct Main *bmain, struct ID *id_a, struct ID *id_b); diff --git a/source/blender/blenkernel/BKE_object.h b/source/blender/blenkernel/BKE_object.h index d830a35dda0..f2a022c84a3 100644 --- a/source/blender/blenkernel/BKE_object.h +++ b/source/blender/blenkernel/BKE_object.h @@ -139,7 +139,7 @@ bool BKE_object_obdata_is_libdata(const struct Object *ob); struct Object *BKE_object_duplicate(struct Main *bmain, struct Object *ob, - const uint dupflag, + uint dupflag, const uint duplicate_options); void BKE_object_obdata_size_init(struct Object *ob, const float scale); diff --git a/source/blender/blenkernel/intern/anim_data.c b/source/blender/blenkernel/intern/anim_data.c index 3e2c69fbcea..61181278c60 100644 --- a/source/blender/blenkernel/intern/anim_data.c +++ b/source/blender/blenkernel/intern/anim_data.c @@ -375,17 +375,19 @@ bool BKE_animdata_copy_id(Main *bmain, ID *id_to, ID *id_from, const int flag) return true; } -void BKE_animdata_copy_id_action(Main *bmain, ID *id, const bool set_newid) +static void animdata_copy_id_action(Main *bmain, + ID *id, + const bool set_newid, + const bool do_linked_id) { - const bool is_id_liboverride = ID_IS_OVERRIDE_LIBRARY(id); AnimData *adt = BKE_animdata_from_id(id); if (adt) { - if (adt->action && (!is_id_liboverride || !ID_IS_LINKED(adt->action))) { + if (adt->action && (do_linked_id || !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 && (!is_id_liboverride || !ID_IS_LINKED(adt->tmpact))) { + if (adt->tmpact && (do_linked_id || !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); @@ -393,12 +395,27 @@ void BKE_animdata_copy_id_action(Main *bmain, ID *id, const bool set_newid) } bNodeTree *ntree = ntreeFromID(id); if (ntree) { - BKE_animdata_copy_id_action(bmain, &ntree->id, set_newid); + animdata_copy_id_action(bmain, &ntree->id, set_newid, do_linked_id); } /* Note that collections are not animatable currently, so no need to handle scenes' master * collection here. */ } +void BKE_animdata_copy_id_action(Main *bmain, ID *id) +{ + const bool is_id_liboverride = ID_IS_OVERRIDE_LIBRARY(id); + animdata_copy_id_action(bmain, id, false, !is_id_liboverride); +} + +void BKE_animdata_duplicate_id_action(struct Main *bmain, + struct ID *id, + const eDupli_ID_Flags duplicate_flags) +{ + if (duplicate_flags & USER_DUP_ACT) { + animdata_copy_id_action(bmain, id, true, (duplicate_flags & USER_DUP_LINKED_ID) != 0); + } +} + /* Merge copies of the data from the src AnimData into the destination AnimData */ void BKE_animdata_merge_copy( Main *bmain, ID *dst_id, ID *src_id, eAnimData_MergeCopy_Modes action_mode, bool fix_drivers) diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c index 080d61f1500..7e22048379b 100644 --- a/source/blender/blenkernel/intern/collection.c +++ b/source/blender/blenkernel/intern/collection.c @@ -333,7 +333,6 @@ static Collection *collection_duplicate_recursive(Main *bmain, Collection *collection_new; bool do_full_process = false; const bool is_collection_master = (collection_old->flag & COLLECTION_IS_MASTER) != 0; - const bool is_collection_liboverride = ID_IS_OVERRIDE_LIBRARY(collection_old); const bool do_objects = (duplicate_flags & USER_DUP_OBJECT) != 0; @@ -346,7 +345,12 @@ static Collection *collection_duplicate_recursive(Main *bmain, } else if (collection_old->id.newid == NULL) { collection_new = (Collection *)BKE_id_copy_for_duplicate( - bmain, (ID *)collection_old, is_collection_liboverride, duplicate_flags); + bmain, (ID *)collection_old, duplicate_flags); + + if (collection_new == collection_old) { + return collection_new; + } + do_full_process = true; } else { @@ -382,17 +386,15 @@ 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, duplicate_flags, duplicate_options | LIB_ID_DUPLICATE_IS_SUBPROCESS); } + if (ob_new == ob_old) { + continue; + } + collection_object_add(bmain, collection_new, ob_new, 0, true); collection_object_remove(bmain, collection_new, ob_old, false); } @@ -403,13 +405,11 @@ static Collection *collection_duplicate_recursive(Main *bmain, LISTBASE_FOREACH_MUTABLE (CollectionChild *, child, &collection_old->children) { Collection *child_collection_old = child->collection; - if (is_collection_liboverride && ID_IS_LINKED(child_collection_old)) { - continue; - } - - collection_duplicate_recursive( + Collection *child_collection_new = collection_duplicate_recursive( bmain, collection_new, child_collection_old, duplicate_flags, duplicate_options); - collection_child_remove(collection_new, child_collection_old); + if (child_collection_new != child_collection_old) { + collection_child_remove(collection_new, child_collection_old); + } } return collection_new; @@ -434,6 +434,11 @@ Collection *BKE_collection_duplicate(Main *bmain, if (!is_subprocess) { BKE_main_id_tag_all(bmain, LIB_TAG_NEW, false); BKE_main_id_clear_newpoins(bmain); + /* In case root duplicated ID is linked, assume we want to get a local copy of it and duplicate + * all expected linked data. */ + if (ID_IS_LINKED(collection)) { + duplicate_flags |= USER_DUP_LINKED_ID; + } } Collection *collection_new = collection_duplicate_recursive( diff --git a/source/blender/blenkernel/intern/lib_id.c b/source/blender/blenkernel/intern/lib_id.c index 7c09ae51344..eb440de1a6f 100644 --- a/source/blender/blenkernel/intern/lib_id.c +++ b/source/blender/blenkernel/intern/lib_id.c @@ -611,41 +611,39 @@ bool BKE_id_copy(Main *bmain, const ID *id, ID **newid) * Invokes the appropriate copy method for the block and returns the result in * newid, unless test. Returns true if the block can be copied. */ -ID *BKE_id_copy_for_duplicate(Main *bmain, - ID *id, - const bool is_owner_id_liboverride, - const eDupli_ID_Flags duplicate_flags) +ID *BKE_id_copy_for_duplicate(Main *bmain, ID *id, const eDupli_ID_Flags duplicate_flags) { if (id == NULL) { - return NULL; + return id; } if (id->newid == NULL) { - if (!is_owner_id_liboverride || !ID_IS_LINKED(id)) { - ID *id_new; - BKE_id_copy(bmain, id, &id_new); - /* Copying add one user by default, need to get rid of that one. */ - id_us_min(id_new); - ID_NEW_SET(id, id_new); - - /* Shape keys are always copied with their owner ID, by default. */ - ID *key_new = (ID *)BKE_key_from_id(id_new); - ID *key = (ID *)BKE_key_from_id(id); - if (key != NULL) { - ID_NEW_SET(key, key_new); - } + const bool do_linked_id = (duplicate_flags & USER_DUP_LINKED_ID) != 0; + if (!(do_linked_id || !ID_IS_LINKED(id))) { + return id; + } - /* Note: embedded data (root nodetrees and master collections) should never be referenced by - * anything else, so we do not need to set their newid pointer and flag. */ + ID *id_new; + BKE_id_copy(bmain, id, &id_new); + /* Copying add one user by default, need to get rid of that one. */ + id_us_min(id_new); + ID_NEW_SET(id, id_new); - if (duplicate_flags & USER_DUP_ACT) { - BKE_animdata_copy_id_action(bmain, id_new, true); - if (key_new != NULL) { - BKE_animdata_copy_id_action(bmain, key_new, true); - } - /* Note that actions of embedded data (root nodetrees and master collections) are handled - * by `BKE_animdata_copy_id_action` as well. */ - } + /* Shape keys are always copied with their owner ID, by default. */ + ID *key_new = (ID *)BKE_key_from_id(id_new); + ID *key = (ID *)BKE_key_from_id(id); + if (key != NULL) { + ID_NEW_SET(key, key_new); + } + + /* Note: embedded data (root nodetrees and master collections) should never be referenced by + * anything else, so we do not need to set their newid pointer and flag. */ + + BKE_animdata_duplicate_id_action(bmain, id_new, duplicate_flags); + if (key_new != NULL) { + BKE_animdata_duplicate_id_action(bmain, id_new, duplicate_flags); } + /* Note that actions of embedded data (root nodetrees and master collections) are handled + * by `BKE_animdata_duplicate_id_action` as well. */ } return id->newid; } diff --git a/source/blender/blenkernel/intern/object.c b/source/blender/blenkernel/intern/object.c index 6331f87f09f..d48ea33cc65 100644 --- a/source/blender/blenkernel/intern/object.c +++ b/source/blender/blenkernel/intern/object.c @@ -1760,7 +1760,7 @@ Object *BKE_object_copy(Main *bmain, const Object *ob) */ Object *BKE_object_duplicate(Main *bmain, Object *ob, - const eDupli_ID_Flags dupflag, + eDupli_ID_Flags dupflag, const eLibIDDuplicateFlags duplicate_options) { const bool is_subprocess = (duplicate_options & LIB_ID_DUPLICATE_IS_SUBPROCESS) != 0; @@ -1768,10 +1768,14 @@ Object *BKE_object_duplicate(Main *bmain, if (!is_subprocess) { BKE_main_id_tag_all(bmain, LIB_TAG_NEW, false); BKE_main_id_clear_newpoins(bmain); + /* In case root duplicated ID is linked, assume we want to get a local copy of it and duplicate + * all expected linked data. */ + if (ID_IS_LINKED(ob)) { + dupflag |= USER_DUP_LINKED_ID; + } } Material ***matarar; - const bool is_object_liboverride = ID_IS_OVERRIDE_LIBRARY(ob); Object *obn; BKE_id_copy(bmain, &ob->id, (ID **)&obn); @@ -1785,112 +1789,109 @@ Object *BKE_object_duplicate(Main *bmain, return obn; } - /* duplicates using userflags */ - if (dupflag & USER_DUP_ACT) { - BKE_animdata_copy_id_action(bmain, &obn->id, true); - } + BKE_animdata_duplicate_id_action(bmain, &obn->id, dupflag); if (dupflag & USER_DUP_MAT) { for (int i = 0; i < obn->totcol; i++) { - BKE_id_copy_for_duplicate(bmain, (ID *)obn->mat[i], is_object_liboverride, dupflag); + BKE_id_copy_for_duplicate(bmain, (ID *)obn->mat[i], dupflag); } } if (dupflag & USER_DUP_PSYS) { ParticleSystem *psys; for (psys = obn->particlesystem.first; psys; psys = psys->next) { - BKE_id_copy_for_duplicate(bmain, (ID *)psys->part, is_object_liboverride, dupflag); + BKE_id_copy_for_duplicate(bmain, (ID *)psys->part, dupflag); } } - ID *id = obn->data; + ID *id_old = obn->data; ID *id_new = NULL; - const bool need_to_duplicate_obdata = (id != NULL) && (id->newid == NULL); + const bool need_to_duplicate_obdata = (id_old != NULL) && (id_old->newid == NULL); switch (obn->type) { case OB_MESH: if (dupflag & USER_DUP_MESH) { - id_new = BKE_id_copy_for_duplicate(bmain, id, is_object_liboverride, dupflag); + id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag); } break; case OB_CURVE: if (dupflag & USER_DUP_CURVE) { - id_new = BKE_id_copy_for_duplicate(bmain, id, is_object_liboverride, dupflag); + id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag); } break; case OB_SURF: if (dupflag & USER_DUP_SURF) { - id_new = BKE_id_copy_for_duplicate(bmain, id, is_object_liboverride, dupflag); + id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag); } break; case OB_FONT: if (dupflag & USER_DUP_FONT) { - id_new = BKE_id_copy_for_duplicate(bmain, id, is_object_liboverride, dupflag); + id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag); } break; case OB_MBALL: if (dupflag & USER_DUP_MBALL) { - id_new = BKE_id_copy_for_duplicate(bmain, id, is_object_liboverride, dupflag); + id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag); } break; case OB_LAMP: if (dupflag & USER_DUP_LAMP) { - id_new = BKE_id_copy_for_duplicate(bmain, id, is_object_liboverride, dupflag); + id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag); } break; case OB_ARMATURE: if (dupflag & USER_DUP_ARM) { - id_new = BKE_id_copy_for_duplicate(bmain, id, is_object_liboverride, dupflag); + id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag); } break; case OB_LATTICE: if (dupflag != 0) { - id_new = BKE_id_copy_for_duplicate(bmain, id, is_object_liboverride, dupflag); + id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag); } break; case OB_CAMERA: if (dupflag != 0) { - id_new = BKE_id_copy_for_duplicate(bmain, id, is_object_liboverride, dupflag); + id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag); } break; case OB_LIGHTPROBE: if (dupflag & USER_DUP_LIGHTPROBE) { - id_new = BKE_id_copy_for_duplicate(bmain, id, is_object_liboverride, dupflag); + id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag); } break; case OB_SPEAKER: if (dupflag != 0) { - id_new = BKE_id_copy_for_duplicate(bmain, id, is_object_liboverride, dupflag); + id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag); } break; case OB_GPENCIL: if (dupflag & USER_DUP_GPENCIL) { - id_new = BKE_id_copy_for_duplicate(bmain, id, is_object_liboverride, dupflag); + id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag); } break; case OB_HAIR: if (dupflag & USER_DUP_HAIR) { - id_new = BKE_id_copy_for_duplicate(bmain, id, is_object_liboverride, dupflag); + id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag); } break; case OB_POINTCLOUD: if (dupflag & USER_DUP_POINTCLOUD) { - id_new = BKE_id_copy_for_duplicate(bmain, id, is_object_liboverride, dupflag); + id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag); } break; case OB_VOLUME: if (dupflag & USER_DUP_VOLUME) { - id_new = BKE_id_copy_for_duplicate(bmain, id, is_object_liboverride, dupflag); + id_new = BKE_id_copy_for_duplicate(bmain, id_old, dupflag); } break; } /* If obdata has been copied, we may also have to duplicate the materials assigned to it. */ - if (need_to_duplicate_obdata && id_new != NULL) { + if (need_to_duplicate_obdata && !ELEM(id_new, NULL, id_old)) { if (dupflag & USER_DUP_MAT) { matarar = BKE_object_material_array_p(obn); if (matarar) { for (int i = 0; i < obn->totcol; i++) { - BKE_id_copy_for_duplicate(bmain, (ID *)(*matarar)[i], is_object_liboverride, dupflag); + BKE_id_copy_for_duplicate(bmain, (ID *)(*matarar)[i], dupflag); } } } diff --git a/source/blender/blenkernel/intern/scene.c b/source/blender/blenkernel/intern/scene.c index a457d278e1d..5ae2f4b9005 100644 --- a/source/blender/blenkernel/intern/scene.c +++ b/source/blender/blenkernel/intern/scene.c @@ -770,7 +770,6 @@ void BKE_scene_copy_data_eevee(Scene *sce_dst, const Scene *sce_src) Scene *BKE_scene_duplicate(Main *bmain, Scene *sce, eSceneCopyMethod type) { - const bool is_scene_liboverride = ID_IS_OVERRIDE_LIBRARY(sce); Scene *sce_copy; /* TODO this should/could most likely be replaced by call to more generic code at some point... @@ -841,15 +840,13 @@ Scene *BKE_scene_duplicate(Main *bmain, Scene *sce, eSceneCopyMethod type) return sce_copy; } else { - const eDupli_ID_Flags duplicate_flags = U.dupflag | USER_DUP_OBJECT; + eDupli_ID_Flags duplicate_flags = U.dupflag | USER_DUP_OBJECT; BKE_id_copy(bmain, (ID *)sce, (ID **)&sce_copy); id_us_min(&sce_copy->id); id_us_ensure_real(&sce_copy->id); - if (duplicate_flags & USER_DUP_ACT) { - BKE_animdata_copy_id_action(bmain, &sce_copy->id, true); - } + BKE_animdata_duplicate_id_action(bmain, &sce_copy->id, duplicate_flags); /* Extra actions, most notably SCE_FULL_COPY also duplicates several 'children' datablocks. */ @@ -860,22 +857,26 @@ Scene *BKE_scene_duplicate(Main *bmain, Scene *sce, eSceneCopyMethod type) if (!is_subprocess) { BKE_main_id_tag_all(bmain, LIB_TAG_NEW, false); BKE_main_id_clear_newpoins(bmain); + /* In case root duplicated ID is linked, assume we want to get a local copy of it and + * duplicate all expected linked data. */ + if (ID_IS_LINKED(sce)) { + duplicate_flags |= USER_DUP_LINKED_ID; + } } /* Copy Freestyle LineStyle datablocks. */ LISTBASE_FOREACH (ViewLayer *, view_layer_dst, &sce_copy->view_layers) { LISTBASE_FOREACH ( FreestyleLineSet *, lineset, &view_layer_dst->freestyle_config.linesets) { - BKE_id_copy_for_duplicate( - bmain, &lineset->linestyle->id, is_scene_liboverride, duplicate_flags); + BKE_id_copy_for_duplicate(bmain, (ID *)lineset->linestyle, duplicate_flags); } } /* Full copy of world (included animations) */ - BKE_id_copy_for_duplicate(bmain, &sce->world->id, is_scene_liboverride, duplicate_flags); + BKE_id_copy_for_duplicate(bmain, (ID *)sce->world, duplicate_flags); /* Full copy of GreasePencil. */ - BKE_id_copy_for_duplicate(bmain, &sce->gpd->id, is_scene_liboverride, duplicate_flags); + BKE_id_copy_for_duplicate(bmain, (ID *)sce->gpd, duplicate_flags); /* Deep-duplicate collections and objects (using preferences' settings for which sub-data to * duplicate along the object itself). */ diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c index d37f03b7f55..ac41028089c 100644 --- a/source/blender/editors/object/object_relations.c +++ b/source/blender/editors/object/object_relations.c @@ -1878,7 +1878,7 @@ static void single_obdata_users( /* Needed to remap texcomesh below. */ me = ob->data = ID_NEW_SET(ob->data, BKE_mesh_copy(bmain, ob->data)); if (me->key) { /* We do not need to set me->key->id.newid here... */ - BKE_animdata_copy_id_action(bmain, (ID *)me->key, false); + BKE_animdata_copy_id_action(bmain, (ID *)me->key); } break; case OB_MBALL: @@ -1891,13 +1891,13 @@ static void single_obdata_users( ID_NEW_REMAP(cu->bevobj); ID_NEW_REMAP(cu->taperobj); if (cu->key) { /* We do not need to set cu->key->id.newid here... */ - BKE_animdata_copy_id_action(bmain, (ID *)cu->key, false); + BKE_animdata_copy_id_action(bmain, (ID *)cu->key); } break; case OB_LATTICE: ob->data = lat = ID_NEW_SET(ob->data, BKE_lattice_copy(bmain, ob->data)); if (lat->key) { /* We do not need to set lat->key->id.newid here... */ - BKE_animdata_copy_id_action(bmain, (ID *)lat->key, false); + BKE_animdata_copy_id_action(bmain, (ID *)lat->key); } break; case OB_ARMATURE: @@ -1937,7 +1937,7 @@ static void single_obdata_users( * AnimData structure, which is not what we want. * (sergey) */ - BKE_animdata_copy_id_action(bmain, (ID *)ob->data, false); + BKE_animdata_copy_id_action(bmain, (ID *)ob->data); id_us_min(id); } @@ -1958,7 +1958,7 @@ static void single_object_action_users( FOREACH_OBJECT_FLAG_BEGIN (scene, view_layer, v3d, flag, ob) { if (!ID_IS_LINKED(ob)) { DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY); - BKE_animdata_copy_id_action(bmain, &ob->id, false); + BKE_animdata_copy_id_action(bmain, &ob->id); } } FOREACH_OBJECT_FLAG_END; @@ -1980,7 +1980,7 @@ static void single_mat_users( if (ma->id.us > 1) { man = BKE_material_copy(bmain, ma); - BKE_animdata_copy_id_action(bmain, &man->id, false); + BKE_animdata_copy_id_action(bmain, &man->id); man->id.us = 0; BKE_object_material_assign(bmain, ob, man, a, BKE_MAT_ASSIGN_USERPREF); diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h index d751ad9ac47..911e0ee4893 100644 --- a/source/blender/makesdna/DNA_userdef_types.h +++ b/source/blender/makesdna/DNA_userdef_types.h @@ -1160,6 +1160,8 @@ typedef enum eDupli_ID_Flags { USER_DUP_OBJECT = (1 << 24), /* USER_DUP_COLLECTION = (1 << 25), */ /* UNUSED, keep because we may implement. */ + /* Duplicate (and hence make local) linked data. */ + USER_DUP_LINKED_ID = (1 << 30), } eDupli_ID_Flags; /** |