Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBastien Montagne <bastien@blender.org>2021-12-22 18:57:07 +0300
committerBastien Montagne <bastien@blender.org>2021-12-22 19:34:13 +0300
commit8d3e57f338234995c30ae702fff62ed6229f762e (patch)
treed27b1f8a3a9de4c4404aa06fb5743e6044228479 /source/blender/blenkernel/intern/collection.c
parent902318f0fd0e4f5ad73887451dcbe4f482e26702 (diff)
Fix T93799: Outliner: Remaping objects could result in duplicates in a collection.
Fix is similar to how CollectionObject with NULL object pointers are handled. Using one of the 'free' pad bytes in Object_Runtime struct instead of a gset (or other external way to detect object duplicates), as this is several times faster. NOTE: This makes remapping slightly slower again (adds 10 extra seconds to file case in T94059). General improvements of remapping time complexity, especially when remapping a lot of IDs at once, is a separate topic currently investigated in D13615.
Diffstat (limited to 'source/blender/blenkernel/intern/collection.c')
-rw-r--r--source/blender/blenkernel/intern/collection.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c
index 21a9159004f..57fe61b8ad4 100644
--- a/source/blender/blenkernel/intern/collection.c
+++ b/source/blender/blenkernel/intern/collection.c
@@ -1231,6 +1231,50 @@ void BKE_collections_object_remove_nulls(Main *bmain)
}
}
+/*
+ * Remove all duplicate objects from collections.
+ * This is used for library remapping, happens when remapping an object to another one already
+ * present in the collection. Otherwise this should never happen.
+ */
+static void collection_object_remove_duplicates(Collection *collection)
+{
+ bool changed = false;
+
+ LISTBASE_FOREACH_MUTABLE (CollectionObject *, cob, &collection->gobject) {
+ if (cob->ob->runtime.collection_management) {
+ BLI_freelinkN(&collection->gobject, cob);
+ changed = true;
+ continue;
+ }
+ cob->ob->runtime.collection_management = true;
+ }
+
+ /* Cleanup. */
+ LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
+ cob->ob->runtime.collection_management = false;
+ }
+
+ if (changed) {
+ BKE_collection_object_cache_free(collection);
+ }
+}
+
+void BKE_collections_object_remove_duplicates(struct Main *bmain)
+{
+ LISTBASE_FOREACH (Object *, ob, &bmain->objects) {
+ ob->runtime.collection_management = false;
+ }
+
+ for (Scene *scene = bmain->scenes.first; scene; scene = scene->id.next) {
+ collection_object_remove_duplicates(scene->master_collection);
+ }
+
+ for (Collection *collection = bmain->collections.first; collection;
+ collection = collection->id.next) {
+ collection_object_remove_duplicates(collection);
+ }
+}
+
static void collection_null_children_remove(Collection *collection)
{
for (CollectionChild *child = collection->children.first, *child_next = NULL; child;