Blender V4.3
animrig/intern/nla_test.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
5#include "ANIM_action.hh"
6#include "ANIM_nla.hh"
7
8#include "BKE_action.hh"
9#include "BKE_anim_data.hh"
10#include "BKE_fcurve.hh"
11#include "BKE_idtype.hh"
12#include "BKE_lib_id.hh"
13#include "BKE_main.hh"
14#include "BKE_nla.hh"
15#include "BKE_object.hh"
16
17#include "DNA_anim_types.h"
18#include "DNA_object_types.h"
19
20#include "BLI_listbase.h"
21#include "BLI_string_utf8.h"
22
23#include <limits>
24
25#include "CLG_log.h"
26#include "testing/testing.h"
27
29
30class NLASlottedActionTest : public testing::Test {
31 public:
35
36 static void SetUpTestSuite()
37 {
38 /* BKE_id_free() hits a code path that uses CLOG, which crashes if not initialized properly. */
39 CLG_init();
40
41 /* To make id_can_have_animdata() and friends work, the `id_types` array needs to be set up. */
43 }
44
45 static void TearDownTestSuite()
46 {
47 CLG_exit();
48 }
49
50 void SetUp() override
51 {
53 action = static_cast<Action *>(BKE_id_new(bmain, ID_AC, "ACÄnimåtië"));
54 action->id.us = 0; /* Nothing references this yet. */
56 cube->id.us = 0; /* Nothing references this yet. */
57 }
58
59 void TearDown() override
60 {
62 }
63};
64
65TEST_F(NLASlottedActionTest, assign_slot_to_nla_strip)
66{
67 ASSERT_EQ(action->id.us, 0);
68
69 AnimData *adt = BKE_animdata_ensure_id(&cube->id);
70 NlaTrack *track = BKE_nlatrack_new_tail(&adt->nla_tracks, false);
71
72 /* Create a strip. This automatically assigns the Action, but for now with the old flow. */
73 NlaStrip *strip = BKE_nlastrip_new(action, cube->id);
74 BKE_nlatrack_add_strip(track, strip, false);
75
77 EXPECT_STREQ(strip->action_slot_name, "");
78
79 /* Unassign the Action that was automatically assigned via BKE_nlastrip_new(). */
80 nla::unassign_action(*strip, cube->id);
81 EXPECT_EQ(strip->act, nullptr);
82 EXPECT_EQ(action->id.us, 0);
83
84 /* Assign an Action with an unrelated slot. This should not be picked. */
85 action->slot_add();
86
87 /* Assign the Action. */
88 EXPECT_FALSE(nla::assign_action(*strip, *action, cube->id));
90 EXPECT_STREQ(strip->action_slot_name, "");
91 EXPECT_EQ(action->id.us, 1);
92 EXPECT_EQ(strip->act, action);
93
94 /* Unassign the Action. */
95 nla::unassign_action(*strip, cube->id);
96 EXPECT_EQ(strip->act, nullptr);
97 EXPECT_EQ(action->id.us, 0);
98
99 /* Create a slot for this ID. Assigning the Action should auto-pick it. */
100 Slot &slot = action->slot_add_for_id(cube->id);
101 EXPECT_TRUE(nla::assign_action(*strip, *action, cube->id));
102 EXPECT_EQ(strip->action_slot_handle, slot.handle);
103 EXPECT_STREQ(strip->action_slot_name, slot.name);
104 EXPECT_EQ(action->id.us, 1);
105 EXPECT_EQ(strip->act, action);
106 EXPECT_TRUE(slot.runtime_users().contains(&cube->id));
107
108 /* Unassign the slot, but keep the Action assigned. */
111 EXPECT_STREQ(strip->action_slot_name, slot.name);
112 EXPECT_EQ(action->id.us, 1);
113 EXPECT_EQ(strip->act, action);
114 EXPECT_FALSE(slot.runtime_users().contains(&cube->id));
115
116 /* Unassign the Action, then reassign it. It should pick the same slot again. */
117 nla::unassign_action(*strip, cube->id);
118 EXPECT_TRUE(nla::assign_action(*strip, *action, cube->id));
119 EXPECT_EQ(strip->action_slot_handle, slot.handle);
120 EXPECT_TRUE(slot.runtime_users().contains(&cube->id));
121}
122
123TEST_F(NLASlottedActionTest, assign_slot_to_multiple_strips)
124{
125 AnimData *adt = BKE_animdata_ensure_id(&cube->id);
126 NlaTrack *track = BKE_nlatrack_new_tail(&adt->nla_tracks, false);
127
128 /* Create two strips. This automatically assigns the Action, but for now with
129 * the old flow (so no slots). */
130 NlaStrip *strip1 = BKE_nlastrip_new(action, cube->id);
131 strip1->start = 1;
132 strip1->end = 4;
133 NlaStrip *strip2 = BKE_nlastrip_new(action, cube->id);
134 strip1->start = 47;
135 strip1->end = 327;
136 ASSERT_TRUE(BKE_nlatrack_add_strip(track, strip1, false));
137 ASSERT_TRUE(BKE_nlatrack_add_strip(track, strip2, false));
138 ASSERT_EQ(1, BLI_listbase_count(&adt->nla_tracks));
139 ASSERT_EQ(2, BLI_listbase_count(&track->strips));
140
141 nla::unassign_action(*strip1, cube->id);
142 nla::unassign_action(*strip2, cube->id);
143
144 /* Create an unrelated slot, it should not be auto-picked. */
145 Slot &slot = action->slot_add();
146 EXPECT_FALSE(nla::assign_action(*strip1, *action, cube->id));
148
149 /* Assign the slot 'manually'. */
151 EXPECT_EQ(strip1->action_slot_handle, slot.handle);
152
153 /* Assign the Action + slot to the second strip.*/
154 EXPECT_FALSE(nla::assign_action(*strip2, *action, cube->id));
156
157 /* The cube should be registered as user of the slot. */
158 EXPECT_TRUE(slot.runtime_users().contains(&cube->id));
159
160 nla::unassign_action(*strip1, cube->id);
161
162 /* The cube should still be registered as user of the slot, as there is a 2nd
163 * strip that references it. */
164 EXPECT_TRUE(slot.runtime_users().contains(&cube->id));
165
166 /* Remove the last use of this slot. */
167 nla::unassign_action(*strip2, cube->id);
168 EXPECT_FALSE(slot.runtime_users().contains(&cube->id));
169}
170
171} // namespace blender::animrig::nla::tests
Functions and classes to work with Actions.
Blender kernel action and pose functionality.
AnimData * BKE_animdata_ensure_id(ID *id)
Definition anim_data.cc:103
void BKE_idtype_init()
Definition idtype.cc:127
void * BKE_id_new(Main *bmain, short type, const char *name)
Definition lib_id.cc:1482
Main * BKE_main_new(void)
Definition main.cc:45
void BKE_main_free(Main *bmain)
Definition main.cc:175
bool BKE_nlatrack_add_strip(NlaTrack *nlt, NlaStrip *strip, bool is_liboverride)
NlaStrip * BKE_nlastrip_new(bAction *act, ID &animated_id)
NlaTrack * BKE_nlatrack_new_tail(ListBase *nla_tracks, const bool is_liboverride)
General operations, lookup, etc. for blender objects.
Object * BKE_object_add_only_object(Main *bmain, int type, const char *name) ATTR_RETURNS_NONNULL
EXPECT_EQ(BLI_expr_pylike_eval(expr, nullptr, 0, &result), EXPR_PYLIKE_INVALID)
int BLI_listbase_count(const struct ListBase *listbase) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
void CLG_exit(void)
Definition clog.c:706
void CLG_init(void)
Definition clog.c:699
@ ID_AC
Object is a sort of wrapper for general info.
@ OB_EMPTY
bool contains(const T &value) const
static constexpr slot_handle_t unassigned
TEST_F(NLASlottedActionTest, assign_slot_to_nla_strip)
void unassign_action(NlaStrip &strip, ID &animated_id)
bool assign_action(NlaStrip &strip, Action &action, ID &animated_id)
ActionSlotAssignmentResult assign_action_slot(NlaStrip &strip, Slot *slot_to_assign, ID &animated_id)
ListBase nla_tracks
int us
Definition DNA_ID.h:435
char action_slot_name[66]
int32_t action_slot_handle
bAction * act
ListBase strips