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:
@@ -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)
|
||||
|
||||
@@ -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. */
|
||||
|
||||
Reference in New Issue
Block a user