[Bf-blender-cvs] [ad6cfcef017] blender-v2.90-release: Fix (unreported) crash in reload library code related to shpaekeys.

Bastien Montagne noreply at git.blender.org
Thu Jul 23 17:15:40 CEST 2020


Commit: ad6cfcef0174109ac2ddf88ae7e143bb60483d6c
Author: Bastien Montagne
Date:   Thu Jul 23 17:03:02 2020 +0200
Branches: blender-v2.90-release
https://developer.blender.org/rBad6cfcef0174109ac2ddf88ae7e143bb60483d6c

Fix (unreported) crash in reload library code related to shpaekeys.

Once again, we need lots of unatural twisting and convolutions to get
those nasty things to work...

Note that in previous versions of Blender, this would not crash, but was
still broken (shapekeys were never actually reloaded from libraries).

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

M	source/blender/windowmanager/intern/wm_files_link.c

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

diff --git a/source/blender/windowmanager/intern/wm_files_link.c b/source/blender/windowmanager/intern/wm_files_link.c
index c8574a5a7fb..6bc87ecb6cf 100644
--- a/source/blender/windowmanager/intern/wm_files_link.c
+++ b/source/blender/windowmanager/intern/wm_files_link.c
@@ -34,6 +34,7 @@
 #include "MEM_guardedalloc.h"
 
 #include "DNA_ID.h"
+#include "DNA_key_types.h"
 #include "DNA_scene_types.h"
 #include "DNA_screen_types.h"
 #include "DNA_windowmanager_types.h"
@@ -50,8 +51,10 @@
 
 #include "BKE_context.h"
 #include "BKE_global.h"
+#include "BKE_key.h"
 #include "BKE_layer.h"
 #include "BKE_lib_id.h"
+#include "BKE_lib_override.h"
 #include "BKE_lib_remap.h"
 #include "BKE_main.h"
 #include "BKE_report.h"
@@ -694,6 +697,92 @@ static int wm_lib_relocate_invoke(bContext *C, wmOperator *op, const wmEvent *UN
   return OPERATOR_CANCELLED;
 }
 
