Anim: find Action Slot users on embedded IDs
Find Action Slot users on embedded IDs, such as the Node Tree used by a Material. Pull Request: #125666
This commit is contained in:
parent
835e626a28
commit
402e87c6d2
@ -10,6 +10,7 @@
|
||||
|
||||
#include "BKE_anim_data.hh"
|
||||
#include "BKE_global.hh"
|
||||
#include "BKE_lib_query.hh"
|
||||
#include "BKE_main.hh"
|
||||
|
||||
#include "BLI_set.hh"
|
||||
@ -42,6 +43,39 @@ void rebuild_slot_user_cache(Main &bmain)
|
||||
* runtime directly, but this is IMO a bit cleaner. */
|
||||
bmain.is_action_slot_to_id_map_dirty = false;
|
||||
|
||||
/* Visit any ID to see which Action+Slot it is using. Returns whether the ID
|
||||
* was visited for the first time. */
|
||||
Set<ID *> visited_ids;
|
||||
auto visit_id = [&visited_ids](ID *id) -> bool {
|
||||
BLI_assert(id);
|
||||
|
||||
if (!visited_ids.add(id)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::optional<std::pair<Action *, Slot *>> action_slot = get_action_slot_pair(*id);
|
||||
if (action_slot) {
|
||||
Slot &slot = *action_slot->second;
|
||||
slot.users_add(*id);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
auto visit_linked_id = [&](LibraryIDLinkCallbackData *cb_data) -> int {
|
||||
ID *id = *cb_data->id_pointer;
|
||||
if (!id) {
|
||||
/* Can happen when the 'foreach' code visits a nullptr. */
|
||||
return IDWALK_RET_NOP;
|
||||
}
|
||||
|
||||
if (!visit_id(id)) {
|
||||
/* When we hit an ID that was already visited, the recursion can stop. */
|
||||
return IDWALK_RET_STOP_RECURSION;
|
||||
}
|
||||
|
||||
return IDWALK_RET_NOP;
|
||||
};
|
||||
|
||||
/* Loop over all IDs to cache their slot usage. */
|
||||
ListBase *ids_of_idtype;
|
||||
ID *id;
|
||||
@ -55,13 +89,22 @@ void rebuild_slot_user_cache(Main &bmain)
|
||||
FOREACH_MAIN_LISTBASE_ID_BEGIN (ids_of_idtype, id) {
|
||||
BLI_assert(id_can_have_animdata(id));
|
||||
|
||||
std::optional<std::pair<Action *, Slot *>> action_slot = get_action_slot_pair(*id);
|
||||
if (!action_slot) {
|
||||
/* Process the ID itself.*/
|
||||
if (!visit_id(id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Slot &slot = *action_slot->second;
|
||||
slot.users_add(*id);
|
||||
/* Process embedded IDs, as these are not listed in bmain, but still can
|
||||
* have their own Action+Slot. */
|
||||
BKE_library_foreach_ID_link(
|
||||
&bmain,
|
||||
id,
|
||||
visit_linked_id,
|
||||
nullptr,
|
||||
IDWALK_READONLY | IDWALK_RECURSE |
|
||||
/* This is more about "we don't care" than "must be ignored". We don't pass an owner
|
||||
* ID, and it's not used in the callback either, so don't bother looking it up. */
|
||||
IDWALK_IGNORE_MISSING_OWNER_ID);
|
||||
}
|
||||
FOREACH_MAIN_LISTBASE_ID_END;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user