Commit: 96667e33913e37e257ae444009c5f7bea57b0d72
Author: Bastien Montagne
Date:   Tue Jan 25 16:42:31 2022 +0100
Branches: master
https://developer.blender.org/rB96667e33913e37e257ae444009c5f7bea57b0d72

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.

===================================================================

M       source/blender/blenkernel/BKE_layer.h
M       source/blender/blenkernel/intern/layer.c
M       source/blender/blenloader/intern/versioning_280.c

===================================================================

diff --git a/source/blender/blenkernel/BKE_layer.h 
b/source/blender/blenkernel/BKE_layer.h
index bc2249b93b9..6460dedb736 100644
--- a/source/blender/blenkernel/BKE_layer.h
+++ b/source/blender/blenkernel/BKE_layer.h
@@ -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);
 /**
diff --git a/source/blender/blenkernel/intern/layer.c 
b/source/blender/blenkernel/intern/layer.c
index 9e3cea40fb8..a59dd6f2e0e 100644
--- a/source/blender/blenkernel/intern/layer.c
+++ b/source/blender/blenkernel/intern/layer.c
@@ -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);
diff --git a/source/blender/blenloader/intern/versioning_280.c 
b/source/blender/blenloader/intern/versioning_280.c
index d9052c6b1f7..ceddc451a46 100644
--- a/source/blender/blenloader/intern/versioning_280.c
+++ b/source/blender/blenloader/intern/versioning_280.c
@@ -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(

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
List details, subscription details or unsubscribe:
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to