105 callback_data.
cb_flag = cb_flag;
106 const int callback_return =
data->callback(&callback_data);
113 "Iteration over ID usages should not be interrupted by the callback in "
114 "non-readonly cases");
144 data->cb_flag = cb_flag;
147 data->cb_flag |= cb_flag;
149 return cb_flag_backup;
210 if (
data->ids_handled !=
nullptr) {
252 data.ids_handled =
nullptr;
256 data.callback = callback;
257 data.user_data = user_data;
259#define CALLBACK_INVOKE_ID(check_id, cb_flag) \
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); \
270#define CALLBACK_INVOKE(check_id_super, cb_flag) \
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); \
288 data.owner_id = owner_id ? owner_id : id;
303 data.owner_id = owner_id;
315 if (inherit_data ==
nullptr) {
327 bool use_bmain_relations = bmain !=
nullptr && bmain->
relations !=
nullptr &&
334 use_bmain_relations =
false;
337 if (use_bmain_relations &&
341 use_bmain_relations =
false;
343 if (use_bmain_relations) {
352 to_id_entry = to_id_entry->
next)
355 &
data, to_id_entry->id_pointer.to, to_id_entry->usage_flag);
389 BKE_lib_query_idpropertiesForeachIDLink_callback(prop, &data);
397 BKE_lib_query_idpropertiesForeachIDLink_callback(prop, &data);
427#undef CALLBACK_INVOKE_ID
428#undef CALLBACK_INVOKE
465 data.owner_id = owner_id;
466 data.self_id = self_id;
467 data.ids_handled =
nullptr;
470 data.callback = callback;
471 data.user_data = user_data;
473 subdata_foreach_id(&
data);
477 const bool include_ui,
507 if (!owner_id_type) {
522 return (can_be_used & filter_id_type_used) != 0;
550 if (*id_p == iter->
id) {
553 "%s uses %s (refcounted: %d, userone: %d, used_one: %d, used_one_active: %d, "
554 "indirect_usage: %d)\n",
557 (cb_flag & IDWALK_USER) ? 1 : 0,
558 (cb_flag & IDWALK_USER_ONE) ? 1 : 0,
561 (cb_flag & IDWALK_INDIRECT_USAGE) ? 1 : 0);
594 int i = lb_array.size();
595 ID *
id =
static_cast<ID *
>(idv);
596 bool is_defined =
false;
600 while (
i-- && !is_defined) {
601 ID *id_curr =
static_cast<ID *
>(lb_array[
i]->first);
607 for (; id_curr && !is_defined; id_curr =
static_cast<ID *
>(id_curr->
next)) {
635 bool *r_is_used_local,
636 bool *r_is_used_linked)
640 int i = lb_array.size();
641 ID *
id =
static_cast<ID *
>(idv);
642 bool is_defined =
false;
646 while (
i-- && !is_defined) {
647 ID *id_curr =
static_cast<ID *
>(lb_array[
i]->first);
653 for (; id_curr && !is_defined; id_curr =
static_cast<ID *
>(id_curr->
next)) {
714 std::array<int, INDEX_ID_MAX> &
num_total,
715 std::array<int, INDEX_ID_MAX> &
num_local,
730 if (
data.filter_fn && !
data.filter_fn(
id)) {
733 id->tag |=
data.id_tag;
734 data.unused_ids.add(
id);
738 (*
data.num_total)[id_code]++;
741 (*
data.num_linked)[id_code]++;
745 (*
data.num_local)[id_code]++;
753 id.tag &=
~data.id_tag;
754 data.unused_ids.remove_contained(&
id);
758 (*
data.num_total)[id_code]--;
761 (*
data.num_linked)[id_code]--;
765 (*
data.num_local)[id_code]--;
799 if (!
data.unused_ids.contains(from->id_pointer.from)) {
808 const Image &image =
reinterpret_cast<Image &
>(id);
845 if (
data.unused_ids.contains(
id)) {
880 bool has_valid_from_users =
false;
881 bool is_part_of_dependency_loop =
false;
884 id_from_item = id_from_item->
next)
886 if ((id_from_item->usage_flag & ignored_usages) != 0 ||
887 (id_from_item->usage_flag & required_usages) == 0)
892 ID *id_from = id_from_item->id_pointer.from;
902 is_part_of_dependency_loop =
true;
905 if (!
data.unused_ids.contains(id_from)) {
906 has_valid_from_users =
true;
910 if (!has_valid_from_users && !is_part_of_dependency_loop) {
924 if (has_valid_from_users || !is_part_of_dependency_loop) {
933 return is_part_of_dependency_loop && !has_valid_from_users;
946 id->tag &=
~data.id_tag;
948 else if (id->
us == 0) {
952 id->tag &=
~data.id_tag;
962 constexpr int max_loop_num = 10;
964 for (loop_num = 0; loop_num < max_loop_num; loop_num++) {
965 bool do_loop =
false;
967 if (!
data.unused_ids.contains(
id)) {
980 if (loop_num >= max_loop_num) {
981 CLOG_WARN(&
LOG,
"Unexpected levels of dependencies between non-instantiated but used Objects");
984 if (!
data.do_recursive) {
998 if (!
data.unused_ids.contains(
id)) {
1021 std::array<int, INDEX_ID_MAX> num_dummy{0};
1049 data.do_local_ids =
true;
1051 data.num_total = &num_dummy;
1054 data.num_linked = &num_dummy;
1093 bool *is_changed =
static_cast<bool *
>(cb_data->
user_data);
1129 for (
bool do_loop =
true; do_loop;) {
1144 bool do_loop =
true;
1147 int i = lb_array.size();
void BKE_animdata_foreach_id(AnimData *adt, LibraryForeachIDData *data)
AnimData * BKE_animdata_from_id(const ID *id)
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)
uint64_t BKE_idtype_idcode_to_idfilter(short idcode)
@ IDTYPE_FLAGS_NEVER_UNUSED
int BKE_idtype_idcode_to_index(short idcode)
ID * BKE_id_owner_get(ID *id, const bool debug_relationship_assert=true)
void id_us_ensure_real(ID *id)
@ IDWALK_RET_STOP_RECURSION
LibraryForeachIDCallbackFlag
@ IDWALK_CB_OVERRIDE_LIBRARY_NOT_OVERRIDABLE
@ IDWALK_CB_EMBEDDED_NOT_OWNING
@ IDWALK_CB_DIRECT_WEAK_LINK
@ IDWALK_CB_OVERRIDE_LIBRARY_REFERENCE
@ IDWALK_CB_INDIRECT_USAGE
#define BKE_LIB_FOREACHID_PROCESS_ID(data_, id_, cb_flag_)
@ IDWALK_DO_DEPRECATED_POINTERS
@ IDWALK_IGNORE_MISSING_OWNER_ID
@ IDWALK_DO_LIBRARY_POINTER
@ IDWALK_DO_INTERNAL_RUNTIME_POINTERS
@ IDWALK_NO_ORIG_POINTERS_ACCESS
@ IDWALK_IGNORE_EMBEDDED_ID
#define FOREACH_MAIN_ID_END
MainListsArray BKE_main_lists_get(Main &bmain)
#define FOREACH_MAIN_LISTBASE_ID_END
std::array< ListBase *, INDEX_ID_MAX - 1 > MainListsArray
@ MAINIDRELATIONS_INCLUDE_UI
#define FOREACH_MAIN_LISTBASE_ID_BEGIN(_lb, _id)
@ MAINIDRELATIONS_ENTRY_TAGS_PROCESSED
@ MAINIDRELATIONS_ENTRY_TAGS_INPROGRESS
void BKE_main_relations_tag_set(Main *bmain, eMainIDRelationsEntryTags tag, bool value)
void BKE_main_relations_create(Main *bmain, short flag)
#define FOREACH_MAIN_ID_BEGIN(_bmain, _id)
void BKE_main_relations_free(Main *bmain)
#define BLI_assert_unreachable()
#define BLI_assert_msg(a, msg)
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
bool BLI_ghashutil_ptrcmp(const void *a, const void *b)
void * BLI_ghash_lookup(const GHash *gh, const void *key) ATTR_WARN_UNUSED_RESULT
void BLI_gset_free(GSet *gs, GSetKeyFreeFP keyfreefp)
bool BLI_gset_add(GSet *gs, void *key)
BLI_LINKSTACK_*** wrapper macros for using a LinkNode to store a stack of pointers,...
#define BLI_LINKSTACK_PUSH(var, ptr)
#define BLI_LINKSTACK_FREE(var)
#define BLI_LINKSTACK_INIT(var)
#define BLI_LINKSTACK_POP(var)
#define LISTBASE_FOREACH(type, var, list)
#define CLOG_WARN(clg_ref,...)
@ ID_TAG_NO_USER_REFCOUNT
#define ID_IS_OVERRIDE_LIBRARY_REAL(_id)
#define ID_IS_LINKED(_id)
@ IDP_FLAG_OVERRIDABLE_LIBRARY
BMesh const char void * data
unsigned long long int uint64_t
void BKE_library_ID_test_usages(Main *bmain, void *idv, bool *r_is_used_local, bool *r_is_used_linked)
void BKE_lib_query_foreachid_process(LibraryForeachIDData *data, ID **id_pp, LibraryForeachIDCallbackFlag cb_flag)
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)
void BKE_library_foreach_ID_embedded(LibraryForeachIDData *data, ID **id_pp)
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)
static bool library_ID_is_used(Main *bmain, void *idv, const bool check_linked)
static void lib_query_unused_ids_untag_id(ID &id, UnusedIDsData &data)
Main * BKE_lib_query_foreachid_process_main_get(const LibraryForeachIDData *data)
#define CALLBACK_INVOKE(check_id_super, cb_flag)
void BKE_lib_query_unused_ids_amounts(Main *bmain, LibQueryUnusedIDsData ¶meters)
static bool lib_query_unused_ids_tag_recurse(ID *id, UnusedIDsData &data)
int BKE_library_ID_use_ID(ID *id_user, ID *id_used)
static void lib_query_unused_ids_tag_id(ID *id, UnusedIDsData &data)
static void library_foreach_ID_data_cleanup(LibraryForeachIDData *data)
void BKE_lib_query_unused_ids_tag(Main *bmain, const int tag, LibQueryUnusedIDsData ¶meters)
bool BKE_library_id_can_use_idtype(ID *owner_id, const short id_type_used)
int BKE_lib_query_foreachid_process_callback_flag_override(LibraryForeachIDData *data, const LibraryForeachIDCallbackFlag cb_flag, const bool do_replace)
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)
#define CALLBACK_INVOKE_ID(check_id, cb_flag)
static bool lib_query_unused_ids_has_exception_user(ID &id, UnusedIDsData &data)
void BKE_lib_query_idpropertiesForeachIDLink_callback(IDProperty *id_prop, void *user_data)
LibraryForeachIDFlag BKE_lib_query_foreachid_process_flags_get(const LibraryForeachIDData *data)
bool BKE_lib_query_foreachid_iter_stop(const LibraryForeachIDData *data)
static int foreach_libblock_id_users_callback(LibraryIDLinkCallbackData *cb_data)
void BKE_library_update_ID_link_user(ID *id_dst, ID *id_src, const int cb_flag)
static void lib_query_unused_ids_tag(UnusedIDsData &data)
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)
bool BKE_library_ID_is_locally_used(Main *bmain, void *idv)
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)
bNodeTree * node_tree_from_id(ID *id)
struct ID * hierarchy_root
uint64_t dependencies_id_types
IDTypeForeachIDFunction foreach_id
IDProperty * system_properties
IDOverrideLibrary * override_library
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
LibraryForeachIDCallbackFlag cb_flag_clear
blender::FunctionRef< LibraryIDLinkCallback > callback
BLI_LINKSTACK_DECLARE(ids_todo, ID *)
LibraryForeachIDFlag flag
LibraryForeachIDCallbackFlag cb_flag
MainIDRelationsEntryItem * next
MainIDRelationsEntryItem * from_ids
MainIDRelationsEntryItem * to_ids
GHash * relations_from_pointers
MainIDRelations * relations
blender::FunctionRef< bool(ID *id)> filter_fn
std::array< int, INDEX_ID_MAX > * num_total
blender::Set< ID * > unused_ids
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)
UnusedIDsData(Main *bmain, const int id_tag, LibQueryUnusedIDsData ¶meters)
std::array< int, INDEX_ID_MAX > * num_linked
std::array< int, INDEX_ID_MAX > * num_local