[Bf-blender-cvs] [d1f96f9b119] master: BKE Collection: Add new function to rebuild parent relationships.

Bastien Montagne noreply at git.blender.org
Wed May 22 23:37:56 CEST 2019


Commit: d1f96f9b1194404ffafd2540cd2928048779656e
Author: Bastien Montagne
Date:   Wed May 22 22:51:36 2019 +0200
Branches: master
https://developer.blender.org/rBd1f96f9b1194404ffafd2540cd2928048779656e

BKE Collection: Add new function to rebuild parent relationships.

It's not always possible to keep 'by hand' parent relationships valid in
collections hierarchy. Add functions to remake those
(re-using/factorizing code from `readfile.c` `lib_link_collection_data()`
function).

Can't stress again how painful it is to have those kind of backward
relationships in our data structures, those *always* end up being
serious issues to keep in sync... Should only be generated on the fly
when needed, period. :(

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

M	source/blender/blenkernel/BKE_collection.h
M	source/blender/blenkernel/intern/collection.c
M	source/blender/blenloader/intern/readfile.c

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

diff --git a/source/blender/blenkernel/BKE_collection.h b/source/blender/blenkernel/BKE_collection.h
index 0e093bb086b..502c949be9a 100644
--- a/source/blender/blenkernel/BKE_collection.h
+++ b/source/blender/blenkernel/BKE_collection.h
@@ -163,6 +163,9 @@ bool BKE_collection_find_cycle(struct Collection *new_ancestor, struct Collectio
 
 bool BKE_collection_has_collection(struct Collection *parent, struct Collection *collection);
 
+void BKE_collection_parent_relations_rebuild(struct Collection *collection);
+void BKE_main_collections_parent_relations_rebuild(struct Main *bmain);
+
 /* Iteration callbacks. */
 
 typedef void (*BKE_scene_objects_Cb)(struct Object *ob, void *data);
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
index d2ca304e973..68392bf0d03 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -1056,6 +1056,72 @@ bool BKE_collection_child_remove(Main *bmain, Collection *parent, Collection *ch
   return true;
 }
 
+/**
+ * Rebuild parent relationships from child ones, for all children of given \a collection.
+ *
+ * \note Given collection is assumed to already have valid parents.
+ */
+void BKE_collection_parent_relations_rebuild(Collection *collection)
+{
+  for (CollectionChild *child = collection->children.first, *child_next = NULL; child;
+       child = child_next) {
+    child_next = child->next;
+
+    if (child->collection == NULL || BKE_collection_find_cycle(collection, child->collection)) {
+      BLI_freelinkN(&collection->children, child);
+    }
+    else {
+      CollectionParent *cparent = MEM_callocN(sizeof(CollectionParent), __func__);
+      cparent->collection = collection;
+      BLI_addtail(&child->collection->parents, cparent);
+    }
+  }
+}
+
+static void collection_parents_rebuild_recursive(Collection *collection)
+{
+  BKE_collection_parent_relations_rebuild(collection);
+  collection->id.tag &= ~LIB_TAG_DOIT;
+
+  for (CollectionChild *child = collection->children.first; child != NULL; child = child->next) {
+    collection_parents_rebuild_recursive(child->collection);
+  }
+}
+
+/**
+ * Rebuild parent relationships from child ones, for all collections in given \a bmain.
+ *
+ * \note Uses LIB_TAG_DOIT internally...
+ */
+void BKE_main_collections_parent_relations_rebuild(Main *bmain)
+{
+  /* Only collections not in bmain (master ones in scenes) have no parent... */
+  for (Collection *collection = bmain->collections.first; collection != NULL;
+       collection = collection->id.next) {
+    BLI_freelistN(&collection->parents);
+
+    collection->id.tag |= LIB_TAG_DOIT;
+  }
+
+  /* Scene's master collections will be 'root' parent of most of our collections, so start with
+   * them. */
+  for (Scene *scene = bmain->scenes.first; scene != NULL; scene = scene->id.next) {
+    collection_parents_rebuild_recursive(scene->master_collection);
+  }
+
+  /* We may have parent chains outside of scene's master_collection context? At least, readfile's
+   * lib_link_collection_data() seems to assume that, so do the same here. */
+  for (Collection *collection = bmain->collections.first; collection != NULL;
+       collection = collection->id.next) {
+    if (collection->id.tag & LIB_TAG_DOIT) {
+      /* Note: we do not have easy access to 'which collections is root' info in that case, which
+       * means test for cycles in collection relationships may fail here. I don't think that is an
+       * issue in practice here, but worth keeping in mind... */
+      collection_parents_rebuild_recursive(collection);
+    }
+  }
+}
+
 /********************** Collection index *********************/
 
 static Collection *collection_from_index_recursive(Collection *collection,
diff --git a/source/blender/blenloader/intern/readfile.c b/source/blender/blenloader/intern/readfile.c
index 5edba272cd4..de6e5a80912 100644
--- a/source/blender/blenloader/intern/readfile.c
+++ b/source/blender/blenloader/intern/readfile.c
@@ -6228,20 +6228,11 @@ static void lib_link_collection_data(FileData *fd, Library *lib, Collection *col
     }
   }
 
-  for (CollectionChild *child = collection->children.first, *child_next = NULL; child;
-       child = child_next) {
-    child_next = child->next;
+  for (CollectionChild *child = collection->children.first; child != NULL; child = child->next) {
     child->collection = newlibadr_us(fd, lib, child->collection);
-
-    if (child->collection == NULL || BKE_collection_find_cycle(collection, child->collection)) {
-      BLI_freelinkN(&collection->children, child);
-    }
-    else {
-      CollectionParent *cparent = MEM_callocN(sizeof(CollectionParent), "CollectionParent");
-      cparent->collection = collection;
-      BLI_addtail(&child->collection->parents, cparent);
-    }
   }
+
+  BKE_collection_parent_relations_rebuild(collection);
 }
 
 static void lib_link_collection(FileData *fd, Main *main)



More information about the Bf-blender-cvs mailing list