diff options
author | Bastien Montagne <bastien@blender.org> | 2021-06-03 11:18:44 +0300 |
---|---|---|
committer | Bastien Montagne <bastien@blender.org> | 2021-06-03 11:27:05 +0300 |
commit | 2ef192a55b2ca65f07f678aada199357b06713e9 (patch) | |
tree | 99141ea19636117401be509d0e62eaaad973089e | |
parent | a51f8f94d5dc7c0b8f61de35f277052144299662 (diff) |
IDManagement: Collection: Fix several issues in relationships building code.
`BKE_main_collections_parent_relations_rebuild`,
`BKE_collection_parent_relations_rebuild` anf their internal
dependencies had two issues fixed by this commit:
* Main one was that a same collection could be processed several times,
sometimes even in an infinite loop (in some rare corner cases), by
`collection_parents_rebuild_recursive`.
* More exotic, code here would not ensure that the collections it was
processing were actually in Main (or a master one from a scene in
Main), which became an issue with some advanced ID management
processes involving partially out-of-main remapping, like liboverride
resync.
-rw-r--r-- | source/blender/blenkernel/intern/collection.c | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c index be827cd338d..5a7fe71de8e 100644 --- a/source/blender/blenkernel/intern/collection.c +++ b/source/blender/blenkernel/intern/collection.c @@ -1643,6 +1643,13 @@ void BKE_collection_parent_relations_rebuild(Collection *collection) continue; } + /* Can happen when remaping data partially out-of-Main (during advanced ID management + * operations like liboverride resync e.g.). */ + if ((child->collection->id.tag & (LIB_TAG_NO_MAIN | LIB_TAG_COPIED_ON_WRITE)) != 0) { + continue; + } + + BLI_assert(collection_find_parent(child->collection, collection) == NULL); CollectionParent *cparent = MEM_callocN(sizeof(CollectionParent), __func__); cparent->collection = collection; BLI_addtail(&child->collection->parents, cparent); @@ -1651,10 +1658,19 @@ void BKE_collection_parent_relations_rebuild(Collection *collection) static void collection_parents_rebuild_recursive(Collection *collection) { + /* A same collection may be child of several others, no need to process it more than once. */ + if ((collection->tag & COLLECTION_TAG_RELATION_REBUILD) == 0) { + return; + } + BKE_collection_parent_relations_rebuild(collection); collection->tag &= ~COLLECTION_TAG_RELATION_REBUILD; for (CollectionChild *child = collection->children.first; child != NULL; child = child->next) { + /* See comment above in `BKE_collection_parent_relations_rebuild`. */ + if ((collection->id.tag & (LIB_TAG_NO_MAIN | LIB_TAG_COPIED_ON_WRITE)) != 0) { + continue; + } collection_parents_rebuild_recursive(child->collection); } } @@ -1678,6 +1694,8 @@ void BKE_main_collections_parent_relations_rebuild(Main *bmain) /* This function can be called from readfile.c, when this pointer is not guaranteed to be NULL. */ if (scene->master_collection != NULL) { + BLI_assert(BLI_listbase_is_empty(&scene->master_collection->parents)); + scene->master_collection->tag |= COLLECTION_TAG_RELATION_REBUILD; collection_parents_rebuild_recursive(scene->master_collection); } } |