diff options
author | Bastien Montagne <bastien@blender.org> | 2020-08-20 12:20:47 +0300 |
---|---|---|
committer | Bastien Montagne <bastien@blender.org> | 2020-08-20 18:47:56 +0300 |
commit | 05e1ccf108366ee9ef95b41643dcbd656d819f5a (patch) | |
tree | f1abe27ffb26913ec433890d7114fa86cdd43f54 /source | |
parent | c74b4caa724bf74de41ba3928cdd824aa9ba59d2 (diff) |
Fix T79931: Infinite loop in scene "Full Copy" in 2.90.
Code dealing with object copy of master collection was bugy in case one
of the new object copy would get a name lesser than the original object,
leading to new copy being inserted before original one in lists.
Maniphest Tasks: T79931
Differential Revision: https://developer.blender.org/D8656
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/intern/collection.c | 22 |
1 files changed, 16 insertions, 6 deletions
diff --git a/source/blender/blenkernel/intern/collection.c b/source/blender/blenkernel/intern/collection.c index 5c618c8e9ce..461b40c6856 100644 --- a/source/blender/blenkernel/intern/collection.c +++ b/source/blender/blenkernel/intern/collection.c @@ -408,18 +408,28 @@ static Collection *collection_duplicate_recursive(Main *bmain, } if (do_objects) { + /* We need to first duplicate the objects in a separate loop, to support the master collection + * case, where both old and new collections are the same. + * Otherwise, depending on naming scheme and sorting, we may end up duplicating the new objects + * we just added, in some infinite loop. */ + LISTBASE_FOREACH (CollectionObject *, cob, &collection_old->gobject) { + Object *ob_old = cob->ob; + + if (ob_old->id.newid == NULL) { + BKE_object_duplicate( + bmain, ob_old, duplicate_flags, duplicate_options | LIB_ID_DUPLICATE_IS_SUBPROCESS); + } + } + /* We can loop on collection_old's objects, but have to consider it mutable because with master * collections collection_old and collection_new are the same data here. */ LISTBASE_FOREACH_MUTABLE (CollectionObject *, cob, &collection_old->gobject) { Object *ob_old = cob->ob; Object *ob_new = (Object *)ob_old->id.newid; - if (ob_new == NULL) { - ob_new = BKE_object_duplicate( - bmain, ob_old, duplicate_flags, duplicate_options | LIB_ID_DUPLICATE_IS_SUBPROCESS); - } - - if (ob_new == ob_old) { + /* New object can be NULL in master collection case, since new and old objects are in same + * collection. */ + if (ELEM(ob_new, ob_old, NULL)) { continue; } |