Fix #147317 Crash on undo/redo with PackedData.

The issue here was that when an archive library ID is read from
blendfile (memfile undo buffer in that case), a new split main is
immediately created for it in `direct_link_library`, and the newly
read Library is assigned to its `Main::curlib` pointer.

However, in undo readfile code, when an old matching ID is found, the
new data is moved into that old address, to avoid modifying all other
unchanged ID using that re-read data-block.

For (archive) libraries, it means that their split main `curlib` pointer
also needs to be re-assigned to the re-used old address.

Pull Request: https://projects.blender.org/blender/blender/pulls/147744
This commit is contained in:
Bastien Montagne
2025-10-15 11:09:01 +02:00
committed by Bastien Montagne
parent a5618366cb
commit 408a0b58d4

View File

@@ -3094,6 +3094,31 @@ static void read_libblock_undo_restore_at_old_address(FileData *fd, Main *main,
BLI_addtail(new_lb, id_old);
BLI_addtail(old_lb, id);
/* In case a library has been re-read, it has added already its own split main to the new Main
* (see #direct_link_library code).
*
* Since we are replacing it with the 'id_old' address, we need to update that Main::curlib
* pointer accordingly.
*
* Note that:
* - This code is only for undo, and on undo we do not re-read regular libraries, only archive
* ones for packed data.
* - The new split main should still be empty at this stage (this code and adding the split
* Main in #direct_link_library are part of the same #read_libblock call).
*/
if (GS(id_old->name) == ID_LI) {
Library *lib_old = blender::id_cast<Library *>(id_old);
Library *lib = blender::id_cast<Library *>(id);
BLI_assert(lib_old->flag & LIBRARY_FLAG_IS_ARCHIVE);
for (Main *bmain_iter : *fd->bmain->split_mains) {
if (bmain_iter->curlib == lib) {
BLI_assert(BKE_main_is_empty(bmain_iter));
bmain_iter->curlib = lib_old;
}
}
}
}
static bool read_libblock_undo_restore(