Blender  V3.3
action_test.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later
2  * Copyright 2021 Blender Foundation. All rights reserved. */
3 
4 #include "BKE_action.h"
5 
6 #include "DNA_action_types.h"
7 #include "DNA_anim_types.h"
8 
9 #include "BLI_listbase.h"
10 
11 #include "MEM_guardedalloc.h"
12 
13 #include "testing/testing.h"
14 
16 
17 TEST(action_groups, ReconstructGroupsWithReordering)
18 {
19  /* Construct an Action with three groups. */
20  bAction action = {{nullptr}};
21  FCurve groupAcurve1 = {nullptr};
22  FCurve groupAcurve2 = {nullptr};
23  FCurve groupBcurve1 = {nullptr};
24  FCurve groupBcurve2 = {nullptr};
25  FCurve groupBcurve3 = {nullptr};
26  /* Group C has no curves intentionally. */
27  FCurve groupDcurve1 = {nullptr};
28  FCurve groupDcurve2 = {nullptr};
29 
30  groupAcurve1.rna_path = (char *)"groupAcurve1";
31  groupAcurve2.rna_path = (char *)"groupAcurve2";
32  groupBcurve1.rna_path = (char *)"groupBcurve1";
33  groupBcurve2.rna_path = (char *)"groupBcurve2";
34  groupDcurve1.rna_path = (char *)"groupDcurve1";
35  groupBcurve3.rna_path = (char *)"groupBcurve3";
36  groupDcurve2.rna_path = (char *)"groupDcurve2";
37 
38  BLI_addtail(&action.curves, &groupAcurve1);
39  BLI_addtail(&action.curves, &groupAcurve2);
40  BLI_addtail(&action.curves, &groupBcurve1);
41  BLI_addtail(&action.curves, &groupBcurve2);
42  BLI_addtail(&action.curves, &groupDcurve1);
43  BLI_addtail(&action.curves, &groupBcurve3); /* <-- The error that should be corrected. */
44  BLI_addtail(&action.curves, &groupDcurve2);
45 
46  /* Introduce another error type, by changing some `prev` pointers. */
47  groupBcurve1.prev = nullptr;
48  groupBcurve3.prev = &groupBcurve2;
49  groupDcurve1.prev = &groupBcurve3;
50 
51  bActionGroup groupA = {nullptr};
52  bActionGroup groupB = {nullptr};
53  bActionGroup groupC = {nullptr};
54  bActionGroup groupD = {nullptr};
55  strcpy(groupA.name, "groupA");
56  strcpy(groupB.name, "groupB");
57  strcpy(groupC.name, "groupC");
58  strcpy(groupD.name, "groupD");
59 
60  BLI_addtail(&action.groups, &groupA);
61  BLI_addtail(&action.groups, &groupB);
62  BLI_addtail(&action.groups, &groupC);
63  BLI_addtail(&action.groups, &groupD);
64 
65  groupAcurve1.grp = &groupA;
66  groupAcurve2.grp = &groupA;
67  groupBcurve1.grp = &groupB;
68  groupBcurve2.grp = &groupB;
69  groupBcurve3.grp = &groupB;
70  groupDcurve1.grp = &groupD;
71  groupDcurve2.grp = &groupD;
72 
73  groupA.channels.first = &groupAcurve1;
74  groupA.channels.last = &groupAcurve2;
75  groupB.channels.first = &groupBcurve1;
76  groupB.channels.last = &groupBcurve3; /* The last channel in group B, after group C curve 1. */
77  groupD.channels.first = &groupDcurve1;
78  groupD.channels.last = &groupDcurve2;
79 
80  EXPECT_EQ(groupA.channels.first, &groupAcurve1);
81  EXPECT_EQ(groupA.channels.last, &groupAcurve2);
82  EXPECT_EQ(groupB.channels.first, &groupBcurve1);
83  EXPECT_EQ(groupB.channels.last, &groupBcurve3);
84  EXPECT_EQ(groupC.channels.first, nullptr);
85  EXPECT_EQ(groupC.channels.last, nullptr);
86  EXPECT_EQ(groupD.channels.first, &groupDcurve1);
87  EXPECT_EQ(groupD.channels.last, &groupDcurve2);
88 
90 
91  EXPECT_EQ(action.curves.first, &groupAcurve1);
92  EXPECT_EQ(action.curves.last, &groupDcurve2);
93 
94  EXPECT_EQ(groupA.prev, nullptr);
95  EXPECT_EQ(groupB.prev, &groupA);
96  EXPECT_EQ(groupC.prev, &groupB);
97  EXPECT_EQ(groupD.prev, &groupC);
98 
99  EXPECT_EQ(groupA.next, &groupB);
100  EXPECT_EQ(groupB.next, &groupC);
101  EXPECT_EQ(groupC.next, &groupD);
102  EXPECT_EQ(groupD.next, nullptr);
103 
104  EXPECT_EQ(groupA.channels.first, &groupAcurve1);
105  EXPECT_EQ(groupA.channels.last, &groupAcurve2);
106  EXPECT_EQ(groupB.channels.first, &groupBcurve1);
107  EXPECT_EQ(groupB.channels.last, &groupBcurve3);
108  EXPECT_EQ(groupC.channels.first, nullptr);
109  EXPECT_EQ(groupC.channels.last, nullptr);
110  EXPECT_EQ(groupD.channels.first, &groupDcurve1);
111  EXPECT_EQ(groupD.channels.last, &groupDcurve2);
112 
113  EXPECT_EQ(groupAcurve1.prev, nullptr);
114  EXPECT_EQ(groupAcurve2.prev, &groupAcurve1);
115  EXPECT_EQ(groupBcurve1.prev, &groupAcurve2);
116  EXPECT_EQ(groupBcurve2.prev, &groupBcurve1);
117  EXPECT_EQ(groupBcurve3.prev, &groupBcurve2);
118  EXPECT_EQ(groupDcurve1.prev, &groupBcurve3);
119  EXPECT_EQ(groupDcurve2.prev, &groupDcurve1);
120 
121  EXPECT_EQ(groupAcurve1.next, &groupAcurve2);
122  EXPECT_EQ(groupAcurve2.next, &groupBcurve1);
123  EXPECT_EQ(groupBcurve1.next, &groupBcurve2);
124  EXPECT_EQ(groupBcurve2.next, &groupBcurve3);
125  EXPECT_EQ(groupBcurve3.next, &groupDcurve1);
126  EXPECT_EQ(groupDcurve1.next, &groupDcurve2);
127  EXPECT_EQ(groupDcurve2.next, nullptr);
128 }
129 
130 namespace {
131 
132 /* Allocate fcu->bezt, and also return a unique_ptr to it for easily freeing the memory. */
133 std::unique_ptr<BezTriple[]> allocate_keyframes(FCurve *fcu, const size_t num_keyframes)
134 {
135  auto bezt_uptr = std::make_unique<BezTriple[]>(num_keyframes);
136  fcu->bezt = bezt_uptr.get();
137  return bezt_uptr;
138 }
139 
140 /* Append keyframe, assumes that fcu->bezt is allocated and has enough space. */
141 void add_keyframe(FCurve *fcu, float x, float y)
142 {
143  /* The insert_keyframe functions are in the editors, so we cannot link to those here. */
144  BezTriple the_keyframe;
145  memset(&the_keyframe, 0, sizeof(the_keyframe));
146 
147  /* Copied from insert_vert_fcurve() in keyframing.c. */
148  the_keyframe.vec[0][0] = x - 1.0f;
149  the_keyframe.vec[0][1] = y;
150  the_keyframe.vec[1][0] = x;
151  the_keyframe.vec[1][1] = y;
152  the_keyframe.vec[2][0] = x + 1.0f;
153  the_keyframe.vec[2][1] = y;
154 
155  memcpy(&fcu->bezt[fcu->totvert], &the_keyframe, sizeof(the_keyframe));
156  fcu->totvert++;
157 }
158 
159 } // namespace
160 
162 {
163  /* NULL action. */
164  EXPECT_FALSE(BKE_action_has_single_frame(nullptr)) << "NULL Action cannot have a single frame.";
165 
166  /* No FCurves. */
167  {
168  const bAction empty = {{nullptr}};
169  EXPECT_FALSE(BKE_action_has_single_frame(&empty))
170  << "Action without FCurves cannot have a single frame.";
171  }
172 
173  /* One curve with one key. */
174  {
175  FCurve fcu = {nullptr};
176  std::unique_ptr<BezTriple[]> bezt = allocate_keyframes(&fcu, 1);
177  add_keyframe(&fcu, 1.0f, 2.0f);
178 
179  bAction action = {{nullptr}};
180  BLI_addtail(&action.curves, &fcu);
181 
182  EXPECT_TRUE(BKE_action_has_single_frame(&action))
183  << "Action with one FCurve and one key should have single frame.";
184  }
185 
186  /* Two curves with one key each. */
187  {
188  FCurve fcu1 = {nullptr};
189  FCurve fcu2 = {nullptr};
190  std::unique_ptr<BezTriple[]> bezt1 = allocate_keyframes(&fcu1, 1);
191  std::unique_ptr<BezTriple[]> bezt2 = allocate_keyframes(&fcu2, 1);
192  add_keyframe(&fcu1, 1.0f, 327.0f);
193  add_keyframe(&fcu2, 1.0f, 47.0f); /* Same X-coordinate as the other one. */
194 
195  bAction action = {{nullptr}};
196  BLI_addtail(&action.curves, &fcu1);
197  BLI_addtail(&action.curves, &fcu2);
198 
199  EXPECT_TRUE(BKE_action_has_single_frame(&action))
200  << "Two FCurves with keys on the same frame should have single frame.";
201 
202  /* Modify the 2nd curve so it's keyed on a different frame. */
203  fcu2.bezt[0].vec[1][0] = 2.0f;
204  EXPECT_FALSE(BKE_action_has_single_frame(&action))
205  << "Two FCurves with keys on different frames should have animation.";
206  }
207 
208  /* One curve with two keys. */
209  {
210  FCurve fcu = {nullptr};
211  std::unique_ptr<BezTriple[]> bezt = allocate_keyframes(&fcu, 2);
212  add_keyframe(&fcu, 1.0f, 2.0f);
213  add_keyframe(&fcu, 2.0f, 2.5f);
214 
215  bAction action = {{nullptr}};
216  BLI_addtail(&action.curves, &fcu);
217 
218  EXPECT_FALSE(BKE_action_has_single_frame(&action))
219  << "Action with one FCurve and two keys must have animation.";
220  }
221 }
222 
223 } // namespace blender::bke::tests
Blender kernel action and pose functionality.
void BKE_action_groups_reconstruct(struct bAction *act)
Definition: action.c:503
bool BKE_action_has_single_frame(const struct bAction *act)
Definition: action.c:1352
EXPECT_EQ(BLI_expr_pylike_eval(expr, nullptr, 0, &result), EXPR_PYLIKE_INVALID)
void BLI_addtail(struct ListBase *listbase, void *vlink) ATTR_NONNULL(1)
Definition: listbase.c:80
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
Read Guarded memory(de)allocation.
TEST(action_groups, ReconstructGroupsWithReordering)
Definition: action_test.cc:17
float vec[3][3]
struct FCurve * next
bActionGroup * grp
char * rna_path
BezTriple * bezt
struct FCurve * prev
unsigned int totvert
void * last
Definition: DNA_listBase.h:31
void * first
Definition: DNA_listBase.h:31
struct bActionGroup * prev
struct bActionGroup * next
ListBase curves
ListBase groups