Fix #107913: LibOverride: Hard Crash Opening Blender File with overriden active scene.

The main issue was the fact that if a Scene is overridden, it's content
will be fully invalidated when updating the liboverride at the end of
the file reading process. Since the FileData keeps a pointer to the
active view layer, it needs to be udated then.

As a side consequence, the liblinking of global data also needs to
happen before liboverrides are updated.
This commit is contained in:
Bastien Montagne
2023-05-24 17:37:42 +02:00
parent 43e6f110f4
commit babdfc2294
2 changed files with 27 additions and 4 deletions

View File

@@ -2667,8 +2667,8 @@ static bool lib_override_library_main_resync_id_skip_check(ID *id,
/**
* Clear 'unreachable' tag of existing liboverrides if they are using another reachable liboverride
* (typical case: Mesh object which only relationship to the rest of the liboverride hierarchy is
* though its 'parent' pointer (i.e. rest of the hierarchy has no actual relationship to this mesh
* object). Sadge.
* through its 'parent' pointer (i.e. rest of the hierarchy has no actual relationship to this mesh
* object).
*
* Logic and rational of this function are very similar to these of
* #lib_override_hierarchy_dependencies_recursive_tag_from, but withing specific resync context.
@@ -4440,10 +4440,20 @@ void BKE_lib_override_library_main_unused_cleanup(Main *bmain)
static void lib_override_id_swap(Main *bmain, ID *id_local, ID *id_temp)
{
/* Ensure ViewLayers are in sync in case a Scene is being swapped, and prevent any further resync
* during the swapping itself. */
if (GS(id_local->name) == ID_SCE) {
BKE_scene_view_layers_synced_ensure(reinterpret_cast<Scene *>(id_local));
BKE_scene_view_layers_synced_ensure(reinterpret_cast<Scene *>(id_temp));
}
BKE_layer_collection_resync_forbid();
BKE_lib_id_swap(bmain, id_local, id_temp, true, 0);
/* We need to keep these tags from temp ID into orig one.
* ID swap does not swap most of ID data itself. */
id_local->tag |= (id_temp->tag & LIB_TAG_LIBOVERRIDE_NEED_RESYNC);
BKE_layer_collection_resync_allow();
}
void BKE_lib_override_library_update(Main *bmain, ID *local)

View File

@@ -3956,15 +3956,30 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
BKE_main_id_tag_all(bfd->main, LIB_TAG_NEW, false);
/* Must happen before applying liboverrides, as this process may fully invalidate e.g. view
* layer pointers in case a Scene is a liboverride. */
link_global(fd, bfd);
/* Now that all our data-blocks are loaded,
* we can re-generate overrides from their references. */
if ((fd->flags & FD_FLAGS_IS_MEMFILE) == 0) {
/* Do not apply in undo case! */
fd->reports->duration.lib_overrides = PIL_check_seconds_timer();
std::string cur_view_layer_name = bfd->cur_view_layer != nullptr ?
bfd->cur_view_layer->name :
"";
BKE_lib_override_library_main_validate(bfd->main, fd->reports->reports);
BKE_lib_override_library_main_update(bfd->main);
/* In case the current scene is a liboverride, while the ID pointer itself remains valid,
* above update of liboverrides will have completely invalidated its old content, so the
* current viewlayer needs to be searched for again. */
if (bfd->cur_view_layer != nullptr) {
bfd->cur_view_layer = BKE_view_layer_find(bfd->curscene, cur_view_layer_name.c_str());
}
/* FIXME Temporary 'fix' to a problem in how temp ID are copied in
* `BKE_lib_override_library_main_update`, see #103062.
* Proper fix involves first addressing #90610. */
@@ -3978,8 +3993,6 @@ BlendFileData *blo_read_file_internal(FileData *fd, const char *filepath)
/* Make all relative paths, relative to the open blend file. */
fix_relpaths_library(fd->relabase, bfd->main);
link_global(fd, bfd); /* as last */
}
fd->mainlist = nullptr; /* Safety, this is local variable, shall not be used afterward. */