[Bf-blender-cvs] [c37121f16c1] master: Fix T91410: Make Single User operation ignores linked data-blocks.

Bastien Montagne noreply at git.blender.org
Fri Oct 22 10:26:51 CEST 2021


Commit: c37121f16c14519a9056217a2f02fc9078b6e05e
Author: Bastien Montagne
Date:   Thu Oct 21 17:34:05 2021 +0200
Branches: master
https://developer.blender.org/rBc37121f16c14519a9056217a2f02fc9078b6e05e

Fix T91410: Make Single User operation ignores linked data-blocks.

Now 'Make Single User' will also create local copy of linked data as
needed.

IMPORTANT: Unlike with local data, this always happen, even if linked
data has only one user. This avoids e.g. cases like two local objects
sharing a same linked mesh, then when calling 'Make Single User ->
Object and ObData' on both objects, yu expect both of your objects to
get localized meshes, not one of them keeping its linked, un-editable
mesh.

===================================================================

M	source/blender/editors/object/object_relations.c

===================================================================

diff --git a/source/blender/editors/object/object_relations.c b/source/blender/editors/object/object_relations.c
index 5c7e1e1fa01..1cc293ba227 100644
--- a/source/blender/editors/object/object_relations.c
+++ b/source/blender/editors/object/object_relations.c
@@ -1677,6 +1677,14 @@ void OBJECT_OT_make_links_data(wmOperatorType *ot)
 /** \name Make Single User Operator
  * \{ */
 
+static bool single_data_needs_duplication(ID *id)
+{
+  /* NOTE: When dealing with linked data, we always make alocal copy of it.
+   * While in theory we could rather make it local when it only has one user, this is difficult
+   * in practice with current code of this function. */
+  return (id != NULL && (id->us > 1 || ID_IS_LINKED(id)));
+}
+
 static void libblock_relink_collection(Collection *collection, const bool do_collection)
 {
   if (do_collection) {
@@ -1800,8 +1808,7 @@ static void single_obdata_users(
   FOREACH_OBJECT_FLAG_BEGIN (scene, view_layer, v3d, flag, ob) {
     if (!ID_IS_LINKED(ob)) {
       id = ob->data;
-
-      if (id && id->us > 1 && !ID_IS_LINKED(id)) {
+      if (single_data_needs_duplication(id)) {
         DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
 
         switch (ob->type) {
@@ -1895,8 +1902,16 @@ 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);
+      AnimData *adt = BKE_animdata_from_id(&ob->id);
+      if (adt == NULL) {
+        continue;
+      }
+
+      ID *id_act = (ID *)adt->action;
+      if (single_data_needs_duplication(id_act)) {
+        DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
+        BKE_animdata_duplicate_id_action(bmain, &ob->id, USER_DUP_ACT | USER_DUP_LINKED_ID);
+      }
     }
   }
   FOREACH_OBJECT_FLAG_END;
@@ -1909,10 +1924,14 @@ static void single_objectdata_action_users(
     if (!ID_IS_LINKED(ob) && ob->data != NULL) {
       ID *id_obdata = (ID *)ob->data;
       AnimData *adt = BKE_animdata_from_id(id_obdata);
+      if (adt == NULL) {
+        continue;
+      }
+
       ID *id_act = (ID *)adt->action;
-      if (id_act && id_act->us > 1) {
+      if (single_data_needs_duplication(id_act)) {
         DEG_id_tag_update(&ob->id, ID_RECALC_GEOMETRY);
-        BKE_animdata_copy_id_action(bmain, id_obdata);
+        BKE_animdata_duplicate_id_action(bmain, &ob->id, USER_DUP_ACT | USER_DUP_LINKED_ID);
       }
     }
   }
@@ -1928,18 +1947,13 @@ static void single_mat_users(
   FOREACH_OBJECT_FLAG_BEGIN (scene, view_layer, v3d, flag, ob) {
     if (!ID_IS_LINKED(ob)) {
       for (a = 1; a <= ob->totcol; a++) {
-        ma = BKE_object_material_get(ob, a);
-        if (ma) {
-          /* do not test for LIB_TAG_NEW or use newid:
-           * this functions guaranteed delivers single_users! */
-
-          if (ma->id.us > 1) {
-            man = (Material *)BKE_id_copy(bmain, &ma->id);
-            BKE_animdata_copy_id_action(bmain, &man->id);
+        ma = BKE_object_material_get(ob, (short)a);
+        if (single_data_needs_duplication(&ma->id)) {
+          man = (Material *)BKE_id_copy(bmain, &ma->id);
+          BKE_animdata_copy_id_action(bmain, &man->id);
 
-            man->id.us = 0;
-            BKE_object_material_assign(bmain, ob, man, a, BKE_MAT_ASSIGN_USERPREF);
-          }
+          man->id.us = 0;
+          BKE_object_material_assign(bmain, ob, man, (short)a, BKE_MAT_ASSIGN_USERPREF);
         }
       }
     }
@@ -1982,9 +1996,7 @@ static void tag_localizable_objects(bContext *C, const int mode)
   CTX_DATA_BEGIN (C, Object *, object, selected_objects) {
     object->id.tag |= LIB_TAG_DOIT;
 
-    /* If data is also gonna to become local, mark data we're interested in
-     * as gonna-to-be-local.
-     */
+    /* If obdata is also going to become local, mark it as such too. */
     if (mode == MAKE_LOCAL_SELECT_OBDATA && object->data) {
       ID *data_id = (ID *)object->data;
       data_id->tag |= LIB_TAG_DOIT;



More information about the Bf-blender-cvs mailing list