Blender V4.3
action_runtime.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
11#include "BKE_anim_data.hh"
12#include "BKE_global.hh"
13#include "BKE_lib_query.hh"
14#include "BKE_main.hh"
15#include "BKE_nla.hh"
16
17#include "BLI_set.hh"
18
19#include "DNA_anim_types.h"
20
21#include "ANIM_action.hh"
23
24#include "action_runtime.hh"
25
27
29{
30 /* Loop over all Actions and clear their slots' user cache. */
31 LISTBASE_FOREACH (bAction *, dna_action, &bmain.actions) {
32 Action &action = dna_action->wrap();
33 for (Slot *slot : action.slots()) {
34 BLI_assert_msg(slot->runtime, "Slot::runtime should always be allocated");
35 slot->runtime->users.clear();
36 }
37 }
38
39 /* Mark all Slots as clear. This is a bit of a lie, because the code below still has to run.
40 * However, this is a necessity to make the `slot.users_add(*id)` call work without triggering
41 * an infinite recursion.
42 *
43 * The alternative would be to go around the `slot.users_add()` function and access the
44 * runtime directly, but this is IMO a bit cleaner. */
46
47 /* Visit any ID to see which Action+Slot it is using. Returns whether the ID
48 * was visited for the first time. */
49 Set<ID *> visited_ids;
50 auto visit_id = [&visited_ids](ID *id) -> bool {
51 BLI_assert(id);
52
53 if (!visited_ids.add(id)) {
54 return false;
55 }
56
57 foreach_action_slot_use(*id, [&](const Action &action, slot_handle_t slot_handle) {
58 const Slot *slot = action.slot_for_handle(slot_handle);
59 if (!slot) {
60 return true;
61 }
62 /* Constant cast because the `foreach` produces const Actions, and I (Sybren)
63 * didn't want to make a non-const duplicate. */
64 const_cast<Slot *>(slot)->users_add(*id);
65 return true;
66 });
67
68 return true;
69 };
70
71 auto visit_linked_id = [&](LibraryIDLinkCallbackData *cb_data) -> int {
72 ID *id = *cb_data->id_pointer;
73 if (!id) {
74 /* Can happen when the 'foreach' code visits a nullptr. */
75 return IDWALK_RET_NOP;
76 }
77
78 if (!visit_id(id)) {
79 /* When we hit an ID that was already visited, the recursion can stop. */
81 }
82
83 return IDWALK_RET_NOP;
84 };
85
86 /* Loop over all IDs to cache their slot usage. */
87 ListBase *ids_of_idtype;
88 ID *id;
89 FOREACH_MAIN_LISTBASE_BEGIN (&bmain, ids_of_idtype) {
90 /* Check whether this ID type can be animated. If not, just skip all IDs of this type. */
91 id = static_cast<ID *>(ids_of_idtype->first);
92 if (!id || !id_type_can_have_animdata(GS(id->name))) {
93 continue;
94 }
95
96 FOREACH_MAIN_LISTBASE_ID_BEGIN (ids_of_idtype, id) {
98
99 /* Process the ID itself.*/
100 if (!visit_id(id)) {
101 continue;
102 }
103
104 /* Process embedded IDs, as these are not listed in bmain, but still can
105 * have their own Action+Slot. */
107 &bmain,
108 id,
109 visit_linked_id,
110 nullptr,
112 /* This is more about "we don't care" than "must be ignored". We don't pass an owner
113 * ID, and it's not used in the callback either, so don't bother looking it up. */
115 }
117 }
119}
120
121} // namespace blender::animrig::internal
Functions and classes to work with Actions.
Functionality to iterate an Action in various ways.
bool id_can_have_animdata(const ID *id)
Definition anim_data.cc:79
bool id_type_can_have_animdata(short id_type)
Definition anim_data.cc:70
@ IDWALK_RET_STOP_RECURSION
@ IDWALK_RET_NOP
void BKE_library_foreach_ID_link(Main *bmain, ID *id, blender::FunctionRef< LibraryIDLinkCallback > callback, void *user_data, int flag)
Definition lib_query.cc:416
@ IDWALK_RECURSE
@ IDWALK_IGNORE_MISSING_OWNER_ID
@ IDWALK_READONLY
#define FOREACH_MAIN_LISTBASE_ID_END
Definition BKE_main.hh:469
#define FOREACH_MAIN_LISTBASE_ID_BEGIN(_lb, _id)
Definition BKE_main.hh:463
#define FOREACH_MAIN_LISTBASE_END
Definition BKE_main.hh:481
#define FOREACH_MAIN_LISTBASE_BEGIN(_bmain, _lb)
Definition BKE_main.hh:474
#define BLI_assert(a)
Definition BLI_assert.h:50
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:57
#define LISTBASE_FOREACH(type, var, list)
Internal C++ functions to deal with Actions, Slots, and their runtime data.
bool add(const Key &key)
Definition BLI_set.hh:248
blender::Span< const Slot * > slots() const
Slot * slot_for_handle(slot_handle_t handle)
#define GS(x)
Definition iris.cc:202
void rebuild_slot_user_cache(Main &bmain)
decltype(::ActionSlot::handle) slot_handle_t
bool foreach_action_slot_use(const ID &animated_id, FunctionRef< bool(const Action &action, slot_handle_t slot_handle)> callback)
Definition DNA_ID.h:413
void * first
ListBase actions
Definition BKE_main.hh:233
bool is_action_slot_to_id_map_dirty
Definition BKE_main.hh:205