Blender V5.0
lib_query.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2014 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <cstdlib>
10
11#include "CLG_log.h"
12
13#include "DNA_anim_types.h"
14
15#include "BLI_function_ref.hh"
16#include "BLI_ghash.h"
17#include "BLI_linklist_stack.h"
18#include "BLI_listbase.h"
19#include "BLI_set.hh"
20
21#include "BKE_anim_data.hh"
22#include "BKE_idprop.hh"
23#include "BKE_idtype.hh"
24#include "BKE_lib_id.hh"
25#include "BKE_lib_query.hh"
26#include "BKE_main.hh"
27#include "BKE_node.hh"
28
29static CLG_LogRef LOG = {"lib.query"};
30
31/* status */
32enum {
33 IDWALK_STOP = 1 << 0,
34};
35
72
74{
75 return (data->status & IDWALK_STOP) != 0;
76}
77
79 ID **id_pp,
81{
83 return;
84 }
85
86 const LibraryForeachIDFlag flag = data->flag;
87 ID *old_id = *id_pp;
88
89 /* Update the callback flags with the ones defined (or forbidden) in `data` by the generic
90 * caller code. */
91 cb_flag = LibraryForeachIDCallbackFlag((cb_flag | data->cb_flag) & ~data->cb_flag_clear);
92
93 /* Update the callback flags with some extra information regarding overrides: all "loop-back",
94 * "internal", "embedded" etc. ID pointers are never overridable. */
97 }
98
99 LibraryIDLinkCallbackData callback_data{};
100 callback_data.user_data = data->user_data;
101 callback_data.bmain = data->bmain;
102 callback_data.owner_id = data->owner_id;
103 callback_data.self_id = data->self_id;
104 callback_data.id_pointer = id_pp;
105 callback_data.cb_flag = cb_flag;
106 const int callback_return = data->callback(&callback_data);
107
108 if (flag & IDWALK_READONLY) {
109 BLI_assert(*(id_pp) == old_id);
110 }
111 else {
113 "Iteration over ID usages should not be interrupted by the callback in "
114 "non-readonly cases");
115 }
116
117 if (old_id && (flag & IDWALK_RECURSE)) {
118 if (BLI_gset_add((data)->ids_handled, old_id)) {
119 if (!(callback_return & IDWALK_RET_STOP_RECURSION)) {
120 BLI_LINKSTACK_PUSH(data->ids_todo, old_id);
121 }
122 }
123 }
124 if (callback_return & IDWALK_RET_STOP_ITER) {
125 data->status |= IDWALK_STOP;
126 }
127}
128
133
138
140 LibraryForeachIDData *data, const LibraryForeachIDCallbackFlag cb_flag, const bool do_replace)
141{
142 const LibraryForeachIDCallbackFlag cb_flag_backup = data->cb_flag;
143 if (do_replace) {
144 data->cb_flag = cb_flag;
145 }
146 else {
147 data->cb_flag |= cb_flag;
148 }
149 return cb_flag_backup;
150}
151
152static bool library_foreach_ID_link(Main *bmain,
153 ID *owner_id,
154 ID *id,
156 void *user_data,
158 LibraryForeachIDData *inherit_data);
159
171
173{
174 /* Needed e.g. for callbacks handling relationships. This call should be absolutely read-only. */
175 ID *id = *id_pp;
176 const LibraryForeachIDFlag flag = data->flag;
177
180 return;
181 }
182 BLI_assert(id == *id_pp);
183
184 if (id == nullptr) {
185 return;
186 }
187
189 /* Do Nothing. */
190 }
191 else if (flag & IDWALK_RECURSE) {
192 /* Defer handling into main loop, recursively calling BKE_library_foreach_ID_link in
193 * IDWALK_RECURSE case is troublesome, see #49553. */
194 if (BLI_gset_add(data->ids_handled, id)) {
195 BLI_LINKSTACK_PUSH(data->ids_todo, id);
196 }
197 }
198 else {
200 data->bmain, data->owner_id, id, data->callback, data->user_data, data->flag, data))
201 {
202 data->status |= IDWALK_STOP;
203 return;
204 }
205 }
206}
207
209{
210 if (data->ids_handled != nullptr) {
211 BLI_gset_free(data->ids_handled, nullptr);
212 BLI_LINKSTACK_FREE(data->ids_todo);
213 }
214}
215
217static bool library_foreach_ID_link(Main *bmain,
218 ID *owner_id,
219 ID *id,
221 void *user_data,
223 LibraryForeachIDData *inherit_data)
224{
226 data.bmain = bmain;
227
228 BLI_assert(inherit_data == nullptr || data.bmain == inherit_data->bmain);
229 /* `IDWALK_NO_ORIG_POINTERS_ACCESS` is mutually exclusive with `IDWALK_RECURSE`. */
232
235 }
236
237 if (flag & IDWALK_RECURSE) {
238 /* For now, recursion implies read-only, and no internal pointers. */
241
242 /* NOTE: This function itself should never be called recursively when IDWALK_RECURSE is set,
243 * see also comments in #BKE_library_foreach_ID_embedded.
244 * This is why we can always create this data here, and do not need to try and re-use it from
245 * `inherit_data`. */
247 BLI_LINKSTACK_INIT(data.ids_todo);
248
249 BLI_gset_add(data.ids_handled, id);
250 }
251 else {
252 data.ids_handled = nullptr;
253 }
254 data.flag = flag;
255 data.status = 0;
256 data.callback = callback;
257 data.user_data = user_data;
258
259#define CALLBACK_INVOKE_ID(check_id, cb_flag) \
260 { \
261 CHECK_TYPE_ANY((check_id), ID *, void *); \
262 BKE_lib_query_foreachid_process(&data, (ID **)&(check_id), (cb_flag)); \
263 if (BKE_lib_query_foreachid_iter_stop(&data)) { \
264 library_foreach_ID_data_cleanup(&data); \
265 return false; \
266 } \
267 } \
268 ((void)0)
269
270#define CALLBACK_INVOKE(check_id_super, cb_flag) \
271 { \
272 CHECK_TYPE(&((check_id_super)->id), ID *); \
273 BKE_lib_query_foreachid_process(&data, (ID **)&(check_id_super), (cb_flag)); \
274 if (BKE_lib_query_foreachid_iter_stop(&data)) { \
275 library_foreach_ID_data_cleanup(&data); \
276 return false; \
277 } \
278 } \
279 ((void)0)
280
281 for (; id != nullptr; id = (flag & IDWALK_RECURSE) ? BLI_LINKSTACK_POP(data.ids_todo) : nullptr,
282 owner_id = nullptr)
283 {
284 data.self_id = id;
285 /* owner ID is same as self ID, except for embedded ID case. */
286 if (id->flag & ID_FLAG_EMBEDDED_DATA) {
288 data.owner_id = owner_id ? owner_id : id;
289 }
290 else {
291 /* NOTE: Unfortunately it is not possible to ensure validity of the set owner_id pointer
292 * here. `foreach_id` is used a lot by code remapping pointers, and in such cases the
293 * current owner ID of the processed embedded ID is indeed invalid - and the given one is
294 * to be assumed valid for the purpose of the current process.
295 *
296 * In other words, it is the responsibility of the code calling this `foreach_id` process
297 * to ensure that the given owner ID is valid for its own purpose, or that it is not used.
298 */
299 // BLI_assert(owner_id == nullptr || BKE_id_owner_get(id) == owner_id);
300 if (!owner_id) {
301 owner_id = BKE_id_owner_get(id, false);
302 }
303 data.owner_id = owner_id;
304 }
305 }
306 else {
307 BLI_assert(ELEM(owner_id, nullptr, id));
308 data.owner_id = id;
309 }
310
311 /* inherit_data is non-nullptr when this function is called for some sub-data ID
312 * (like root node-tree of a material).
313 * In that case, we do not want to generate those 'generic flags' from our current sub-data ID
314 * (the node tree), but re-use those generated for the 'owner' ID (the material). */
315 if (inherit_data == nullptr) {
317 /* When an ID is defined as not reference-counting its ID usages, it should never do it. */
318 data.cb_flag_clear = (id->tag & ID_TAG_NO_USER_REFCOUNT) ?
321 }
322 else {
323 data.cb_flag = inherit_data->cb_flag;
324 data.cb_flag_clear = inherit_data->cb_flag_clear;
325 }
326
327 bool use_bmain_relations = bmain != nullptr && bmain->relations != nullptr &&
329 /* Including UI-related ID pointers should match with the relevant setting in Main relations
330 * cache. */
331 if (use_bmain_relations && (((bmain->relations->flag & MAINIDRELATIONS_INCLUDE_UI) == 0) !=
332 ((data.flag & IDWALK_INCLUDE_UI) == 0)))
333 {
334 use_bmain_relations = false;
335 }
336 /* No special 'internal' handling of ID pointers is covered by Main relations cache. */
337 if (use_bmain_relations &&
340 {
341 use_bmain_relations = false;
342 }
343 if (use_bmain_relations) {
344 /* Note that this is minor optimization, even in worst cases (like id being an object with
345 * lots of drivers and constraints and modifiers, or material etc. with huge node tree),
346 * but we might as well use it (Main->relations is always assumed valid,
347 * it's responsibility of code creating it to free it,
348 * especially if/when it starts modifying Main database). */
349 MainIDRelationsEntry *entry = static_cast<MainIDRelationsEntry *>(
351 for (MainIDRelationsEntryItem *to_id_entry = entry->to_ids; to_id_entry != nullptr;
352 to_id_entry = to_id_entry->next)
353 {
355 &data, to_id_entry->id_pointer.to, to_id_entry->usage_flag);
358 return false;
359 }
360 }
361 continue;
362 }
363
366 }
367
371 }
372
373 if (id->override_library != nullptr) {
376
379 LISTBASE_FOREACH (IDOverrideLibraryPropertyOperation *, opop, &op->operations) {
380 CALLBACK_INVOKE_ID(opop->subitem_reference_id,
382 CALLBACK_INVOKE_ID(opop->subitem_local_id,
384 }
385 }
386 }
387
389 BKE_lib_query_idpropertiesForeachIDLink_callback(prop, &data);
390 });
393 return false;
394 }
395
397 BKE_lib_query_idpropertiesForeachIDLink_callback(prop, &data);
398 });
401 return false;
402 }
403
405 if (adt) {
409 return false;
410 }
411 }
412
413 const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(id);
414 if (id_type->foreach_id != nullptr) {
415 id_type->foreach_id(id, &data);
416
419 return false;
420 }
421 }
422 }
423
425 return true;
426
427#undef CALLBACK_INVOKE_ID
428#undef CALLBACK_INVOKE
429}
430
432 ID *id,
434 void *user_data,
436{
437 library_foreach_ID_link(bmain, nullptr, id, callback, user_data, flag, nullptr);
438}
439
440void BKE_library_update_ID_link_user(ID *id_dst, ID *id_src, const int cb_flag)
441{
442 if (cb_flag & IDWALK_CB_USER) {
443 id_us_min(id_src);
444 id_us_plus(id_dst);
445 }
446 else if (cb_flag & IDWALK_CB_USER_ONE) {
447 id_us_ensure_real(id_dst);
448 }
449}
450
452 Main *bmain,
453 ID *owner_id,
454 ID *self_id,
455 blender::FunctionRef<void(LibraryForeachIDData *data)> subdata_foreach_id,
457 void *user_data,
459{
462
464 data.bmain = bmain;
465 data.owner_id = owner_id;
466 data.self_id = self_id;
467 data.ids_handled = nullptr;
468 data.flag = flag;
469 data.status = 0;
470 data.callback = callback;
471 data.user_data = user_data;
472
473 subdata_foreach_id(&data);
474}
475
477 const bool include_ui,
478 const IDTypeInfo *owner_id_type)
479{
480 /* any type of ID can be used in custom props. */
481 if (owner_id->properties) {
482 return FILTER_ID_ALL;
483 }
484 /* When including UI data (i.e. editors), Screen UI IDs can also link to virtually any ID
485 * (through e.g. the Outliner). */
486 if (include_ui && GS(owner_id->name) == ID_SCR) {
487 return FILTER_ID_ALL;
488 }
489
490 /* Casting to non const.
491 * TODO(jbakker): We should introduce a ntree_id_has_tree function as we are actually not
492 * interested in the result. */
493 if (blender::bke::node_tree_from_id(const_cast<ID *>(owner_id))) {
494 return FILTER_ID_ALL;
495 }
496
497 if (BKE_animdata_from_id(owner_id)) {
498 /* AnimationData can use virtually any kind of data-blocks, through drivers especially. */
499 return FILTER_ID_ALL;
500 }
501
502 if (ID_IS_OVERRIDE_LIBRARY_REAL(owner_id)) {
503 /* LibOverride data 'hierarchy root' can virtually point back to any type of ID. */
504 return FILTER_ID_ALL;
505 }
506
507 if (!owner_id_type) {
508 owner_id_type = BKE_idtype_get_info_from_id(owner_id);
509 }
510 if (owner_id_type) {
511 return owner_id_type->dependencies_id_types;
512 }
514 return 0;
515}
516
517bool BKE_library_id_can_use_idtype(ID *owner_id, const short id_type_used)
518{
519 const IDTypeInfo *owner_id_type = BKE_idtype_get_info_from_id(owner_id);
520 const uint64_t filter_id_type_used = BKE_idtype_idcode_to_idfilter(id_type_used);
521 const uint64_t can_be_used = BKE_library_id_can_use_filter_id(owner_id, false, owner_id_type);
522 return (can_be_used & filter_id_type_used) != 0;
523}
524
525/* ***** ID users iterator. ***** */
528
529 // ListBase *lb_array[INDEX_ID_MAX]; /* UNUSED. */
530 // int lb_idx; /* UNUSED. */
531
533 int count_direct, count_indirect; /* Set by callback. */
534};
535
537{
538 ID **id_p = cb_data->id_pointer;
539 const LibraryForeachIDCallbackFlag cb_flag = cb_data->cb_flag;
540 IDUsersIter *iter = static_cast<IDUsersIter *>(cb_data->user_data);
541
542 if (*id_p) {
543 /* "Loop-back" ID pointers (the ugly *from* ones, like `Key->from`).
544 * Those are not actually ID usage, we can ignore them here.
545 */
546 if (cb_flag & IDWALK_CB_LOOPBACK) {
547 return IDWALK_RET_NOP;
548 }
549
550 if (*id_p == iter->id) {
551#if 0
552 printf(
553 "%s uses %s (refcounted: %d, userone: %d, used_one: %d, used_one_active: %d, "
554 "indirect_usage: %d)\n",
555 iter->curr_id->name,
556 iter->id->name,
557 (cb_flag & IDWALK_USER) ? 1 : 0,
558 (cb_flag & IDWALK_USER_ONE) ? 1 : 0,
559 (iter->id->tag & ID_TAG_EXTRAUSER) ? 1 : 0,
560 (iter->id->tag & ID_TAG_EXTRAUSER_SET) ? 1 : 0,
561 (cb_flag & IDWALK_INDIRECT_USAGE) ? 1 : 0);
562#endif
563 if (cb_flag & IDWALK_CB_INDIRECT_USAGE) {
564 iter->count_indirect++;
565 }
566 else {
567 iter->count_direct++;
568 }
569 }
570 }
571
572 return IDWALK_RET_NOP;
573}
574
575int BKE_library_ID_use_ID(ID *id_user, ID *id_used)
576{
577 IDUsersIter iter;
578
579 /* We do not care about iter.lb_array/lb_idx here... */
580 iter.id = id_used;
581 iter.curr_id = id_user;
582 iter.count_direct = iter.count_indirect = 0;
583
585 nullptr, iter.curr_id, foreach_libblock_id_users_callback, (void *)&iter, IDWALK_READONLY);
586
587 return iter.count_direct + iter.count_indirect;
588}
589
590static bool library_ID_is_used(Main *bmain, void *idv, const bool check_linked)
591{
592 IDUsersIter iter;
593 MainListsArray lb_array = BKE_main_lists_get(*bmain);
594 int i = lb_array.size();
595 ID *id = static_cast<ID *>(idv);
596 bool is_defined = false;
597
598 iter.id = id;
599 iter.count_direct = iter.count_indirect = 0;
600 while (i-- && !is_defined) {
601 ID *id_curr = static_cast<ID *>(lb_array[i]->first);
602
603 if (!id_curr || !BKE_library_id_can_use_idtype(id_curr, GS(id->name))) {
604 continue;
605 }
606
607 for (; id_curr && !is_defined; id_curr = static_cast<ID *>(id_curr->next)) {
608 if (id_curr == id) {
609 /* We are not interested in self-usages (mostly from drivers or bone constraints...). */
610 continue;
611 }
612 iter.curr_id = id_curr;
615
616 is_defined = ((check_linked ? iter.count_indirect : iter.count_direct) != 0);
617 }
618 }
619
620 return is_defined;
621}
622
624{
625 return library_ID_is_used(bmain, idv, false);
626}
627
629{
630 return library_ID_is_used(bmain, idv, true);
631}
632
634 void *idv,
635 bool *r_is_used_local,
636 bool *r_is_used_linked)
637{
638 IDUsersIter iter;
639 MainListsArray lb_array = BKE_main_lists_get(*bmain);
640 int i = lb_array.size();
641 ID *id = static_cast<ID *>(idv);
642 bool is_defined = false;
643
644 iter.id = id;
645 iter.count_direct = iter.count_indirect = 0;
646 while (i-- && !is_defined) {
647 ID *id_curr = static_cast<ID *>(lb_array[i]->first);
648
649 if (!id_curr || !BKE_library_id_can_use_idtype(id_curr, GS(id->name))) {
650 continue;
651 }
652
653 for (; id_curr && !is_defined; id_curr = static_cast<ID *>(id_curr->next)) {
654 if (id_curr == id) {
655 /* We are not interested in self-usages (mostly from drivers or bone constraints...). */
656 continue;
657 }
658 iter.curr_id = id_curr;
661
662 is_defined = (iter.count_direct != 0 && iter.count_indirect != 0);
663 }
664 }
665
666 *r_is_used_local = (iter.count_direct != 0);
667 *r_is_used_linked = (iter.count_indirect != 0);
668}
669
670/* ***** IDs usages.checking/tagging. ***** */
671
683
684 const int id_tag;
685
689
691
692 std::array<int, INDEX_ID_MAX> *num_total;
693 std::array<int, INDEX_ID_MAX> *num_local;
694 std::array<int, INDEX_ID_MAX> *num_linked;
695
697
699 : bmain(bmain),
700 id_tag(id_tag),
701 do_local_ids(parameters.do_local_ids),
702 do_linked_ids(parameters.do_linked_ids),
703 do_recursive(parameters.do_recursive),
704 filter_fn(parameters.filter_fn),
705 num_total(&parameters.num_total),
706 num_local(&parameters.num_local),
707 num_linked(&parameters.num_linked)
708 {
709 }
710
711 void reset(const bool do_local_ids,
712 const bool do_linked_ids,
713 const bool do_recursive,
714 std::array<int, INDEX_ID_MAX> &num_total,
715 std::array<int, INDEX_ID_MAX> &num_local,
716 std::array<int, INDEX_ID_MAX> &num_linked)
717 {
718 unused_ids.clear();
719 this->do_local_ids = do_local_ids;
720 this->do_linked_ids = do_linked_ids;
721 this->do_recursive = do_recursive;
722 this->num_total = &num_total;
723 this->num_local = &num_local;
724 this->num_linked = &num_linked;
725 }
726};
727
729{
730 if (data.filter_fn && !data.filter_fn(id)) {
731 return;
732 }
733 id->tag |= data.id_tag;
734 data.unused_ids.add(id);
735
736 const int id_code = BKE_idtype_idcode_to_index(GS(id->name));
737 (*data.num_total)[INDEX_ID_NULL]++;
738 (*data.num_total)[id_code]++;
739 if (ID_IS_LINKED(id)) {
740 (*data.num_linked)[INDEX_ID_NULL]++;
741 (*data.num_linked)[id_code]++;
742 }
743 else {
744 (*data.num_local)[INDEX_ID_NULL]++;
745 (*data.num_local)[id_code]++;
746 }
747}
748
750{
751 BLI_assert(data.unused_ids.contains(&id));
752
753 id.tag &= ~data.id_tag;
754 data.unused_ids.remove_contained(&id);
755
756 const int id_code = BKE_idtype_idcode_to_index(GS(id.name));
757 (*data.num_total)[INDEX_ID_NULL]--;
758 (*data.num_total)[id_code]--;
759 if (ID_IS_LINKED(&id)) {
760 (*data.num_linked)[INDEX_ID_NULL]--;
761 (*data.num_linked)[id_code]--;
762 }
763 else {
764 (*data.num_local)[INDEX_ID_NULL]--;
765 (*data.num_local)[id_code]--;
766 }
767}
768
774{
775 switch (GS(id.name)) {
776 case ID_OB: {
777 /* FIXME: This is a workaround until Object usages are handled more soundly.
778 *
779 * Historically, only reference-counting Object usages were the Collection ones. All other
780 * references (e.g. as Constraints or Modifiers targets) did not increase their user-count.
781 *
782 * This is not entirely true anymore (e.g. some type-agnostic ID usages like IDPointer custom
783 * properties do refcount Object ones too), but there are still many Object usages that
784 * should refcount them and don't do it.
785 *
786 * This becomes a problem with linked data, as in that case instancing of linked Objects in
787 * the scene is not enforced (to avoid cluttering the scene), which leaves some actually used
788 * linked objects with a `0` user-count.
789 *
790 * So this is a special check to consider linked objects as used also in case some other
791 * used ID uses them.
792 */
793 if (!ID_IS_LINKED(&id)) {
794 return false;
795 }
796 MainIDRelationsEntry *id_relations = static_cast<MainIDRelationsEntry *>(
797 BLI_ghash_lookup(data.bmain->relations->relations_from_pointers, &id));
798 for (MainIDRelationsEntryItem *from = id_relations->from_ids; from; from = from->next) {
799 if (!data.unused_ids.contains(from->id_pointer.from)) {
800 return true;
801 }
802 }
803 break;
804 }
805 case ID_IM: {
806 /* Images which have a 'viewer' source (e.g. render results) should not be considered as
807 * orphaned/unused data. */
808 const Image &image = reinterpret_cast<Image &>(id);
809 if (image.source == IMA_SRC_VIEWER) {
810 return true;
811 }
812 break;
813 }
814 default:
815 return false;
816 }
817 return false;
818}
819
824{
825 /* We should never deal with embedded, not-in-main IDs here. */
827
828 MainIDRelationsEntry *id_relations = static_cast<MainIDRelationsEntry *>(
829 BLI_ghash_lookup(data.bmain->relations->relations_from_pointers, id));
830
831 if ((id_relations->tags & MAINIDRELATIONS_ENTRY_TAGS_PROCESSED) != 0) {
832 return false;
833 }
834 if ((id_relations->tags & MAINIDRELATIONS_ENTRY_TAGS_INPROGRESS) != 0) {
835 /* This ID has not yet been fully processed. If this condition is reached, it means this is a
836 * dependency loop case. */
837 return true;
838 }
839
840 if ((!data.do_linked_ids && ID_IS_LINKED(id)) || (!data.do_local_ids && !ID_IS_LINKED(id))) {
842 return false;
843 }
844
845 if (data.unused_ids.contains(id)) {
847 return false;
848 }
849
850 if ((id->flag & ID_FLAG_FAKEUSER) != 0) {
851 /* This ID is forcefully kept around, and therefore never unused, no need to check it further.
852 */
854 return false;
855 }
856
857 const IDTypeInfo *id_type = BKE_idtype_get_info_from_id(id);
858 if (id_type->flags & IDTYPE_FLAGS_NEVER_UNUSED) {
859 /* Some 'root' ID types are never unused (even though they may not have actual users), unless
860 * their actual user-count is set to 0. */
862 return false;
863 }
864
867 return false;
868 }
869
870 /* An ID user is 'valid' (i.e. may affect the 'used'/'not used' status of the ID it uses) if it
871 * does not match `ignored_usages`, and does match `required_usages`. */
872 const int ignored_usages = (IDWALK_CB_LOOPBACK | IDWALK_CB_EMBEDDED |
874 const int required_usages = (IDWALK_CB_USER | IDWALK_CB_USER_ONE);
875
876 /* This ID may be tagged as unused if none of its users are 'valid', as defined above.
877 *
878 * First recursively check all its valid users, if all of them can be tagged as
879 * unused, then we can tag this ID as such too. */
880 bool has_valid_from_users = false;
881 bool is_part_of_dependency_loop = false;
883 for (MainIDRelationsEntryItem *id_from_item = id_relations->from_ids; id_from_item != nullptr;
884 id_from_item = id_from_item->next)
885 {
886 if ((id_from_item->usage_flag & ignored_usages) != 0 ||
887 (id_from_item->usage_flag & required_usages) == 0)
888 {
889 continue;
890 }
891
892 ID *id_from = id_from_item->id_pointer.from;
893 if ((id_from->flag & ID_FLAG_EMBEDDED_DATA) != 0) {
894 /* Directly 'by-pass' to actual real ID owner. */
895 id_from = BKE_id_owner_get(id_from);
896 BLI_assert(id_from != nullptr);
897 }
898
900 /* Dependency loop case, ignore the `id_from` tag value here (as it should not be considered
901 * as valid yet), and presume that this is a 'valid user' case for now. */
902 is_part_of_dependency_loop = true;
903 continue;
904 }
905 if (!data.unused_ids.contains(id_from)) {
906 has_valid_from_users = true;
907 break;
908 }
909 }
910 if (!has_valid_from_users && !is_part_of_dependency_loop) {
911 /* Tag the ID as unused, only in case it is not part of a dependency loop. */
913 }
914
915 /* This ID is not being processed anymore.
916 *
917 * However, we can only tag is as successfully processed if either it was detected as part of a
918 * valid usage hierarchy, or, if detected as unused, if it was not part of a dependency loop.
919 *
920 * Otherwise, this is an undecided state, it will be resolved at the entry point of this
921 * recursive process for the root id (see below in #BKE_lib_query_unused_ids_tag calling code).
922 */
924 if (has_valid_from_users || !is_part_of_dependency_loop) {
926 }
927
928 /* If that ID is part of a dependency loop, but it does have a valid user (which is not part of
929 * that loop), then that dependency loop does not form (or is not part of) an unused archipelago.
930 *
931 * In other words, this current `id` is used, and is therefore a valid user of the 'calling ID'
932 * from previous recursion level.. */
933 return is_part_of_dependency_loop && !has_valid_from_users;
934}
935
937{
938 BLI_assert(data.bmain->relations != nullptr);
940
941 /* First loop, to only check for immediately unused IDs (those with 0 user count).
942 * NOTE: It also takes care of clearing given tag for used IDs. */
943 ID *id;
944 FOREACH_MAIN_ID_BEGIN (data.bmain, id) {
945 if ((!data.do_linked_ids && ID_IS_LINKED(id)) || (!data.do_local_ids && !ID_IS_LINKED(id))) {
946 id->tag &= ~data.id_tag;
947 }
948 else if (id->us == 0) {
950 }
951 else {
952 id->tag &= ~data.id_tag;
953 }
954 }
956
957 /* Special post-process to handle linked objects with no users, see
958 * #lib_query_unused_ids_has_exception_user for details.
959 *
960 * NOTE: Here needs to be in a separate loop, so that all directly unused users of objects have
961 * been tagged as such already by the previous loop. */
962 constexpr int max_loop_num = 10;
963 int loop_num;
964 for (loop_num = 0; loop_num < max_loop_num; loop_num++) {
965 bool do_loop = false;
966 FOREACH_MAIN_LISTBASE_ID_BEGIN (&data.bmain->objects, id) {
967 if (!data.unused_ids.contains(id)) {
968 continue;
969 }
972 do_loop = true;
973 }
974 }
976 if (!do_loop) {
977 break;
978 }
979 }
980 if (loop_num >= max_loop_num) {
981 CLOG_WARN(&LOG, "Unexpected levels of dependencies between non-instantiated but used Objects");
982 }
983
984 if (!data.do_recursive) {
985 return;
986 }
987
988 FOREACH_MAIN_ID_BEGIN (data.bmain, id) {
990 /* This root processed ID is part of one or more dependency loops.
991 *
992 * If it was not tagged, and its matching relations entry is not marked as processed, it
993 * means that it's the first encountered entry point of an 'unused archipelago' (i.e. the
994 * entry point to a set of IDs with relationships to each other, but no 'valid usage'
995 * relations to the current Blender file (like being part of a scene, etc.).
996 *
997 * So the entry can be tagged as processed, and the ID tagged as unused. */
998 if (!data.unused_ids.contains(id)) {
999 MainIDRelationsEntry *id_relations = static_cast<MainIDRelationsEntry *>(
1000 BLI_ghash_lookup(data.bmain->relations->relations_from_pointers, id));
1001 if ((id_relations->tags & MAINIDRELATIONS_ENTRY_TAGS_PROCESSED) == 0) {
1004 }
1005 }
1006 }
1007
1008#ifndef NDEBUG
1009 /* Relation entry for the root processed ID should always be marked as processed now. */
1010 MainIDRelationsEntry *id_relations = static_cast<MainIDRelationsEntry *>(
1011 BLI_ghash_lookup(data.bmain->relations->relations_from_pointers, id));
1014#endif
1015 }
1017}
1018
1020{
1021 std::array<int, INDEX_ID_MAX> num_dummy{0};
1022 BKE_main_relations_create(bmain, 0);
1023
1024 parameters.num_total.fill(0);
1025 parameters.num_local.fill(0);
1026 parameters.num_linked.fill(0);
1027
1028 /* The complex fiddling with the two calls, which data they each get, based on the `do_local_ids`
1029 * and `do_linked_ids`, is here to reduce as much as possible the extra processing:
1030 *
1031 * If both local and linked options are enabled, a single call with all given parameters gives
1032 * all required data about unused IDs.
1033 *
1034 * If both local and linked options are disabled, total amount is left at zero, and each local
1035 * and linked amounts are computed separately.
1036 *
1037 * If local is disabled and linked is enabled, the first call will compute the amount of local
1038 * IDs that would be unused if the local option was enabled. Therefore, only the local amount can
1039 * be kept from this call. The second call will compute valid values for both linked, and total
1040 * data.
1041 *
1042 * If local is enabled and linked is disabled, the first call will compute valid values for both
1043 * local, and total data. The second call will compute the amount of linked IDs that would be
1044 * unused if the linked option was enabled. Therefore, only the linked amount can be kept from
1045 * this call.
1046 */
1047
1048 UnusedIDsData data(bmain, 0, parameters);
1049 data.do_local_ids = true;
1050 if (!parameters.do_local_ids) {
1051 data.num_total = &num_dummy;
1052 }
1053 if (!(parameters.do_local_ids && parameters.do_linked_ids)) {
1054 data.num_linked = &num_dummy;
1055 }
1057
1058 if (!(parameters.do_local_ids && parameters.do_linked_ids)) {
1059 /* In case a second run is required, clear runtime data and update settings for linked data. */
1060 data.reset(parameters.do_local_ids,
1061 true,
1062 parameters.do_recursive,
1063 (!parameters.do_local_ids && parameters.do_linked_ids) ? parameters.num_total :
1064 num_dummy,
1065 num_dummy,
1066 parameters.num_linked);
1068 }
1069
1071}
1072
1073void BKE_lib_query_unused_ids_tag(Main *bmain, const int tag, LibQueryUnusedIDsData &parameters)
1074{
1075 BLI_assert(tag != 0);
1076
1077 parameters.num_total.fill(0);
1078 parameters.num_local.fill(0);
1079 parameters.num_linked.fill(0);
1080
1081 UnusedIDsData data(bmain, tag, parameters);
1082
1083 BKE_main_relations_create(bmain, 0);
1086}
1087
1089{
1090 ID *self_id = cb_data->self_id;
1091 ID **id_p = cb_data->id_pointer;
1092 const LibraryForeachIDCallbackFlag cb_flag = cb_data->cb_flag;
1093 bool *is_changed = static_cast<bool *>(cb_data->user_data);
1094
1095 if (*id_p) {
1096 /* The infamous 'from' pointers (Key.from, ...).
1097 * those are not actually ID usage, so we ignore them here. */
1098 if (cb_flag & IDWALK_CB_LOOPBACK) {
1099 return IDWALK_RET_NOP;
1100 }
1101
1102 /* If checked id is used by an assumed used ID,
1103 * then it is also used and not part of any linked archipelago. */
1104 if (!(self_id->tag & ID_TAG_DOIT) && ((*id_p)->tag & ID_TAG_DOIT)) {
1105 (*id_p)->tag &= ~ID_TAG_DOIT;
1106 *is_changed = true;
1107 }
1108 }
1109
1110 return IDWALK_RET_NOP;
1111}
1112
1113void BKE_library_unused_linked_data_set_tag(Main *bmain, const bool do_init_tag)
1114{
1115 ID *id;
1116
1117 if (do_init_tag) {
1118 FOREACH_MAIN_ID_BEGIN (bmain, id) {
1119 if (id->lib && (id->tag & ID_TAG_INDIRECT) != 0) {
1120 id->tag |= ID_TAG_DOIT;
1121 }
1122 else {
1123 id->tag &= ~ID_TAG_DOIT;
1124 }
1125 }
1127 }
1128
1129 for (bool do_loop = true; do_loop;) {
1130 do_loop = false;
1131 FOREACH_MAIN_ID_BEGIN (bmain, id) {
1132 /* We only want to check that ID if it is currently known as used... */
1133 if ((id->tag & ID_TAG_DOIT) == 0) {
1136 }
1137 }
1139 }
1140}
1141
1143{
1144 bool do_loop = true;
1145 while (do_loop) {
1146 MainListsArray lb_array = BKE_main_lists_get(*bmain);
1147 int i = lb_array.size();
1148 do_loop = false;
1149
1150 while (i--) {
1151 LISTBASE_FOREACH (ID *, id, lb_array[i]) {
1152 if (!ID_IS_LINKED(id) || id->tag & ID_TAG_DOIT) {
1153 /* Local or non-indirectly-used ID (so far), no need to check it further. */
1154 continue;
1155 }
1158 }
1159 }
1160 }
1161}
void BKE_animdata_foreach_id(AnimData *adt, LibraryForeachIDData *data)
Definition anim_data.cc:263
AnimData * BKE_animdata_from_id(const ID *id)
Definition anim_data.cc:83
void IDP_foreach_property(IDProperty *id_property_root, int type_filter, blender::FunctionRef< void(IDProperty *id_property)> callback)
const IDTypeInfo * BKE_idtype_get_info_from_id(const ID *id)
Definition idtype.cc:146
uint64_t BKE_idtype_idcode_to_idfilter(short idcode)
Definition idtype.cc:363
@ IDTYPE_FLAGS_NEVER_UNUSED
Definition BKE_idtype.hh:72
int BKE_idtype_idcode_to_index(short idcode)
Definition idtype.cc:228
void id_us_plus(ID *id)
Definition lib_id.cc:358
ID * BKE_id_owner_get(ID *id, const bool debug_relationship_assert=true)
Definition lib_id.cc:2511
void id_us_ensure_real(ID *id)
Definition lib_id.cc:313
void id_us_min(ID *id)
Definition lib_id.cc:366
@ IDWALK_RET_STOP_RECURSION
@ IDWALK_RET_STOP_ITER
@ IDWALK_RET_NOP
LibraryForeachIDCallbackFlag
@ IDWALK_CB_LOOPBACK
@ IDWALK_CB_OVERRIDE_LIBRARY_NOT_OVERRIDABLE
@ IDWALK_CB_NEVER_SELF
@ IDWALK_CB_USER_ONE
@ IDWALK_CB_USER
@ IDWALK_CB_INTERNAL
@ IDWALK_CB_EMBEDDED_NOT_OWNING
@ IDWALK_CB_EMBEDDED
@ IDWALK_CB_DIRECT_WEAK_LINK
@ IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE
@ IDWALK_CB_NOP
@ IDWALK_CB_INDIRECT_USAGE
#define BKE_LIB_FOREACHID_PROCESS_ID(data_, id_, cb_flag_)
LibraryForeachIDFlag
@ IDWALK_DO_DEPRECATED_POINTERS
@ IDWALK_RECURSE
@ IDWALK_INCLUDE_UI
@ IDWALK_IGNORE_MISSING_OWNER_ID
@ IDWALK_DO_LIBRARY_POINTER
@ IDWALK_READONLY
@ IDWALK_DO_INTERNAL_RUNTIME_POINTERS
@ IDWALK_NO_ORIG_POINTERS_ACCESS
@ IDWALK_IGNORE_EMBEDDED_ID
#define FOREACH_MAIN_ID_END
Definition BKE_main.hh:583
MainListsArray BKE_main_lists_get(Main &bmain)
Definition main.cc:987
#define FOREACH_MAIN_LISTBASE_ID_END
Definition BKE_main.hh:552
std::array< ListBase *, INDEX_ID_MAX - 1 > MainListsArray
Definition BKE_main.hh:645
@ MAINIDRELATIONS_INCLUDE_UI
Definition BKE_main.hh:141
#define FOREACH_MAIN_LISTBASE_ID_BEGIN(_lb, _id)
Definition BKE_main.hh:546
@ MAINIDRELATIONS_ENTRY_TAGS_PROCESSED
Definition BKE_main.hh:102
@ MAINIDRELATIONS_ENTRY_TAGS_INPROGRESS
Definition BKE_main.hh:121
void BKE_main_relations_tag_set(Main *bmain, eMainIDRelationsEntryTags tag, bool value)
Definition main.cc:600
void BKE_main_relations_create(Main *bmain, short flag)
Definition main.cc:551
#define FOREACH_MAIN_ID_BEGIN(_bmain, _id)
Definition BKE_main.hh:577
void BKE_main_relations_free(Main *bmain)
Definition main.cc:588
#define BLI_assert_unreachable()
Definition BLI_assert.h:93
#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
unsigned int BLI_ghashutil_ptrhash(const void *key)
GSet * BLI_gset_new(GSetHashFP hashfp, GSetCmpFP cmpfp, const char *info) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.cc:944
bool BLI_ghashutil_ptrcmp(const void *a, const void *b)
void * BLI_ghash_lookup(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
Definition BLI_ghash.cc:731
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
bool BLI_gset_add(GSet *gs, void *key)
Definition BLI_ghash.cc:966
#define LISTBASE_FOREACH(type, var, list)
#define ELEM(...)
#define CLOG_WARN(clg_ref,...)
Definition CLG_log.h:189
@ ID_TAG_EXTRAUSER
Definition DNA_ID.h:878
@ ID_TAG_NO_USER_REFCOUNT
Definition DNA_ID.h:1018
@ ID_TAG_INDIRECT
Definition DNA_ID.h:848
@ ID_TAG_DOIT
Definition DNA_ID.h:1036
@ ID_TAG_EXTRAUSER_SET
Definition DNA_ID.h:884
#define FILTER_ID_ALL
Definition DNA_ID.h:1239
#define ID_IS_OVERRIDE_LIBRARY_REAL(_id)
Definition DNA_ID.h:723
#define ID_IS_LINKED(_id)
Definition DNA_ID.h:694
@ INDEX_ID_NULL
Definition DNA_ID.h:1357
@ ID_FLAG_FAKEUSER
Definition DNA_ID.h:769
@ ID_FLAG_EMBEDDED_DATA
Definition DNA_ID.h:774
@ ID_IM
@ ID_SCR
@ ID_OB
@ IDP_ID
@ IDP_FLAG_OVERRIDABLE_LIBRARY
@ IDP_TYPE_FILTER_ID
@ IMA_SRC_VIEWER
BMesh const char void * data
unsigned long long int uint64_t
#define GS(x)
#define printf(...)
void BKE_library_ID_test_usages(Main *bmain, void *idv, bool *r_is_used_local, bool *r_is_used_linked)
Definition lib_query.cc:633
void BKE_lib_query_foreachid_process(LibraryForeachIDData *data, ID **id_pp, LibraryForeachIDCallbackFlag cb_flag)
Definition lib_query.cc:78
void BKE_library_unused_linked_data_set_tag(Main *bmain, const bool do_init_tag)
bool BKE_library_ID_is_indirectly_used(Main *bmain, void *idv)
Definition lib_query.cc:628
void BKE_library_foreach_ID_embedded(LibraryForeachIDData *data, ID **id_pp)
Definition lib_query.cc:172
static bool library_foreach_ID_link(Main *bmain, ID *owner_id, ID *id, blender::FunctionRef< LibraryIDLinkCallback > callback, void *user_data, LibraryForeachIDFlag flag, LibraryForeachIDData *inherit_data)
Definition lib_query.cc:217
static bool library_ID_is_used(Main *bmain, void *idv, const bool check_linked)
Definition lib_query.cc:590
static void lib_query_unused_ids_untag_id(ID &id, UnusedIDsData &data)
Definition lib_query.cc:749
Main * BKE_lib_query_foreachid_process_main_get(const LibraryForeachIDData *data)
Definition lib_query.cc:134
#define CALLBACK_INVOKE(check_id_super, cb_flag)
void BKE_lib_query_unused_ids_amounts(Main *bmain, LibQueryUnusedIDsData &parameters)
static bool lib_query_unused_ids_tag_recurse(ID *id, UnusedIDsData &data)
Definition lib_query.cc:823
int BKE_library_ID_use_ID(ID *id_user, ID *id_used)
Definition lib_query.cc:575
static void lib_query_unused_ids_tag_id(ID *id, UnusedIDsData &data)
Definition lib_query.cc:728
static void library_foreach_ID_data_cleanup(LibraryForeachIDData *data)
Definition lib_query.cc:208
void BKE_lib_query_unused_ids_tag(Main *bmain, const int tag, LibQueryUnusedIDsData &parameters)
bool BKE_library_id_can_use_idtype(ID *owner_id, const short id_type_used)
Definition lib_query.cc:517
int BKE_lib_query_foreachid_process_callback_flag_override(LibraryForeachIDData *data, const LibraryForeachIDCallbackFlag cb_flag, const bool do_replace)
Definition lib_query.cc:139
void BKE_library_foreach_subdata_id(Main *bmain, ID *owner_id, ID *self_id, blender::FunctionRef< void(LibraryForeachIDData *data)> subdata_foreach_id, blender::FunctionRef< LibraryIDLinkCallback > callback, void *user_data, const LibraryForeachIDFlag flag)
Definition lib_query.cc:451
#define CALLBACK_INVOKE_ID(check_id, cb_flag)
static bool lib_query_unused_ids_has_exception_user(ID &id, UnusedIDsData &data)
Definition lib_query.cc:773
@ IDWALK_STOP
Definition lib_query.cc:33
void BKE_lib_query_idpropertiesForeachIDLink_callback(IDProperty *id_prop, void *user_data)
Definition lib_query.cc:160
LibraryForeachIDFlag BKE_lib_query_foreachid_process_flags_get(const LibraryForeachIDData *data)
Definition lib_query.cc:129
bool BKE_lib_query_foreachid_iter_stop(const LibraryForeachIDData *data)
Definition lib_query.cc:73
static int foreach_libblock_id_users_callback(LibraryIDLinkCallbackData *cb_data)
Definition lib_query.cc:536
void BKE_library_update_ID_link_user(ID *id_dst, ID *id_src, const int cb_flag)
Definition lib_query.cc:440
static void lib_query_unused_ids_tag(UnusedIDsData &data)
Definition lib_query.cc:936
void BKE_library_indirectly_used_data_tag_clear(Main *bmain)
uint64_t BKE_library_id_can_use_filter_id(const ID *owner_id, const bool include_ui, const IDTypeInfo *owner_id_type)
Definition lib_query.cc:476
bool BKE_library_ID_is_locally_used(Main *bmain, void *idv)
Definition lib_query.cc:623
static int foreach_libblock_used_linked_data_tag_clear_cb(LibraryIDLinkCallbackData *cb_data)
void BKE_library_foreach_ID_link(Main *bmain, ID *id, blender::FunctionRef< LibraryIDLinkCallback > callback, void *user_data, const LibraryForeachIDFlag flag)
Definition lib_query.cc:431
#define LOG(level)
Definition log.h:97
bNodeTree * node_tree_from_id(ID *id)
Definition node.cc:4568
const char * name
ListBase properties
Definition DNA_ID.h:336
struct ID * hierarchy_root
Definition DNA_ID.h:344
struct ID * reference
Definition DNA_ID.h:334
void * pointer
Definition DNA_ID.h:142
short flag
Definition DNA_ID.h:163
IDPropertyData data
Definition DNA_ID.h:169
char type
Definition DNA_ID.h:156
uint64_t dependencies_id_types
IDTypeForeachIDFunction foreach_id
uint32_t flags
int count_indirect
Definition lib_query.cc:533
Definition DNA_ID.h:414
int tag
Definition DNA_ID.h:442
struct Library * lib
Definition DNA_ID.h:420
char name[258]
Definition DNA_ID.h:432
IDProperty * system_properties
Definition DNA_ID.h:489
int us
Definition DNA_ID.h:443
struct ID * newid
Definition DNA_ID.h:418
IDProperty * properties
Definition DNA_ID.h:480
IDOverrideLibrary * override_library
Definition DNA_ID.h:494
struct ID * orig_id
Definition DNA_ID.h:501
short flag
Definition DNA_ID.h:438
void * next
Definition DNA_ID.h:417
short source
std::array< int, INDEX_ID_MAX > num_total
std::array< int, INDEX_ID_MAX > num_linked
std::array< int, INDEX_ID_MAX > num_local
LibraryForeachIDCallbackFlag cb_flag
Definition lib_query.cc:52
LibraryForeachIDCallbackFlag cb_flag_clear
Definition lib_query.cc:54
blender::FunctionRef< LibraryIDLinkCallback > callback
Definition lib_query.cc:60
BLI_LINKSTACK_DECLARE(ids_todo, ID *)
LibraryForeachIDFlag flag
Definition lib_query.cc:50
LibraryForeachIDCallbackFlag cb_flag
MainIDRelationsEntryItem * next
Definition BKE_main.hh:58
MainIDRelationsEntryItem * from_ids
Definition BKE_main.hh:75
MainIDRelationsEntryItem * to_ids
Definition BKE_main.hh:77
GHash * relations_from_pointers
Definition BKE_main.hh:130
MainIDRelations * relations
Definition BKE_main.hh:329
blender::FunctionRef< bool(ID *id)> filter_fn
Definition lib_query.cc:690
std::array< int, INDEX_ID_MAX > * num_total
Definition lib_query.cc:692
const int id_tag
Definition lib_query.cc:684
blender::Set< ID * > unused_ids
Definition lib_query.cc:696
void reset(const bool do_local_ids, const bool do_linked_ids, const bool do_recursive, std::array< int, INDEX_ID_MAX > &num_total, std::array< int, INDEX_ID_MAX > &num_local, std::array< int, INDEX_ID_MAX > &num_linked)
Definition lib_query.cc:711
UnusedIDsData(Main *bmain, const int id_tag, LibQueryUnusedIDsData &parameters)
Definition lib_query.cc:698
std::array< int, INDEX_ID_MAX > * num_linked
Definition lib_query.cc:694
std::array< int, INDEX_ID_MAX > * num_local
Definition lib_query.cc:693
i
Definition text_draw.cc:230
uint8_t flag
Definition wm_window.cc:145