Blender V4.5
collection.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9/* Allow using deprecated functionality for .blend file I/O. */
10#define DNA_DEPRECATED_ALLOW
11
12#include "CLG_log.h"
13
14#include <cstring>
15#include <optional>
16
17#include "BLI_iterator.h"
18#include "BLI_listbase.h"
19#include "BLI_math_base.h"
20#include "BLI_mutex.hh"
21#include "BLI_string.h"
22#include "BLI_string_utils.hh"
23
24#include "BLT_translation.hh"
25
26#include "BKE_anim_data.hh"
27#include "BKE_collection.hh"
28#include "BKE_idprop.hh"
29#include "BKE_idtype.hh"
30#include "BKE_layer.hh"
31#include "BKE_lib_id.hh"
32#include "BKE_lib_query.hh"
33#include "BKE_lib_remap.hh"
34#include "BKE_library.hh"
35#include "BKE_main.hh"
36#include "BKE_object.hh"
37#include "BKE_preview_image.hh"
38#include "BKE_rigidbody.h"
39#include "BKE_scene.hh"
40
41#include "DNA_defaults.h"
42
43#include "DNA_ID.h"
45#include "DNA_layer_types.h"
46#include "DNA_object_types.h"
47#include "DNA_rigidbody_types.h"
48#include "DNA_scene_types.h"
49
50#include "DEG_depsgraph.hh"
52
53#include "MEM_guardedalloc.h"
54
55#include "BLO_read_write.hh"
56
57static CLG_LogRef LOG = {"bke.collection"};
58
62// #define USE_DEBUG_EXTRA_GOBJECT_ASSERT
63
64/* -------------------------------------------------------------------- */
67
69static bool collection_child_add(Main *bmain,
70 Collection *parent,
71 Collection *collection,
72 const CollectionLightLinking *light_linking,
73 const int id_create_flag,
74 const bool add_us);
76static bool collection_child_remove(Main *bmain,
77 Collection *parent,
78 Collection *collection,
79 const int id_create_flag);
81static bool collection_object_add(Main *bmain,
82 Collection *collection,
83 Object *ob,
84 CollectionLightLinking *light_linking,
85 const int id_create_flag,
86 const bool add_us);
87
90 Collection *collection,
92 const int id_create_flag,
93 const bool free_us);
95static bool collection_object_remove(
96 Main *bmain, Collection *collection, Object *ob, const int id_create_flag, const bool free_us);
97
99
100static bool collection_find_child_recursive(const Collection *parent,
101 const Collection *collection);
102
104static void collection_object_cache_free(const Main *bmain,
105 Collection *collection,
106 const int id_create_flag,
107 const uint id_recalc_flag);
108
109static void collection_gobject_hash_ensure(Collection *collection);
111 Object *ob_old,
112 CollectionObject *cob);
114
116
117/* -------------------------------------------------------------------- */
120
121static void collection_init_data(ID *id)
122{
123 Collection *collection = (Collection *)id;
125
127}
128
139static void collection_copy_data(Main *bmain,
140 std::optional<Library *> /*owner_library*/,
141 ID *id_dst,
142 const ID *id_src,
143 const int flag)
144{
145 Collection *collection_dst = (Collection *)id_dst;
146 const Collection *collection_src = (const Collection *)id_src;
147
148 BLI_assert(((collection_src->flag & COLLECTION_IS_MASTER) != 0) ==
149 ((collection_src->id.flag & ID_FLAG_EMBEDDED_DATA) != 0));
150
151 if ((flag & LIB_ID_COPY_NO_PREVIEW) == 0) {
152 BKE_previewimg_id_copy(&collection_dst->id, &collection_src->id);
153 }
154 else {
155 collection_dst->preview = nullptr;
156 }
157
159 BLI_listbase_clear(&collection_dst->runtime.object_cache);
161
162 BLI_listbase_clear(&collection_dst->gobject);
163 BLI_listbase_clear(&collection_dst->children);
164 BLI_listbase_clear(&collection_dst->exporters);
165 BLI_listbase_clear(&collection_dst->runtime.parents);
166 collection_dst->runtime.gobject_hash = nullptr;
167
168 LISTBASE_FOREACH (CollectionChild *, child, &collection_src->children) {
170 bmain, collection_dst, child->collection, &child->light_linking, flag, false);
171 }
172 LISTBASE_FOREACH (CollectionObject *, cob, &collection_src->gobject) {
173 collection_object_add(bmain, collection_dst, cob->ob, &cob->light_linking, flag, false);
174 }
175 LISTBASE_FOREACH (CollectionExport *, data, &collection_src->exporters) {
176 collection_exporter_copy(collection_dst, data);
177 }
178}
179
180static void collection_free_data(ID *id)
181{
182 Collection *collection = (Collection *)id;
183
184 /* No animation-data here. */
185 BKE_previewimg_free(&collection->preview);
186
187 BLI_freelistN(&collection->gobject);
188 if (collection->runtime.gobject_hash) {
189 BLI_ghash_free(collection->runtime.gobject_hash, nullptr, nullptr);
190 collection->runtime.gobject_hash = nullptr;
191 }
192
193 BLI_freelistN(&collection->children);
194 BLI_freelistN(&collection->runtime.parents);
195
198 }
199 BLI_freelistN(&collection->exporters);
200
201 /* No need for depsgraph tagging here, since the data is being deleted. */
203}
204
206{
207 Collection *collection = (Collection *)id;
208 const int data_flags = BKE_lib_query_foreachid_process_flags_get(data);
209
211 data,
212 collection->owner_id,
214
215 LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
216 Object *cob_ob_old = cob->ob;
217
220
221 if (collection->runtime.gobject_hash) {
222 /* If the remapping does not create inconsistent data (nullptr object pointer or duplicate
223 * CollectionObjects), keeping the ghash consistent is also possible. Otherwise, this call
224 * will take care of tagging the collection objects list as dirty. */
225 collection_gobject_hash_update_object(collection, cob_ob_old, cob);
226 }
227 else if (cob_ob_old != cob->ob || cob->ob == nullptr) {
228 /* If there is no reference GHash, duplicates cannot be reliably detected, so assume that any
229 * nullptr pointer or changed pointer may create an invalid collection object list. */
231 }
232 }
233 LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
235 child->collection,
238 }
239 LISTBASE_FOREACH (CollectionParent *, parent, &collection->runtime.parents) {
240 /* XXX This is very weak. The whole idea of keeping pointers to private IDs is very bad
241 * anyway... */
242 const LibraryForeachIDCallbackFlag cb_flag =
243 ((parent->collection != nullptr && (data_flags & IDWALK_NO_ORIG_POINTERS_ACCESS) == 0 &&
244 (parent->collection->id.flag & ID_FLAG_EMBEDDED_DATA) != 0) ?
248 data, parent->collection, IDWALK_CB_NEVER_SELF | IDWALK_CB_LOOPBACK | cb_flag);
249 }
250}
251
252static ID **collection_owner_pointer_get(ID *id, const bool debug_relationship_assert)
253{
254 if ((id->flag & ID_FLAG_EMBEDDED_DATA) == 0) {
255 return nullptr;
256 }
257
258 Collection *master_collection = (Collection *)id;
259 BLI_assert((master_collection->flag & COLLECTION_IS_MASTER) != 0);
260 if (debug_relationship_assert) {
261 BLI_assert(master_collection->owner_id != nullptr);
262 BLI_assert(GS(master_collection->owner_id->name) == ID_SCE);
263 BLI_assert(((Scene *)master_collection->owner_id)->master_collection == master_collection);
264 }
265
266 return &master_collection->owner_id;
267}
268
270{
271 collection->runtime = Collection_Runtime{};
272 /* Clean up, important in undo case to reduce false detection of changed data-blocks. */
273 collection->flag &= ~COLLECTION_FLAG_ALL_RUNTIME;
274}
275
277{
278 BKE_id_blend_write(writer, &collection->id);
279
280 /* Shared function for collection data-blocks and scene master collection. */
281 BKE_previewimg_blend_write(writer, collection->preview);
282
283 LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
285 }
286
287 LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
288 BLO_write_struct(writer, CollectionChild, child);
289 }
290
293 if (data->export_properties) {
294 IDP_BlendWrite(writer, data->export_properties);
295 }
296 }
297}
298
299static void collection_blend_write(BlendWriter *writer, ID *id, const void *id_address)
300{
301 Collection *collection = (Collection *)id;
302
304
305 /* write LibData */
306 BLO_write_id_struct(writer, Collection, id_address, &collection->id);
307
308 BKE_collection_blend_write_nolib(writer, collection);
309}
310
311void BKE_collection_blend_read_data(BlendDataReader *reader, Collection *collection, ID *owner_id)
312{
313 /* Special case for this pointer, do not rely on regular `lib_link` process here. Avoids needs
314 * for do_versioning, and ensures coherence of data in any case.
315 *
316 * NOTE: Old versions are very often 'broken' here, just fix it silently in these cases.
317 */
318 if (BLO_read_fileversion_get(reader) > 300) {
319 BLI_assert((collection->id.flag & ID_FLAG_EMBEDDED_DATA) != 0 || owner_id == nullptr);
320 }
321 BLI_assert(owner_id == nullptr || owner_id->lib == collection->id.lib);
322 if (owner_id != nullptr && (collection->id.flag & ID_FLAG_EMBEDDED_DATA) == 0) {
323 /* This is unfortunate, but currently a lot of existing files (including startup ones) have
324 * missing `ID_FLAG_EMBEDDED_DATA` flag.
325 *
326 * NOTE: Using do_version is not a solution here, since this code will be called before any
327 * do_version takes place. Keeping it here also ensures future (or unknown existing) similar
328 * bugs won't go easily unnoticed. */
329 if (BLO_read_fileversion_get(reader) > 300) {
330 CLOG_WARN(&LOG,
331 "Fixing root node tree '%s' owned by '%s' missing EMBEDDED tag, please consider "
332 "re-saving your (startup) file",
333 collection->id.name,
334 owner_id->name);
335 }
336 collection->id.flag |= ID_FLAG_EMBEDDED_DATA;
337 }
338
339 collection->runtime = Collection_Runtime{};
340 collection->flag &= ~COLLECTION_FLAG_ALL_RUNTIME;
341
342 collection->owner_id = owner_id;
343
344 BLO_read_struct_list(reader, CollectionObject, &collection->gobject);
345 BLO_read_struct_list(reader, CollectionChild, &collection->children);
346
347 BLO_read_struct_list(reader, CollectionExport, &collection->exporters);
349 BLO_read_struct(reader, IDProperty, &data->export_properties);
350 IDP_BlendDataRead(reader, &data->export_properties);
351 }
352
353 BLO_read_struct(reader, PreviewImage, &collection->preview);
354 BKE_previewimg_blend_read(reader, collection->preview);
355}
356
358{
359 Collection *collection = (Collection *)id;
360 BKE_collection_blend_read_data(reader, collection, nullptr);
361}
362
364{
365 Collection *collection = reinterpret_cast<Collection *>(id);
366
367 /* Sanity check over Collection/Object data. */
368 BLI_assert(collection->runtime.gobject_hash == nullptr);
369 LISTBASE_FOREACH_MUTABLE (CollectionObject *, cob, &collection->gobject) {
370 if (cob->ob == nullptr) {
371 BLI_freelinkN(&collection->gobject, cob);
372 }
373 }
374
375 /* foreach_id code called by generic lib_link process has most likely set this flag, however it
376 * is not needed during readfile process since the runtime data is affects are not yet built, so
377 * just clear it here. */
378 BLI_assert(collection->runtime.gobject_hash == nullptr);
380}
381
383 /*id_code*/ Collection::id_type,
384 /*id_filter*/ FILTER_ID_GR,
385 /*dependencies_id_types*/ FILTER_ID_OB | FILTER_ID_GR,
386 /*main_listbase_index*/ INDEX_ID_GR,
387 /*struct_size*/ sizeof(Collection),
388 /*name*/ "Collection",
389 /*name_plural*/ N_("collections"),
390 /*translation_context*/ BLT_I18NCONTEXT_ID_COLLECTION,
392 /*asset_type_info*/ nullptr,
393
394 /*init_data*/ collection_init_data,
395 /*copy_data*/ collection_copy_data,
396 /*free_data*/ collection_free_data,
397 /*make_local*/ nullptr,
398 /*foreach_id*/ collection_foreach_id,
399 /*foreach_cache*/ nullptr,
400 /*foreach_path*/ nullptr,
401 /*owner_pointer_get*/ collection_owner_pointer_get,
402
403 /*blend_write*/ collection_blend_write,
404 /*blend_read_data*/ collection_blend_read_data,
405 /*blend_read_after_liblink*/ collection_blend_read_after_liblink,
406
407 /*blend_read_undo_preserve*/ nullptr,
408
409 /*lib_override_apply_post*/ nullptr,
410};
411
413
414/* -------------------------------------------------------------------- */
417
418/* Add new collection, without view layer syncing. */
420 Collection *collection_parent,
421 const char *name_custom)
422{
423 /* Determine new collection name. */
424 char name[MAX_NAME];
425
426 if (name_custom) {
427 STRNCPY(name, name_custom);
428 }
429 else {
430 BKE_collection_new_name_get(collection_parent, name);
431 }
432
433 /* Create new collection. */
434 Collection *collection = BKE_id_new<Collection>(bmain, name);
435
436 /* We increase collection user count when linking to Collections. */
437 id_us_min(&collection->id);
438
439 /* Optionally add to parent collection. */
440 if (collection_parent) {
441 collection_child_add(bmain, collection_parent, collection, nullptr, 0, true);
442 }
443
444 return collection;
445}
446
447Collection *BKE_collection_add(Main *bmain, Collection *collection_parent, const char *name_custom)
448{
449 Collection *collection = collection_add(bmain, collection_parent, name_custom);
451 return collection;
452}
453
455 Scene *scene,
456 const Object *ob_src,
457 Collection *collection_dst)
458{
459 bool is_instantiated = false;
460
461 FOREACH_SCENE_COLLECTION_BEGIN (scene, collection) {
462 if (!ID_IS_LINKED(collection) && !ID_IS_OVERRIDABLE_LIBRARY(collection) &&
463 BKE_collection_has_object(collection, ob_src))
464 {
465 collection_child_add(bmain, collection, collection_dst, nullptr, 0, true);
466 is_instantiated = true;
467 }
468 }
470
471 if (!is_instantiated) {
472 collection_child_add(bmain, scene->master_collection, collection_dst, nullptr, 0, true);
473 }
474
476}
477
479 Scene *scene,
480 Collection *collection_src,
481 Collection *collection_dst)
482{
483 bool is_instantiated = false;
484
485 FOREACH_SCENE_COLLECTION_BEGIN (scene, collection) {
486 if (ID_IS_EDITABLE(collection) && !ID_IS_OVERRIDE_LIBRARY(collection) &&
487 BKE_collection_child_find(collection, collection_src))
488 {
489 collection_child_add(bmain, collection, collection_dst, nullptr, 0, true);
490 is_instantiated = true;
491 }
492 else if (!is_instantiated && BKE_collection_child_find(collection, collection_dst)) {
493 /* If given collection_dst is already instantiated in scene, even if its 'model'
494 * collection_src one is not, do not add it to master scene collection. */
495 is_instantiated = true;
496 }
497 }
499
500 if (!is_instantiated) {
501 collection_child_add(bmain, scene->master_collection, collection_dst, nullptr, 0, true);
502 }
503
505}
506
508
509/* -------------------------------------------------------------------- */
512
514{
515 BKE_libblock_free_data(&collection->id, false);
516 collection_free_data(&collection->id);
517}
518
521 const char *newname)
522{
523 /* Only use the new name if it's not empty. */
524 if (newname && newname[0] != '\0') {
525 const ListBase list = exporters ? *exporters : BLI_listbase_from_link((Link *)data);
526
527 STRNCPY(data->name, newname);
529 &list, data, newname, '.', offsetof(CollectionExport, name), sizeof(data->name));
530 }
531}
532
534{
535 if (data->export_properties) {
536 IDP_FreeProperty(data->export_properties);
537 }
538}
539
540bool BKE_collection_delete(Main *bmain, Collection *collection, bool hierarchy)
541{
542 /* Master collection is not real datablock, can't be removed. */
543 if (collection->flag & COLLECTION_IS_MASTER) {
544 BLI_assert_msg(0, "Scene master collection can't be deleted");
545 return false;
546 }
547
548 /* This is being deleted, no need to handle each item.
549 * NOTE: While it might seem an advantage to use the hash instead of the list-lookup
550 * it is in fact slower because the items are removed in-order,
551 * so the list-lookup succeeds on the first test. */
552 if (collection->runtime.gobject_hash) {
553 BLI_ghash_free(collection->runtime.gobject_hash, nullptr, nullptr);
554 collection->runtime.gobject_hash = nullptr;
555 }
556
557 if (hierarchy) {
558 /* Remove child objects. */
559 CollectionObject *cob = static_cast<CollectionObject *>(collection->gobject.first);
560 while (cob != nullptr) {
562 bmain, collection, cob, LIB_ID_CREATE_NO_DEG_TAG, true);
563 cob = static_cast<CollectionObject *>(collection->gobject.first);
564 }
565
566 /* Delete all child collections recursively. */
567 CollectionChild *child = static_cast<CollectionChild *>(collection->children.first);
568 while (child != nullptr) {
569 BKE_collection_delete(bmain, child->collection, hierarchy);
570 child = static_cast<CollectionChild *>(collection->children.first);
571 }
572 }
573 else {
574 /* Link child collections into parent collection. */
575 LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
576 LISTBASE_FOREACH (CollectionParent *, cparent, &collection->runtime.parents) {
577 Collection *parent = cparent->collection;
578 collection_child_add(bmain, parent, child->collection, nullptr, 0, true);
579 }
580 }
581
582 CollectionObject *cob = static_cast<CollectionObject *>(collection->gobject.first);
583 while (cob != nullptr) {
584 /* Link child object into parent collections. */
585 LISTBASE_FOREACH (CollectionParent *, cparent, &collection->runtime.parents) {
586 Collection *parent = cparent->collection;
587 collection_object_add(bmain, parent, cob->ob, nullptr, 0, true);
588 }
589
590 /* Remove child object. */
592 bmain, collection, cob, LIB_ID_CREATE_NO_DEG_TAG, true);
593 cob = static_cast<CollectionObject *>(collection->gobject.first);
594 }
595 }
596
597 BKE_id_delete(bmain, collection);
598
600
601 return true;
602}
603
605
606/* -------------------------------------------------------------------- */
609
611 Collection *parent,
612 Collection *collection_old,
613 CollectionChild *child_old,
614 const int id_create_flag,
615 const eDupli_ID_Flags duplicate_flags,
616 const eLibIDDuplicateFlags duplicate_options)
617{
618 Collection *collection_new;
619 bool do_full_process = false;
620 const bool is_collection_master = (collection_old->flag & COLLECTION_IS_MASTER) != 0;
621
622 const bool do_objects = (duplicate_flags & USER_DUP_OBJECT) != 0;
623
624 if (is_collection_master) {
625 /* We never duplicate master collections here, but we can still deep-copy their objects and
626 * collections. */
627 BLI_assert(parent == nullptr);
628 collection_new = collection_old;
629 do_full_process = true;
630 }
631 else if (collection_old->id.newid == nullptr) {
632 collection_new = (Collection *)BKE_id_copy_for_duplicate(
633 bmain, (ID *)collection_old, duplicate_flags, id_create_flag);
634
635 if (collection_new == collection_old) {
636 return collection_new;
637 }
638
639 do_full_process = true;
640 }
641 else {
642 collection_new = (Collection *)collection_old->id.newid;
643 }
644
645 /* Optionally add to parent (we always want to do that,
646 * even if collection_old had already been duplicated). */
647 if (parent != nullptr) {
648 if (collection_child_add(bmain,
649 parent,
650 collection_new,
651 child_old ? &child_old->light_linking : nullptr,
652 id_create_flag,
653 true))
654 {
655 /* Put collection right after existing one.
656 * NOTE: Lookup child in the actual parent, as the parent might be different
657 * one when duplicating collection in a linked parent. */
658 CollectionChild *child = BKE_collection_child_find(parent, collection_old);
659 CollectionChild *child_new = BKE_collection_child_find(parent, collection_new);
660
661 if (child && child_new) {
662 BLI_remlink(&parent->children, child_new);
663 BLI_insertlinkafter(&parent->children, child, child_new);
664 }
665 }
666 }
667
668 /* If we are not doing any kind of deep-copy, we can return immediately.
669 * False do_full_process means collection_old had already been duplicated,
670 * no need to redo some deep-copy on it. */
671 if (!do_full_process) {
672 return collection_new;
673 }
674
675 if (do_objects) {
676 /* We need to first duplicate the objects in a separate loop, to support the master collection
677 * case, where both old and new collections are the same.
678 * Otherwise, depending on naming scheme and sorting, we may end up duplicating the new objects
679 * we just added, in some infinite loop. */
680 LISTBASE_FOREACH (CollectionObject *, cob, &collection_old->gobject) {
681 Object *ob_old = cob->ob;
682
683 if (ob_old->id.newid == nullptr) {
685 bmain, ob_old, duplicate_flags, duplicate_options | LIB_ID_DUPLICATE_IS_SUBPROCESS);
686 }
687 }
688
689 /* We can loop on collection_old's objects, but have to consider it mutable because with master
690 * collections collection_old and collection_new are the same data here. */
691 LISTBASE_FOREACH_MUTABLE (CollectionObject *, cob, &collection_old->gobject) {
692 Object *ob_old = cob->ob;
693 Object *ob_new = (Object *)ob_old->id.newid;
694
695 /* New object can be nullptr in master collection case, since new and old objects are in same
696 * collection. */
697 if (ELEM(ob_new, ob_old, nullptr)) {
698 continue;
699 }
700
702 bmain, collection_new, ob_new, &cob->light_linking, id_create_flag, true);
703 collection_object_remove(bmain, collection_new, ob_old, id_create_flag, false);
704 }
705 }
706
707 /* We can loop on collection_old's children,
708 * that list is currently identical the collection_new' children, and won't be changed here. */
709 LISTBASE_FOREACH_MUTABLE (CollectionChild *, child_iter, &collection_old->children) {
710 Collection *child_collection_old = child_iter->collection;
711
712 Collection *child_collection_new = collection_duplicate_recursive(bmain,
713 collection_new,
714 child_collection_old,
715 child_iter,
716 id_create_flag,
717 duplicate_flags,
718 duplicate_options);
719 if (child_collection_new != child_collection_old) {
720 collection_child_remove(bmain, collection_new, child_collection_old, id_create_flag);
721 }
722 }
723
724 return collection_new;
725}
726
728 Collection *parent,
729 CollectionChild *child_old,
730 Collection *collection,
731 eDupli_ID_Flags duplicate_flags,
732 /*eLibIDDuplicateFlags*/ uint duplicate_options)
733{
734 const bool is_subprocess = (duplicate_options & LIB_ID_DUPLICATE_IS_SUBPROCESS) != 0;
735 const bool is_root_id = (duplicate_options & LIB_ID_DUPLICATE_IS_ROOT_ID) != 0;
736 const int id_create_flag = (collection->id.tag & ID_TAG_NO_MAIN) ? LIB_ID_CREATE_NO_MAIN : 0;
737
738 if (!is_subprocess) {
740 }
741 if (is_root_id) {
742 /* In case root duplicated ID is linked, assume we want to get a local copy of it and duplicate
743 * all expected linked data. */
744 if (ID_IS_LINKED(collection)) {
745 duplicate_flags |= USER_DUP_LINKED_ID;
746 }
747 duplicate_options &= ~LIB_ID_DUPLICATE_IS_ROOT_ID;
748 }
749
751 bmain,
752 parent,
753 collection,
754 child_old,
755 id_create_flag,
756 duplicate_flags,
757 eLibIDDuplicateFlags(duplicate_options));
758
759 if (!is_subprocess) {
760 /* `collection_duplicate_recursive` will also tag our 'root' collection, which is not required
761 * unless its duplication is a sub-process of another one. */
762 collection_new->id.tag &= ~ID_TAG_NEW;
763
764 /* This code will follow into all ID links using an ID tagged with ID_TAG_NEW. */
765 /* Unfortunate, but with some types (e.g. meshes), an object is considered in Edit mode if its
766 * obdata contains edit mode runtime data. This can be the case of all newly duplicated
767 * objects, as even though duplicate code move the object back in Object mode, they are still
768 * using the original obdata ID, leading to them being falsly detected as being in Edit mode,
769 * and therefore not remapping their obdata to the newly duplicated one.
770 * See #139715. */
772
773#ifndef NDEBUG
774 /* Call to `BKE_libblock_relink_to_newid` above is supposed to have cleared all those flags. */
775 ID *id_iter;
776 FOREACH_MAIN_ID_BEGIN (bmain, id_iter) {
777 if (id_iter->tag & ID_TAG_NEW) {
778 BLI_assert((id_iter->tag & ID_TAG_NEW) == 0);
779 }
780 }
782#endif
783
784 /* Cleanup. */
786
788 }
789
790 return collection_new;
791}
792
794
795/* -------------------------------------------------------------------- */
798
799void BKE_collection_new_name_get(Collection *collection_parent, char *rname)
800{
801 char *name;
802
803 if (!collection_parent) {
804 name = BLI_strdup(DATA_("Collection"));
805 }
806 else if (collection_parent->flag & COLLECTION_IS_MASTER) {
807 name = BLI_sprintfN(DATA_("Collection %d"),
808 BLI_listbase_count(&collection_parent->children) + 1);
809 }
810 else {
811 const int number = BLI_listbase_count(&collection_parent->children) + 1;
812 const int digits = integer_digits_i(number);
813 const int max_len = sizeof(collection_parent->id.name) - 1 /* Null terminator. */ -
814 (1 + digits) /* " %d" */ - 2 /* ID */;
815 name = BLI_sprintfN("%.*s %d", max_len, collection_parent->id.name + 2, number);
816 }
817
818 BLI_strncpy(rname, name, MAX_NAME);
819 MEM_freeN(name);
820}
821
823{
824 if (collection->flag & COLLECTION_IS_MASTER) {
825 return IFACE_("Scene Collection");
826 }
827
828 return collection->id.name + 2;
829}
830
832
833/* -------------------------------------------------------------------- */
836
838 Collection *collection,
839 int parent_restrict,
840 bool with_instances)
841{
842 int child_restrict = collection->flag | parent_restrict;
843
844 LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
845 Base *base = static_cast<Base *>(BLI_findptr(lb, cob->ob, offsetof(Base, object)));
846
847 if (base == nullptr) {
848 base = MEM_callocN<Base>("Object Base");
849 base->object = cob->ob;
850 BLI_addtail(lb, base);
851 if (with_instances && cob->ob->instance_collection) {
853 lb, cob->ob->instance_collection, child_restrict, with_instances);
854 }
855 }
856
857 /* Only collection flags are checked here currently, object restrict flag is checked
858 * in FOREACH_COLLECTION_VISIBLE_OBJECT_RECURSIVE_BEGIN since it can be animated
859 * without updating the cache. */
860 if ((child_restrict & COLLECTION_HIDE_VIEWPORT) == 0) {
862 }
863 if ((child_restrict & COLLECTION_HIDE_RENDER) == 0) {
864 base->flag |= BASE_ENABLED_RENDER;
865 }
866 }
867
868 LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
869 collection_object_cache_fill(lb, child->collection, child_restrict, with_instances);
870 }
871}
872
874{
875 if (!(collection->flag & COLLECTION_HAS_OBJECT_CACHE)) {
876 static blender::Mutex cache_lock;
877
878 std::scoped_lock lock(cache_lock);
879 if (!(collection->flag & COLLECTION_HAS_OBJECT_CACHE)) {
880 collection_object_cache_fill(&collection->runtime.object_cache, collection, 0, false);
881 collection->flag |= COLLECTION_HAS_OBJECT_CACHE;
882 }
883 }
884
885 return collection->runtime.object_cache;
886}
887
889{
890 if (!(collection->flag & COLLECTION_HAS_OBJECT_CACHE_INSTANCED)) {
891 static blender::Mutex cache_lock;
892
893 std::scoped_lock lock(cache_lock);
894 if (!(collection->flag & COLLECTION_HAS_OBJECT_CACHE_INSTANCED)) {
896 &collection->runtime.object_cache_instanced, collection, 0, true);
898 }
899 }
900
901 return collection->runtime.object_cache_instanced;
902}
903
904static void collection_object_cache_free(const Main *bmain,
905 Collection *collection,
906 const int id_create_flag,
907 const uint id_recalc_flag)
908{
910 BLI_freelistN(&collection->runtime.object_cache);
912
913 /* Although it may seem abusive to call depsgraph updates from this utility function,
914 * it is called from any code-path modifying the collections hierarchy and/or their objects.
915 * Including the reversed-hierarchy walked by #collection_object_cache_free_parent_recursive.
916 *
917 * Plus, the main reason to tag the hierarchy of parents for deg update is because their object
918 * caches are being freed.
919 *
920 * Having this code here avoids the need for another utility tagging function processing the
921 * parent hierarchy as well. */
922 if (id_recalc_flag && (id_create_flag & (LIB_ID_CREATE_NO_MAIN | LIB_ID_CREATE_NO_DEG_TAG)) == 0)
923 {
924 BLI_assert(bmain != nullptr);
925 DEG_id_tag_update_ex(const_cast<Main *>(bmain), &collection->id, id_recalc_flag);
926 }
927}
928
931 Collection *collection,
932 const int id_create_flag,
933 const uint id_recalc_flag)
934{
935 collection_object_cache_free(bmain, collection, id_create_flag, id_recalc_flag);
936
937 /* Clear cache in all parents recursively, since those are affected by changes as well. */
938 LISTBASE_FOREACH (CollectionParent *, parent, &collection->runtime.parents) {
939 /* In theory there should be no nullptr pointer here. However, this code can be called from
940 * non-valid temporary states (e.g. indirectly from #BKE_collections_object_remove_invalids
941 * as part of ID remapping process). */
942 if (parent->collection == nullptr) {
943 continue;
944 }
946 bmain, parent->collection, id_create_flag, id_recalc_flag);
947 }
948}
949
951 Collection *collection,
952 const int id_create_flag)
953{
954 BLI_assert(collection != nullptr);
956 bmain, collection, id_create_flag, ID_RECALC_HIERARCHY | ID_RECALC_GEOMETRY);
957}
958
960{
961 for (Scene *scene = static_cast<Scene *>(bmain->scenes.first); scene != nullptr;
962 scene = static_cast<Scene *>(scene->id.next))
963 {
965 bmain, scene->master_collection, 0, ID_RECALC_HIERARCHY | ID_RECALC_GEOMETRY);
966 }
967
968 for (Collection *collection = static_cast<Collection *>(bmain->collections.first);
969 collection != nullptr;
970 collection = static_cast<Collection *>(collection->id.next))
971 {
973 }
974}
975
977 ViewLayer *view_layer,
978 Collection *collection)
979{
980 if (collection) {
981 return static_cast<Base *>(BKE_collection_object_cache_get(collection).first);
982 }
983 BKE_view_layer_synced_ensure(scene, view_layer);
984 return static_cast<Base *>(BKE_view_layer_object_bases_get(view_layer)->first);
985}
986
988
989/* -------------------------------------------------------------------- */
992
994{
995 BLI_assert(scene != nullptr && scene->master_collection == nullptr);
996
997 /* Not an actual datablock, but owned by scene. */
998 Collection *master_collection = static_cast<Collection *>(BKE_libblock_alloc_in_lib(
1000 master_collection->id.flag |= ID_FLAG_EMBEDDED_DATA;
1001 master_collection->owner_id = &scene->id;
1002 master_collection->flag |= COLLECTION_IS_MASTER;
1003 master_collection->color_tag = COLLECTION_COLOR_NONE;
1004
1005 BLI_assert(scene->id.lib == master_collection->id.lib);
1006
1007 return master_collection;
1008}
1009
1011
1012/* -------------------------------------------------------------------- */
1015
1017{
1018 if (object->instance_collection) {
1019 Collection *dup_collection = object->instance_collection;
1020 if ((dup_collection->id.tag & ID_TAG_DOIT) == 0) {
1021 /* Cycle already exists in collections, let's prevent further creepiness. */
1022 return true;
1023 }
1024 /* flag the object to identify cyclic dependencies in further dupli collections */
1025 dup_collection->id.tag &= ~ID_TAG_DOIT;
1026
1027 if (dup_collection == collection) {
1028 return true;
1029 }
1030
1031 FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN (dup_collection, collection_object) {
1032 if (collection_object_cyclic_check_internal(collection_object, dup_collection)) {
1033 return true;
1034 }
1035 }
1037
1038 /* un-flag the object, it's allowed to have the same collection multiple times in parallel */
1039 dup_collection->id.tag |= ID_TAG_DOIT;
1040 }
1041
1042 return false;
1043}
1044
1046{
1047 /* first flag all collections */
1049
1050 return collection_object_cyclic_check_internal(object, collection);
1051}
1052
1054
1055/* -------------------------------------------------------------------- */
1058
1059bool BKE_collection_has_object(Collection *collection, const Object *ob)
1060{
1061 if (ELEM(nullptr, collection, ob)) {
1062 return false;
1063 }
1065 return BLI_ghash_lookup(collection->runtime.gobject_hash, ob);
1066}
1067
1069{
1070 if (ELEM(nullptr, collection, ob)) {
1071 return false;
1072 }
1073
1074 const ListBase objects = BKE_collection_object_cache_get(collection);
1075 return BLI_findptr(&objects, ob, offsetof(Base, object));
1076}
1077
1079{
1080 if (ELEM(nullptr, collection, ob)) {
1081 return false;
1082 }
1083
1084 const ListBase objects = BKE_collection_object_cache_instanced_get(collection);
1085 return BLI_findptr(&objects, ob, offsetof(Base, object));
1086}
1087
1089 Object *object_eval)
1090{
1091 BLI_assert(collection_eval->id.tag & ID_TAG_COPIED_ON_EVAL);
1092 const Object *ob_orig = DEG_get_original(object_eval);
1093 const ListBase objects = BKE_collection_object_cache_instanced_get(collection_eval);
1094 LISTBASE_FOREACH (Base *, base, &objects) {
1095 if (DEG_get_original(base->object) == ob_orig) {
1096 return true;
1097 }
1098 }
1099 return false;
1100}
1101
1102static Collection *collection_next_find(Main *bmain, Scene *scene, Collection *collection)
1103{
1104 if (scene && collection == scene->master_collection) {
1105 return static_cast<Collection *>(bmain->collections.first);
1106 }
1107
1108 return static_cast<Collection *>(collection->id.next);
1109}
1110
1112 Scene *scene,
1113 Collection *collection,
1114 Object *ob)
1115{
1116 if (collection) {
1117 collection = collection_next_find(bmain, scene, collection);
1118 }
1119 else if (scene) {
1120 collection = scene->master_collection;
1121 }
1122 else {
1123 collection = static_cast<Collection *>(bmain->collections.first);
1124 }
1125
1126 while (collection) {
1127 if (BKE_collection_has_object(collection, ob)) {
1128 return collection;
1129 }
1130 collection = collection_next_find(bmain, scene, collection);
1131 }
1132 return nullptr;
1133}
1134
1136{
1137 return BLI_listbase_is_empty(&collection->gobject) &&
1138 BLI_listbase_is_empty(&collection->children);
1139}
1140
1142
1143/* -------------------------------------------------------------------- */
1146
1148 const bool do_extensive_check);
1149
1151{
1152 return BLI_ghash_ptr_new_ex(__func__, uint(BLI_listbase_count(&collection->gobject)));
1153}
1154
1156{
1157 GHash *gobject_hash = collection_gobject_hash_alloc(collection);
1158 LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
1159 if (UNLIKELY(cob->ob == nullptr)) {
1161 continue;
1162 }
1163 CollectionObject **cob_p;
1164 /* Do not overwrite an already existing entry. */
1165 if (UNLIKELY(BLI_ghash_ensure_p(gobject_hash, cob->ob, (void ***)&cob_p))) {
1167 continue;
1168 }
1169 *cob_p = cob;
1170 }
1171 collection->runtime.gobject_hash = gobject_hash;
1172}
1173
1175{
1176 if (collection->runtime.gobject_hash) {
1177#ifdef USE_DEBUG_EXTRA_GOBJECT_ASSERT
1179#endif
1180 return;
1181 }
1182
1184
1186}
1187
1193{
1194 bool changed = false;
1195
1196 if ((collection->runtime.tag & COLLECTION_TAG_COLLECTION_OBJECT_DIRTY) == 0) {
1197#ifdef USE_DEBUG_EXTRA_GOBJECT_ASSERT
1199#endif
1200 return;
1201 }
1202
1203 GHash *gobject_hash = collection->runtime.gobject_hash;
1204 if (gobject_hash) {
1205 BLI_ghash_clear_ex(gobject_hash, nullptr, nullptr, BLI_ghash_len(gobject_hash));
1206 }
1207 else {
1208 collection->runtime.gobject_hash = gobject_hash = collection_gobject_hash_alloc(collection);
1209 }
1210
1211 LISTBASE_FOREACH_MUTABLE (CollectionObject *, cob, &collection->gobject) {
1212 if (cob->ob == nullptr) {
1213 BLI_freelinkN(&collection->gobject, cob);
1214 changed = true;
1215 continue;
1216 }
1217 CollectionObject **cob_p;
1218 if (BLI_ghash_ensure_p(gobject_hash, cob->ob, (void ***)&cob_p)) {
1219 BLI_freelinkN(&collection->gobject, cob);
1220 changed = true;
1221 continue;
1222 }
1223 *cob_p = cob;
1224 }
1225
1226 if (changed) {
1227 BKE_collection_object_cache_free(bmain, collection, 0);
1228 }
1229
1232}
1233
1249 Object *ob_old,
1250 CollectionObject *cob)
1251{
1252 if (ob_old == cob->ob) {
1253 return;
1254 }
1255
1256 if (ob_old) {
1257 CollectionObject *cob_old = static_cast<CollectionObject *>(
1258 BLI_ghash_popkey(collection->runtime.gobject_hash, ob_old, nullptr));
1259 if (cob_old != cob) {
1260 /* Old object already removed from the #GHash. */
1262 }
1263 }
1264
1265 if (cob->ob) {
1266 CollectionObject **cob_p;
1267 if (!BLI_ghash_ensure_p(collection->runtime.gobject_hash, cob->ob, (void ***)&cob_p)) {
1268 *cob_p = cob;
1269 }
1270 else {
1271 /* Duplicate #CollectionObject entries. */
1273 }
1274 }
1275 else {
1276 /* #CollectionObject with nullptr object pointer. */
1278 }
1279}
1280
1295 const bool do_extensive_check)
1296{
1298 if (!do_extensive_check) {
1299 return;
1300 }
1301
1302 if (collection->runtime.gobject_hash == nullptr) {
1303 /* NOTE: If the `ghash` does not exist yet, it's creation will assert on errors,
1304 * so in theory the second loop below could be skipped. */
1306 }
1307 GHash *gobject_hash = collection->runtime.gobject_hash;
1308 UNUSED_VARS_NDEBUG(gobject_hash);
1309 LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
1310 BLI_assert(cob->ob != nullptr);
1311 /* If there are more than one #CollectionObject for the same object,
1312 * at most one of them will pass this test. */
1313 BLI_assert(BLI_ghash_lookup(gobject_hash, cob->ob) == cob);
1314 }
1315}
1316
1326 Collection *collection,
1327 bool &r_is_in_viewlayer)
1328{
1329 LayerCollection *layer_collection = view_layer ?
1331 view_layer, collection) :
1332 nullptr;
1333 r_is_in_viewlayer = layer_collection != nullptr;
1334
1335 if (!ID_IS_EDITABLE(collection) || ID_IS_OVERRIDE_LIBRARY(collection)) {
1336 return false;
1337 }
1338 if (!view_layer) {
1339 return true;
1340 }
1341
1342 if (!layer_collection) {
1343 return false;
1344 }
1345 if (layer_collection->flag & LAYER_COLLECTION_EXCLUDE) {
1346 return false;
1347 }
1348 return true;
1349}
1350
1352 Collection *collection)
1353{
1354 bool is_in_viewlayer = false;
1355 if (collection_is_editable_in_viewlayer(view_layer, collection, is_in_viewlayer)) {
1356 return collection;
1357 }
1358 if (view_layer && !is_in_viewlayer) {
1359 /* In case the collection is not in given view_layer, there is no point in searching in its
1360 * ancestors either. */
1361 return nullptr;
1362 }
1363
1364 if (collection->flag & COLLECTION_IS_MASTER) {
1365 return nullptr;
1366 }
1367
1368 LISTBASE_FOREACH (CollectionParent *, collection_parent, &collection->runtime.parents) {
1370 view_layer, collection_parent->collection);
1371 if (editable_collection) {
1372 return editable_collection;
1373 }
1374 }
1375
1376 return nullptr;
1377}
1378
1379static bool collection_object_add(Main *bmain,
1380 Collection *collection,
1381 Object *ob,
1382 CollectionLightLinking *light_linking,
1383 const int id_create_flag,
1384 const bool add_us)
1385{
1386 /* Cyclic dependency check. */
1387 if (ob->instance_collection) {
1388 if ((ob->instance_collection == collection) ||
1390 {
1391 return false;
1392 }
1393 }
1394
1396 CollectionObject **cob_p;
1397 if (BLI_ghash_ensure_p(collection->runtime.gobject_hash, ob, (void ***)&cob_p)) {
1398 return false;
1399 }
1400
1402 cob->ob = ob;
1403 if (light_linking) {
1404 cob->light_linking = *light_linking;
1405 }
1406 *cob_p = cob;
1407 BLI_addtail(&collection->gobject, cob);
1408 BKE_collection_object_cache_free(bmain, collection, id_create_flag);
1409
1410 if (add_us && (id_create_flag & LIB_ID_CREATE_NO_USER_REFCOUNT) == 0) {
1411 id_us_plus(&ob->id);
1412 }
1413
1414 if ((id_create_flag & LIB_ID_CREATE_NO_MAIN) == 0) {
1415 BKE_rigidbody_main_collection_object_add(bmain, collection, ob);
1416 }
1417
1418 return true;
1419}
1420
1426 Collection *collection,
1427 CollectionObject *cob,
1428 const int id_create_flag,
1429 const bool free_us)
1430{
1431 Object *ob = cob->ob;
1432 BLI_freelinkN(&collection->gobject, cob);
1433 BKE_collection_object_cache_free(bmain, collection, id_create_flag);
1434
1435 if (free_us) {
1436 BKE_id_free_us(bmain, ob);
1437 }
1438 else {
1439 id_us_min(&ob->id);
1440 }
1441}
1442
1444 Main *bmain, Collection *collection, Object *ob, const int id_create_flag, const bool free_us)
1445{
1447 CollectionObject *cob = static_cast<CollectionObject *>(
1448 BLI_ghash_popkey(collection->runtime.gobject_hash, ob, nullptr));
1449 if (cob == nullptr) {
1450 return false;
1451 }
1452 collection_object_remove_no_gobject_hash(bmain, collection, cob, id_create_flag, free_us);
1453 return true;
1454}
1455
1457{
1458 CollectionExport *new_data = MEM_callocN<CollectionExport>("CollectionExport");
1459 STRNCPY(new_data->fh_idname, data->fh_idname);
1460 new_data->export_properties = IDP_CopyProperty(data->export_properties);
1461 new_data->flag = data->flag;
1462
1463 /* Clear the `filepath` property. */
1464 IDProperty *filepath = IDP_GetPropertyFromGroup(new_data->export_properties, "filepath");
1465 if (filepath) {
1466 IDP_AssignString(filepath, "");
1467 }
1468
1469 BLI_addtail(&collection->exporters, new_data);
1470}
1471
1473{
1474 if (ob == nullptr) {
1475 return false;
1476 }
1477
1478 /* Only case where this pointer can be nullptr is when scene itself is linked, this case should
1479 * never be reached. */
1480 BLI_assert(collection != nullptr);
1481 if (collection == nullptr) {
1482 return false;
1483 }
1484
1485 const int id_create_flag = (collection->id.tag & ID_TAG_NO_MAIN) ? LIB_ID_CREATE_NO_MAIN : 0;
1486 if (!collection_object_add(bmain, collection, ob, nullptr, id_create_flag, true)) {
1487 return false;
1488 }
1489
1490 if (BKE_collection_is_in_scene(collection)) {
1492 }
1493
1494 return true;
1495}
1496
1497bool BKE_collection_object_add(Main *bmain, Collection *collection, Object *ob)
1498{
1499 return BKE_collection_viewlayer_object_add(bmain, nullptr, collection, ob);
1500}
1501
1503 const ViewLayer *view_layer,
1504 Collection *collection,
1505 Object *ob)
1506{
1507 if (collection == nullptr) {
1508 return false;
1509 }
1510
1511 collection = BKE_collection_parent_editable_find_recursive(view_layer, collection);
1512
1513 if (collection == nullptr) {
1514 return false;
1515 }
1516
1517 return BKE_collection_object_add_notest(bmain, collection, ob);
1518}
1519
1520void BKE_collection_object_add_from(Main *bmain, Scene *scene, Object *ob_src, Object *ob_dst)
1521{
1522 bool is_instantiated = false;
1523
1524 FOREACH_SCENE_COLLECTION_BEGIN (scene, collection) {
1525 if (ID_IS_EDITABLE(collection) && !ID_IS_OVERRIDE_LIBRARY(collection) &&
1526 BKE_collection_has_object(collection, ob_src))
1527 {
1528 collection_object_add(bmain, collection, ob_dst, nullptr, 0, true);
1529 is_instantiated = true;
1530 }
1531 }
1533
1534 if (!is_instantiated) {
1535 /* In case we could not find any non-linked collections in which instantiate our ob_dst,
1536 * fall back to scene's master collection... */
1537 collection_object_add(bmain, scene->master_collection, ob_dst, nullptr, 0, true);
1538 }
1539
1541}
1542
1544 Collection *collection,
1545 Object *ob,
1546 const bool free_us)
1547{
1548 if (ELEM(nullptr, collection, ob)) {
1549 return false;
1550 }
1551
1552 const int id_create_flag = (collection->id.tag & ID_TAG_NO_MAIN) ? LIB_ID_CREATE_NO_MAIN : 0;
1553 if (!collection_object_remove(bmain, collection, ob, id_create_flag, free_us)) {
1554 return false;
1555 }
1556
1557 if (BKE_collection_is_in_scene(collection)) {
1559 }
1560
1561 return true;
1562}
1563
1565 Collection *collection,
1566 Object *ob_old,
1567 Object *ob_new)
1568{
1570 CollectionObject *cob;
1571 cob = static_cast<CollectionObject *>(
1572 BLI_ghash_popkey(collection->runtime.gobject_hash, ob_old, nullptr));
1573 if (cob == nullptr) {
1574 return false;
1575 }
1576
1577 if (!BLI_ghash_haskey(collection->runtime.gobject_hash, ob_new)) {
1578 id_us_min(&cob->ob->id);
1579 cob->ob = ob_new;
1580 id_us_plus(&cob->ob->id);
1581
1582 BLI_ghash_insert(collection->runtime.gobject_hash, cob->ob, cob);
1583 }
1584 else {
1585 collection_object_remove_no_gobject_hash(bmain, collection, cob, 0, false);
1586 }
1587
1588 if (BKE_collection_is_in_scene(collection)) {
1590 }
1591
1592 return true;
1593}
1594
1600 Main *bmain, Scene *scene, Object *ob, const bool free_us, Collection *collection_skip)
1601{
1602 bool removed = false;
1603 const int id_create_flag = (scene->id.tag & ID_TAG_NO_MAIN) ? LIB_ID_CREATE_NO_MAIN : 0;
1604
1605 /* If given object is removed from all collections in given scene, then it can also be safely
1606 * removed from rigidbody world for given scene. */
1607 if (collection_skip == nullptr) {
1608 BKE_scene_remove_rigidbody_object(bmain, scene, ob, free_us);
1609 }
1610
1611 FOREACH_SCENE_COLLECTION_BEGIN (scene, collection) {
1612 if (!ID_IS_EDITABLE(collection) || ID_IS_OVERRIDE_LIBRARY(collection)) {
1613 continue;
1614 }
1615 if (collection == collection_skip) {
1616 continue;
1617 }
1618
1619 removed |= collection_object_remove(bmain, collection, ob, id_create_flag, free_us);
1620 }
1622
1624
1625 return removed;
1626}
1627
1628bool BKE_scene_collections_object_remove(Main *bmain, Scene *scene, Object *ob, const bool free_us)
1629{
1630 return scene_collections_object_remove(bmain, scene, ob, free_us, nullptr);
1631}
1632
1634{
1635 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
1636 collection_gobject_hash_ensure_fix(bmain, scene->master_collection);
1637 }
1638
1639 LISTBASE_FOREACH (Collection *, collection, &bmain->collections) {
1640 collection_gobject_hash_ensure_fix(bmain, collection);
1641 }
1642}
1643
1645{
1646 LISTBASE_FOREACH_MUTABLE (CollectionChild *, child, &collection->children) {
1647 if (child->collection == nullptr) {
1648 BLI_freelinkN(&collection->children, child);
1649 }
1650 }
1651}
1652
1654{
1655 LISTBASE_FOREACH_MUTABLE (CollectionParent *, parent, &collection->runtime.parents) {
1656 if ((parent->collection == nullptr) ||
1657 !BKE_collection_child_find(parent->collection, collection))
1658 {
1659 BLI_freelinkN(&collection->runtime.parents, parent);
1660 }
1661 }
1662}
1663
1665 Collection *parent_collection,
1666 Collection *child_collection)
1667{
1668 if (child_collection == nullptr) {
1669 if (parent_collection != nullptr) {
1670 collection_null_children_remove(parent_collection);
1671 }
1672 else {
1673 /* We need to do the checks in two steps when more than one collection may be involved,
1674 * otherwise we can miss some cases...
1675 * Also, master collections are not in bmain, so we also need to loop over scenes.
1676 */
1677 LISTBASE_FOREACH (Collection *, collection, &bmain->collections) {
1679 }
1680 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
1681 collection_null_children_remove(scene->master_collection);
1682 }
1683 }
1684
1685 LISTBASE_FOREACH (Collection *, collection, &bmain->collections) {
1687 }
1688 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
1689 collection_missing_parents_remove(scene->master_collection);
1690 }
1691 }
1692 else {
1693 LISTBASE_FOREACH_MUTABLE (CollectionParent *, parent, &child_collection->runtime.parents) {
1694 collection_null_children_remove(parent->collection);
1695
1696 if (!BKE_collection_child_find(parent->collection, child_collection)) {
1697 BLI_freelinkN(&child_collection->runtime.parents, parent);
1698 }
1699 }
1700 }
1701}
1702
1704 Main *bmain, Scene *scene, Collection *collection_dst, Collection *collection_src, Object *ob)
1705{
1706 /* In both cases we first add the object, then remove it from the other collections.
1707 * Otherwise we lose the original base and whether it was active and selected. */
1708 if (collection_src != nullptr) {
1709 if (BKE_collection_object_add(bmain, collection_dst, ob)) {
1710 BKE_collection_object_remove(bmain, collection_src, ob, false);
1711 }
1712 }
1713 else {
1714 /* Adding will fail if object is already in collection.
1715 * However we still need to remove it from the other collections. */
1716 BKE_collection_object_add(bmain, collection_dst, ob);
1717 scene_collections_object_remove(bmain, scene, ob, false, collection_dst);
1718 }
1719}
1720
1722
1723/* -------------------------------------------------------------------- */
1726
1728{
1729 if (collection->flag & COLLECTION_IS_MASTER) {
1730 return true;
1731 }
1732
1733 LISTBASE_FOREACH (CollectionParent *, cparent, &collection->runtime.parents) {
1734 if (BKE_collection_is_in_scene(cparent->collection)) {
1735 return true;
1736 }
1737 }
1738
1739 return false;
1740}
1741
1743{
1744 /* Need to update layer collections because objects might have changed
1745 * in linked files, and because undo push does not include updated base
1746 * flags since those are refreshed after the operator completes. */
1748}
1749
1751
1752/* -------------------------------------------------------------------- */
1755
1757 Collection *instance_collection)
1758{
1759 LISTBASE_FOREACH (CollectionObject *, collection_object, &collection->gobject) {
1760 if (collection_object->ob != nullptr &&
1761 /* Object from a given collection should never instantiate that collection either. */
1762 ELEM(collection_object->ob->instance_collection, instance_collection, collection))
1763 {
1764 return true;
1765 }
1766 }
1767
1768 LISTBASE_FOREACH (CollectionChild *, collection_child, &collection->children) {
1769 if (collection_child->collection != nullptr &&
1770 collection_instance_find_recursive(collection_child->collection, instance_collection))
1771 {
1772 return true;
1773 }
1774 }
1775
1776 return false;
1777}
1778
1779bool BKE_collection_cycle_find(Collection *new_ancestor, Collection *collection)
1780{
1781 if (collection == new_ancestor) {
1782 return true;
1783 }
1784
1785 if (collection == nullptr) {
1786 collection = new_ancestor;
1787 }
1788
1789 LISTBASE_FOREACH (CollectionParent *, parent, &new_ancestor->runtime.parents) {
1790 if (BKE_collection_cycle_find(parent->collection, collection)) {
1791 return true;
1792 }
1793 }
1794
1795 /* Find possible objects in collection or its children, that would instantiate the given ancestor
1796 * collection (that would also make a fully invalid cycle of dependencies). */
1797 return collection_instance_find_recursive(collection, new_ancestor);
1798}
1799
1800static bool collection_instance_fix_recursive(Collection *parent_collection,
1801 Collection *collection)
1802{
1803 bool cycles_found = false;
1804
1805 LISTBASE_FOREACH (CollectionObject *, collection_object, &parent_collection->gobject) {
1806 if (collection_object->ob != nullptr &&
1807 collection_object->ob->instance_collection == collection)
1808 {
1809 id_us_min(&collection->id);
1810 collection_object->ob->instance_collection = nullptr;
1811 cycles_found = true;
1812 }
1813 }
1814
1815 LISTBASE_FOREACH (CollectionChild *, collection_child, &parent_collection->children) {
1816 if (collection_instance_fix_recursive(collection_child->collection, collection)) {
1817 cycles_found = true;
1818 }
1819 }
1820
1821 return cycles_found;
1822}
1823
1825 Collection *parent_collection,
1826 Collection *collection)
1827{
1828 bool cycles_found = false;
1829
1830 LISTBASE_FOREACH_MUTABLE (CollectionParent *, parent, &parent_collection->runtime.parents) {
1831 if (BKE_collection_cycle_find(parent->collection, collection)) {
1832 BKE_collection_child_remove(bmain, parent->collection, parent_collection);
1833 cycles_found = true;
1834 }
1835 else if (collection_cycle_fix_recursive(bmain, parent->collection, collection)) {
1836 cycles_found = true;
1837 }
1838 }
1839
1840 return cycles_found;
1841}
1842
1844{
1845 return collection_cycle_fix_recursive(bmain, collection, collection) ||
1846 collection_instance_fix_recursive(collection, collection);
1847}
1848
1850{
1851 return static_cast<CollectionChild *>(
1852 BLI_findptr(&parent->children, collection, offsetof(CollectionChild, collection)));
1853}
1854
1855static bool collection_find_child_recursive(const Collection *parent, const Collection *collection)
1856{
1857 LISTBASE_FOREACH (const CollectionChild *, child, &parent->children) {
1858 if (child->collection == collection) {
1859 return true;
1860 }
1861
1862 if (collection_find_child_recursive(child->collection, collection)) {
1863 return true;
1864 }
1865 }
1866
1867 return false;
1868}
1869
1870bool BKE_collection_has_collection(const Collection *parent, const Collection *collection)
1871{
1872 return collection_find_child_recursive(parent, collection);
1873}
1874
1876{
1877 return static_cast<CollectionParent *>(
1878 BLI_findptr(&child->runtime.parents, collection, offsetof(CollectionParent, collection)));
1879}
1880
1881static bool collection_child_add(Main *bmain,
1882 Collection *parent,
1883 Collection *collection,
1884 const CollectionLightLinking *light_linking,
1885 const int id_create_flag,
1886 const bool add_us)
1887{
1888 CollectionChild *child = BKE_collection_child_find(parent, collection);
1889 if (child) {
1890 return false;
1891 }
1892 if (BKE_collection_cycle_find(parent, collection)) {
1893 return false;
1894 }
1895
1896 child = MEM_callocN<CollectionChild>("CollectionChild");
1897 child->collection = collection;
1898 if (light_linking) {
1899 child->light_linking = *light_linking;
1900 }
1901 BLI_addtail(&parent->children, child);
1902
1903 /* Don't add parent links for depsgraph datablocks, these are not kept in sync. */
1904 if ((id_create_flag & LIB_ID_CREATE_NO_MAIN) == 0) {
1905 CollectionParent *cparent = MEM_callocN<CollectionParent>("CollectionParent");
1906 cparent->collection = parent;
1907 BLI_addtail(&collection->runtime.parents, cparent);
1908 }
1909
1910 if (add_us) {
1911 id_us_plus(&collection->id);
1912 }
1913
1914 BKE_collection_object_cache_free(bmain, parent, id_create_flag);
1915
1916 return true;
1917}
1918
1920 Collection *parent,
1921 Collection *collection,
1922 const int id_create_flag)
1923{
1924 CollectionChild *child = BKE_collection_child_find(parent, collection);
1925 if (child == nullptr) {
1926 return false;
1927 }
1928
1929 CollectionParent *cparent = collection_find_parent(collection, parent);
1930 BLI_freelinkN(&collection->runtime.parents, cparent);
1931 BLI_freelinkN(&parent->children, child);
1932
1933 id_us_min(&collection->id);
1934
1935 BKE_collection_object_cache_free(bmain, parent, id_create_flag);
1936
1937 return true;
1938}
1939
1941{
1942 if (!collection_child_add(bmain, parent, child, nullptr, 0, true)) {
1943 return false;
1944 }
1945
1947 return true;
1948}
1949
1951{
1952 return collection_child_add(bmain, parent, child, nullptr, 0, true);
1953}
1954
1956{
1957 if (!collection_child_remove(bmain, parent, child, 0)) {
1958 return false;
1959 }
1960
1962 return true;
1963}
1964
1966{
1967 LISTBASE_FOREACH_MUTABLE (CollectionChild *, child, &collection->children) {
1968 /* Check for duplicated children (can happen with remapping e.g.). */
1969 CollectionChild *other_child = BKE_collection_child_find(collection, child->collection);
1970 if (other_child != child) {
1971 BLI_freelinkN(&collection->children, child);
1972 continue;
1973 }
1974
1975 /* Invalid child, either without a collection, or because it creates a dependency cycle. */
1976 if (child->collection == nullptr || BKE_collection_cycle_find(collection, child->collection)) {
1977 BLI_freelinkN(&collection->children, child);
1978 continue;
1979 }
1980
1981 /* Can happen when remapping data partially out-of-Main (during advanced ID management
1982 * operations like lib-override resync e.g.). */
1983 if ((child->collection->id.tag & (ID_TAG_NO_MAIN | ID_TAG_COPIED_ON_EVAL)) != 0) {
1984 continue;
1985 }
1986
1987 BLI_assert(collection_find_parent(child->collection, collection) == nullptr);
1989 cparent->collection = collection;
1990 BLI_addtail(&child->collection->runtime.parents, cparent);
1991 }
1992}
1993
1995{
1996 /* A same collection may be child of several others, no need to process it more than once. */
1997 if ((collection->runtime.tag & COLLECTION_TAG_RELATION_REBUILD) == 0) {
1998 return;
1999 }
2000
2003
2004 LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
2005 /* See comment above in `BKE_collection_parent_relations_rebuild`. */
2006 if ((child->collection->id.tag & (ID_TAG_NO_MAIN | ID_TAG_COPIED_ON_EVAL)) != 0) {
2007 continue;
2008 }
2009 collection_parents_rebuild_recursive(child->collection);
2010 }
2011}
2012
2014{
2015 /* Only collections not in bmain (master ones in scenes) have no parent... */
2016 LISTBASE_FOREACH (Collection *, collection, &bmain->collections) {
2017 BLI_freelistN(&collection->runtime.parents);
2018
2019 collection->runtime.tag |= COLLECTION_TAG_RELATION_REBUILD;
2020 }
2021
2022 /* Scene's master collections will be 'root' parent of most of our collections, so start with
2023 * them. */
2024 LISTBASE_FOREACH (Scene *, scene, &bmain->scenes) {
2025 /* This function can be called from `readfile.cc`, when this pointer is not guaranteed to be
2026 * nullptr.
2027 */
2028 if (scene->master_collection != nullptr) {
2029 BLI_assert(BLI_listbase_is_empty(&scene->master_collection->runtime.parents));
2030 scene->master_collection->runtime.tag |= COLLECTION_TAG_RELATION_REBUILD;
2031 collection_parents_rebuild_recursive(scene->master_collection);
2032 }
2033 }
2034
2035 /* We may have parent chains outside of scene's master_collection context? At least, readfile's
2036 * #collection_blend_read_after_liblink() seems to assume that, so do the same here. */
2037 LISTBASE_FOREACH (Collection *, collection, &bmain->collections) {
2038 if (collection->runtime.tag & COLLECTION_TAG_RELATION_REBUILD) {
2039 /* NOTE: we do not have easy access to 'which collections is root' info in that case, which
2040 * means test for cycles in collection relationships may fail here. I don't think that is an
2041 * issue in practice here, but worth keeping in mind... */
2043 }
2044 }
2045}
2046
2048{
2049 if (!BLI_listbase_validate(&collection->children)) {
2050 return false;
2051 }
2052 if (!BLI_listbase_validate(&collection->runtime.parents)) {
2053 return false;
2054 }
2055 if (BKE_collection_cycle_find(collection, nullptr)) {
2056 return false;
2057 }
2058
2059 bool is_ok = true;
2060
2061 /* Check that children have each collection used/referenced only once. */
2062 GSet *processed_collections = BLI_gset_ptr_new(__func__);
2063 LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
2064 void **r_key;
2065 if (BLI_gset_ensure_p_ex(processed_collections, child->collection, &r_key)) {
2066 is_ok = false;
2067 }
2068 else {
2069 *r_key = child->collection;
2070 }
2071 }
2072
2073 /* Check that parents have each collection used/referenced only once. */
2074 BLI_gset_clear(processed_collections, nullptr);
2075 LISTBASE_FOREACH (CollectionParent *, parent, &collection->runtime.parents) {
2076 void **r_key;
2077 if (BLI_gset_ensure_p_ex(processed_collections, parent->collection, &r_key)) {
2078 is_ok = false;
2079 }
2080 else {
2081 *r_key = parent->collection;
2082 }
2083 }
2084
2085 BLI_gset_free(processed_collections, nullptr);
2086 return is_ok;
2087}
2088
2090
2091/* -------------------------------------------------------------------- */
2094
2096 const int index,
2097 int *index_current)
2098{
2099 if (index == (*index_current)) {
2100 return collection;
2101 }
2102
2103 (*index_current)++;
2104
2105 LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
2106 Collection *nested = collection_from_index_recursive(child->collection, index, index_current);
2107 if (nested != nullptr) {
2108 return nested;
2109 }
2110 }
2111 return nullptr;
2112}
2113
2115{
2116 int index_current = 0;
2117 Collection *master_collection = scene->master_collection;
2118 return collection_from_index_recursive(master_collection, index, &index_current);
2119}
2120
2121static bool collection_objects_select(const Scene *scene,
2122 ViewLayer *view_layer,
2123 Collection *collection,
2124 bool deselect)
2125{
2126 bool changed = false;
2127
2128 if (collection->flag & COLLECTION_HIDE_SELECT) {
2129 return false;
2130 }
2131
2132 BKE_view_layer_synced_ensure(scene, view_layer);
2133 LISTBASE_FOREACH (CollectionObject *, cob, &collection->gobject) {
2134 Base *base = BKE_view_layer_base_find(view_layer, cob->ob);
2135
2136 if (base) {
2137 if (deselect) {
2138 if (base->flag & BASE_SELECTED) {
2139 base->flag &= ~BASE_SELECTED;
2140 changed = true;
2141 }
2142 }
2143 else {
2144 if ((base->flag & BASE_SELECTABLE) && !(base->flag & BASE_SELECTED)) {
2145 base->flag |= BASE_SELECTED;
2146 changed = true;
2147 }
2148 }
2149 }
2150 }
2151
2152 LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
2153 if (collection_objects_select(scene, view_layer, collection, deselect)) {
2154 changed = true;
2155 }
2156 }
2157
2158 return changed;
2159}
2160
2162 ViewLayer *view_layer,
2163 Collection *collection,
2164 bool deselect)
2165{
2167 collection);
2168
2169 if (layer_collection != nullptr) {
2170 return BKE_layer_collection_objects_select(scene, view_layer, layer_collection, deselect);
2171 }
2172
2173 return collection_objects_select(scene, view_layer, collection, deselect);
2174}
2175
2177
2178/* -------------------------------------------------------------------- */
2181
2183 Collection *to_parent,
2184 Collection *from_parent,
2185 Collection *relative,
2186 bool relative_after,
2187 Collection *collection)
2188{
2189 if (collection->flag & COLLECTION_IS_MASTER) {
2190 return false;
2191 }
2192 if (BKE_collection_cycle_find(to_parent, collection)) {
2193 return false;
2194 }
2195
2196 /* Move to new parent collection */
2197 if (from_parent) {
2198 collection_child_remove(bmain, from_parent, collection, 0);
2199 }
2200
2201 collection_child_add(bmain, to_parent, collection, nullptr, 0, true);
2202
2203 /* Move to specified location under parent. */
2204 if (relative) {
2205 CollectionChild *child = BKE_collection_child_find(to_parent, collection);
2206 CollectionChild *relative_child = BKE_collection_child_find(to_parent, relative);
2207
2208 if (relative_child) {
2209 BLI_remlink(&to_parent->children, child);
2210
2211 if (relative_after) {
2212 BLI_insertlinkafter(&to_parent->children, relative_child, child);
2213 }
2214 else {
2215 BLI_insertlinkbefore(&to_parent->children, relative_child, child);
2216 }
2217
2218 BKE_collection_object_cache_free(bmain, to_parent, 0);
2219 }
2220 }
2221
2222 /* Update layer collections. */
2224
2225 return true;
2226}
2227
2229
2230/* -------------------------------------------------------------------- */
2233
2234/* Scene collection iterator. */
2235
2241
2243 BKE_scene_collections_Cb callback,
2244 void *data)
2245{
2246 callback(collection, data);
2247
2248 LISTBASE_FOREACH (CollectionChild *, child, &collection->children) {
2249 scene_collection_callback(child->collection, callback, data);
2250 }
2251}
2252
2253static void scene_collections_count(Collection * /*collection*/, void *data)
2254{
2255 int *tot = static_cast<int *>(data);
2256 (*tot)++;
2257}
2258
2259static void scene_collections_build_array(Collection *collection, void *data)
2260{
2261 Collection ***array = static_cast<Collection ***>(data);
2262 **array = collection;
2263 (*array)++;
2264}
2265
2267 Collection ***r_collections_array,
2268 int *r_collections_array_len)
2269{
2270 *r_collections_array = nullptr;
2271 *r_collections_array_len = 0;
2272
2273 if (scene == nullptr) {
2274 return;
2275 }
2276
2277 Collection *collection = scene->master_collection;
2278 BLI_assert(collection != nullptr);
2279 scene_collection_callback(collection, scene_collections_count, r_collections_array_len);
2280
2281 BLI_assert(*r_collections_array_len > 0);
2282
2283 Collection **array = MEM_malloc_arrayN<Collection *>(size_t(*r_collections_array_len),
2284 "CollectionArray");
2285 *r_collections_array = array;
2287}
2288
2290{
2291 Scene *scene = static_cast<Scene *>(data_in);
2293
2294 data->scene = scene;
2295
2296 BLI_ITERATOR_INIT(iter);
2297 iter->data = data;
2298
2299 scene_collections_array(scene, (Collection ***)&data->array, &data->tot);
2300 BLI_assert(data->tot != 0);
2301
2302 data->cur = 0;
2303 iter->current = data->array[data->cur];
2304}
2305
2307{
2309
2310 if (++data->cur < data->tot) {
2311 iter->current = data->array[data->cur];
2312 }
2313 else {
2314 iter->valid = false;
2315 }
2316}
2317
2319{
2321
2322 if (data) {
2323 if (data->array) {
2324 MEM_freeN(data->array);
2325 }
2326 MEM_freeN(data);
2327 }
2328 iter->valid = false;
2329}
2330
2331/* scene objects iterator */
2332
2338
2339static void scene_objects_iterator_begin(BLI_Iterator *iter, Scene *scene, GSet *visited_objects)
2340{
2342
2343 BLI_ITERATOR_INIT(iter);
2344 iter->data = data;
2345
2346 /* Lookup list to make sure that each object is only processed once. */
2347 if (visited_objects != nullptr) {
2348 data->visited = visited_objects;
2349 }
2350 else {
2351 data->visited = BLI_gset_ptr_new(__func__);
2352 }
2353
2354 /* We wrap the scene-collection iterator here to go over the scene collections. */
2355 BKE_scene_collections_iterator_begin(&data->scene_collection_iter, scene);
2356
2357 Collection *collection = static_cast<Collection *>(data->scene_collection_iter.current);
2358 data->cob_next = static_cast<CollectionObject *>(collection->gobject.first);
2359
2361}
2362
2364{
2365 Scene *scene = static_cast<Scene *>(data_in);
2366
2367 scene_objects_iterator_begin(iter, scene, nullptr);
2368}
2369
2371{
2372 if (!iter->valid) {
2373 return;
2374 }
2375
2376 /* Unpack the data. */
2378 iter->data = data->iter_data;
2379
2380 Object *ob = static_cast<Object *>(iter->current);
2381 if (ob && (ob->flag & data->flag) == 0) {
2382 iter->skip = true;
2383 }
2384
2385 /* Pack the data. */
2386 data->iter_data = iter->data;
2387 iter->data = data;
2388}
2389
2391{
2393
2395
2396 /* Pack the data. */
2397 data->iter_data = iter->data;
2398 iter->data = data_in;
2399
2401}
2402
2404{
2405 /* Unpack the data. */
2407 iter->data = data->iter_data;
2408
2410
2411 /* Pack the data. */
2412 data->iter_data = iter->data;
2413 iter->data = data;
2414
2416}
2417
2419{
2420 /* Unpack the data. */
2422 iter->data = data->iter_data;
2423
2425
2426 /* Pack the data. */
2427 data->iter_data = iter->data;
2428 iter->data = data;
2429}
2430
2435{
2436 for (; cob != nullptr; cob = cob->next) {
2437 Object *ob = cob->ob;
2438 void **ob_key_p;
2439 if (!BLI_gset_ensure_p_ex(gs, ob, &ob_key_p)) {
2440 *ob_key_p = ob;
2441 return cob;
2442 }
2443 }
2444 return nullptr;
2445}
2446
2448{
2450 CollectionObject *cob = data->cob_next ? object_base_unique(data->visited, data->cob_next) :
2451 nullptr;
2452
2453 if (cob) {
2454 data->cob_next = cob->next;
2455 iter->current = cob->ob;
2456 }
2457 else {
2458 /* if this is the last object of this ListBase look at the next Collection */
2459 Collection *collection;
2460 BKE_scene_collections_iterator_next(&data->scene_collection_iter);
2461 do {
2462 collection = static_cast<Collection *>(data->scene_collection_iter.current);
2463 /* get the first unique object of this collection */
2465 data->visited, static_cast<CollectionObject *>(collection->gobject.first));
2466 if (new_cob) {
2467 data->cob_next = new_cob->next;
2468 iter->current = new_cob->ob;
2469 return;
2470 }
2471 BKE_scene_collections_iterator_next(&data->scene_collection_iter);
2472 } while (data->scene_collection_iter.valid);
2473
2474 if (!data->scene_collection_iter.valid) {
2475 iter->valid = false;
2476 }
2477 }
2478}
2479
2481{
2483 if (data) {
2484 BKE_scene_collections_iterator_end(&data->scene_collection_iter);
2485 if (data->visited != nullptr) {
2486 BLI_gset_free(data->visited, nullptr);
2487 }
2488 MEM_freeN(data);
2489 }
2490}
2491
2493{
2494 BLI_Iterator iter;
2495 scene_objects_iterator_begin(&iter, scene, objects_gset);
2496 while (iter.valid) {
2498 }
2499
2500 /* `return_gset` is either given `objects_gset` (if non-nullptr), or the GSet allocated by the
2501 * iterator. Either way, we want to get it back, and prevent `BKE_scene_objects_iterator_end`
2502 * from freeing it. */
2503 GSet *return_gset = ((SceneObjectsIteratorData *)iter.data)->visited;
2504 ((SceneObjectsIteratorData *)iter.data)->visited = nullptr;
2506
2507 return return_gset;
2508}
2509
#define FOREACH_COLLECTION_OBJECT_RECURSIVE_END
CollectionChild * BKE_collection_child_find(Collection *parent, Collection *collection)
void(*)(Collection *ob, void *data) BKE_scene_collections_Cb
#define FOREACH_SCENE_COLLECTION_END
#define FOREACH_SCENE_COLLECTION_BEGIN(scene, _instance)
#define FOREACH_COLLECTION_OBJECT_RECURSIVE_BEGIN(_collection, _object)
bool BKE_collection_cycle_find(Collection *new_ancestor, Collection *collection)
#define BKE_SCENE_COLLECTION_NAME
IDProperty * IDP_GetPropertyFromGroup(const IDProperty *prop, blender::StringRef name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition idprop.cc:766
void IDP_AssignString(IDProperty *prop, const char *st) ATTR_NONNULL()
Definition idprop.cc:431
#define IDP_BlendDataRead(reader, prop)
void IDP_FreeProperty(IDProperty *prop)
Definition idprop.cc:1243
IDProperty * IDP_CopyProperty(const IDProperty *prop) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition idprop.cc:873
void IDP_BlendWrite(BlendWriter *writer, const IDProperty *prop)
Definition idprop.cc:1453
@ IDTYPE_FLAGS_APPEND_IS_REUSABLE
Definition BKE_idtype.hh:44
@ IDTYPE_FLAGS_NO_ANIMDATA
Definition BKE_idtype.hh:46
IDTypeInfo IDType_ID_GR
LayerCollection * BKE_layer_collection_first_from_scene_collection(const ViewLayer *view_layer, const Collection *collection)
void BKE_view_layer_synced_ensure(const Scene *scene, ViewLayer *view_layer)
bool BKE_layer_collection_objects_select(const Scene *scene, ViewLayer *view_layer, LayerCollection *lc, bool deselect)
void BKE_main_collection_sync(const Main *bmain)
Base * BKE_view_layer_base_find(ViewLayer *view_layer, Object *ob)
ListBase * BKE_view_layer_object_bases_get(ViewLayer *view_layer)
ID * BKE_id_copy_for_duplicate(Main *bmain, ID *id, eDupli_ID_Flags duplicate_flags, int copy_flags)
Definition lib_id.cc:777
void BKE_id_delete(Main *bmain, void *idv) ATTR_NONNULL()
@ LIB_ID_COPY_NO_PREVIEW
@ LIB_ID_CREATE_NO_USER_REFCOUNT
@ LIB_ID_CREATE_NO_MAIN
@ LIB_ID_CREATE_NO_DEG_TAG
void BKE_id_free_us(Main *bmain, void *idv) ATTR_NONNULL()
void id_us_plus(ID *id)
Definition lib_id.cc:353
void BKE_libblock_free_data(ID *id, bool do_id_user) ATTR_NONNULL()
void BKE_main_id_newptr_and_tag_clear(Main *bmain)
Definition lib_id.cc:1981
void * BKE_id_new(Main *bmain, short type, const char *name)
Definition lib_id.cc:1495
void id_us_min(ID *id)
Definition lib_id.cc:361
void * BKE_libblock_alloc_in_lib(Main *bmain, std::optional< Library * > owner_library, short type, const char *name, int flag) ATTR_WARN_UNUSED_RESULT
Definition lib_id.cc:1334
void BKE_main_id_tag_listbase(ListBase *lb, int tag, bool value)
Definition lib_id.cc:1191
eLibIDDuplicateFlags
@ LIB_ID_DUPLICATE_IS_ROOT_ID
@ LIB_ID_DUPLICATE_IS_SUBPROCESS
void BKE_id_blend_write(BlendWriter *writer, ID *id)
Definition lib_id.cc:2611
#define BKE_LIB_FOREACHID_PROCESS_IDSUPER(data_, id_super_, cb_flag_)
LibraryForeachIDCallbackFlag
@ IDWALK_CB_LOOPBACK
@ IDWALK_CB_NEVER_SELF
@ IDWALK_CB_USER
@ IDWALK_CB_EMBEDDED_NOT_OWNING
@ IDWALK_CB_OVERRIDE_LIBRARY_HIERARCHY_DEFAULT
@ IDWALK_CB_READFILE_IGNORE
@ IDWALK_CB_NOP
#define BKE_LIB_FOREACHID_PROCESS_ID(data_, id_, cb_flag_)
LibraryForeachIDFlag BKE_lib_query_foreachid_process_flags_get(const LibraryForeachIDData *data)
Definition lib_query.cc:129
@ IDWALK_NO_ORIG_POINTERS_ACCESS
void BKE_libblock_relink_to_newid(Main *bmain, ID *id, int remap_flag) ATTR_NONNULL()
Definition lib_remap.cc:919
@ ID_REMAP_FORCE_OBDATA_IN_EDITMODE
#define FOREACH_MAIN_ID_END
Definition BKE_main.hh:563
#define FOREACH_MAIN_ID_BEGIN(_bmain, _id)
Definition BKE_main.hh:557
General operations, lookup, etc. for blender objects.
Object * BKE_object_duplicate(Main *bmain, Object *ob, eDupli_ID_Flags dupflag, uint duplicate_options)
void BKE_previewimg_blend_write(BlendWriter *writer, const PreviewImage *prv)
void BKE_previewimg_free(PreviewImage **prv)
void BKE_previewimg_blend_read(BlendDataReader *reader, PreviewImage *prv)
void BKE_previewimg_id_copy(ID *new_id, const ID *old_id)
API for Blender-side Rigid Body stuff.
void BKE_rigidbody_main_collection_object_add(struct Main *bmain, struct Collection *collection, struct Object *object)
void BKE_scene_remove_rigidbody_object(Main *bmain, Scene *scene, Object *ob, bool free_us)
Definition scene.cc:2333
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
struct GSet GSet
Definition BLI_ghash.h:337
GSet * BLI_gset_ptr_new(const char *info)
bool BLI_ghash_haskey(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.cc:819
bool BLI_gset_ensure_p_ex(GSet *gs, const void *key, void ***r_key)
Definition BLI_ghash.cc:971
void BLI_gset_clear(GSet *gs, GSetKeyFreeFP keyfreefp)
void * BLI_ghash_popkey(GHash *gh, const void *key, GHashKeyFreeFP keyfreefp) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.cc:802
GHash * BLI_ghash_ptr_new_ex(const char *info, unsigned int nentries_reserve) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
unsigned int BLI_ghash_len(const GHash *gh) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.cc:702
void * BLI_ghash_lookup(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.cc:731
void BLI_ghash_insert(GHash *gh, void *key, void *val)
Definition BLI_ghash.cc:707
void BLI_ghash_free(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp)
Definition BLI_ghash.cc:860
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
void BLI_ghash_clear_ex(GHash *gh, GHashKeyFreeFP keyfreefp, GHashValFreeFP valfreefp, unsigned int nentries_reserve)
Definition BLI_ghash.cc:842
bool BLI_ghash_ensure_p(GHash *gh, void *key, void ***r_val) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.cc:752
#define BLI_ITERATOR_INIT(iter)
#define LISTBASE_FOREACH(type, var, list)
BLI_INLINE void BLI_listbase_clear(ListBase *lb)
BLI_INLINE bool BLI_listbase_is_empty(const ListBase *lb)
void BLI_freelinkN(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:270
#define LISTBASE_FOREACH_MUTABLE(type, var, list)
void void BLI_freelistN(ListBase *listbase) ATTR_NONNULL(1)
Definition listbase.cc:497
void BLI_addtail(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:111
void BLI_insertlinkafter(ListBase *listbase, void *vprevlink, void *vnewlink) ATTR_NONNULL(1)
Definition listbase.cc:332
void BLI_remlink(ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition listbase.cc:131
void * BLI_findptr(const struct ListBase *listbase, const void *ptr, int offset) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
ListBase BLI_listbase_from_link(Link *some_link)
Definition listbase.cc:800
int BLI_listbase_count(const ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition listbase.cc:524
bool BLI_listbase_validate(ListBase *lb)
Definition listbase.cc:881
void BLI_insertlinkbefore(ListBase *listbase, void *vnextlink, void *vnewlink) ATTR_NONNULL(1)
Definition listbase.cc:371
MINLINE int integer_digits_i(int i)
char * BLI_sprintfN(const char *__restrict format,...) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC ATTR_PRINTF_FORMAT(1
char * BLI_strdup(const char *str) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1) ATTR_MALLOC
Definition string.cc:41
char * STRNCPY(char(&dst)[N], const char *src)
Definition BLI_string.h:688
char * BLI_strncpy(char *__restrict dst, const char *__restrict src, size_t dst_maxncpy) ATTR_NONNULL(1
void BLI_uniquename(const struct ListBase *list, void *vlink, const char *defname, char delim, int name_offset, size_t name_maxncpy) ATTR_NONNULL(1
unsigned int uint
#define UNUSED_VARS_NDEBUG(...)
#define UNLIKELY(x)
#define ELEM(...)
#define MEMCMP_STRUCT_AFTER_IS_ZERO(struct_var, member)
#define MEMCPY_STRUCT_AFTER(struct_dst, struct_src, member)
int BLO_read_fileversion_get(BlendDataReader *reader)
Definition readfile.cc:5239
#define BLO_write_id_struct(writer, struct_name, id_address, id)
#define BLO_write_struct(writer, struct_name, data_ptr)
#define BLO_read_struct_list(reader, struct_name, list)
#define BLO_read_struct(reader, struct_name, ptr_p)
#define IFACE_(msgid)
#define BLT_I18NCONTEXT_ID_COLLECTION
#define DATA_(msgid)
#define CLOG_WARN(clg_ref,...)
Definition CLG_log.h:181
T * DEG_get_original(T *id)
ID and Library types, which are fundamental for SDNA.
@ ID_RECALC_HIERARCHY
Definition DNA_ID.h:1066
@ ID_RECALC_GEOMETRY
Definition DNA_ID.h:982
@ ID_TAG_NEW
Definition DNA_ID.h:827
@ ID_TAG_COPIED_ON_EVAL
Definition DNA_ID.h:905
@ ID_TAG_DOIT
Definition DNA_ID.h:944
@ ID_TAG_NO_MAIN
Definition DNA_ID.h:886
@ ID_FLAG_EMBEDDED_DATA
Definition DNA_ID.h:687
@ INDEX_ID_GR
Definition DNA_ID.h:1249
@ ID_SCE
@ ID_GR
Object groups, one object can be in many groups at once.
@ COLLECTION_HIDE_RENDER
@ COLLECTION_HAS_OBJECT_CACHE_INSTANCED
@ COLLECTION_HIDE_SELECT
@ COLLECTION_IS_MASTER
@ COLLECTION_HAS_OBJECT_CACHE
@ COLLECTION_HIDE_VIEWPORT
#define COLLECTION_FLAG_ALL_RUNTIME
@ COLLECTION_TAG_COLLECTION_OBJECT_DIRTY
@ COLLECTION_TAG_RELATION_REBUILD
@ COLLECTION_COLOR_NONE
#define DNA_struct_default_get(struct_name)
@ LAYER_COLLECTION_EXCLUDE
@ BASE_ENABLED_RENDER
@ BASE_ENABLED_VIEWPORT
Object is a sort of wrapper for general info.
Types and defines for representing Rigid Body entities.
#define BASE_SELECTED(v3d, base)
#define BASE_SELECTABLE(v3d, base)
eDupli_ID_Flags
@ USER_DUP_LINKED_ID
@ USER_DUP_OBJECT
Read Guarded memory(de)allocation.
volatile int lock
BMesh const char void * data
static void collection_object_cache_fill(ListBase *lb, Collection *collection, int parent_restrict, bool with_instances)
static bool collection_object_add(Main *bmain, Collection *collection, Object *ob, CollectionLightLinking *light_linking, const int id_create_flag, const bool add_us)
static bool collection_cycle_fix_recursive(Main *bmain, Collection *parent_collection, Collection *collection)
static Collection * collection_from_index_recursive(Collection *collection, const int index, int *index_current)
static bool collection_child_remove(Main *bmain, Collection *parent, Collection *collection, const int id_create_flag)
bool BKE_collection_has_object_recursive_instanced(Collection *collection, Object *ob)
static Collection * collection_duplicate_recursive(Main *bmain, Collection *parent, Collection *collection_old, CollectionChild *child_old, const int id_create_flag, const eDupli_ID_Flags duplicate_flags, const eLibIDDuplicateFlags duplicate_options)
static CollectionObject * object_base_unique(GSet *gs, CollectionObject *cob)
void BKE_scene_objects_iterator_begin_ex(BLI_Iterator *iter, void *data_in)
void BKE_scene_objects_iterator_next_ex(BLI_Iterator *iter)
Collection * BKE_collection_master_add(Scene *scene)
static CollectionParent * collection_find_parent(Collection *child, Collection *collection)
void BKE_collection_object_cache_free(const Main *bmain, Collection *collection, const int id_create_flag)
bool BKE_collection_has_object_recursive(Collection *collection, Object *ob)
static void collection_exporter_copy(Collection *collection, CollectionExport *data)
static void collection_gobject_assert_internal_consistency(Collection *collection, const bool do_extensive_check)
CollectionChild * BKE_collection_child_find(Collection *parent, Collection *collection)
void BKE_collection_add_from_collection(Main *bmain, Scene *scene, Collection *collection_src, Collection *collection_dst)
const char * BKE_collection_ui_name_get(Collection *collection)
static Collection * collection_add(Main *bmain, Collection *collection_parent, const char *name_custom)
void BKE_collection_exporter_free_data(CollectionExport *data)
bool BKE_collection_has_object_recursive_instanced_orig_id(Collection *collection_eval, Object *object_eval)
static ID ** collection_owner_pointer_get(ID *id, const bool debug_relationship_assert)
void BKE_collection_blend_write_nolib(BlendWriter *writer, Collection *collection)
bool BKE_collection_child_remove(Main *bmain, Collection *parent, Collection *child)
bool BKE_collection_viewlayer_object_add(Main *bmain, const ViewLayer *view_layer, Collection *collection, Object *ob)
void BKE_scene_collections_iterator_next(BLI_Iterator *iter)
static GHash * collection_gobject_hash_alloc(const Collection *collection)
static bool collection_instance_find_recursive(Collection *collection, Collection *instance_collection)
Collection * BKE_collection_add(Main *bmain, Collection *collection_parent, const char *name_custom)
bool BKE_collection_has_object(Collection *collection, const Object *ob)
static void collection_copy_data(Main *bmain, std::optional< Library * >, ID *id_dst, const ID *id_src, const int flag)
ListBase BKE_collection_object_cache_instanced_get(Collection *collection)
void BKE_collections_object_remove_invalids(Main *bmain)
Base * BKE_collection_or_layer_objects(const Scene *scene, ViewLayer *view_layer, Collection *collection)
void BKE_scene_objects_iterator_end(BLI_Iterator *iter)
bool BKE_collection_object_replace(Main *bmain, Collection *collection, Object *ob_old, Object *ob_new)
bool BKE_collection_is_empty(const Collection *collection)
static void collection_parents_rebuild_recursive(Collection *collection)
static void collection_gobject_hash_ensure_fix(Main *bmain, Collection *collection)
Collection * BKE_collection_duplicate(Main *bmain, Collection *parent, CollectionChild *child_old, Collection *collection, eDupli_ID_Flags duplicate_flags, uint duplicate_options)
bool BKE_collection_move(Main *bmain, Collection *to_parent, Collection *from_parent, Collection *relative, bool relative_after, Collection *collection)
bool BKE_collection_is_in_scene(Collection *collection)
static void scene_collection_callback(Collection *collection, BKE_scene_collections_Cb callback, void *data)
bool BKE_collection_child_add(Main *bmain, Collection *parent, Collection *child)
void BKE_collection_object_move(Main *bmain, Scene *scene, Collection *collection_dst, Collection *collection_src, Object *ob)
void BKE_collection_add_from_object(Main *bmain, Scene *scene, const Object *ob_src, Collection *collection_dst)
static Collection * collection_next_find(Main *bmain, Scene *scene, Collection *collection)
static bool collection_child_add(Main *bmain, Collection *parent, Collection *collection, const CollectionLightLinking *light_linking, const int id_create_flag, const bool add_us)
static bool collection_object_cyclic_check_internal(Object *object, Collection *collection)
bool BKE_scene_collections_object_remove(Main *bmain, Scene *scene, Object *ob, const bool free_us)
void BKE_collections_child_remove_nulls(Main *bmain, Collection *parent_collection, Collection *child_collection)
void BKE_collection_exporter_name_set(const ListBase *exporters, CollectionExport *data, const char *newname)
GSet * BKE_scene_objects_as_gset(Scene *scene, GSet *objects_gset)
bool BKE_collection_validate(Collection *collection)
bool BKE_collection_object_remove(Main *bmain, Collection *collection, Object *ob, const bool free_us)
bool BKE_collection_child_add_no_sync(Main *bmain, Collection *parent, Collection *child)
void BKE_collection_blend_write_prepare_nolib(BlendWriter *, Collection *collection)
static void collection_gobject_hash_create(Collection *collection)
void BKE_scene_collections_iterator_begin(BLI_Iterator *iter, void *data_in)
void BKE_collection_new_name_get(Collection *collection_parent, char *rname)
void BKE_collection_free_data(Collection *collection)
static bool collection_objects_select(const Scene *scene, ViewLayer *view_layer, Collection *collection, bool deselect)
static bool collection_find_child_recursive(const Collection *parent, const Collection *collection)
static void collection_gobject_hash_ensure(Collection *collection)
static void scene_collections_count(Collection *, void *data)
void BKE_main_collections_object_cache_free(const Main *bmain)
Collection * BKE_collection_object_find(Main *bmain, Scene *scene, Collection *collection, Object *ob)
Collection * BKE_collection_from_index(Scene *scene, const int index)
static void collection_gobject_hash_update_object(Collection *collection, Object *ob_old, CollectionObject *cob)
void BKE_scene_collections_iterator_end(BLI_Iterator *iter)
bool BKE_collection_cycles_fix(Main *bmain, Collection *collection)
static bool collection_object_remove(Main *bmain, Collection *collection, Object *ob, const int id_create_flag, const bool free_us)
bool BKE_collection_object_add_notest(Main *bmain, Collection *collection, Object *ob)
void BKE_scene_objects_iterator_end_ex(BLI_Iterator *iter)
static void collection_free_data(ID *id)
static bool collection_instance_fix_recursive(Collection *parent_collection, Collection *collection)
void BKE_collection_object_add_from(Main *bmain, Scene *scene, Object *ob_src, Object *ob_dst)
static void collection_blend_read_data(BlendDataReader *reader, ID *id)
Collection * BKE_collection_parent_editable_find_recursive(const ViewLayer *view_layer, Collection *collection)
static void scene_collections_array(Scene *scene, Collection ***r_collections_array, int *r_collections_array_len)
static void collection_object_cache_free(const Main *bmain, Collection *collection, const int id_create_flag, const uint id_recalc_flag)
bool BKE_collection_delete(Main *bmain, Collection *collection, bool hierarchy)
bool BKE_collection_cycle_find(Collection *new_ancestor, Collection *collection)
static void scene_objects_iterator_begin(BLI_Iterator *iter, Scene *scene, GSet *visited_objects)
static void collection_null_children_remove(Collection *collection)
static void collection_blend_write(BlendWriter *writer, ID *id, const void *id_address)
bool BKE_collection_object_cyclic_check(Main *bmain, Object *object, Collection *collection)
static void collection_missing_parents_remove(Collection *collection)
void BKE_collections_after_lib_link(Main *bmain)
bool BKE_collection_has_collection(const Collection *parent, const Collection *collection)
static void scene_collections_build_array(Collection *collection, void *data)
static void collection_object_remove_no_gobject_hash(Main *bmain, Collection *collection, CollectionObject *cob, const int id_create_flag, const bool free_us)
static bool scene_collections_object_remove(Main *bmain, Scene *scene, Object *ob, const bool free_us, Collection *collection_skip)
static void collection_init_data(ID *id)
static void collection_object_cache_free_parent_recursive(const Main *bmain, Collection *collection, const int id_create_flag, const uint id_recalc_flag)
ListBase BKE_collection_object_cache_get(Collection *collection)
void BKE_collection_blend_read_data(BlendDataReader *reader, Collection *collection, ID *owner_id)
void BKE_scene_objects_iterator_begin(BLI_Iterator *iter, void *data_in)
void BKE_collection_parent_relations_rebuild(Collection *collection)
bool BKE_collection_objects_select(const Scene *scene, ViewLayer *view_layer, Collection *collection, bool deselect)
static void scene_objects_iterator_skip_invalid_flag(BLI_Iterator *iter)
static bool collection_is_editable_in_viewlayer(const ViewLayer *view_layer, Collection *collection, bool &r_is_in_viewlayer)
static void collection_blend_read_after_liblink(BlendLibReader *, ID *id)
void BKE_scene_objects_iterator_next(BLI_Iterator *iter)
static void collection_foreach_id(ID *id, LibraryForeachIDData *data)
void BKE_main_collections_parent_relations_rebuild(Main *bmain)
bool BKE_collection_object_add(Main *bmain, Collection *collection, Object *ob)
#define offsetof(t, d)
#define FILTER_ID_OB
#define ID_IS_OVERRIDABLE_LIBRARY(_id)
#define ID_IS_LINKED(_id)
#define FILTER_ID_GR
#define ID_IS_EDITABLE(_id)
#define MAX_NAME
#define ID_IS_OVERRIDE_LIBRARY(_id)
#define GS(a)
DEG_id_tag_update_ex(cb_data->bmain, cb_data->owner_id, ID_RECALC_TAG_FOR_UNDO|ID_RECALC_SYNC_TO_EVAL)
#define LOG(severity)
Definition log.h:32
void * MEM_callocN(size_t len, const char *str)
Definition mallocn.cc:118
void * MEM_malloc_arrayN(size_t len, size_t size, const char *str)
Definition mallocn.cc:133
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
std::mutex Mutex
Definition BLI_mutex.hh:47
short flag
struct Object * object
struct Collection * collection
CollectionLightLinking light_linking
IDProperty * export_properties
struct CollectionObject * next
CollectionLightLinking light_linking
struct Collection * collection
struct PreviewImage * preview
Collection_Runtime runtime
Definition DNA_ID.h:404
int tag
Definition DNA_ID.h:424
struct Library * lib
Definition DNA_ID.h:410
struct ID * newid
Definition DNA_ID.h:408
short flag
Definition DNA_ID.h:420
void * next
Definition DNA_ID.h:407
char name[66]
Definition DNA_ID.h:415
void * first
ListBase scenes
Definition BKE_main.hh:245
ListBase collections
Definition BKE_main.hh:267
struct Collection * instance_collection
LightLinking * light_linking
BLI_Iterator scene_collection_iter
CollectionObject * cob_next
struct Collection * master_collection
#define N_(msgid)
uint8_t flag
Definition wm_window.cc:139