Fix T93058: Crash on opening old pre-2.80 .blend files.
Layer resync code would not yet fully properly deal with all possible invalid status of ViewLayer comming from those older files. Now put 2.80-doversion specific fixes into their own dedicated function, so that they do not affect actual regular layer resync code anymore. Also added some sanity-checks in main `BKE_layer_collection_sync` code.
This commit is contained in:
parent
6c25aabddf
commit
96667e3391
Notes:
blender-bot
2023-02-14 00:13:36 +01:00
Referenced by issue #93058, Instant crash when opening some of the Eevee sample scenes
|
@ -157,6 +157,13 @@ int BKE_layer_collection_findindex(struct ViewLayer *view_layer, const struct La
|
|||
void BKE_layer_collection_resync_forbid(void);
|
||||
void BKE_layer_collection_resync_allow(void);
|
||||
|
||||
/** Helper to fix older pre-2.80 blendfiles.
|
||||
*
|
||||
* Ensures the given `view_layer` as a valid first-level layer collection, i.e. a single one
|
||||
* matching the scene's master collection. This is a requirement for `BKE_layer_collection_sync`.
|
||||
*/
|
||||
void BKE_layer_collection_doversion_2_80(const struct Scene *scene, struct ViewLayer *view_layer);
|
||||
|
||||
void BKE_main_collection_sync(const struct Main *bmain);
|
||||
void BKE_scene_collection_sync(const struct Scene *scene);
|
||||
/**
|
||||
|
|
|
@ -1196,6 +1196,23 @@ static bool view_layer_objects_base_cache_validate(ViewLayer *UNUSED(view_layer)
|
|||
}
|
||||
#endif
|
||||
|
||||
void BKE_layer_collection_doversion_2_80(const Scene *scene, ViewLayer *view_layer)
|
||||
{
|
||||
LayerCollection *first_layer_collection = view_layer->layer_collections.first;
|
||||
if (BLI_listbase_count_at_most(&view_layer->layer_collections, 2) > 1 ||
|
||||
first_layer_collection->collection != scene->master_collection) {
|
||||
/* In some cases (from older files) we do have a master collection, but no matching layer,
|
||||
* instead all the children of the master collection have their layer collections in the
|
||||
* viewlayer's list. This is not a valid situation, add a layer for the master collection and
|
||||
* add all existing first-level layers as children of that new master layer. */
|
||||
ListBase layer_collections = view_layer->layer_collections;
|
||||
BLI_listbase_clear(&view_layer->layer_collections);
|
||||
LayerCollection *master_layer_collection = layer_collection_add(&view_layer->layer_collections,
|
||||
scene->master_collection);
|
||||
master_layer_collection->layer_collections = layer_collections;
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_layer_collection_sync(const Scene *scene, ViewLayer *view_layer)
|
||||
{
|
||||
if (no_resync) {
|
||||
|
@ -1208,21 +1225,24 @@ void BKE_layer_collection_sync(const Scene *scene, ViewLayer *view_layer)
|
|||
}
|
||||
|
||||
if (BLI_listbase_is_empty(&view_layer->layer_collections)) {
|
||||
/* In some cases (from older files) we do have a master collection, yet no matching layer.
|
||||
* Create the master one here, so that the rest of the code can work as expected. */
|
||||
/* In some cases (from older files, or when creating a new ViewLayer from
|
||||
* #BKE_view_layer_add), we do have a master collection, yet no matching layer. Create the
|
||||
* master one here, so that the rest of the code can work as expected. */
|
||||
layer_collection_add(&view_layer->layer_collections, scene->master_collection);
|
||||
}
|
||||
else if (BLI_listbase_count_at_most(&view_layer->layer_collections, 2) > 1) {
|
||||
/* In some cases (from older files) we do have a master collection, but no matching layer,
|
||||
* instead all the children of the master collection have their layer collections in the
|
||||
* viewlayer's list. This is not a valid situation, add a layer for the master collection and
|
||||
* add all existing first-level layers as children of that new master layer. */
|
||||
ListBase layer_collections = view_layer->layer_collections;
|
||||
BLI_listbase_clear(&view_layer->layer_collections);
|
||||
LayerCollection *master_layer_collection = layer_collection_add(&view_layer->layer_collections,
|
||||
scene->master_collection);
|
||||
master_layer_collection->layer_collections = layer_collections;
|
||||
|
||||
#ifndef NDEBUG
|
||||
{
|
||||
BLI_assert_msg(BLI_listbase_count_at_most(&view_layer->layer_collections, 2) == 1,
|
||||
"ViewLayer's first level of children layer collections should always have "
|
||||
"exactly one item");
|
||||
|
||||
LayerCollection *first_layer_collection = view_layer->layer_collections.first;
|
||||
BLI_assert_msg(first_layer_collection->collection == scene->master_collection,
|
||||
"ViewLayer's first layer collection should always be the one for the scene's "
|
||||
"master collection");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Free cache. */
|
||||
MEM_SAFE_FREE(view_layer->object_bases_array);
|
||||
|
|
|
@ -402,6 +402,8 @@ static void do_version_scene_collection_to_collection(Main *bmain, Scene *scene)
|
|||
do_version_layer_collection_pre(
|
||||
view_layer, &view_layer->layer_collections, enabled_set, selectable_set);
|
||||
|
||||
BKE_layer_collection_doversion_2_80(scene, view_layer);
|
||||
|
||||
BKE_layer_collection_sync(scene, view_layer);
|
||||
|
||||
do_version_layer_collection_post(
|
||||
|
|
Loading…
Reference in New Issue