+static void lib_relocate_do_remap(Main *bmain,
+                                  ID *old_id,
+                                  ID *new_id,
+                                  ReportList *reports,
+                                  const bool do_reload,
+                                  const short remap_flags)
+{
+  BLI_assert(old_id);
+  if (do_reload) {
+    /* Since we asked for placeholders in case of missing IDs,
+     * we expect to always get a valid one. */
+    BLI_assert(new_id);
+  }
+  if (new_id) {
+#ifdef PRINT_DEBUG
+    printf("before remap of %s, old_id users: %d, new_id users: %d\n",
+           old_id->name,
+           old_id->us,
+           new_id->us);
+#endif
+    BKE_libblock_remap_locked(bmain, old_id, new_id, remap_flags);
+
+    if (old_id->flag & LIB_FAKEUSER) {
+      id_fake_user_clear(old_id);
+      id_fake_user_set(new_id);
+    }
+
+#ifdef PRINT_DEBUG
+    printf("after remap of %s, old_id users: %d, new_id users: %d\n",
+           old_id->name,
+           old_id->us,
+           new_id->us);
+#endif
+
+    /* In some cases, new_id might become direct link, remove parent of library in this case. */
+    if (new_id->lib->parent && (new_id->tag & LIB_TAG_INDIRECT) == 0) {
+      if (do_reload) {
+        BLI_assert(0); /* Should not happen in 'pure' reload case... */
+      }
+      new_id->lib->parent = NULL;
+    }
+  }
+
+  if (old_id->us > 0 && new_id && old_id->lib == new_id->lib) {
+    /* Note that this *should* not happen - but better be safe than sorry in this area,
+     * at least until we are 100% sure this cannot ever happen.
+     * Also, we can safely assume names were unique so far,
+     * so just replacing '.' by '~' should work,
+     * but this does not totally rules out the possibility of name collision. */
+    size_t len = strlen(old_id->name);
+    size_t dot_pos;
+    bool has_num = false;
+
+    for (dot_pos = len; dot_pos--;) {
+      char c = old_id->name[dot_pos];
+      if (c == '.') {
+        break;
+      }
+      else if (c < '0' || c > '9') {
+        has_num = false;
+        break;
+      }
+      has_num = true;
+    }
+
+    if (has_num) {
+      old_id->name[dot_pos] = '~';
+    }
+    else {
+      len = MIN2(len, MAX_ID_NAME - 7);
+      BLI_strncpy(&old_id->name[len], "~000", 7);
+    }
+
+    id_sort_by_name(which_libbase(bmain, GS(old_id->name)), old_id, NULL);
+
+    BKE_reportf(
+        reports,
+        RPT_WARNING,
+        "Lib Reload: Replacing all references to old data-block '%s' by reloaded one failed, "
+        "old one (%d remaining users) had to be kept and was renamed to '%s'",
+        new_id->name,
+        old_id->us,
+        old_id->name);
+  }
+}
+
 static void lib_relocate_do(Main *bmain,
                             Library *library,
                             WMLinkAppendData *lapp_data,
@@ -725,6 +814,12 @@ static void lib_relocate_do(Main *bmain,
         /* We remove it from current Main, and add it to items to link... */
         /* Note that non-linkable IDs (like e.g. shapekeys) are also explicitly linked here... */
         BLI_remlink(lbarray[lba_idx], id);
+        /* Usual special code for ShapeKeys snowflakes... */
+        Key *old_key = BKE_key_from_id(id);
+        if (old_key != NULL) {
+          BLI_remlink(which_libbase(bmain, GS(old_key->id.name)), &old_key->id);
+        }
+
         item = wm_link_append_data_item_add(lapp_data, id->name + 2, idcode, id);
         BLI_bitmap_set_all(item->libraries, true, lapp_data->num_libraries);
 
@@ -757,6 +852,12 @@ static void lib_relocate_do(Main *bmain,
 
     BLI_assert(old_id);
     BLI_addtail(which_libbase(bmain, GS(old_id->name)), old_id);
+
+    /* Usual special code for ShapeKeys snowflakes... */
+    Key *old_key = BKE_key_from_id(old_id);
+    if (old_key != NULL) {
+      BLI_addtail(which_libbase(bmain, GS(old_key->id.name)), &old_key->id);
+    }
   }
 
   /* Since our (old) reloaded IDs were removed from main, the user count done for them in linking
@@ -773,82 +874,20 @@ static void lib_relocate_do(Main *bmain,
     ID *old_id = item->customdata;
     ID *new_id = item->new_id;
 
-    BLI_assert(old_id);
-    if (do_reload) {
-      /* Since we asked for placeholders in case of missing IDs,
-       * we expect to always get a valid one. */
-      BLI_assert(new_id);
-    }
-    if (new_id) {
-#ifdef PRINT_DEBUG
-      printf("before remap of %s, old_id users: %d, new_id users: %d\n",
-             old_id->name,
-             old_id->us,
-             new_id->us);
-#endif
-      BKE_libblock_remap_locked(bmain, old_id, new_id, remap_flags);
-
-      if (old_id->flag & LIB_FAKEUSER) {
-        id_fake_user_clear(old_id);
-        id_fake_user_set(new_id);
-      }
-
-#ifdef PRINT_DEBUG
-      printf("after remap of %s, old_id users: %d, new_id users: %d\n",
-             old_id->name,
-             old_id->us,
-             new_id->us);
-#endif
-
-      /* In some cases, new_id might become direct link, remove parent of library in this case. */
-      if (new_id->lib->parent && (new_id->tag & LIB_TAG_INDIRECT) == 0) {
-        if (do_reload) {
-          BLI_assert(0); /* Should not happen in 'pure' reload case... */
-        }
-        new_id->lib->parent = NULL;
-      }
+    lib_relocate_do_remap(bmain, old_id, new_id, reports, do_reload, remap_flags);
+    /* Usual special code for ShapeKeys snowflakes... */
+    Key **old_key_p = BKE_key_from_id_p(old_id);
+    if (old_key_p == NULL) {
+      continue;
     }
-
-    if (old_id->us > 0 && new_id && old_id->lib == new_id->lib) {
-      /* Note that this *should* not happen - but better be safe than sorry in this area,
-       * at least until we are 100% sure this cannot ever happen.
-       * Also, we can safely assume names were unique so far,
-       * so just replacing '.' by '~' should work,
-       * but this does not totally rules out the possibility of name collision. */
-      size_t len = strlen(old_id->name);
-      size_t dot_pos;
-      bool has_num = false;
-
-      for (dot_pos = len; dot_pos--;) {
-        char c = old_id->name[dot_pos];
-        if (c == '.') {
-          break;
-        }
-        else if (c < '0' || c > '9') {
-          has_num = false;
-          break;
-        }
-        has_num = true;
-      }
-
-      if (has_num) {
-        old_id->name[dot_pos] = '~';
-      }
-      else {
-        len = MIN2(len, MAX_ID_NAME - 7);
-        BLI_strncpy(&old_id->name[len], "~000", 7);
-      }
-
-      id_sort_by_name(which_libbase(bmain, GS(old_id->name)), old_id, NULL);
-
-      BKE_reportf(
-          reports,
-          RPT_WARNING,
-          "Lib Reload: Replacing all references to old data-block '%s' by reloaded one failed, "
-          "old one (%d remaining users) had to be kept and was renamed to '%s'",
-          new_id->name,
-          old_id->us,
-          old_id->name);
+    Key *old_key = *old_key_p;
+    Key *new_key = BKE_key_from_id(new_id);
+    if (old_key != NULL) {
+      *old_key_p = NULL;
+      id_us_min(&old_key->id);
+      lib_relocate_do_remap(bmain, &old_key->id, &new_key->id, reports, do_reload, remap_flags);
+      *old_key_p = old_key;
+      id_us_plus_no_lib(&old_key->id);
     }
   }
 
@@ -900,6 +939,8 @@ static void lib_relocate_do(Main *bmain,
     }
   }
 
+  BKE_main_collection_sync(bmain);
+
   BKE_main_lib_objects_recalc_all(bmain);
   IMB_colormanagement_check_file_config(bmain);



More information about the Bf-blender-cvs mailing list