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 <brechtvanlommel@gmail.com>2018-10-18 20:51:34 +0300
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2018-10-18 21:21:36 +0300
commitde3f9303eb958d34e4793ff91fafedda0b41ee98 (patch)
treefc2a542a361226324a45a5219789c6754eb13e19 /source/blender/blenkernel/intern/blendfile.c
parent5f8222501c2267ae82829ccf6f6df295a8b8ec55 (diff)
Fix Copy Selection to Buffer breaking library paths.
This is a bug experienced by animators in the Blender Studio that developers have been trying to fix for a /long/ time. What happens is that partial file writing extracts the needed datablocks from the main list of datablocks into a smaller one. Afterwards they are added back to the main list, but in some cases not exactly in the same order. There is file path remapping code that depends on the datablocks being in exactly the same order as before, and when this was not the case filepaths would get swapped between datablocks The reason datablocks are not restored in the same order is because the sorting of datablocks by name is a) case insensitive and b) undefined if there are multiple datablocks with the same name from different libraries. This should be made well defined, but the fix in this commit is simpler. The way animators ran into this bug is that they use the Copy Attributes addon a lot, which has as the first item in the menu Copy Selection to Buffer. In some cases this would be clicked accidentally when menu is near the edge of the window, breaking the library paths which would only be noticed a much later on file save and reload. The way this bug was finally tracked down is that it was suspected that the undo system was the cause, and so Bastien added library validation for undo. When Hjalti then did undo and noticed the error, he remembered accidentally clicking Copy Selection to Buffer just before, and we could finally reproduce the bug.
Diffstat (limited to 'source/blender/blenkernel/intern/blendfile.c')
-rw-r--r--source/blender/blenkernel/intern/blendfile.c26
1 files changed, 17 insertions, 9 deletions
diff --git a/source/blender/blenkernel/intern/blendfile.c b/source/blender/blenkernel/intern/blendfile.c
index aa5530704c6..c92648da67c 100644
--- a/source/blender/blenkernel/intern/blendfile.c
+++ b/source/blender/blenkernel/intern/blendfile.c
@@ -590,10 +590,6 @@ bool BKE_blendfile_write_partial(
* (otherwise main->name will not be set at read time). */
BLI_strncpy(bmain_dst->name, bmain_src->name, sizeof(bmain_dst->name));
- if (write_flags & G_FILE_RELATIVE_REMAP) {
- path_list_backup = BKE_bpath_list_backup(bmain_src, path_list_flag);
- }
-
BLO_main_expander(blendfile_write_partial_cb);
BLO_expand_main(NULL, bmain_src);
@@ -613,10 +609,27 @@ bool BKE_blendfile_write_partial(
}
}
+ /* Backup paths because remap relative will overwrite them.
+ *
+ * NOTE: we do this only on the list of datablocks that we are writing
+ * because the restored full list is not guaranteed to be in the same
+ * order as before, as expected by BKE_bpath_list_restore.
+ *
+ * This happens because id_sort_by_name does not take into account
+ * string case or the library name, so the order is not strictly
+ * defined for two linked datablocks with the same name! */
+ if (write_flags & G_FILE_RELATIVE_REMAP) {
+ path_list_backup = BKE_bpath_list_backup(bmain_dst, path_list_flag);
+ }
/* save the buffer */
retval = BLO_write_file(bmain_dst, filepath, write_flags, reports, NULL);
+ if (path_list_backup) {
+ BKE_bpath_list_restore(bmain_dst, path_list_flag, path_list_backup);
+ BKE_bpath_list_free(path_list_backup);
+ }
+
/* move back the main, now sorted again */
set_listbasepointers(bmain_src, lbarray_dst);
a = set_listbasepointers(bmain_dst, lbarray_src);
@@ -632,11 +645,6 @@ bool BKE_blendfile_write_partial(
MEM_freeN(bmain_dst);
- if (path_list_backup) {
- BKE_bpath_list_restore(bmain_src, path_list_flag, path_list_backup);
- BKE_bpath_list_free(path_list_backup);
- }
-
return retval;
}