Blender V5.0
scene_test.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2025 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
5#include "BKE_anim_data.hh"
6#include "BKE_appdir.hh"
7#include "BKE_idprop.hh"
8#include "BKE_idtype.hh"
9#include "BKE_lib_id.hh"
10#include "BKE_main.hh"
11#include "BKE_scene.hh"
12
13#include "BLO_userdef_default.h"
14
15#include "IMB_imbuf.hh"
16
17#include "DNA_action_types.h"
18#include "DNA_anim_types.h"
19#include "DNA_scene_types.h"
20#include "DNA_userdef_types.h"
21
22#include "CLG_log.h"
23
24#include "testing/testing.h"
25
26namespace blender::bke::tests {
27
28TEST(scene, frame_snap_by_seconds)
29{
30 Scene fake_scene = {};
31
32 /* Regular 24 FPS snapping. */
33 fake_scene.r.frs_sec = 24;
34 fake_scene.r.frs_sec_base = 1.0;
35 EXPECT_FLOAT_EQ(48.0, BKE_scene_frame_snap_by_seconds(&fake_scene, 1.0, 47));
36 EXPECT_FLOAT_EQ(48.0, BKE_scene_frame_snap_by_seconds(&fake_scene, 1.0, 49));
37 EXPECT_FLOAT_EQ(48.0, BKE_scene_frame_snap_by_seconds(&fake_scene, 1.0, 59));
38 EXPECT_FLOAT_EQ(72.0, BKE_scene_frame_snap_by_seconds(&fake_scene, 1.0, 60));
39 EXPECT_FLOAT_EQ(9984.0, BKE_scene_frame_snap_by_seconds(&fake_scene, 2.0, 10000.0));
40
41 /* 12 FPS snapping by incrementing the base. */
42 fake_scene.r.frs_sec = 24;
43 fake_scene.r.frs_sec_base = 2.0;
44 EXPECT_FLOAT_EQ(48.0, BKE_scene_frame_snap_by_seconds(&fake_scene, 1.0, 47));
45 EXPECT_FLOAT_EQ(48.0, BKE_scene_frame_snap_by_seconds(&fake_scene, 1.0, 49));
46 EXPECT_FLOAT_EQ(48.0, BKE_scene_frame_snap_by_seconds(&fake_scene, 1.0, 53));
47 EXPECT_FLOAT_EQ(60.0, BKE_scene_frame_snap_by_seconds(&fake_scene, 1.0, 54));
48 EXPECT_FLOAT_EQ(9996.0, BKE_scene_frame_snap_by_seconds(&fake_scene, 1.0, 10000.0));
49
50 /* 0.1 FPS snapping to 2-second intervals. */
51 fake_scene.r.frs_sec = 1;
52 fake_scene.r.frs_sec_base = 10.0;
53 EXPECT_FLOAT_EQ(48.0, BKE_scene_frame_snap_by_seconds(&fake_scene, 2.0, 48.0));
54 EXPECT_FLOAT_EQ(48.0, BKE_scene_frame_snap_by_seconds(&fake_scene, 2.0, 48.1));
55 EXPECT_FLOAT_EQ(48.2, BKE_scene_frame_snap_by_seconds(&fake_scene, 2.0, 48.2));
56 EXPECT_FLOAT_EQ(10000.0, BKE_scene_frame_snap_by_seconds(&fake_scene, 2.0, 10000.0));
57}
58
59class SceneTest : public ::testing::Test {
60 public:
62
63 static void SetUpTestSuite()
64 {
65 CLG_init();
67 IMB_init();
69 /* #BKE_scene_duplicate() uses #U::dupflag. */
70 U = blender::dna::shallow_copy(U_default);
71 }
72
73 static void TearDownTestSuite()
74 {
75 IMB_exit();
77 CLG_exit();
78 }
79
80 void SetUp() override
81 {
83 }
84
85 void TearDown() override
86 {
88 }
89};
90
91TEST_F(SceneTest, linked_copy_id_remapping)
92{
93 Scene *scene_src = BKE_id_new<Scene>(bmain, "Scene_source");
94 bAction *action_src = BKE_id_new<bAction>(bmain, "Scene_source_action");
95 BKE_animdata_set_action(nullptr, &scene_src->id, action_src);
96 AnimData *animdata_src = BKE_animdata_from_id(&scene_src->id);
97 ASSERT_NE(animdata_src, nullptr);
98 EXPECT_EQ(animdata_src->action, action_src);
99
100 constexpr blender::StringRef idp_scene2scene_name = "scene2scene";
101 constexpr blender::StringRef idp_scene2action_name = "scene2action";
102 constexpr blender::StringRef idp_action2scene_name = "action2scene";
103 constexpr blender::StringRef idp_action2action_name = "action2action";
104
105 IDProperty *scene_idgroup_src = IDP_EnsureProperties(&scene_src->id);
106 IDP_AddToGroup(scene_idgroup_src,
107 bke::idprop::create(idp_scene2scene_name, &scene_src->id).release());
108 IDP_AddToGroup(scene_idgroup_src,
109 bke::idprop::create(idp_scene2action_name, &action_src->id).release());
110
111 IDProperty *action_idgroup_src = IDP_EnsureProperties(&action_src->id);
112 IDP_AddToGroup(action_idgroup_src,
113 bke::idprop::create(idp_action2scene_name, &scene_src->id).release());
114 IDP_AddToGroup(action_idgroup_src,
115 bke::idprop::create(idp_action2action_name, &action_src->id).release());
116
117 Scene *scene_copy = BKE_scene_duplicate(
118 bmain,
119 scene_src,
121 static_cast<eDupli_ID_Flags>(U.dupflag | USER_DUP_OBJECT),
123
124 /* Source data should remain unchanged. */
125
126 EXPECT_EQ(IDP_ID_get(IDP_GetPropertyFromGroup(scene_idgroup_src, idp_scene2scene_name)),
127 &scene_src->id);
128 EXPECT_EQ(IDP_ID_get(IDP_GetPropertyFromGroup(scene_idgroup_src, idp_scene2action_name)),
129 &action_src->id);
130
131 EXPECT_EQ(IDP_ID_get(IDP_GetPropertyFromGroup(action_idgroup_src, idp_action2scene_name)),
132 &scene_src->id);
133 EXPECT_EQ(IDP_ID_get(IDP_GetPropertyFromGroup(action_idgroup_src, idp_action2action_name)),
134 &action_src->id);
135
136 /* Copied data should have its ID usages remapped to new copies if possible. */
137
138 EXPECT_NE(scene_copy, scene_src);
139 AnimData *animdata_copy = BKE_animdata_from_id(&scene_copy->id);
140 ASSERT_NE(animdata_copy, nullptr);
141 EXPECT_NE(animdata_copy, animdata_src);
142 bAction *action_copy = animdata_copy->action;
143 ASSERT_NE(action_copy, nullptr);
144 EXPECT_NE(action_copy, action_src);
145
146 IDProperty *scene_idgroup_copy = IDP_GetProperties(&scene_copy->id);
147 ASSERT_NE(scene_idgroup_copy, nullptr);
148 EXPECT_EQ(IDP_ID_get(IDP_GetPropertyFromGroup(scene_idgroup_copy, idp_scene2scene_name)),
149 &scene_copy->id);
150 EXPECT_EQ(IDP_ID_get(IDP_GetPropertyFromGroup(scene_idgroup_copy, idp_scene2action_name)),
151 &action_copy->id);
152
153 IDProperty *action_idgroup_copy = IDP_GetProperties(&action_copy->id);
154 ASSERT_NE(action_idgroup_copy, nullptr);
155 EXPECT_EQ(IDP_ID_get(IDP_GetPropertyFromGroup(action_idgroup_copy, idp_action2scene_name)),
156 &scene_copy->id);
157 EXPECT_EQ(IDP_ID_get(IDP_GetPropertyFromGroup(action_idgroup_copy, idp_action2action_name)),
158 &action_copy->id);
159}
160
161} // namespace blender::bke::tests
bool BKE_animdata_set_action(ReportList *reports, ID *id, bAction *act)
Definition anim_data.cc:125
AnimData * BKE_animdata_from_id(const ID *id)
Definition anim_data.cc:83
void BKE_appdir_init()
Definition appdir.cc:93
void BKE_appdir_exit()
Definition appdir.cc:101
#define IDP_ID_get(prop)
IDProperty * IDP_GetPropertyFromGroup(const IDProperty *prop, blender::StringRef name) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL()
Definition idprop.cc:747
bool IDP_AddToGroup(IDProperty *group, IDProperty *prop) ATTR_NONNULL()
Definition idprop.cc:717
IDProperty * IDP_EnsureProperties(ID *id) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition idprop.cc:882
IDProperty * IDP_GetProperties(ID *id) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1)
Definition idprop.cc:877
void BKE_idtype_init()
Definition idtype.cc:121
void * BKE_id_new(Main *bmain, short type, const char *name)
Definition lib_id.cc:1514
@ LIB_ID_DUPLICATE_IS_ROOT_ID
Main * BKE_main_new()
Definition main.cc:89
void BKE_main_free(Main *bmain)
Definition main.cc:192
float BKE_scene_frame_snap_by_seconds(const Scene *scene, double interval_in_seconds, float frame)
Definition scene.cc:2321
@ SCE_COPY_LINK_COLLECTION
Definition BKE_scene.hh:35
Scene * BKE_scene_duplicate(Main *bmain, Scene *sce, eSceneCopyMethod type, eDupli_ID_Flags duplicate_flags, uint duplicate_options)
Definition scene.cc:1783
EXPECT_EQ(BLI_expr_pylike_eval(expr, nullptr, 0, &result), EXPR_PYLIKE_INVALID)
const UserDef U_default
void CLG_exit()
Definition clog.cc:880
void CLG_init()
Definition clog.cc:873
eDupli_ID_Flags
@ USER_DUP_OBJECT
void IMB_exit()
Definition module.cc:21
void IMB_init()
Definition module.cc:15
#define U
std::unique_ptr< IDProperty, IDPropertyDeleter > create(StringRef prop_name, int32_t value, eIDPropertyFlag flags={})
Allocate a new IDProperty of type IDP_INT, set its name and value.
TEST_F(ArmatureDeformTest, MeshDeform)
TEST(action_groups, ReconstructGroupsWithReordering)
bAction * action
struct RenderData r