Blender V5.0
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
10
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#include "BKE_node.hh"
17
18#include "BLI_listbase.h"
19#include "BLI_set.hh"
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 /* Loop over all IDs to cache their slot usage. */
72 ListBase *ids_of_idtype;
73 ID *id;
74 FOREACH_MAIN_LISTBASE_BEGIN (&bmain, ids_of_idtype) {
75 /* Check whether this ID type can be animated. If not, just skip all IDs of this type. */
76 id = static_cast<ID *>(ids_of_idtype->first);
77 if (!id || !id_type_can_have_animdata(GS(id->name))) {
78 continue;
79 }
80
81 FOREACH_MAIN_LISTBASE_ID_BEGIN (ids_of_idtype, id) {
83
84 /* Process the ID itself. */
85 if (!visit_id(id)) {
86 continue;
87 }
88
89 /* Process embedded IDs, as these are not listed in bmain, but still can
90 * have their own Action+Slot. Unfortunately there is no generic looper
91 * for embedded IDs. At this moment the only animatable embedded ID is a
92 * node tree. */
93 bNodeTree *node_tree = bke::node_tree_from_id(id);
94 if (node_tree) {
95 visit_id(&node_tree->id);
96 }
97 }
99 }
101}
102
103} // 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:73
bool id_type_can_have_animdata(short id_type)
Definition anim_data.cc:64
#define FOREACH_MAIN_LISTBASE_ID_END
Definition BKE_main.hh:552
#define FOREACH_MAIN_LISTBASE_ID_BEGIN(_lb, _id)
Definition BKE_main.hh:546
#define FOREACH_MAIN_LISTBASE_END
Definition BKE_main.hh:564
#define FOREACH_MAIN_LISTBASE_BEGIN(_bmain, _lb)
Definition BKE_main.hh:557
#define BLI_assert(a)
Definition BLI_assert.h:46
#define BLI_assert_msg(a, msg)
Definition BLI_assert.h:53
#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)
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)
bNodeTree * node_tree_from_id(ID *id)
Definition node.cc:4568
Definition DNA_ID.h:414
char name[258]
Definition DNA_ID.h:432
void * first
ListBase actions
Definition BKE_main.hh:300
bool is_action_slot_to_id_map_dirty
Definition BKE_main.hh:253