2 * ***** BEGIN GPL LICENSE BLOCK *****
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software Foundation,
16 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 * Contributor(s): Dalai Felinto
20 * ***** END GPL LICENSE BLOCK *****
23 /** \file blender/blenkernel/intern/collection.c
29 #include "BLI_blenlib.h"
30 #include "BLI_ghash.h"
31 #include "BLI_iterator.h"
32 #include "BLI_listbase.h"
33 #include "BLI_math_base.h"
34 #include "BLI_threads.h"
35 #include "BLT_translation.h"
36 #include "BLI_string_utils.h"
38 #include "BKE_collection.h"
39 #include "BKE_icons.h"
40 #include "BKE_idprop.h"
41 #include "BKE_layer.h"
42 #include "BKE_library.h"
44 #include "BKE_object.h"
45 #include "BKE_rigidbody.h"
46 #include "BKE_scene.h"
49 #include "DNA_collection_types.h"
50 #include "DNA_layer_types.h"
51 #include "DNA_object_types.h"
52 #include "DNA_scene_types.h"
54 #include "DEG_depsgraph.h"
55 #include "DEG_depsgraph_query.h"
57 #include "MEM_guardedalloc.h"
59 /******************************** Prototypes ********************************/
61 static bool collection_child_add(Collection *parent, Collection *collection, const int flag, const bool add_us);
62 static bool collection_child_remove(Collection *parent, Collection *collection);
63 static bool collection_object_add(Main *bmain, Collection *collection, Object *ob, int flag, const bool add_us);
64 static bool collection_object_remove(Main *bmain, Collection *collection, Object *ob, const bool free_us);
66 static CollectionChild *collection_find_child(Collection *parent, Collection *collection);
67 static CollectionParent *collection_find_parent(Collection *child, Collection *collection);
69 static bool collection_find_child_recursive(Collection *parent, Collection *collection);
71 /***************************** Add Collection *******************************/
73 /* Add new collection, without view layer syncing. */
74 static Collection *collection_add(Main *bmain, Collection *collection_parent, const char *name_custom)
76 /* Determine new collection name. */
80 STRNCPY(name, name_custom);
83 BKE_collection_new_name_get(collection_parent, name);
86 /* Create new collection. */
87 Collection *collection = BKE_libblock_alloc(bmain, ID_GR, name, 0);
89 /* We increase collection user count when linking to Collections. */
90 id_us_min(&collection->id);
92 /* Optionally add to parent collection. */
93 if (collection_parent) {
94 collection_child_add(collection_parent, collection, 0, true);
101 * Add a collection to a collection ListBase and synchronize all render layers
102 * The ListBase is NULL when the collection is to be added to the master collection
104 Collection *BKE_collection_add(Main *bmain, Collection *collection_parent, const char *name_custom)
106 Collection *collection = collection_add(bmain, collection_parent, name_custom);
107 BKE_main_collection_sync(bmain);
111 /*********************** Free and Delete Collection ****************************/
113 /** Free (or release) any data used by this collection (does not free the collection itself). */
114 void BKE_collection_free(Collection *collection)
116 /* No animdata here. */
117 BKE_previewimg_free(&collection->preview);
119 BLI_freelistN(&collection->gobject);
120 BLI_freelistN(&collection->children);
121 BLI_freelistN(&collection->parents);
123 BKE_collection_object_cache_free(collection);
127 * Remove a collection, optionally removing its child objects or moving
128 * them to parent collections.
130 bool BKE_collection_delete(Main *bmain, Collection *collection, bool hierarchy)
132 /* Master collection is not real datablock, can't be removed. */
133 if (collection->flag & COLLECTION_IS_MASTER) {
134 BLI_assert(!"Scene master collection can't be deleted");
139 /* Remove child objects. */
140 CollectionObject *cob = collection->gobject.first;
141 while (cob != NULL) {
142 collection_object_remove(bmain, collection, cob->ob, true);
143 cob = collection->gobject.first;
146 /* Delete all child collections recursively. */
147 CollectionChild *child = collection->children.first;
148 while (child != NULL) {
149 BKE_collection_delete(bmain, child->collection, hierarchy);
150 child = collection->children.first;
154 /* Link child collections into parent collection. */
155 for (CollectionChild *child = collection->children.first; child; child = child->next) {
156 for (CollectionParent *cparent = collection->parents.first; cparent; cparent = cparent->next) {
157 Collection *parent = cparent->collection;
158 collection_child_add(parent, child->collection, 0, true);
162 CollectionObject *cob = collection->gobject.first;
163 while (cob != NULL) {
164 /* Link child object into parent collections. */
165 for (CollectionParent *cparent = collection->parents.first; cparent; cparent = cparent->next) {
166 Collection *parent = cparent->collection;
167 collection_object_add(bmain, parent, cob->ob, 0, true);
170 /* Remove child object. */
171 collection_object_remove(bmain, collection, cob->ob, true);
172 cob = collection->gobject.first;
176 BKE_libblock_delete(bmain, collection);
178 BKE_main_collection_sync(bmain);
183 /***************************** Collection Copy *******************************/
186 * Only copy internal data of Collection ID from source to already allocated/initialized destination.
187 * You probably nerver want to use that directly, use id_copy or BKE_id_copy_ex for typical needs.
189 * WARNING! This function will not handle ID user count!
191 * \param flag: Copying options (see BKE_library.h's LIB_ID_COPY_... flags for more).
193 void BKE_collection_copy_data(
194 Main *bmain, Collection *collection_dst, const Collection *collection_src, const int flag)
196 /* Do not copy collection's preview (same behavior as for objects). */
197 if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0 && false) { /* XXX TODO temp hack */
198 BKE_previewimg_id_copy(&collection_dst->id, &collection_src->id);
201 collection_dst->preview = NULL;
204 collection_dst->flag &= ~COLLECTION_HAS_OBJECT_CACHE;
205 BLI_listbase_clear(&collection_dst->object_cache);
207 BLI_listbase_clear(&collection_dst->gobject);
208 BLI_listbase_clear(&collection_dst->children);
209 BLI_listbase_clear(&collection_dst->parents);
211 for (CollectionChild *child = collection_src->children.first; child; child = child->next) {
212 collection_child_add(collection_dst, child->collection, flag, false);
214 for (CollectionObject *cob = collection_src->gobject.first; cob; cob = cob->next) {
215 collection_object_add(bmain, collection_dst, cob->ob, flag, false);
220 * Makes a shallow copy of a Collection
222 * Add a new collection in the same level as the old one, copy any nested collections
223 * but link the objects to the new collection (as oppose to copy them).
225 Collection *BKE_collection_copy(Main *bmain, Collection *parent, Collection *collection)
227 /* It's not allowed to copy the master collection. */
228 if (collection->flag & COLLECTION_IS_MASTER) {
229 BLI_assert("!Master collection can't be copied");
233 Collection *collection_new;
234 BKE_id_copy_ex(bmain, &collection->id, (ID **)&collection_new, 0, false);
235 id_us_min(&collection_new->id); /* Copying add one user by default, need to get rid of that one. */
237 /* Optionally add to parent. */
239 if (collection_child_add(parent, collection_new, 0, true)) {
240 /* Put collection right after existing one. */
241 CollectionChild *child = collection_find_child(parent, collection);
242 CollectionChild *child_new = collection_find_child(parent, collection_new);
244 if (child && child_new) {
245 BLI_remlink(&parent->children, child_new);
246 BLI_insertlinkafter(&parent->children, child, child_new);
251 BKE_main_collection_sync(bmain);
253 return collection_new;
256 Collection *BKE_collection_copy_master(Main *bmain, Collection *collection, const int flag)
258 BLI_assert(collection->flag & COLLECTION_IS_MASTER);
260 Collection *collection_dst = MEM_dupallocN(collection);
261 BKE_collection_copy_data(bmain, collection_dst, collection, flag);
262 return collection_dst;
265 void BKE_collection_copy_full(Main *UNUSED(bmain), Collection *UNUSED(collection))
267 // TODO: implement full scene copy
270 void BKE_collection_make_local(Main *bmain, Collection *collection, const bool lib_local)
272 BKE_id_make_local_generic(bmain, &collection->id, true, lib_local);
275 /********************************* Naming *******************************/
278 * The automatic/fallback name of a new collection.
280 void BKE_collection_new_name_get(Collection *collection_parent, char *rname)
284 if (!collection_parent) {
285 name = BLI_sprintfN("Collection");
287 else if (collection_parent->flag & COLLECTION_IS_MASTER) {
288 name = BLI_sprintfN("Collection %d", BLI_listbase_count(&collection_parent->children) + 1);
291 const int number = BLI_listbase_count(&collection_parent->children) + 1;
292 const int digits = integer_digits_i(number);
294 sizeof(collection_parent->id.name) - 1 /* NULL terminator */ - (1 + digits) /* " %d" */ - 2 /* ID */;
295 name = BLI_sprintfN("%.*s %d", max_len, collection_parent->id.name + 2, number);
298 BLI_strncpy(rname, name, MAX_NAME);
303 * The name to show in the interface.
305 const char *BKE_collection_ui_name_get(struct Collection *collection)
307 if (collection->flag & COLLECTION_IS_MASTER) {
308 return IFACE_("Scene Collection");
311 return collection->id.name + 2;
315 /* **************** Object List Cache *******************/
317 static void collection_object_cache_fill(ListBase *lb, Collection *collection, int parent_restrict)
319 int child_restrict = collection->flag | parent_restrict;
321 for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
322 Base *base = BLI_findptr(lb, cob->ob, offsetof(Base, object));
325 base = MEM_callocN(sizeof(Base), "Object Base");
326 base->object = cob->ob;
327 BLI_addtail(lb, base);
330 int object_restrict = base->object->restrictflag;
332 if (((child_restrict & COLLECTION_RESTRICT_VIEW) == 0) &&
333 ((object_restrict & OB_RESTRICT_VIEW) == 0))
335 base->flag |= BASE_ENABLED_VIEWPORT;
338 if (((child_restrict & COLLECTION_RESTRICT_RENDER) == 0) &&
339 ((object_restrict & OB_RESTRICT_RENDER) == 0))
341 base->flag |= BASE_ENABLED_RENDER;
345 for (CollectionChild *child = collection->children.first; child; child = child->next) {
346 collection_object_cache_fill(lb, child->collection, child_restrict);
350 ListBase BKE_collection_object_cache_get(Collection *collection)
352 if (!(collection->flag & COLLECTION_HAS_OBJECT_CACHE)) {
353 static ThreadMutex cache_lock = BLI_MUTEX_INITIALIZER;
355 BLI_mutex_lock(&cache_lock);
356 if (!(collection->flag & COLLECTION_HAS_OBJECT_CACHE)) {
357 collection_object_cache_fill(&collection->object_cache, collection, 0);
358 collection->flag |= COLLECTION_HAS_OBJECT_CACHE;
360 BLI_mutex_unlock(&cache_lock);
363 return collection->object_cache;
366 static void collection_object_cache_free(Collection *collection)
368 /* Clear own cache an for all parents, since those are affected by changes as well. */
369 collection->flag &= ~COLLECTION_HAS_OBJECT_CACHE;
370 BLI_freelistN(&collection->object_cache);
372 for (CollectionParent *parent = collection->parents.first; parent; parent = parent->next) {
373 collection_object_cache_free(parent->collection);
377 void BKE_collection_object_cache_free(Collection *collection)
379 collection_object_cache_free(collection);
382 Base *BKE_collection_or_layer_objects(const ViewLayer *view_layer, Collection *collection)
385 return BKE_collection_object_cache_get(collection).first;
388 return FIRSTBASE(view_layer);
392 /*********************** Scene Master Collection ***************/
394 Collection *BKE_collection_master_add()
396 /* Not an actual datablock, but owned by scene. */
397 Collection *master_collection = MEM_callocN(sizeof(Collection), "Master Collection");
398 STRNCPY(master_collection->id.name, "GRMaster Collection");
399 master_collection->flag |= COLLECTION_IS_MASTER;
400 return master_collection;
403 Collection *BKE_collection_master(const Scene *scene)
405 return scene->master_collection;
408 /*********************** Cyclic Checks ************************/
410 static bool collection_object_cyclic_check_internal(Object *object, Collection *collection)
412 if (object->dup_group) {
413 Collection *dup_collection = object->dup_group;
414 if ((dup_collection->id.tag & LIB_TAG_DOIT) == 0) {
415 /* Cycle already exists in collections, let's prevent further crappyness */
418 /* flag the object to identify cyclic dependencies in further dupli collections */
419 dup_collection->id.tag &= ~LIB_TAG_DOIT;
421 if (dup_collection == collection) {
425 FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(dup_collection, collection_object)
427 if (collection_object_cyclic_check_internal(collection_object, dup_collection)) {
431 FOREACH_COLLECTION_OBJECT_RECURSIVE_END;
434 /* un-flag the object, it's allowed to have the same collection multiple times in parallel */
435 dup_collection->id.tag |= LIB_TAG_DOIT;
441 bool BKE_collection_object_cyclic_check(Main *bmain, Object *object, Collection *collection)
443 /* first flag all collections */
444 BKE_main_id_tag_listbase(&bmain->collection, LIB_TAG_DOIT, true);
446 return collection_object_cyclic_check_internal(object, collection);
449 /******************* Collection Object Membership *******************/
451 bool BKE_collection_has_object(Collection *collection, Object *ob)
453 if (ELEM(NULL, collection, ob)) {
457 return (BLI_findptr(&collection->gobject, ob, offsetof(CollectionObject, ob)));
460 bool BKE_collection_has_object_recursive(Collection *collection, Object *ob)
462 if (ELEM(NULL, collection, ob)) {
466 const ListBase objects = BKE_collection_object_cache_get(collection);
467 return (BLI_findptr(&objects, ob, offsetof(Base, object)));
470 Collection *BKE_collection_object_find(Main *bmain, Collection *collection, Object *ob)
473 collection = collection->id.next;
475 collection = bmain->collection.first;
478 if (BKE_collection_has_object(collection, ob))
480 collection = collection->id.next;
485 bool BKE_collection_is_empty(Collection *collection)
487 return BLI_listbase_is_empty(&collection->gobject) && BLI_listbase_is_empty(&collection->children);
490 /********************** Collection Objects *********************/
492 static bool collection_object_add(Main *bmain, Collection *collection, Object *ob, int flag, const bool add_us)
495 /* Cyclic dependency check. */
496 if (collection_find_child_recursive(ob->dup_group, collection)) {
501 CollectionObject *cob = BLI_findptr(&collection->gobject, ob, offsetof(CollectionObject, ob));
506 cob = MEM_callocN(sizeof(CollectionObject), __func__);
508 BLI_addtail(&collection->gobject, cob);
509 BKE_collection_object_cache_free(collection);
511 if (add_us && (flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
515 if ((flag & LIB_ID_CREATE_NO_MAIN) == 0) {
516 DEG_id_tag_update_ex(bmain, &collection->id, ID_RECALC_COPY_ON_WRITE);
519 if ((flag & LIB_ID_CREATE_NO_MAIN) == 0) {
520 BKE_rigidbody_main_collection_object_add(bmain, collection, ob);
526 static bool collection_object_remove(Main *bmain, Collection *collection, Object *ob, const bool free_us)
528 CollectionObject *cob = BLI_findptr(&collection->gobject, ob, offsetof(CollectionObject, ob));
533 BLI_freelinkN(&collection->gobject, cob);
534 BKE_collection_object_cache_free(collection);
537 BKE_libblock_free_us(bmain, ob);
543 DEG_id_tag_update_ex(bmain, &collection->id, ID_RECALC_COPY_ON_WRITE);
549 * Add object to collection
551 bool BKE_collection_object_add(Main *bmain, Collection *collection, Object *ob)
553 if (ELEM(NULL, collection, ob)) {
557 if (!collection_object_add(bmain, collection, ob, 0, true)) {
561 if (BKE_collection_is_in_scene(collection)) {
562 BKE_main_collection_sync(bmain);
569 * Add object to all scene collections that reference objects is in
570 * (used to copy objects)
572 void BKE_collection_object_add_from(Main *bmain, Scene *scene, Object *ob_src, Object *ob_dst)
574 FOREACH_SCENE_COLLECTION_BEGIN(scene, collection)
576 if (BKE_collection_has_object(collection, ob_src)) {
577 collection_object_add(bmain, collection, ob_dst, 0, true);
580 FOREACH_SCENE_COLLECTION_END;
582 BKE_main_collection_sync(bmain);
586 * Remove object from collection.
588 bool BKE_collection_object_remove(Main *bmain, Collection *collection, Object *ob, const bool free_us)
590 if (ELEM(NULL, collection, ob)) {
594 if (!collection_object_remove(bmain, collection, ob, free_us)) {
598 if (BKE_collection_is_in_scene(collection)) {
599 BKE_main_collection_sync(bmain);
606 * Remove object from all collections of scene
607 * \param scene_collection_skip: Don't remove base from this collection.
609 static bool scene_collections_object_remove(Main *bmain, Scene *scene, Object *ob, const bool free_us,
610 Collection *collection_skip)
612 bool removed = false;
614 BKE_scene_remove_rigidbody_object(bmain, scene, ob);
616 FOREACH_SCENE_COLLECTION_BEGIN(scene, collection)
618 if (collection != collection_skip) {
619 removed |= collection_object_remove(bmain, collection, ob, free_us);
622 FOREACH_SCENE_COLLECTION_END;
624 BKE_main_collection_sync(bmain);
630 * Remove object from all collections of scene
632 bool BKE_scene_collections_object_remove(Main *bmain, Scene *scene, Object *ob, const bool free_us)
634 return scene_collections_object_remove(bmain, scene, ob, free_us, NULL);
638 * Remove all NULL objects from collections.
639 * This is used for library remapping, where these pointers have been set to NULL.
640 * Otherwise this should never happen.
642 static void collection_object_remove_nulls(Collection *collection)
644 bool changed = false;
646 for (CollectionObject *cob = collection->gobject.first, *cob_next = NULL; cob; cob = cob_next) {
647 cob_next = cob->next;
649 if (cob->ob == NULL) {
650 BLI_freelinkN(&collection->gobject, cob);
656 BKE_collection_object_cache_free(collection);
660 void BKE_collections_object_remove_nulls(Main *bmain)
662 for (Scene *scene = bmain->scene.first; scene; scene = scene->id.next) {
663 collection_object_remove_nulls(scene->master_collection);
666 for (Collection *collection = bmain->collection.first; collection; collection = collection->id.next) {
667 collection_object_remove_nulls(collection);
671 static void collection_null_children_remove(Collection *collection)
673 for (CollectionChild *child = collection->children.first, *child_next = NULL; child; child = child_next) {
674 child_next = child->next;
676 if (child->collection == NULL) {
677 BLI_freelinkN(&collection->children, child);
682 static void collection_missing_parents_remove(Collection *collection)
684 for (CollectionParent *parent = collection->parents.first, *parent_next; parent != NULL; parent = parent_next) {
685 parent_next = parent->next;
687 if (!collection_find_child(parent->collection, collection)) {
688 BLI_freelinkN(&collection->parents, parent);
694 * Remove all NULL children from parent collections of changed \a collection.
695 * This is used for library remapping, where these pointers have been set to NULL.
696 * Otherwise this should never happen.
698 * \note caller must ensure BKE_main_collection_sync_remap() is called afterwards!
700 * \param collection: may be \a NULL, in which case whole \a bmain database of collections is checked.
702 void BKE_collections_child_remove_nulls(Main *bmain, Collection *collection)
704 if (collection == NULL) {
705 /* We need to do the checks in two steps when more than one collection may be involved,
706 * otherwise we can miss some cases...
707 * Also, master collections are not in bmain, so we also need to loop over scenes.
709 for (collection = bmain->collection.first; collection != NULL; collection = collection->id.next) {
710 collection_null_children_remove(collection);
712 for (Scene *scene = bmain->scene.first; scene != NULL; scene = scene->id.next) {
713 collection_null_children_remove(BKE_collection_master(scene));
716 for (collection = bmain->collection.first; collection != NULL; collection = collection->id.next) {
717 collection_missing_parents_remove(collection);
719 for (Scene *scene = bmain->scene.first; scene != NULL; scene = scene->id.next) {
720 collection_missing_parents_remove(BKE_collection_master(scene));
724 for (CollectionParent *parent = collection->parents.first, *parent_next; parent; parent = parent_next) {
725 parent_next = parent->next;
727 collection_null_children_remove(parent->collection);
729 if (!collection_find_child(parent->collection, collection)) {
730 BLI_freelinkN(&collection->parents, parent);
737 * Move object from a collection into another
739 * If source collection is NULL move it from all the existing collections.
741 void BKE_collection_object_move(
742 Main *bmain, Scene *scene, Collection *collection_dst, Collection *collection_src, Object *ob)
744 /* In both cases we first add the object, then remove it from the other collections.
745 * Otherwise we lose the original base and whether it was active and selected. */
746 if (collection_src != NULL) {
747 if (BKE_collection_object_add(bmain, collection_dst, ob)) {
748 BKE_collection_object_remove(bmain, collection_src, ob, false);
752 /* Adding will fail if object is already in collection.
753 * However we still need to remove it from the other collections. */
754 BKE_collection_object_add(bmain, collection_dst, ob);
755 scene_collections_object_remove(bmain, scene, ob, false, collection_dst);
759 /***************** Collection Scene Membership ****************/
761 bool BKE_collection_is_in_scene(Collection *collection)
763 if (collection->flag & COLLECTION_IS_MASTER) {
767 for (CollectionParent *cparent = collection->parents.first; cparent; cparent = cparent->next) {
768 if (BKE_collection_is_in_scene(cparent->collection)) {
776 void BKE_collections_after_lib_link(Main *bmain)
778 /* Update view layer collections to match any changes in linked
779 * collections after file load. */
780 BKE_main_collection_sync(bmain);
783 /********************** Collection Children *******************/
785 bool BKE_collection_find_cycle(Collection *new_ancestor, Collection *collection)
787 if (collection == new_ancestor) {
791 for (CollectionParent *parent = new_ancestor->parents.first; parent; parent = parent->next) {
792 if (BKE_collection_find_cycle(parent->collection, collection)) {
800 static CollectionChild *collection_find_child(Collection *parent, Collection *collection)
802 return BLI_findptr(&parent->children, collection, offsetof(CollectionChild, collection));
805 static bool collection_find_child_recursive(Collection *parent, Collection *collection)
807 for (CollectionChild *child = parent->children.first; child; child = child->next) {
808 if (child->collection == collection) {
812 if (collection_find_child_recursive(child->collection, collection)) {
820 static CollectionParent *collection_find_parent(Collection *child, Collection *collection)
822 return BLI_findptr(&child->parents, collection, offsetof(CollectionParent, collection));
825 static bool collection_child_add(Collection *parent, Collection *collection, const int flag, const bool add_us)
827 CollectionChild *child = collection_find_child(parent, collection);
831 if (BKE_collection_find_cycle(parent, collection)) {
835 child = MEM_callocN(sizeof(CollectionChild), "CollectionChild");
836 child->collection = collection;
837 BLI_addtail(&parent->children, child);
839 /* Don't add parent links for depsgraph datablocks, these are not kept in sync. */
840 if ((flag & LIB_ID_CREATE_NO_MAIN) == 0) {
841 CollectionParent *cparent = MEM_callocN(sizeof(CollectionParent), "CollectionParent");
842 cparent->collection = parent;
843 BLI_addtail(&collection->parents, cparent);
847 id_us_plus(&collection->id);
850 BKE_collection_object_cache_free(parent);
855 static bool collection_child_remove(Collection *parent, Collection *collection)
857 CollectionChild *child = collection_find_child(parent, collection);
862 CollectionParent *cparent = collection_find_parent(collection, parent);
863 BLI_freelinkN(&collection->parents, cparent);
864 BLI_freelinkN(&parent->children, child);
866 id_us_min(&collection->id);
868 BKE_collection_object_cache_free(parent);
873 bool BKE_collection_child_add(Main *bmain, Collection *parent, Collection *child)
875 if (!collection_child_add(parent, child, 0, true)) {
879 BKE_main_collection_sync(bmain);
883 bool BKE_collection_child_remove(Main *bmain, Collection *parent, Collection *child)
885 if (!collection_child_remove(parent, child)) {
889 BKE_main_collection_sync(bmain);
893 /********************** Collection index *********************/
895 static Collection *collection_from_index_recursive(Collection *collection, const int index, int *index_current)
897 if (index == (*index_current)) {
903 for (CollectionChild *child = collection->children.first; child; child = child->next) {
904 Collection *nested = collection_from_index_recursive(child->collection, index, index_current);
905 if (nested != NULL) {
913 * Return Scene Collection for a given index.
915 * The index is calculated from top to bottom counting the children before the siblings.
917 Collection *BKE_collection_from_index(Scene *scene, const int index)
919 int index_current = 0;
920 Collection *master_collection = BKE_collection_master(scene);
921 return collection_from_index_recursive(master_collection, index, &index_current);
924 static bool collection_objects_select(ViewLayer *view_layer, Collection *collection, bool deselect)
926 bool changed = false;
928 if (collection->flag & COLLECTION_RESTRICT_SELECT) {
932 for (CollectionObject *cob = collection->gobject.first; cob; cob = cob->next) {
933 Base *base = BKE_view_layer_base_find(view_layer, cob->ob);
937 if (base->flag & BASE_SELECTED) {
938 base->flag &= ~BASE_SELECTED;
943 if ((base->flag & BASE_SELECTABLE) && !(base->flag & BASE_SELECTED)) {
944 base->flag |= BASE_SELECTED;
951 for (CollectionChild *child = collection->children.first; child; child = child->next) {
952 if (collection_objects_select(view_layer, collection, deselect)) {
961 * Select all the objects in this Collection (and its nested collections) for this ViewLayer.
962 * Return true if any object was selected.
964 bool BKE_collection_objects_select(ViewLayer *view_layer, Collection *collection, bool deselect)
966 LayerCollection *layer_collection = BKE_layer_collection_first_from_scene_collection(view_layer, collection);
968 if (layer_collection != NULL) {
969 return BKE_layer_collection_objects_select(view_layer, layer_collection, deselect);
972 return collection_objects_select(view_layer, collection, deselect);
976 /***************** Collection move (outliner drag & drop) *********************/
978 bool BKE_collection_move(Main *bmain,
979 Collection *to_parent,
980 Collection *from_parent,
981 Collection *relative,
983 Collection *collection)
985 if (collection->flag & COLLECTION_IS_MASTER) {
988 if (BKE_collection_find_cycle(to_parent, collection)) {
992 /* Move to new parent collection */
994 collection_child_remove(from_parent, collection);
997 collection_child_add(to_parent, collection, 0, true);
999 /* Move to specified location under parent. */
1001 CollectionChild *child = collection_find_child(to_parent, collection);
1002 CollectionChild *relative_child = collection_find_child(to_parent, relative);
1004 if (relative_child) {
1005 BLI_remlink(&to_parent->children, child);
1007 if (relative_after) {
1008 BLI_insertlinkafter(&to_parent->children, relative_child, child);
1011 BLI_insertlinkbefore(&to_parent->children, relative_child, child);
1014 BKE_collection_object_cache_free(to_parent);
1018 BKE_main_collection_sync(bmain);
1023 /**************************** Iterators ******************************/
1025 /* scene collection iteractor */
1027 typedef struct CollectionsIteratorData {
1031 } CollectionsIteratorData;
1033 static void scene_collection_callback(Collection *collection, BKE_scene_collections_Cb callback, void *data)
1035 callback(collection, data);
1037 for (CollectionChild *child = collection->children.first; child; child = child->next) {
1038 scene_collection_callback(child->collection, callback, data);
1042 static void scene_collections_count(Collection *UNUSED(collection), void *data)
1048 static void scene_collections_build_array(Collection *collection, void *data)
1050 Collection ***array = data;
1051 **array = collection;
1055 static void scene_collections_array(Scene *scene, Collection ***collections_array, int *tot)
1057 Collection *collection;
1060 *collections_array = NULL;
1063 if (scene == NULL) {
1067 collection = BKE_collection_master(scene);
1068 BLI_assert(collection != NULL);
1069 scene_collection_callback(collection, scene_collections_count, tot);
1074 *collections_array = array = MEM_mallocN(sizeof(Collection *) * (*tot), "CollectionArray");
1075 scene_collection_callback(collection, scene_collections_build_array, &array);
1079 * Only use this in non-performance critical situations
1080 * (it iterates over all scene collections twice)
1082 void BKE_scene_collections_iterator_begin(BLI_Iterator *iter, void *data_in)
1084 Scene *scene = data_in;
1085 CollectionsIteratorData *data = MEM_callocN(sizeof(CollectionsIteratorData), __func__);
1087 data->scene = scene;
1091 scene_collections_array(scene, (Collection ***)&data->array, &data->tot);
1092 BLI_assert(data->tot != 0);
1095 iter->current = data->array[data->cur];
1098 void BKE_scene_collections_iterator_next(struct BLI_Iterator *iter)
1100 CollectionsIteratorData *data = iter->data;
1102 if (++data->cur < data->tot) {
1103 iter->current = data->array[data->cur];
1106 iter->valid = false;
1110 void BKE_scene_collections_iterator_end(struct BLI_Iterator *iter)
1112 CollectionsIteratorData *data = iter->data;
1116 MEM_freeN(data->array);
1120 iter->valid = false;
1124 /* scene objects iteractor */
1126 typedef struct SceneObjectsIteratorData {
1128 CollectionObject *cob_next;
1129 BLI_Iterator scene_collection_iter;
1130 } SceneObjectsIteratorData;
1132 void BKE_scene_objects_iterator_begin(BLI_Iterator *iter, void *data_in)
1134 Scene *scene = data_in;
1135 SceneObjectsIteratorData *data = MEM_callocN(sizeof(SceneObjectsIteratorData), __func__);
1138 /* lookup list ot make sure each object is object called once */
1139 data->visited = BLI_gset_ptr_new(__func__);
1141 /* we wrap the scenecollection iterator here to go over the scene collections */
1142 BKE_scene_collections_iterator_begin(&data->scene_collection_iter, scene);
1144 Collection *collection = data->scene_collection_iter.current;
1145 data->cob_next = collection->gobject.first;
1147 BKE_scene_objects_iterator_next(iter);
1151 * Ensures we only get each object once, even when included in several collections.
1153 static CollectionObject *object_base_unique(GSet *gs, CollectionObject *cob)
1155 for (; cob != NULL; cob = cob->next) {
1156 Object *ob = cob->ob;
1158 if (!BLI_gset_ensure_p_ex(gs, ob, &ob_key_p)) {
1166 void BKE_scene_objects_iterator_next(BLI_Iterator *iter)
1168 SceneObjectsIteratorData *data = iter->data;
1169 CollectionObject *cob = data->cob_next ? object_base_unique(data->visited, data->cob_next) : NULL;
1172 data->cob_next = cob->next;
1173 iter->current = cob->ob;
1176 /* if this is the last object of this ListBase look at the next Collection */
1177 Collection *collection;
1178 BKE_scene_collections_iterator_next(&data->scene_collection_iter);
1180 collection = data->scene_collection_iter.current;
1181 /* get the first unique object of this collection */
1182 CollectionObject *new_cob = object_base_unique(data->visited, collection->gobject.first);
1184 data->cob_next = new_cob->next;
1185 iter->current = new_cob->ob;
1188 BKE_scene_collections_iterator_next(&data->scene_collection_iter);
1189 } while (data->scene_collection_iter.valid);
1191 if (!data->scene_collection_iter.valid) {
1192 iter->valid = false;
1197 void BKE_scene_objects_iterator_end(BLI_Iterator *iter)
1199 SceneObjectsIteratorData *data = iter->data;
1201 BKE_scene_collections_iterator_end(&data->scene_collection_iter);
1202 BLI_gset_free(data->visited, NULL);