Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brecht@blender.org>2020-04-03 14:34:12 +0300
committerBrecht Van Lommel <brecht@blender.org>2020-04-07 14:19:52 +0300
commitc75aaf5329afa9cfbecbb6ac7f646e76546613ca (patch)
tree1d73214aee67ce1ed8e30ee7c4217a26d03234f1
parent624b231ec49997120cff17ae68a39cb13e267ee7 (diff)
Cleanup: split off library and linked datablock undo restore
Differential Revision: https://developer.blender.org/D7326
-rw-r--r--source/blender/blenloader/intern/readfile.c116
1 files changed, 68 insertions, 48 deletions
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 8f77c80d64b..2cd891a1796 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -9404,6 +9404,67 @@ static BHead *read_data_into_oldnewmap(FileData *fd, BHead *bhead, const char *a
return bhead;
}
+static bool read_libblock_undo_restore_library(FileData *fd, Main *main, const ID *id)
+{
+ /* In undo case, most libs and linked data should be kept as is from previous state
+ * (see BLO_read_from_memfile).
+ * However, some needed by the snapshot being read may have been removed in previous one,
+ * and would go missing.
+ * This leads e.g. to disappearing objects in some undo/redo case, see T34446.
+ * That means we have to carefully check whether current lib or
+ * libdata already exits in old main, if it does we merely copy it over into new main area,
+ * otherwise we have to do a full read of that bhead... */
+ DEBUG_PRINTF("UNDO: restore library %s\n", id->name);
+
+ Main *libmain = fd->old_mainlist->first;
+ /* Skip oldmain itself... */
+ for (libmain = libmain->next; libmain; libmain = libmain->next) {
+ DEBUG_PRINTF(" compare with %s -> ", libmain->curlib ? libmain->curlib->id.name : "<NULL>");
+ if (libmain->curlib && STREQ(id->name, libmain->curlib->id.name)) {
+ Main *oldmain = fd->old_mainlist->first;
+ DEBUG_PRINTF("match!\n");
+ /* In case of a library, we need to re-add its main to fd->mainlist,
+ * because if we have later a missing ID_LINK_PLACEHOLDER,
+ * we need to get the correct lib it is linked to!
+ * Order is crucial, we cannot bulk-add it in BLO_read_from_memfile()
+ * like it used to be. */
+ BLI_remlink(fd->old_mainlist, libmain);
+ BLI_remlink_safe(&oldmain->libraries, libmain->curlib);
+ BLI_addtail(fd->mainlist, libmain);
+ BLI_addtail(&main->libraries, libmain->curlib);
+ return true;
+ }
+ DEBUG_PRINTF("no match\n");
+ }
+
+ return false;
+}
+
+static bool read_libblock_undo_restore_linked(FileData *fd, Main *main, const ID *id, BHead *bhead)
+{
+ DEBUG_PRINTF("UNDO: restore linked datablock %s\n", id->name);
+ DEBUG_PRINTF(" from %s (%s): ",
+ main->curlib ? main->curlib->id.name : "<NULL>",
+ main->curlib ? main->curlib->name : "<NULL>");
+
+ ID *existing_id = BKE_libblock_find_name(main, GS(id->name), id->name + 2);
+ if (existing_id != NULL) {
+ DEBUG_PRINTF(" found!\n");
+ /* Even though we found our linked ID,
+ * there is no guarantee its address is still the same. */
+ if (existing_id != bhead->old) {
+ oldnewmap_insert(fd->libmap, bhead->old, existing_id, GS(existing_id->name));
+ }
+
+ /* No need to do anything else for ID_LINK_PLACEHOLDER,
+ * it's assumed already present in its lib's main. */
+ return true;
+ }
+
+ DEBUG_PRINTF(" not found\n");
+ return false;
+}
+
static BHead *read_libblock(FileData *fd,
Main *main,
BHead *bhead,
@@ -9434,60 +9495,19 @@ static BHead *read_libblock(FileData *fd,
return blo_bhead_next(fd, bhead);
}
- /* In undo case, most libs and linked data should be kept as is from previous state
- * (see BLO_read_from_memfile).
- * However, some needed by the snapshot being read may have been removed in previous one,
- * and would go missing.
- * This leads e.g. to disappearing objects in some undo/redo case, see T34446.
- * That means we have to carefully check whether current lib or
- * libdata already exits in old main, if it does we merely copy it over into new main area,
- * otherwise we have to do a full read of that bhead... */
- if (fd->memfile != NULL && ELEM(bhead->code, ID_LI, ID_LINK_PLACEHOLDER)) {
- DEBUG_PRINTF("Checking %s...\n", id->name);
-
+ /* Restore library and linked datablocks for undo. */
+ if (fd->memfile != NULL) {
if (bhead->code == ID_LI) {
- Main *libmain = fd->old_mainlist->first;
- /* Skip oldmain itself... */
- for (libmain = libmain->next; libmain; libmain = libmain->next) {
- DEBUG_PRINTF("... against %s: ", libmain->curlib ? libmain->curlib->id.name : "<NULL>");
- if (libmain->curlib && STREQ(id->name, libmain->curlib->id.name)) {
- Main *oldmain = fd->old_mainlist->first;
- DEBUG_PRINTF("FOUND!\n");
- /* In case of a library, we need to re-add its main to fd->mainlist,
- * because if we have later a missing ID_LINK_PLACEHOLDER,
- * we need to get the correct lib it is linked to!
- * Order is crucial, we cannot bulk-add it in BLO_read_from_memfile()
- * like it used to be. */
- BLI_remlink(fd->old_mainlist, libmain);
- BLI_remlink_safe(&oldmain->libraries, libmain->curlib);
- BLI_addtail(fd->mainlist, libmain);
- BLI_addtail(&main->libraries, libmain->curlib);
-
- MEM_freeN(id);
- return blo_bhead_next(fd, bhead);
- }
- DEBUG_PRINTF("nothing...\n");
+ if (read_libblock_undo_restore_library(fd, main, id)) {
+ MEM_freeN(id);
+ return blo_bhead_next(fd, bhead);
}
}
- else {
- DEBUG_PRINTF("... in %s (%s): ",
- main->curlib ? main->curlib->id.name : "<NULL>",
- main->curlib ? main->curlib->name : "<NULL>");
- ID *existing_id = BKE_libblock_find_name(main, GS(id->name), id->name + 2);
- if (existing_id != NULL) {
- DEBUG_PRINTF("FOUND!\n");
- /* Even though we found our linked ID,
- * there is no guarantee its address is still the same. */
- if (existing_id != bhead->old) {
- oldnewmap_insert(fd->libmap, bhead->old, existing_id, GS(existing_id->name));
- }
-
- /* No need to do anything else for ID_LINK_PLACEHOLDER,
- * it's assumed already present in its lib's main. */
+ else if (bhead->code == ID_LINK_PLACEHOLDER) {
+ if (read_libblock_undo_restore_linked(fd, main, id, bhead)) {
MEM_freeN(id);
return blo_bhead_next(fd, bhead);
}
- DEBUG_PRINTF("nothing...\n");
}
}