Anim: Remove 'Slotted Actions' experimental flag

This commit takes the 'Slotted Actions' out of the experimental phase.
As a result:

- All newly created Actions will be slotted Actions.
- Legacy Actions loaded from disk will be versioned to slotted Actions.
- The new Python API for slots, layers, strips, and channel bags is
  available.
- The legacy Python API for accessing F-Curves and Action Groups is
  still available, and will operate on the F-Curves/Groups for the first
  slot only.
- Creating an Action by keying (via the UI, operators, or the
  `rna_struct.keyframe_insert` function) will try and share Actions
  between related data-blocks. See !126655 for more info about this.
- Assigning an Action to a data-block will auto-assign a suitable Action
  Slot. The logic for this is described below. However, There are cases
  where this does _not_ automatically assign a slot, and thus the Action
  will effectively _not_ animate the data-block. Effort has been spent
  to make Action selection work both reliably for Blender users as well
  as keep the behaviour the same for Python scripts. Where these two
  goals did not converge, reliability and understandability for users
  was prioritised.

Auto-selection of the Action Slot upon assigning the Action works as
follows. The first rule to find a slot wins.

1. The data-block remembers the slot name that was last assigned. If the
    newly assigned Action has a slot with that name, it is chosen.
2. If the Action has a slot with the same name as the data-block, it is
    chosen.
3. If the Action has only one slot, and it has never been assigned to
    anything, it is chosen.
4. If the Action is assigned to an NLA strip or an Action constraint,
    and the Action has a single slot, and that slot has a suitable ID
    type, it is chosen.

This last step is what I was referring to with "Where these two goals
did not converge, reliability and understandability for users was
prioritised." For regular Action assignments (like via the Action
selectors in the Properties editor) this rule doesn't apply, even though
with legacy Actions the final state ("it is animated by this Action")
differs from the final state with slotted Actions ("it has no slot so is
not animated"). This is done to support the following workflow:

- Create an Action by animating Cube.
- In order to animate Suzanne with that same Action, assign the Action
  to Suzanne.
- Start keying Suzanne. This auto-creates and auto-assigns a new slot
  for Suzanne.

If rule 4. above would apply in this case, the 2nd step would
automatically select the Cube slot for Suzanne as well, which would
immediately overwrite Suzanne's properties with the Cube animation.

Technically, this commit:
- removes the `WITH_ANIM_BAKLAVA` build flag,
- removes the `use_animation_baklava` experimental flag in preferences,
- updates the code to properly deal with the fact that empty Actions are
  now always considered slotted/layered Actions (instead of that relying
  on the user preference).

Note that 'slotted Actions' and 'layered Actions' are the exact same
thing, just focusing on different aspects (slot & layers) of the new
data model.

The "Baklava phase 1" assumptions are still asserted. This means that:
- an Action can have zero or one layer,
- that layer can have zero or one strip,
- that strip must be of type 'keyframe' and be infinite with zero
  offset.

The code to handle legacy Actions is NOT removed in this commit. It will
be removed later. For now it's likely better to keep it around as
reference to the old behaviour in order to aid in some inevitable
bugfixing.

Ref: #120406
This commit is contained in:
Sybren A. Stüvel 2024-10-15 16:29:53 +02:00
parent 74cb86aba4
commit 43d7558e5b
46 changed files with 76 additions and 522 deletions

View file

@ -364,7 +364,7 @@ def bake_action_iter(
atd.use_tweak_mode = False
atd.action = action
if bpy.context.preferences.experimental.use_animation_baklava and action.is_action_layered:
if action.is_action_layered:
slot = action.slots.new(for_id=obj)
atd.action_slot = slot

View file

@ -1128,7 +1128,7 @@ class ConstraintButtonsSubPanel:
col = layout.column(align=True)
col.prop(con, "action")
if context.preferences.experimental.use_animation_baklava and con.action and con.action.is_action_layered:
if con.action and con.action.is_action_layered:
col.context_pointer_set("animated_id", con.id_data)
col.template_search(
con, "action_slot",

View file

@ -29,7 +29,7 @@ def dopesheet_filter(layout, context):
is_action_editor = not is_nla and context.space_data.mode == 'ACTION'
row = layout.row(align=True)
if is_action_editor and context.preferences.experimental.use_animation_baklava:
if is_action_editor:
row.prop(dopesheet, "show_only_slot_of_active_object", text="")
row.prop(dopesheet, "show_only_selected", text="")
row.prop(dopesheet, "show_hidden", text="")
@ -310,9 +310,6 @@ class DOPESHEET_HT_editor_buttons:
row.template_action(animated_id, new="action.new", unlink="action.unlink")
if not context.preferences.experimental.use_animation_baklava:
return
adt = animated_id and animated_id.animation_data
if not adt or not adt.action or not adt.action.is_action_layered:
return
@ -392,8 +389,7 @@ class DOPESHEET_MT_editor_menus(Menu):
layout.menu("DOPESHEET_MT_key")
if st.mode in {'ACTION', 'SHAPEKEY'} and st.action is not None:
if context.preferences.experimental.use_animation_baklava:
layout.menu("DOPESHEET_MT_action")
layout.menu("DOPESHEET_MT_action")
class DOPESHEET_MT_view(Menu):
@ -690,8 +686,6 @@ class DOPESHEET_PT_action_slot(Panel):
@classmethod
def poll(cls, context):
if not context.preferences.experimental.use_animation_baklava:
return False
action = context.active_action
return bool(action and action.slots.active)

View file

@ -124,9 +124,6 @@ class PropertiesAnimationMixin:
layout.template_action(animated_id, new="action.new", unlink="action.unlink")
if not context.preferences.experimental.use_animation_baklava:
return
adt = animated_id.animation_data
if not adt or not adt.action:
return

View file

@ -2896,7 +2896,6 @@ class USERPREF_PT_experimental_prototypes(ExperimentalPanel, Panel):
({"property": "use_new_point_cloud_type"}, ("blender/blender/issues/75717", "#75717")),
({"property": "use_sculpt_texture_paint"}, ("blender/blender/issues/96225", "#96225")),
({"property": "enable_overlay_next"}, ("blender/blender/issues/102179", "#102179")),
({"property": "use_animation_baklava"}, ("/blender/blender/issues/120406", "#120406")),
({"property": "enable_new_cpu_compositor"}, ("/blender/blender/issues/125968", "#125968")),
),
)

View file

@ -70,10 +70,6 @@ set(LIB
PRIVATE bf::intern::clog
)
if(WITH_EXPERIMENTAL_FEATURES)
add_definitions(-DWITH_ANIM_BAKLAVA)
endif()
blender_add_lib(bf_animrig "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
add_library(bf::animrig ALIAS bf_animrig)

View file

@ -871,10 +871,6 @@ static float2 get_frame_range_of_fcurves(Span<const FCurve *> fcurves,
foundmod = true;
}
/* This block is here just so that editors/IDEs do not get confused about the two opening
* curly braces in the `#ifdef WITH_ANIM_BAKLAVA` block above, but one closing curly brace
* here. */
}
if (foundvert || foundmod) {

View file

@ -68,16 +68,13 @@ template<typename ActionType,
typename ChannelBagType>
static Vector<FCurveType *> fcurves_all_templated(ActionType &action)
{
#ifdef WITH_ANIM_BAKLAVA
/* Legacy Action. */
if (action.is_action_legacy()) {
#endif /* WITH_ANIM_BAKLAVA */
Vector<FCurveType *> legacy_fcurves;
LISTBASE_FOREACH (FCurveType *, fcurve, &action.curves) {
legacy_fcurves.append(fcurve);
}
return legacy_fcurves;
#ifdef WITH_ANIM_BAKLAVA
}
/* Layered Action. */
@ -99,7 +96,6 @@ static Vector<FCurveType *> fcurves_all_templated(ActionType &action)
}
}
return all_fcurves;
#endif /* WITH_ANIM_BAKLAVA */
}
Vector<FCurve *> fcurves_all(bAction *action)
@ -151,22 +147,14 @@ template<typename ActionType,
static Vector<FCurveType *> fcurves_for_action_slot_templated(ActionType &action,
const slot_handle_t slot_handle)
{
#ifndef WITH_ANIM_BAKLAVA
UNUSED_VARS(slot_handle);
#endif /* !WITH_ANIM_BAKLAVA */
#ifdef WITH_ANIM_BAKLAVA
/* Legacy Action. */
if (action.is_action_legacy()) {
#endif /* WITH_ANIM_BAKLAVA */
return listbase_to_vector<FCurveType>(action.curves);
#ifdef WITH_ANIM_BAKLAVA
}
/* Layered Action. */
Vector<FCurveType *> as_vector(animrig::fcurves_for_action_slot(action, slot_handle));
return as_vector;
#endif /* WITH_ANIM_BAKLAVA */
}
Vector<FCurve *> fcurves_for_action_slot(bAction *action, const slot_handle_t slot_handle)
@ -234,16 +222,13 @@ Vector<bActionGroup *> channel_groups_all(bAction *action)
Action &action_wrap = action->wrap();
#ifdef WITH_ANIM_BAKLAVA
/* Legacy Action. */
if (action_wrap.is_action_legacy()) {
#endif /* WITH_ANIM_BAKLAVA */
Vector<bActionGroup *> legacy_groups;
LISTBASE_FOREACH (bActionGroup *, group, &action_wrap.groups) {
legacy_groups.append(group);
}
return legacy_groups;
#ifdef WITH_ANIM_BAKLAVA
}
/* Layered Action. */
@ -261,7 +246,6 @@ Vector<bActionGroup *> channel_groups_all(bAction *action)
}
}
return all_groups;
#endif /* WITH_ANIM_BAKLAVA */
}
Vector<bActionGroup *> channel_groups_for_assigned_slot(AnimData *adt)
@ -289,12 +273,12 @@ Vector<bActionGroup *> channel_groups_for_assigned_slot(AnimData *adt)
bool action_treat_as_legacy(const bAction &action)
{
const Action &action_wrap = action.wrap();
if (action_wrap.is_empty()) {
const bool may_do_layered = USER_EXPERIMENTAL_TEST(&U, use_animation_baklava);
return !may_do_layered;
}
return action_wrap.is_action_legacy();
/* At runtime, legacy Actions should have been versioned to layered/slotted Actions. However,
* unit tests can still create legacy Actions, and so this function still has to distinguish
* between them.
*
* Note that empty Actions also count as 'layered'. */
return !action.wrap().is_action_layered();
}
bool action_fcurves_remove(bAction &action,

View file

@ -86,7 +86,6 @@ TEST_F(ActionLegacyTest, fcurves_all)
}
}
#ifdef WITH_ANIM_BAKLAVA
TEST_F(ActionLegacyTest, fcurves_all_layered)
{
Action &action = create_empty_action()->wrap();
@ -103,7 +102,6 @@ TEST_F(ActionLegacyTest, fcurves_all_layered)
Vector<FCurve *> fcurves_expect = {&fcurve1, &fcurve2};
EXPECT_EQ(fcurves_expect, legacy::fcurves_all(&action));
}
#endif /* WITH_ANIM_BAKLAVA */
TEST_F(ActionLegacyTest, fcurves_for_action_slot)
{
@ -130,7 +128,6 @@ TEST_F(ActionLegacyTest, fcurves_for_action_slot)
}
}
#ifdef WITH_ANIM_BAKLAVA
TEST_F(ActionLegacyTest, fcurves_for_action_slot_layered)
{
Action &action = create_empty_action()->wrap();
@ -149,7 +146,6 @@ TEST_F(ActionLegacyTest, fcurves_for_action_slot_layered)
EXPECT_EQ(fcurve1_expect, legacy::fcurves_for_action_slot(&action, slot1.handle));
EXPECT_EQ(fcurve2_expect, legacy::fcurves_for_action_slot(&action, slot2.handle));
}
#endif /* WITH_ANIM_BAKLAVA */
TEST_F(ActionLegacyTest, action_fcurves_remove_legacy)
{
@ -171,7 +167,6 @@ TEST_F(ActionLegacyTest, action_fcurves_remove_legacy)
}
}
#ifdef WITH_ANIM_BAKLAVA
TEST_F(ActionLegacyTest, action_fcurves_remove_layered)
{
/* Create an Action with two slots, to check that the 2nd slot is not affected
@ -206,6 +201,4 @@ TEST_F(ActionLegacyTest, action_fcurves_remove_layered)
<< "Expected all F-Curves for slot 2 to be there after manipulating slot 1";
}
#endif /* WITH_ANIM_BAKLAVA */
} // namespace blender::animrig::tests

View file

@ -825,7 +825,7 @@ TEST_F(ActionLayersTest, action_slot_get_id_for_keying__empty_action)
/* None should return an ID, since there are no slots yet which could have this ID assigned.
* Assignment of the Action itself (cube) shouldn't matter. */
EXPECT_EQ(&cube->id, action_slot_get_id_for_keying(*bmain, *action, 0, &cube->id));
EXPECT_EQ(nullptr, action_slot_get_id_for_keying(*bmain, *action, 0, &cube->id));
EXPECT_EQ(nullptr, action_slot_get_id_for_keying(*bmain, *action, 0, nullptr));
EXPECT_EQ(nullptr, action_slot_get_id_for_keying(*bmain, *action, 0, &suzanne->id));
}
@ -976,9 +976,6 @@ TEST_F(ActionLayersTest, empty_to_layered)
TEST_F(ActionLayersTest, action_move_slot)
{
U.flag |= USER_DEVELOPER_UI;
U.experimental.use_animation_baklava = 1;
Action *action_2 = static_cast<Action *>(BKE_id_new(bmain, ID_AC, "Action 2"));
EXPECT_TRUE(action->is_empty());
@ -1060,15 +1057,11 @@ static void add_keyframe(FCurve &fcu, float x, float y)
static void add_fcurve_to_action(Action &action, FCurve &fcu)
{
#ifdef WITH_ANIM_BAKLAVA
Slot &slot = action.slot_array_num > 0 ? *action.slot(0) : action.slot_add();
action.layer_keystrip_ensure();
StripKeyframeData &strip_data = action.layer(0)->strip(0)->data<StripKeyframeData>(action);
ChannelBag &cbag = strip_data.channelbag_for_slot_ensure(slot);
cbag.fcurve_append(fcu);
#else
BLI_addhead(&action.curves, &fcu);
#endif /* WITH_ANIM_BAKLAVA */
}
class ActionQueryTest : public testing::Test {
@ -1882,7 +1875,6 @@ TEST_F(ActionFCurveMoveTest, test_fcurve_move_legacy)
<< "Destination Action should have its original and the moved F-Curve";
}
#ifdef WITH_ANIM_BAKLAVA
TEST_F(ActionFCurveMoveTest, test_fcurve_move_layered)
{
Action &action_src = action_add(*this->bmain, "SourceAction");
@ -1931,6 +1923,5 @@ TEST_F(ActionFCurveMoveTest, test_fcurve_move_layered)
ASSERT_NE(nullptr, group_dst) << "Expected channel group to be created";
ASSERT_EQ(group_dst, fcurve_to_move.grp) << "Expected group membership to move as well";
}
#endif
} // namespace blender::animrig::tests

View file

@ -203,21 +203,19 @@ bAction *id_action_ensure(Main *bmain, ID *id)
/* init action if none available yet */
/* TODO: need some wizardry to handle NLA stuff correct */
if (adt->action == nullptr) {
bAction *action = nullptr;
if (USER_EXPERIMENTAL_TEST(&U, use_animation_baklava)) {
action = find_related_action(*bmain, *id);
}
bAction *action = find_related_action(*bmain, *id);
if (action == nullptr) {
/* init action name from name of ID block */
char actname[sizeof(id->name) - 2];
if (id->flag & ID_FLAG_EMBEDDED_DATA && USER_EXPERIMENTAL_TEST(&U, use_animation_baklava)) {
if (id->flag & ID_FLAG_EMBEDDED_DATA) {
/* When the ID is embedded, use the name of the owner ID for clarity. */
ID *owner_id = BKE_id_owner_get(id);
/* If the ID is embedded it should have an owner. */
BLI_assert(owner_id != nullptr);
SNPRINTF(actname, DATA_("%sAction"), owner_id->name + 2);
}
else if (GS(id->name) == ID_KE && USER_EXPERIMENTAL_TEST(&U, use_animation_baklava)) {
else if (GS(id->name) == ID_KE) {
Key *key = (Key *)id;
SNPRINTF(actname, DATA_("%sAction"), key->from->name + 2);
}

View file

@ -72,20 +72,11 @@ class KeyframingTest : public testing::Test {
static void TearDownTestSuite()
{
/* Ensure experimental baklava flag is turned off after all tests are run. */
U.flag &= ~USER_DEVELOPER_UI;
U.experimental.use_animation_baklava = 0;
CLG_exit();
}
void SetUp() override
{
/* Ensure experimental baklava flag is turned off first (to be enabled
* selectively in the layered action tests. */
U.flag &= ~USER_DEVELOPER_UI;
U.experimental.use_animation_baklava = 0;
bmain = BKE_main_new();
object = BKE_object_add_only_object(bmain, OB_EMPTY, "Empty");
@ -186,10 +177,6 @@ class KeyframingTest : public testing::Test {
/* Keying a non-array property. */
TEST_F(KeyframingTest, insert_keyframes__layered_action__non_array_property)
{
/* Turn on Baklava experimental flag. */
U.flag |= USER_DEVELOPER_UI;
U.experimental.use_animation_baklava = 1;
AnimationEvalContext anim_eval_context = {nullptr, 1.0};
/* First time should create:
@ -281,10 +268,6 @@ TEST_F(KeyframingTest, insert_keyframes__layered_action__non_array_property)
TEST_F(KeyframingTest, insert_keyframes__layered_action__action_reuse)
{
/* Turn on Baklava experimental flag. */
U.flag |= USER_DEVELOPER_UI;
U.experimental.use_animation_baklava = 1;
AnimationEvalContext anim_eval_context = {nullptr, 1.0};
CombinedKeyingResult result_ob;
result_ob = insert_keyframes(bmain,
@ -323,16 +306,10 @@ TEST_F(KeyframingTest, insert_keyframes__layered_action__action_reuse)
for (Slot *slot : action.slots()) {
ASSERT_TRUE(slot->idtype == ID_AR || slot->idtype == ID_OB);
}
U.experimental.use_animation_baklava = 0;
U.flag &= ~USER_DEVELOPER_UI;
}
TEST_F(KeyframingTest, insert_keyframes__layered_action__action_reuse_material)
{
U.flag |= USER_DEVELOPER_UI;
U.experimental.use_animation_baklava = 1;
AnimationEvalContext anim_eval_context = {nullptr, 1.0};
CombinedKeyingResult result_ob;
@ -394,16 +371,10 @@ TEST_F(KeyframingTest, insert_keyframes__layered_action__action_reuse_material)
ASSERT_TRUE(slot->idtype == ID_ME || slot->idtype == ID_OB);
ASSERT_NE(slot->idtype, ID_MA);
}
U.experimental.use_animation_baklava = 0;
U.flag &= ~USER_DEVELOPER_UI;
}
TEST_F(KeyframingTest, insert_keyframes__layered_action__action_reuse_multiuser)
{
U.flag |= USER_DEVELOPER_UI;
U.experimental.use_animation_baklava = 1;
Object *another_object = BKE_object_add_only_object(bmain, OB_MESH, "another_object");
PointerRNA another_object_rna_pointer = RNA_id_pointer_create(&another_object->id);
BKE_mesh_assign_object(bmain, another_object, cube_mesh);
@ -458,18 +429,11 @@ TEST_F(KeyframingTest, insert_keyframes__layered_action__action_reuse_multiuser)
/* Given that those two objects are connected by a mesh (which due to this has two users) the
* action shouldn't be reused between them. */
ASSERT_NE(cube->adt->action, another_object->adt->action);
U.experimental.use_animation_baklava = 0;
U.flag &= ~USER_DEVELOPER_UI;
}
/* Keying a single element of an array property. */
TEST_F(KeyframingTest, insert_keyframes__layered_action__single_element)
{
/* Turn on Baklava experimental flag. */
U.flag |= USER_DEVELOPER_UI;
U.experimental.use_animation_baklava = 1;
AnimationEvalContext anim_eval_context = {nullptr, 1.0};
const CombinedKeyingResult result = insert_keyframes(bmain,
@ -499,10 +463,6 @@ TEST_F(KeyframingTest, insert_keyframes__layered_action__single_element)
/* Keying all elements of an array property. */
TEST_F(KeyframingTest, insert_keyframes__layered_action__all_elements)
{
/* Turn on Baklava experimental flag. */
U.flag |= USER_DEVELOPER_UI;
U.experimental.use_animation_baklava = 1;
AnimationEvalContext anim_eval_context = {nullptr, 1.0};
const CombinedKeyingResult result = insert_keyframes(bmain,
@ -534,10 +494,6 @@ TEST_F(KeyframingTest, insert_keyframes__layered_action__all_elements)
/* Keying a pose bone from its own RNA pointer. */
TEST_F(KeyframingTest, insert_keyframes__layered_action__pose_bone_rna_pointer)
{
/* Turn on Baklava experimental flag. */
U.flag |= USER_DEVELOPER_UI;
U.experimental.use_animation_baklava = 1;
AnimationEvalContext anim_eval_context = {nullptr, 1.0};
bPoseChannel *pchan = BKE_pose_channel_find_name(armature_object->pose, "Bone");
PointerRNA pose_bone_rna_pointer = RNA_pointer_create(
@ -570,10 +526,6 @@ TEST_F(KeyframingTest, insert_keyframes__layered_action__pose_bone_rna_pointer)
/* Keying a pose bone from its owning ID's RNA pointer. */
TEST_F(KeyframingTest, insert_keyframes__pose_bone_owner_id_pointer)
{
/* Turn on Baklava experimental flag. */
U.flag |= USER_DEVELOPER_UI;
U.experimental.use_animation_baklava = 1;
AnimationEvalContext anim_eval_context = {nullptr, 1.0};
const CombinedKeyingResult result = insert_keyframes(
@ -604,10 +556,6 @@ TEST_F(KeyframingTest, insert_keyframes__pose_bone_owner_id_pointer)
/* Keying multiple elements of multiple properties at once. */
TEST_F(KeyframingTest, insert_keyframes__layered_action__multiple_properties)
{
/* Turn on Baklava experimental flag. */
U.flag |= USER_DEVELOPER_UI;
U.experimental.use_animation_baklava = 1;
AnimationEvalContext anim_eval_context = {nullptr, 1.0};
const CombinedKeyingResult result = insert_keyframes(bmain,
@ -647,10 +595,6 @@ TEST_F(KeyframingTest, insert_keyframes__layered_action__multiple_properties)
/* Keying more than one ID on the same action. */
TEST_F(KeyframingTest, insert_keyframes__layered_action__multiple_ids)
{
/* Turn on Baklava experimental flag. */
U.flag |= USER_DEVELOPER_UI;
U.experimental.use_animation_baklava = 1;
AnimationEvalContext anim_eval_context = {nullptr, 1.0};
/* First object should crate the action and get a slot and channel bag. */
@ -718,26 +662,18 @@ TEST_F(KeyframingTest, insert_keyframes__baklava_legacy_action)
{
AnimationEvalContext anim_eval_context = {nullptr, 1.0};
/* Insert a key with the experimental flag off to create a legacy action. */
const CombinedKeyingResult result_1 = insert_keyframes(bmain,
&object_rna_pointer,
std::nullopt,
{{"empty_display_size"}},
1.0,
anim_eval_context,
BEZT_KEYTYPE_KEYFRAME,
INSERTKEY_NOFLAGS);
EXPECT_EQ(1, result_1.get_count(SingleKeyingResult::SUCCESS));
/* Create a legacy Action and assign it the legacy way. */
{
bAction *action = reinterpret_cast<bAction *>(BKE_id_new(bmain, ID_AC, "LegacyAction"));
action_fcurve_ensure_legacy(bmain, action, nullptr, nullptr, {"testprop", 47});
BKE_animdata_ensure_id(&object->id)->action = action;
}
bAction *action = object->adt->action;
EXPECT_TRUE(action->wrap().is_action_legacy());
EXPECT_FALSE(action->wrap().is_action_layered());
EXPECT_EQ(1, BLI_listbase_count(&action->curves));
/* Turn on Baklava experimental flag. */
U.flag |= USER_DEVELOPER_UI;
U.experimental.use_animation_baklava = 1;
/* Insert more keys, which should also get inserted as part of the same legacy
* action, not a layered action. */
const CombinedKeyingResult result_2 = insert_keyframes(bmain,
@ -759,10 +695,6 @@ TEST_F(KeyframingTest, insert_keyframes__baklava_legacy_action)
/* Keying with the "Only Insert Available" flag. */
TEST_F(KeyframingTest, insert_keyframes__layered_action__only_available)
{
/* Turn on Baklava experimental flag. */
U.flag |= USER_DEVELOPER_UI;
U.experimental.use_animation_baklava = 1;
AnimationEvalContext anim_eval_context = {nullptr, 1.0};
/* First attempt should fail, because there are no fcurves yet. */
@ -832,10 +764,6 @@ TEST_F(KeyframingTest, insert_keyframes__layered_action__only_available)
/* Keying with the "Only Replace" flag. */
TEST_F(KeyframingTest, insert_keyframes__layered_action__only_replace)
{
/* Turn on Baklava experimental flag. */
U.flag |= USER_DEVELOPER_UI;
U.experimental.use_animation_baklava = 1;
AnimationEvalContext anim_eval_context = {nullptr, 1.0};
/* First attempt should fail, because there are no fcurves yet. */
@ -931,10 +859,6 @@ TEST_F(KeyframingTest, insert_keyframes__layered_action__only_replace)
/* Keying with the "Only Insert Needed" flag. */
TEST_F(KeyframingTest, insert_keyframes__layered_action__only_needed)
{
/* Turn on Baklava experimental flag. */
U.flag |= USER_DEVELOPER_UI;
U.experimental.use_animation_baklava = 1;
AnimationEvalContext anim_eval_context = {nullptr, 1.0};
/* First attempt should succeed, because there are no fcurves yet. */

View file

@ -31,7 +31,7 @@ extern "C" {
/* Blender file format version. */
#define BLENDER_FILE_VERSION BLENDER_VERSION
#define BLENDER_FILE_SUBVERSION 1
#define BLENDER_FILE_SUBVERSION 2
/* Minimum Blender version that supports reading file written with the current
* version. Older Blender versions will test this and cancel loading the file, showing a warning to

View file

@ -814,10 +814,6 @@ if(WITH_XR_OPENXR)
add_definitions(-DWITH_XR_OPENXR)
endif()
if(WITH_EXPERIMENTAL_FEATURES)
add_definitions(-DWITH_ANIM_BAKLAVA)
endif()
# # Warnings as errors, this is too strict!
# if(MSVC)
# string(APPEND CMAKE_C_FLAGS " /WX")

View file

@ -310,7 +310,6 @@ static void action_foreach_id(ID *id, LibraryForeachIDData *data)
}
}
#ifdef WITH_ANIM_BAKLAVA
static void write_channelbag(BlendWriter *writer, animrig::ChannelBag &channelbag)
{
BLO_write_struct(writer, ActionChannelBag, &channelbag);
@ -487,13 +486,11 @@ static void action_blend_write_clear_legacy_fcurves_listbase(ListBase &listbase)
BLI_listbase_clear(&listbase);
}
#endif /* WITH_ANIM_BAKLAVA */
static void action_blend_write(BlendWriter *writer, ID *id, const void *id_address)
{
animrig::Action &action = reinterpret_cast<bAction *>(id)->wrap();
#ifdef WITH_ANIM_BAKLAVA
/* Create legacy data for Layered Actions: the F-Curves from the first Slot,
* bottom layer, first Keyframe strip. */
const bool do_write_forward_compat = !BLO_write_is_undo(writer) && action.slot_array_num > 0 &&
@ -517,28 +514,10 @@ static void action_blend_write(BlendWriter *writer, ID *id, const void *id_addre
action_blend_write_make_legacy_channel_groups_listbase(action.groups, bag->channel_groups());
}
}
#else
/* Built without Baklava, so ensure that the written data is clean. This should not change
* anything, as the reading code below also ensures these fields are empty, and the APIs to add
* those should be unavailable. */
BLI_assert_msg(action.layer_array == nullptr,
"Action should not have layers, built without Baklava experimental feature");
BLI_assert_msg(action.layer_array_num == 0,
"Action should not have layers, built without Baklava experimental feature");
BLI_assert_msg(action.slot_array == nullptr,
"Action should not have slots, built without Baklava experimental feature");
BLI_assert_msg(action.slot_array_num == 0,
"Action should not have slots, built without Baklava experimental feature");
action.layer_array = nullptr;
action.layer_array_num = 0;
action.slot_array = nullptr;
action.slot_array_num = 0;
#endif /* WITH_ANIM_BAKLAVA */
BLO_write_id_struct(writer, bAction, id_address, &action.id);
BKE_id_blend_write(writer, &action.id);
#ifdef WITH_ANIM_BAKLAVA
/* Write layered Action data. */
write_strip_keyframe_data_array(writer, action.strip_keyframe_data());
write_layers(writer, action.layers());
@ -560,7 +539,6 @@ static void action_blend_write(BlendWriter *writer, ID *id, const void *id_addre
action_blend_write_clear_legacy_channel_groups_listbase(action.groups);
action_blend_write_clear_legacy_fcurves_listbase(action.curves);
}
#endif /* WITH_ANIM_BAKLAVA */
/* Write legacy F-Curves & Groups. */
BKE_fcurve_blend_write_listbase(writer, &action.curves);
@ -575,8 +553,6 @@ static void action_blend_write(BlendWriter *writer, ID *id, const void *id_addre
BKE_previewimg_blend_write(writer, action.preview);
}
#ifdef WITH_ANIM_BAKLAVA
static void read_channelbag(BlendDataReader *reader, animrig::ChannelBag &channelbag)
{
BLO_read_pointer_array(
@ -680,7 +656,6 @@ static void read_slots(BlendDataReader *reader, animrig::Action &action)
action.slot_array[i]->wrap().blend_read_post();
}
}
#endif /* WITH_ANIM_BAKLAVA */
static void action_blend_read_data(BlendDataReader *reader, ID *id)
{
@ -693,21 +668,9 @@ static void action_blend_read_data(BlendDataReader *reader, ID *id)
BLI_endian_switch_int16(reinterpret_cast<short *>(&act->idroot));
}
#ifdef WITH_ANIM_BAKLAVA
read_strip_keyframe_data_array(reader, action);
read_layers(reader, action);
read_slots(reader, action);
#else
/* Built without Baklava, so do not read the layers, strips, slots, etc.
* This ensures the F-Curves in the legacy `curves` ListBase are read & used
* (these are written by future Blender versions for forward compatibility). */
action.layer_array = nullptr;
action.layer_array_num = 0;
action.slot_array = nullptr;
action.slot_array_num = 0;
action.strip_keyframe_data_array = nullptr;
action.strip_keyframe_data_array_num = 0;
#endif /* WITH_ANIM_BAKLAVA */
if (action.is_action_layered()) {
/* Clear the forward-compatible storage (see action_blend_write_data()). */
@ -731,12 +694,6 @@ static void action_blend_read_data(BlendDataReader *reader, ID *id)
LISTBASE_FOREACH (bActionGroup *, agrp, &action.groups) {
BLO_read_struct(reader, FCurve, &agrp->channels.first);
BLO_read_struct(reader, FCurve, &agrp->channels.last);
#ifndef WITH_ANIM_BAKLAVA
/* Ensure that the group's 'channelbag' pointer is nullptr. This is used to distinguish
* groups from legacy vs layered Actions, and since this Blender is built without layered
* Actions support, the Action should be treated as legacy. */
agrp->channel_bag = nullptr;
#endif
}
}

View file

@ -49,15 +49,12 @@
#include "RNA_access.hh"
#include "RNA_path.hh"
#include "ANIM_action.hh"
#include "ANIM_action_iterators.hh"
#include "ANIM_action_legacy.hh"
#include "CLG_log.h"
#ifdef WITH_ANIM_BAKLAVA
# include "ANIM_action.hh"
#endif // WITH_ANIM_BAKLAVA
static CLG_LogRef LOG = {"bke.anim_sys"};
using namespace blender;
@ -214,11 +211,7 @@ bool BKE_animdata_set_action(ReportList *reports, ID *id, bAction *act)
return false;
}
#ifdef WITH_ANIM_BAKLAVA
return animrig::assign_action(act, {*id, *adt});
#else
return animdata_set_action(reports, id, &adt->action, act);
#endif // WITH_ANIM_BAKLAVA
}
bool BKE_animdata_action_editable(const AnimData *adt)
@ -238,7 +231,6 @@ bool BKE_animdata_action_ensure_idroot(const ID *owner, bAction *action)
return true;
}
#ifdef WITH_ANIM_BAKLAVA
if (!blender::animrig::legacy::action_treat_as_legacy(*action)) {
/* TODO: for layered Actions, this function doesn't make sense. Once all Actions are
* auto-versioned to layered Actions, this entire function can be removed. */
@ -247,7 +239,6 @@ bool BKE_animdata_action_ensure_idroot(const ID *owner, bAction *action)
* that are specialized. */
return true;
}
#endif
if (action->idroot == 0) {
/* First time this Action is assigned, lock it to this ID type. */
@ -278,26 +269,18 @@ void BKE_animdata_free(ID *id, const bool do_id_user)
BKE_nla_tweakmode_exit({*id, *adt});
if (adt->action) {
#ifdef WITH_ANIM_BAKLAVA
const bool unassign_ok = blender::animrig::unassign_action(*id);
BLI_assert_msg(unassign_ok,
"Expecting action un-assignment to always work when not in NLA tweak mode");
UNUSED_VARS_NDEBUG(unassign_ok);
#else
id_us_min(&adt->action->id);
#endif
}
/* same goes for the temporarily displaced action */
if (adt->tmpact) {
#ifdef WITH_ANIM_BAKLAVA
/* This should never happen, as we _just_ exited tweak mode. */
BLI_assert_unreachable();
const bool unassign_ok = blender::animrig::assign_tmpaction(nullptr, {*id, *adt});
BLI_assert_msg(unassign_ok, "Expecting tmpaction un-assignment to always work");
UNUSED_VARS_NDEBUG(unassign_ok);
#else
id_us_min(&adt->tmpact->id);
#endif
}
}
@ -735,15 +718,12 @@ void BKE_animdata_transfer_by_basepath(Main *bmain, ID *srcID, ID *dstID, ListBa
* can be easily found again. */
if (!dstAdt->action) {
animrig::Action &new_action = animrig::action_add(*bmain, srcAdt->action->id.name + 2);
if (USER_EXPERIMENTAL_TEST(&U, use_animation_baklava)) {
new_action.slot_add_for_id(*dstID);
}
new_action.slot_add_for_id(*dstID);
const bool assign_ok = animrig::assign_action(&new_action, dst_owned_adt);
BLI_assert_msg(assign_ok, "Expected Action assignment to work");
UNUSED_VARS_NDEBUG(assign_ok);
if (USER_EXPERIMENTAL_TEST(&U, use_animation_baklava)) {
BLI_assert(dstAdt->slot_handle != animrig::Slot::unassigned);
}
BLI_assert(dstAdt->slot_handle != animrig::Slot::unassigned);
}
/* loop over base paths, trying to fix for each one... */

View file

@ -796,7 +796,6 @@ static void action_idcode_patch_check(ID *id, bAction *act)
return;
}
#ifdef WITH_ANIM_BAKLAVA
if (!blender::animrig::legacy::action_treat_as_legacy(*act)) {
/* Layered Actions can always be assigned to any ID. It's actually the Slot that is limited
* to an ID type (similar to legacy Actions). Layered Actions are evaluated differently,
@ -805,7 +804,6 @@ static void action_idcode_patch_check(ID *id, bAction *act)
/* TODO: when possible, add a BLI_assert_unreachable() here. */
return;
}
#endif
idcode = GS(id->name);
@ -863,24 +861,20 @@ void animsys_evaluate_action_group(PointerRNA *ptr,
}
};
#ifdef WITH_ANIM_BAKLAVA
blender::animrig::ChannelGroup channel_group = agrp->wrap();
if (channel_group.is_legacy()) {
#endif
/* calculate then execute each curve */
for (fcu = static_cast<FCurve *>(agrp->channels.first); (fcu) && (fcu->grp == agrp);
fcu = fcu->next)
{
visit_fcurve(fcu);
}
#ifdef WITH_ANIM_BAKLAVA
return;
}
for (FCurve *fcurve : channel_group.fcurves()) {
visit_fcurve(fcurve);
}
#endif
}
void animsys_evaluate_action(PointerRNA *ptr,

View file

@ -584,9 +584,8 @@ class AnimDataConvertor {
animrig::Action &action = animrig::action_add(
this->conversion_data.bmain,
this->animdata_src->action ? this->animdata_src->action->id.name + 2 : nullptr);
if (USER_EXPERIMENTAL_TEST(&U, use_animation_baklava)) {
action.slot_add_for_id(this->id_dst);
}
action.slot_add_for_id(this->id_dst);
const bool ok = animrig::assign_action(&action, {this->id_dst, *this->animdata_dst});
BLI_assert_msg(ok, "Expecting action assignment to work when converting Grease Pencil");
UNUSED_VARS_NDEBUG(ok);
@ -603,9 +602,8 @@ class AnimDataConvertor {
animrig::Action &tmpact = animrig::action_add(
this->conversion_data.bmain,
this->animdata_src->tmpact ? this->animdata_src->tmpact->id.name + 2 : nullptr);
if (USER_EXPERIMENTAL_TEST(&U, use_animation_baklava)) {
tmpact.slot_add_for_id(this->id_dst);
}
tmpact.slot_add_for_id(this->id_dst);
const bool ok = animrig::assign_tmpaction(&tmpact, {this->id_dst, *this->animdata_dst});
BLI_assert_msg(ok, "Expecting tmpact assignment to work when converting Grease Pencil");
UNUSED_VARS_NDEBUG(ok);

View file

@ -1255,9 +1255,7 @@ void do_versions_after_linking_400(FileData *fd, Main *bmain)
version_node_socket_index_animdata(bmain, NTREE_SHADER, SH_NODE_BSDF_PRINCIPLED, 7, 1, 30);
}
/* Keeping this block is without a `MAIN_VERSION_FILE_ATLEAST` until the experimental flag is
* removed. */
if (USER_EXPERIMENTAL_TEST(&U, use_animation_baklava)) {
if (!MAIN_VERSION_FILE_ATLEAST(bmain, 404, 2)) {
version_legacy_actions_to_layered(bmain);
}

View file

@ -166,10 +166,6 @@ if(WITH_PYTHON)
)
endif()
if(WITH_EXPERIMENTAL_FEATURES)
add_definitions(-DWITH_ANIM_BAKLAVA)
endif()
blender_add_lib(bf_depsgraph "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
add_library(bf::depsgraph ALIAS bf_depsgraph)

View file

@ -1702,7 +1702,6 @@ void DepsgraphRelationBuilder::build_animdata_action_targets(ID *id,
return;
}
#ifdef WITH_ANIM_BAKLAVA
const animrig::Slot *slot = action.slot_for_handle(slot_handle);
if (slot == nullptr) {
/* If there's no matching slot, there's no Action dependency. */
@ -1729,9 +1728,6 @@ void DepsgraphRelationBuilder::build_animdata_action_targets(ID *id,
}
}
}
#else
UNUSED_VARS(slot_handle);
#endif
}
void DepsgraphRelationBuilder::build_animdata_nlastrip_targets(ID *id,
@ -1843,13 +1839,6 @@ void DepsgraphRelationBuilder::build_action(bAction *dna_action)
build_idproperties(dna_action->id.properties);
blender::animrig::Action &action = dna_action->wrap();
#ifndef WITH_ANIM_BAKLAVA
/* Prevent evaluation of data introduced by Project Baklava. */
if (action.is_action_layered()) {
return;
}
#endif
if (!action.is_empty()) {
TimeSourceKey time_src_key;
ComponentKey animation_key(&dna_action->id, NodeType::ANIMATION);

View file

@ -55,10 +55,6 @@ if(WITH_PYTHON)
add_definitions(-DWITH_PYTHON)
endif()
if(WITH_EXPERIMENTAL_FEATURES)
add_definitions(-DWITH_ANIM_BAKLAVA)
endif()
blender_add_lib(bf_editor_animation "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
# RNA_prototypes.hh

View file

@ -1303,8 +1303,6 @@ static bAnimChannelType ACF_NLACURVE = {
/* Object Animation Expander ------------------------------------------- */
#ifdef WITH_ANIM_BAKLAVA
/* TODO: just get this from RNA? */
static int acf_fillanim_icon(bAnimListElem * /*ale*/)
{
@ -1493,8 +1491,6 @@ static bAnimChannelType ACF_ACTION_SLOT = {
/*setting_ptr*/ acf_action_slot_setting_ptr,
};
#endif // WITH_ANIM_BAKLAVA
/* Object Action Expander ------------------------------------------- */
/* TODO: just get this from RNA? */
@ -4542,13 +4538,8 @@ static void ANIM_init_channel_typeinfo_data()
animchannelTypeInfo[type++] = &ACF_NLACONTROLS; /* NLA Control FCurve Expander */
animchannelTypeInfo[type++] = &ACF_NLACURVE; /* NLA Control FCurve Channel */
#ifdef WITH_ANIM_BAKLAVA
animchannelTypeInfo[type++] = &ACF_FILLANIM; /* Object's Layered Action Expander */
animchannelTypeInfo[type++] = &ACF_ACTION_SLOT; /* Action Slot Expander */
#else
animchannelTypeInfo[type++] = nullptr;
animchannelTypeInfo[type++] = nullptr;
#endif
animchannelTypeInfo[type++] = &ACF_FILLACTD; /* Object Action Expander */
animchannelTypeInfo[type++] = &ACF_FILLDRIVERS; /* Drivers Expander */
@ -4589,12 +4580,10 @@ static void ANIM_init_channel_typeinfo_data()
animchannelTypeInfo[type++] = &ACF_NLATRACK; /* NLA Track */
animchannelTypeInfo[type++] = &ACF_NLAACTION; /* NLA Action */
#ifdef WITH_ANIM_BAKLAVA
BLI_assert_msg(animchannelTypeInfo[ANIMTYPE_FILLACT_LAYERED] == &ACF_FILLANIM,
"ANIMTYPE_FILLACT_LAYERED does not match ACF_FILLANIM");
BLI_assert_msg(animchannelTypeInfo[ANIMTYPE_ACTION_SLOT] == &ACF_ACTION_SLOT,
"ANIMTYPE_ACTION_SLOT does not match ACF_ACTION_SLOT");
#endif
}
}
@ -6069,13 +6058,11 @@ void ANIM_channel_draw_widgets(const bContext *C,
UI_block_emboss_set(block, UI_EMBOSS_NONE);
}
#ifdef WITH_ANIM_BAKLAVA
/* Slot ID type indicator. */
if (ale->type == ANIMTYPE_ACTION_SLOT) {
offset -= ICON_WIDTH;
UI_icon_draw(offset, ymid, acf_action_slot_idtype_icon(ale));
}
#endif /* WITH_ANIM_BAKLAVA */
}
/* Draw slider:

View file

@ -5187,8 +5187,6 @@ static void ANIM_OT_channels_bake(wmOperatorType *ot)
"Bake Modifiers into keyframes and delete them after");
}
#ifdef WITH_ANIM_BAKLAVA
static int slot_channels_move_to_new_action_exec(bContext *C, wmOperator * /* op */)
{
using namespace blender::animrig;
@ -5348,8 +5346,6 @@ static void ANIM_OT_separate_slots(wmOperatorType *ot)
ot->flag = OPTYPE_REGISTER | OPTYPE_UNDO;
}
#endif /* WITH_ANIM_BAKLAVA */
/**
* Find a Graph Editor area and set the context arguments accordingly.
*/
@ -5732,10 +5728,8 @@ void ED_operatortypes_animchannels()
WM_operatortype_append(ANIM_OT_channels_bake);
#ifdef WITH_ANIM_BAKLAVA
WM_operatortype_append(ANIM_OT_slot_channels_move_to_new_action);
WM_operatortype_append(ANIM_OT_separate_slots);
#endif
}
void ED_keymap_animchannels(wmKeyConfig *keyconf)

View file

@ -445,12 +445,8 @@ bool ANIM_animdata_can_have_greasepencil(const eAnimCont_Types type)
#define ANIMDATA_HAS_ACTION_LEGACY(id) \
((id)->adt && (id)->adt->action && (id)->adt->action->wrap().is_action_legacy())
#ifdef WITH_ANIM_BAKLAVA
# define ANIMDATA_HAS_ACTION_LAYERED(id) \
((id)->adt && (id)->adt->action && (id)->adt->action->wrap().is_action_layered())
#else
# define ANIMDATA_HAS_ACTION_LAYERED(id) false
#endif
#define ANIMDATA_HAS_ACTION_LAYERED(id) \
((id)->adt && (id)->adt->action && (id)->adt->action->wrap().is_action_layered())
/* quick macro to test if AnimData is usable for drivers */
#define ANIMDATA_HAS_DRIVERS(id) ((id)->adt && (id)->adt->drivers.first)

View file

@ -774,9 +774,7 @@ void ED_add_action_channel(ChannelDrawList *channel_list,
float yscale_fac,
int saction_flag)
{
#ifdef WITH_ANIM_BAKLAVA
BLI_assert(!act || act->wrap().is_action_legacy());
#endif
const bool locked = (act && (!ID_IS_EDITABLE(act) || ID_IS_OVERRIDE_LIBRARY(act)));
saction_flag &= ~SACTION_SHOW_EXTREMES;

View file

@ -179,8 +179,6 @@ static short agrp_keyframes_loop(KeyframeEditData *ked,
return 0;
}
#ifdef WITH_ANIM_BAKLAVA
/* Loop over all keyframes in the layered Action. */
static short action_layered_keyframes_loop(KeyframeEditData *ked,
animrig::Action &action,
@ -203,8 +201,6 @@ static short action_layered_keyframes_loop(KeyframeEditData *ked,
return 0;
}
#endif
/* This function is used to loop over the keyframe data in an Action */
static short action_legacy_keyframes_loop(KeyframeEditData *ked,
bAction *act,
@ -430,26 +426,18 @@ short ANIM_animchannel_keyframes_loop(KeyframeEditData *ked,
case ALE_GROUP: /* action group */
return agrp_keyframes_loop(ked, (bActionGroup *)ale->data, key_ok, key_cb, fcu_cb);
case ALE_ACTION_LAYERED: { /* Layered Action. */
#ifdef WITH_ANIM_BAKLAVA
/* This assumes that the ALE_ACTION_LAYERED channel is shown in the dopesheet context,
* underneath the data-block that owns `ale->adt`. So that means that the loop is limited to
* the keys that belong to that slot. */
animrig::Action &action = static_cast<bAction *>(ale->key_data)->wrap();
animrig::Slot *slot = action.slot_for_handle(ale->adt->slot_handle);
return action_layered_keyframes_loop(ked, action, slot, key_ok, key_cb, fcu_cb);
#else
return 0;
#endif
}
case ALE_ACTION_SLOT: {
#ifdef WITH_ANIM_BAKLAVA
animrig::Action *action = static_cast<animrig::Action *>(ale->key_data);
BLI_assert(action);
animrig::Slot *slot = static_cast<animrig::Slot *>(ale->data);
return action_layered_keyframes_loop(ked, *action, slot, key_ok, key_cb, fcu_cb);
#else
return 0;
#endif
}
case ALE_ACT: /* Legacy Action. */

View file

@ -128,10 +128,6 @@ if(WITH_INPUT_IME)
add_definitions(-DWITH_INPUT_IME)
endif()
if(WITH_EXPERIMENTAL_FEATURES)
add_definitions(-DWITH_ANIM_BAKLAVA)
endif()
blender_add_lib(bf_editor_interface "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
# RNA_prototypes.hh

View file

@ -458,17 +458,13 @@ void ui_rna_collection_search_update_fn(
has_sep_char = ID_IS_LINKED(id);
}
}
#ifdef WITH_ANIM_BAKLAVA
else if (itemptr.type == &RNA_ActionSlot) {
PropertyRNA *prop = RNA_struct_find_property(&itemptr, "name_display");
name = RNA_property_string_get_alloc(&itemptr, prop, name_buf, sizeof(name_buf), nullptr);
}
else {
#endif /* WITH_ANIM_BAKLAVA */
name = RNA_struct_name_get_alloc(&itemptr, name_buf, sizeof(name_buf), nullptr);
#ifdef WITH_ANIM_BAKLAVA
}
#endif /* WITH_ANIM_BAKLAVA */
if (name) {
auto cis = std::make_unique<CollItemSearch>();

View file

@ -2205,16 +2205,12 @@ static void template_search_add_button_name(uiBlock *block,
}
PropertyRNA *name_prop;
#ifdef WITH_ANIM_BAKLAVA
if (type == &RNA_ActionSlot) {
name_prop = RNA_struct_find_property(active_ptr, "name_display");
}
else {
#endif /* WITH_ANIM_BAKLAVA */
name_prop = RNA_struct_name_property(type);
#ifdef WITH_ANIM_BAKLAVA
}
#endif /* WITH_ANIM_BAKLAVA */
const int width = template_search_textbut_width(active_ptr, name_prop);
const int height = template_search_textbut_height();

View file

@ -41,10 +41,6 @@ set(LIB
PRIVATE bf::animrig
)
if(WITH_EXPERIMENTAL_FEATURES)
add_definitions(-DWITH_ANIM_BAKLAVA)
endif()
blender_add_lib(bf_editor_space_action "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
# RNA_prototypes.hh dna_type_offsets.h

View file

@ -39,10 +39,6 @@ set(LIB
PRIVATE bf::intern::guardedalloc
)
if(WITH_EXPERIMENTAL_FEATURES)
add_definitions(-DWITH_ANIM_BAKLAVA)
endif()
blender_add_lib(bf_editor_space_nla "${SRC}" "${INC}" "${INC_SYS}" "${LIB}")
# RNA_prototypes.hh dna_type_offsets.h

View file

@ -483,7 +483,6 @@ static void nla_panel_actclip(const bContext *C, Panel *panel)
column = uiLayoutColumn(layout, true);
uiItemR(column, &strip_ptr, "action", UI_ITEM_NONE, nullptr, ICON_ACTION);
#ifdef WITH_ANIM_BAKLAVA
NlaStrip *strip = static_cast<NlaStrip *>(strip_ptr.data);
if (strip->act) {
BLI_assert(strip_ptr.owner_id);
@ -505,7 +504,6 @@ static void nla_panel_actclip(const bContext *C, Panel *panel)
"Slot");
}
}
#endif
/* action extents */
column = uiLayoutColumn(layout, true);

View file

@ -759,9 +759,8 @@ typedef struct UserDef_Experimental {
char use_new_volume_nodes;
char use_new_file_import_nodes;
char use_shader_node_previews;
char use_animation_baklava;
char enable_new_cpu_compositor;
char _pad[2];
char _pad[3];
/** `makesdna` does not allow empty structs. */
} UserDef_Experimental;

View file

@ -110,7 +110,6 @@ endif()
if(WITH_EXPERIMENTAL_FEATURES)
add_definitions(-DWITH_SIMULATION_DATABLOCK)
add_definitions(-DWITH_ANIM_BAKLAVA)
endif()
set(APISRC

View file

@ -34,7 +34,6 @@
using namespace blender;
#ifdef WITH_ANIM_BAKLAVA
const EnumPropertyItem rna_enum_layer_mix_mode_items[] = {
{int(animrig::Layer::MixMode::Replace),
"REPLACE",
@ -72,7 +71,6 @@ const EnumPropertyItem rna_enum_strip_type_items[] = {
"Strip containing keyframes on F-Curves"},
{0, nullptr, 0, nullptr, nullptr},
};
#endif /* WITH_ANIM_BAKLAVA */
/* Cannot use rna_enum_dummy_DEFAULT_items because the UNSPECIFIED entry needs
* to exist as it is the default. */
@ -116,8 +114,6 @@ static animrig::Action &rna_action(const PointerRNA *ptr)
return reinterpret_cast<bAction *>(ptr->owner_id)->wrap();
}
# ifdef WITH_ANIM_BAKLAVA
static animrig::Slot &rna_data_slot(const PointerRNA *ptr)
{
BLI_assert(ptr->type == &RNA_ActionSlot);
@ -374,7 +370,7 @@ static void rna_ActionSlot_name_update(Main *bmain, Scene *, PointerRNA *ptr)
action.slot_name_propagate(*bmain, slot);
}
# ifndef NDEBUG
# ifndef NDEBUG
static void rna_ActionSlot_debug_log_users(const ID *action_id, ActionSlot *dna_slot, Main *bmain)
{
using namespace blender::animrig;
@ -395,7 +391,7 @@ static void rna_ActionSlot_debug_log_users(const ID *action_id, ActionSlot *dna_
printf(" - %s\n", user->name);
}
}
# endif /* NDEBUG */
# endif /* NDEBUG */
static std::optional<std::string> rna_ActionLayer_path(const PointerRNA *ptr)
{
@ -738,8 +734,6 @@ static ActionChannelBag *rna_ActionStrip_channels(ID *dna_action_id,
return strip_data.channelbag_for_slot(slot_handle);
}
# endif // WITH_ANIM_BAKLAVA
/**
* Iterator for the fcurves in a channel group.
*
@ -858,7 +852,6 @@ static PointerRNA rna_ActionGroup_channels_get(CollectionPropertyIterator *iter)
return rna_pointer_inherit_refine(&iter->parent, &RNA_FCurve, fcurve);
}
# ifdef WITH_ANIM_BAKLAVA
/* Use the backward-compatible API only when we're working with the action as a
* layered action. */
static bool use_backward_compatible_api(animrig::Action &action)
@ -927,13 +920,10 @@ static int rna_iterator_Action_groups_length(PointerRNA *ptr)
return BLI_listbase_count(&action.groups);
}
# endif /* WITH_ANIM_BAKLAVA */
static bActionGroup *rna_Action_groups_new(bAction *act, const char name[])
{
bActionGroup *group;
# ifdef WITH_ANIM_BAKLAVA
animrig::Action &action = act->wrap();
if (use_backward_compatible_api(action)) {
animrig::ChannelBag &channelbag = animrig::legacy::channelbag_ensure(action);
@ -942,9 +932,6 @@ static bActionGroup *rna_Action_groups_new(bAction *act, const char name[])
else {
group = action_groups_add_new(act, name);
}
# else
group = action_groups_add_new(act, name);
# endif
/* I (Sybren) expected that the commented-out notifier below was missing.
* However, the animation filtering code (`animfilter_act_group()`) hides
@ -961,7 +948,6 @@ static void rna_Action_groups_remove(bAction *act, ReportList *reports, PointerR
bActionGroup *agrp = static_cast<bActionGroup *>(agrp_ptr->data);
BLI_assert(agrp); /* Ensured by RNA flag PROP_NEVER_NULL. */
# ifdef WITH_ANIM_BAKLAVA
animrig::Action &action = act->wrap();
if (use_backward_compatible_api(action)) {
animrig::ChannelBag *channelbag = animrig::legacy::channelbag_get(action);
@ -979,7 +965,6 @@ static void rna_Action_groups_remove(bAction *act, ReportList *reports, PointerR
return;
}
# endif
FCurve *fcu, *fcn;
@ -1011,7 +996,6 @@ static void rna_Action_groups_remove(bAction *act, ReportList *reports, PointerR
WM_main_add_notifier(NC_ANIMATION | ND_KEYFRAME | NA_EDITED, nullptr);
}
# ifdef WITH_ANIM_BAKLAVA
static void rna_iterator_Action_fcurves_begin(CollectionPropertyIterator *iter, PointerRNA *ptr)
{
animrig::Action &action = rna_action(ptr);
@ -1073,8 +1057,6 @@ static int rna_iterator_Action_fcurves_length(PointerRNA *ptr)
return BLI_listbase_count(&action.curves);
}
# endif // WITH_ANIM_BAKLAVA
static FCurve *rna_Action_fcurve_new(bAction *act,
Main *bmain,
ReportList *reports,
@ -1093,7 +1075,6 @@ static FCurve *rna_Action_fcurve_new(bAction *act,
fcurve_descriptor.channel_group = group;
}
# ifdef WITH_ANIM_BAKLAVA
animrig::Action &action = act->wrap();
if (use_backward_compatible_api(action)) {
/* Add the F-Curve to the channelbag for the first slot. */
@ -1115,7 +1096,6 @@ static FCurve *rna_Action_fcurve_new(bAction *act,
return fcurve;
}
# endif
/* Annoying, check if this exists. */
if (blender::animrig::fcurve_find_in_action(act, fcurve_descriptor)) {
@ -1145,7 +1125,6 @@ static FCurve *rna_Action_fcurve_find(bAction *act,
return nullptr;
}
# ifdef WITH_ANIM_BAKLAVA
animrig::Action &action = act->wrap();
if (use_backward_compatible_api(action)) {
animrig::ChannelBag *channelbag = animrig::legacy::channelbag_get(action);
@ -1154,7 +1133,6 @@ static FCurve *rna_Action_fcurve_find(bAction *act,
}
return channelbag->fcurve_find({data_path, index});
}
# endif
/* Returns nullptr if not found. */
return animrig::fcurve_find_in_action(act, {data_path, index});
@ -1164,7 +1142,6 @@ static void rna_Action_fcurve_remove(bAction *act, ReportList *reports, PointerR
{
FCurve *fcu = static_cast<FCurve *>(fcu_ptr->data);
# ifdef WITH_ANIM_BAKLAVA
animrig::Action &action = act->wrap();
if (use_backward_compatible_api(action)) {
animrig::ChannelBag *channelbag = animrig::legacy::channelbag_get(action);
@ -1183,7 +1160,6 @@ static void rna_Action_fcurve_remove(bAction *act, ReportList *reports, PointerR
return;
}
# endif
if (fcu->grp) {
if (BLI_findindex(&act->groups, fcu->grp) == -1) {
@ -1216,7 +1192,6 @@ static void rna_Action_fcurve_remove(bAction *act, ReportList *reports, PointerR
static void rna_Action_fcurve_clear(bAction *act)
{
# ifdef WITH_ANIM_BAKLAVA
animrig::Action &action = act->wrap();
if (use_backward_compatible_api(action)) {
animrig::ChannelBag *channelbag = animrig::legacy::channelbag_get(action);
@ -1229,9 +1204,6 @@ static void rna_Action_fcurve_clear(bAction *act)
else {
BKE_action_fcurves_clear(act);
}
# else
BKE_action_fcurves_clear(act);
# endif
WM_main_add_notifier(NC_ANIMATION | ND_KEYFRAME | NA_EDITED, nullptr);
}
@ -1300,7 +1272,6 @@ static void rna_Action_active_pose_marker_index_range(
*max = max_ii(0, BLI_listbase_count(&act->markers) - 1);
}
# ifdef WITH_ANIM_BAKLAVA
static bool rna_Action_is_empty_get(PointerRNA *ptr)
{
animrig::Action &action = rna_action(ptr);
@ -1314,7 +1285,6 @@ static bool rna_Action_is_action_layered_get(PointerRNA *ptr)
{
return rna_action(ptr).is_action_layered();
}
# endif // WITH_ANIM_BAKLAVA
static void rna_Action_frame_range_get(PointerRNA *ptr, float *r_values)
{
@ -1870,8 +1840,6 @@ static void rna_def_dopesheet(BlenderRNA *brna)
/* =========================== Layered Action interface =========================== */
# ifdef WITH_ANIM_BAKLAVA
static void rna_def_action_slots(BlenderRNA *brna, PropertyRNA *cprop)
{
StructRNA *srna;
@ -2045,7 +2013,7 @@ static void rna_def_action_slot(BlenderRNA *brna)
RNA_def_property_clear_flag(prop, PROP_ANIMATABLE);
RNA_def_property_update_notifier(prop, NC_ANIMATION | ND_ANIMCHAN | NA_SELECTED);
# ifndef NDEBUG
# ifndef NDEBUG
/* Slot.debug_log_users() */
{
FunctionRNA *func;
@ -2053,7 +2021,7 @@ static void rna_def_action_slot(BlenderRNA *brna)
func = RNA_def_function(srna, "debug_log_users", "rna_ActionSlot_debug_log_users");
RNA_def_function_flag(func, FUNC_USE_SELF_ID | FUNC_USE_MAIN);
}
# endif
# endif
}
static void rna_def_ActionLayer_strips(BlenderRNA *brna, PropertyRNA *cprop)
@ -2443,7 +2411,6 @@ static void rna_def_action_channelbag(BlenderRNA *brna)
"Groupings of F-Curves for display purposes, in e.g. the dopesheet and graph editor");
rna_def_channelbag_groups(brna, prop);
}
# endif // WITH_ANIM_BAKLAVA
static void rna_def_action_group(BlenderRNA *brna)
{
@ -2535,7 +2502,6 @@ static void rna_def_action_groups(BlenderRNA *brna, PropertyRNA *cprop)
srna = RNA_def_struct(brna, "ActionGroups", nullptr);
RNA_def_struct_sdna(srna, "bAction");
RNA_def_struct_ui_text(srna, "Action Groups", "Collection of action groups");
# ifdef WITH_ANIM_BAKLAVA
RNA_def_property_collection_funcs(cprop,
"rna_iterator_Action_groups_begin",
"rna_iterator_Action_groups_next",
@ -2545,7 +2511,6 @@ static void rna_def_action_groups(BlenderRNA *brna, PropertyRNA *cprop)
nullptr,
nullptr,
nullptr);
# endif
func = RNA_def_function(srna, "new", "rna_Action_groups_new");
RNA_def_function_ui_description(func, "Create a new action group and add it to the action");
@ -2573,7 +2538,6 @@ static void rna_def_action_fcurves(BlenderRNA *brna, PropertyRNA *cprop)
srna = RNA_def_struct(brna, "ActionFCurves", nullptr);
RNA_def_struct_sdna(srna, "bAction");
RNA_def_struct_ui_text(srna, "Action F-Curves", "Collection of action F-Curves");
# ifdef WITH_ANIM_BAKLAVA
RNA_def_property_collection_funcs(cprop,
"rna_iterator_Action_fcurves_begin",
"rna_iterator_Action_fcurves_next",
@ -2583,7 +2547,6 @@ static void rna_def_action_fcurves(BlenderRNA *brna, PropertyRNA *cprop)
nullptr,
nullptr,
nullptr);
# endif
/* Action.fcurves.new(...) */
func = RNA_def_function(srna, "new", "rna_Action_fcurve_new");
@ -2716,7 +2679,6 @@ static void rna_def_action(BlenderRNA *brna)
RNA_def_struct_ui_text(srna, "Action", "A collection of F-Curves for animation");
RNA_def_struct_ui_icon(srna, ICON_ACTION);
# ifdef WITH_ANIM_BAKLAVA
/* Properties. */
prop = RNA_def_property(srna, "is_empty", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
@ -2740,11 +2702,8 @@ static void rna_def_action(BlenderRNA *brna)
"Return whether this is a layered Action. An empty Action considered "
"as both a 'layered' and a 'layered' Action.");
RNA_def_property_boolean_funcs(prop, "rna_Action_is_action_layered_get", nullptr);
# endif // WITH_ANIM_BAKLAVA
/* Collection properties. */
# ifdef WITH_ANIM_BAKLAVA
prop = RNA_def_property(srna, "slots", PROP_COLLECTION, PROP_NONE);
RNA_def_property_struct_type(prop, "ActionSlot");
RNA_def_property_collection_funcs(prop,
@ -2772,7 +2731,6 @@ static void rna_def_action(BlenderRNA *brna)
nullptr);
RNA_def_property_ui_text(prop, "Layers", "The list of layers that make up this Action");
rna_def_action_layers(brna, prop);
# endif // WITH_ANIM_BAKLAVA
prop = RNA_def_property(srna, "pose_markers", PROP_COLLECTION, PROP_NONE);
RNA_def_property_collection_sdna(prop, nullptr, "markers", nullptr);
@ -2872,12 +2830,10 @@ void RNA_def_action(BlenderRNA *brna)
rna_def_action_group(brna);
rna_def_dopesheet(brna);
# ifdef WITH_ANIM_BAKLAVA
rna_def_action_slot(brna);
rna_def_action_layer(brna);
rna_def_action_strip(brna);
rna_def_action_channelbag(brna);
# endif
}
#endif

View file

@ -12,8 +12,7 @@
#pragma once
#ifdef WITH_ANIM_BAKLAVA
# ifdef RNA_RUNTIME
#ifdef RNA_RUNTIME
/**
* Get the Action slot, given this slot handle.
@ -54,5 +53,4 @@ void rna_generic_action_slot_handle_set(blender::animrig::slot_handle_t slot_han
void rna_iterator_generic_action_slots_begin(CollectionPropertyIterator *iter,
bAction *assigned_action);
# endif /* RNA_RUNTIME */
#endif /* WITH_ANIM_BAKLAVA */
#endif /* RNA_RUNTIME */

View file

@ -165,7 +165,6 @@ static PointerRNA rna_AnimData_action_get(PointerRNA *ptr)
static void rna_AnimData_action_set(PointerRNA *ptr, PointerRNA value, ReportList *reports)
{
# ifdef WITH_ANIM_BAKLAVA
using namespace blender::animrig;
BLI_assert(ptr->owner_id);
ID &animated_id = *ptr->owner_id;
@ -174,11 +173,6 @@ static void rna_AnimData_action_set(PointerRNA *ptr, PointerRNA value, ReportLis
if (!assign_action(action, animated_id)) {
BKE_report(reports, RPT_ERROR, "Could not change action");
}
UNUSED_VARS(reports);
# else
ID *ownerId = ptr->owner_id;
BKE_animdata_set_action(reports, ownerId, static_cast<bAction *>(value.data));
# endif
}
static void rna_AnimData_tmpact_set(PointerRNA *ptr, PointerRNA value, ReportList *reports)
@ -231,7 +225,6 @@ bool rna_AnimData_tweakmode_override_apply(Main * /*bmain*/,
return true;
}
# ifdef WITH_ANIM_BAKLAVA
void rna_generic_action_slot_handle_set(blender::animrig::slot_handle_t slot_handle_to_assign,
ID &animated_id,
bAction *&action_ptr_ref,
@ -407,8 +400,6 @@ static void rna_iterator_animdata_action_slots_begin(CollectionPropertyIterator
rna_iterator_generic_action_slots_begin(iter, rna_animdata(ptr).action);
}
# endif /* WITH_ANIM_BAKLAVA */
/* ****************************** */
/* wrapper for poll callback */
@ -1000,12 +991,11 @@ bool rna_AnimaData_override_apply(Main *bmain, RNAPropertyOverrideApplyContext &
adt_dst->action = adt_src->action;
id_us_plus(reinterpret_cast<ID *>(adt_dst->action));
id_us_min(reinterpret_cast<ID *>(adt_dst->tmpact));
# ifdef WITH_ANIM_BAKLAVA
adt_dst->slot_handle = adt_src->slot_handle;
adt_dst->tmp_slot_handle = adt_src->tmp_slot_handle;
STRNCPY(adt_dst->slot_name, adt_src->slot_name);
STRNCPY(adt_dst->tmp_slot_name, adt_src->tmp_slot_name);
# endif
adt_dst->tmpact = adt_src->tmpact;
id_us_plus(reinterpret_cast<ID *>(adt_dst->tmpact));
adt_dst->act_blendmode = adt_src->act_blendmode;
@ -1687,7 +1677,6 @@ static void rna_def_animdata(BlenderRNA *brna)
RNA_def_property_ui_text(prop, "Pin in Graph Editor", "");
RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, nullptr);
# ifdef WITH_ANIM_BAKLAVA
/* This property is not necessary for the Python API (that is better off using
* slot references/pointers directly), but it is needed for library overrides
* to work. */
@ -1746,7 +1735,6 @@ static void rna_def_animdata(BlenderRNA *brna)
nullptr,
nullptr);
RNA_def_property_ui_text(prop, "Slots", "The list of slots in this animation data-block");
# endif /* WITH_ANIM_BAKLAVA */
RNA_define_lib_overridable(false);

View file

@ -29,10 +29,8 @@
#include "ED_object.hh"
#ifdef WITH_ANIM_BAKLAVA
# include "ANIM_action.hh"
# include "rna_action_tools.hh"
#endif
#include "ANIM_action.hh"
#include "rna_action_tools.hh"
/* Please keep the names in sync with `constraint.cc`. */
const EnumPropertyItem rna_enum_constraint_type_items[] = {
@ -773,7 +771,6 @@ static void rna_ActionConstraint_action_set(PointerRNA *ptr, PointerRNA value, R
}
}
# ifdef WITH_ANIM_BAKLAVA
static void rna_ActionConstraint_action_slot_handle_set(
PointerRNA *ptr, const blender::animrig::slot_handle_t new_slot_handle)
{
@ -814,7 +811,6 @@ static void rna_iterator_ActionConstraint_action_slots_begin(CollectionPropertyI
rna_iterator_generic_action_slots_begin(iter, acon->act);
}
# endif /* WITH_ANIM_BAKLAVA */
static int rna_SplineIKConstraint_joint_bindings_get_length(const PointerRNA *ptr,
int length[RNA_MAX_ARRAY_DIMENSION])
@ -1969,7 +1965,6 @@ static void rna_def_constraint_action(BlenderRNA *brna)
RNA_def_property_flag(prop, PROP_EDITABLE);
RNA_def_property_update(prop, NC_OBJECT | ND_CONSTRAINT, "rna_Constraint_update");
# ifdef WITH_ANIM_BAKLAVA
/* This property is not necessary for the Python API (that is better off using
* slot references/pointers directly), but it is needed for library overrides
* to work. */
@ -2032,7 +2027,6 @@ static void rna_def_constraint_action(BlenderRNA *brna)
nullptr);
RNA_def_property_ui_text(
prop, "Action Slots", "The list of action slots suitable for this NLA strip");
# endif /* WITH_ANIM_BAKLAVA */
prop = RNA_def_property(srna, "use_bone_object_action", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, nullptr, "flag", ACTCON_BONE_USE_OBJECT_ACTION);

View file

@ -12,10 +12,8 @@
#include "DNA_anim_types.h"
#include "DNA_scene_types.h"
#ifdef WITH_ANIM_BAKLAVA
# include "ANIM_action.hh"
# include "ANIM_nla.hh"
#endif
#include "ANIM_action.hh"
#include "ANIM_nla.hh"
#include "BLI_utildefines.h"
@ -484,7 +482,6 @@ static int rna_NlaStrip_action_editable(const PointerRNA *ptr, const char ** /*r
return PROP_EDITABLE;
}
# ifdef WITH_ANIM_BAKLAVA
static void rna_NlaStrip_action_slot_handle_set(
PointerRNA *ptr, const blender::animrig::slot_handle_t new_slot_handle)
{
@ -519,7 +516,6 @@ static void rna_iterator_nlastrip_action_slots_begin(CollectionPropertyIterator
NlaStrip *strip = (NlaStrip *)ptr->data;
rna_iterator_generic_action_slots_begin(iter, strip->act);
}
# endif /* WITH_ANIM_BAKLAVA */
static void rna_NlaStrip_action_start_frame_set(PointerRNA *ptr, float value)
{
@ -907,7 +903,6 @@ static void rna_def_nlastrip(BlenderRNA *brna)
RNA_def_property_update(
prop, NC_ANIMATION | ND_NLA | NA_EDITED, "rna_NlaStrip_dependency_update");
# ifdef WITH_ANIM_BAKLAVA
/* This property is not necessary for the Python API (that is better off using
* slot references/pointers directly), but it is needed for library overrides
* to work. */
@ -966,7 +961,6 @@ static void rna_def_nlastrip(BlenderRNA *brna)
nullptr);
RNA_def_property_ui_text(
prop, "Action Slots", "The list of action slots suitable for this NLA strip");
# endif /* WITH_ANIM_BAKLAVA */
/* Action extents */
prop = RNA_def_property(srna, "action_frame_start", PROP_FLOAT, PROP_TIME);

View file

@ -7590,20 +7590,6 @@ static void rna_def_userdef_experimental(BlenderRNA *brna)
"Recompute all ID usercounts before saving to a blendfile. Allows to "
"work around invalid usercount handling in code that may lead to loss "
"of data due to wrongly detected unused data-blocks");
prop = RNA_def_property(srna, "use_animation_baklava", PROP_BOOLEAN, PROP_NONE);
RNA_def_property_boolean_sdna(prop, nullptr, "use_animation_baklava", 1);
RNA_def_property_ui_text(
prop,
"Multi-Slot Actions",
"The new 'layered' Action can contain the animation for multiple data-blocks at once");
# ifndef WITH_ANIM_BAKLAVA
/* Only allow setting this to 'true' when actually built with Baklava. Some of the Baklava code
* is not guarded with `WITH_ANIM_BAKLAVA`, but rather assumes that this flag is always 'false'
* then. */
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
# endif
RNA_def_property_update(prop, 0, "rna_userdef_update");
}
static void rna_def_userdef_addon_collection(BlenderRNA *brna, PropertyRNA *cprop)

View file

@ -400,15 +400,12 @@ add_blender_test(
--testdir "${TEST_SRC_DIR}/animation"
)
if(WITH_EXPERIMENTAL_FEATURES)
# Only run with Project Baklava enabled.
add_blender_test(
bl_animation_action
--python ${CMAKE_CURRENT_LIST_DIR}/bl_animation_action.py
--
--testdir "${TEST_SRC_DIR}/animation"
)
endif()
add_blender_test(
bl_animation_action
--python ${CMAKE_CURRENT_LIST_DIR}/bl_animation_action.py
--
--testdir "${TEST_SRC_DIR}/animation"
)
add_blender_test(
bl_animation_keyframing

View file

@ -13,22 +13,11 @@ blender -b --factory-startup --python tests/python/bl_animation_action.py
"""
def enable_experimental_animation_baklava():
bpy.context.preferences.view.show_developer_ui = True
bpy.context.preferences.experimental.use_animation_baklava = True
def disable_experimental_animation_baklava():
bpy.context.preferences.view.show_developer_ui = False
bpy.context.preferences.experimental.use_animation_baklava = False
class ActionSlotAssignmentTest(unittest.TestCase):
"""Test assigning actions & check reference counts."""
def setUp(self) -> None:
bpy.ops.wm.read_homefile(use_factory_startup=True)
enable_experimental_animation_baklava()
def test_action_assignment(self):
# Create new Action.
@ -154,7 +143,6 @@ class LegacyAPIOnLayeredActionTest(unittest.TestCase):
def setUp(self) -> None:
bpy.ops.wm.read_homefile(use_factory_startup=True)
enable_experimental_animation_baklava()
self.action = bpy.data.actions.new('LayeredAction')
@ -251,35 +239,6 @@ class LegacyAPIOnLayeredActionTest(unittest.TestCase):
self.assertNotIn(group, channelbag.groups[:], "A group should be removable via the legacy API")
class TestLegacyLayered(unittest.TestCase):
"""Test boundaries between legacy & layered Actions.
Layered functionality should not be available on legacy actions.
"""
def test_legacy_action(self) -> None:
"""Test layered operations on a legacy Action"""
# Disable Baklava's backward-compatibility with the legacy API to create an actual legacy Action.
disable_experimental_animation_baklava()
act = bpy.data.actions.new('LegacyAction')
act.fcurves.new("location", index=0) # Add an FCurve to make this a non-empty legacy Action.
self.assertTrue(act.is_action_legacy)
self.assertFalse(act.is_action_layered)
self.assertFalse(act.is_empty)
# Adding a layer should be prevented.
with self.assertRaises(RuntimeError):
act.layers.new("laagje")
self.assertSequenceEqual([], act.layers)
# Adding a slot should be prevented.
with self.assertRaises(RuntimeError):
act.slots.new()
self.assertSequenceEqual([], act.slots)
class ChannelBagsTest(unittest.TestCase):
def setUp(self):
anims = bpy.data.actions
@ -435,12 +394,8 @@ class DataPathTest(unittest.TestCase):
class VersioningTest(unittest.TestCase):
def setUp(self):
enable_experimental_animation_baklava()
bpy.ops.wm.open_mainfile(filepath=str(args.testdir / "layered_action_versioning_42.blend"), load_ui=False)
def tearDown(self) -> None:
disable_experimental_animation_baklava()
def test_nla_conversion(self):
nla_object = bpy.data.objects["nla_object"]
nla_anim_data = nla_object.animation_data

View file

@ -13,16 +13,6 @@ blender -b --factory-startup --python tests/python/bl_animation_keyframing.py --
"""
def enable_experimental_animation_baklava():
bpy.context.preferences.view.show_developer_ui = True
bpy.context.preferences.experimental.use_animation_baklava = True
def disable_experimental_animation_baklava():
bpy.context.preferences.view.show_developer_ui = False
bpy.context.preferences.experimental.use_animation_baklava = False
def _fcurve_paths_match(fcurves: list, expected_paths: list) -> bool:
data_paths = list(set([fcurve.data_path for fcurve in fcurves]))
data_paths.sort()
@ -277,20 +267,6 @@ class InsertKeyTest(AbstractKeyframingTest, unittest.TestCase):
self.assertEqual(["Téšt"], [group.name for group in fgroups])
if hasattr(bpy.types, 'ActionSlot'):
# This test only makes sense when built with slotted/layered Actions.
class LayeredInsertKeyTest(InsertKeyTest):
@classmethod
def setUpClass(cls) -> None:
enable_experimental_animation_baklava()
super().setUpClass()
@classmethod
def tearDownClass(cls) -> None:
disable_experimental_animation_baklava()
super().tearDownClass()
class VisualKeyingTest(AbstractKeyframingTest, unittest.TestCase):
""" Check if visual keying produces the correct keyframe values. """
@ -696,6 +672,7 @@ def _create_nla_anim_object():
fcu.keyframe_points.insert(0, value=0).interpolation = 'LINEAR'
fcu.keyframe_points.insert(10, value=1).interpolation = 'LINEAR'
track.strips.new("base_strip", 0, action_base)
assert action_base.is_action_layered
track = anim_object.animation_data.nla_tracks.new()
track.name = "add"
@ -705,6 +682,7 @@ def _create_nla_anim_object():
fcu.keyframe_points.insert(10, value=1).interpolation = 'LINEAR'
strip = track.strips.new("add_strip", 0, action_add)
strip.blend_type = "ADD"
assert action_add.is_action_layered
track = anim_object.animation_data.nla_tracks.new()
track.name = "top"
@ -713,6 +691,7 @@ def _create_nla_anim_object():
fcu.keyframe_points.insert(0, value=0).interpolation = 'LINEAR'
fcu.keyframe_points.insert(10, value=0).interpolation = 'LINEAR'
track.strips.new("top_strip", 0, action_top)
assert action_top.is_action_layered
return anim_object
@ -734,6 +713,11 @@ class NlaInsertTest(AbstractKeyframingTest, unittest.TestCase):
area.type = "NLA_EDITOR"
break
# Deselect the default cube, because the NLA tests work on a specific
# object created for that test. Operators that work on all selected
# objects shouldn't work on anything else but that object.
bpy.ops.object.select_all(action='DESELECT')
def test_insert_failure(self):
# If the topmost track is set to "REPLACE" the system will fail
# when trying to insert keys into a layer beneath.
@ -762,6 +746,9 @@ class NlaInsertTest(AbstractKeyframingTest, unittest.TestCase):
nla_anim_object = _create_nla_anim_object()
tracks = nla_anim_object.animation_data.nla_tracks
self.assertEqual(nla_anim_object, bpy.context.active_object)
self.assertEqual(None, nla_anim_object.animation_data.action)
# This leaves the additive track as the topmost track with influence
tracks["top"].mute = True
@ -771,12 +758,25 @@ class NlaInsertTest(AbstractKeyframingTest, unittest.TestCase):
tracks["base"].strips[0].select = True
bpy.ops.nla.tweakmode_enter(use_upper_stack_evaluation=True)
base_action = bpy.data.actions["action_base"]
# Verify that tweak mode has switched to the correct Action.
self.assertEqual(base_action, nla_anim_object.animation_data.action)
# Inserting over the existing keyframe.
bpy.context.scene.frame_set(10)
with bpy.context.temp_override(**_get_view3d_context()):
bpy.ops.anim.keyframe_insert()
base_action = bpy.data.actions["action_base"]
# Check that the expected F-Curves exist.
fcurves_actual = {(f.data_path, f.array_index) for f in base_action.fcurves}
fcurves_expect = {
("location", 0),
("location", 1),
("location", 2),
}
self.assertEqual(fcurves_actual, fcurves_expect)
# This should have added keys to Y and Z but not X.
# X already had two keys from the file setup.
self.assertEqual(len(base_action.fcurves.find("location", index=0).keyframe_points), 2)

View file

@ -13,16 +13,6 @@ import sys
import unittest
def enable_experimental_animation_baklava():
bpy.context.preferences.view.show_developer_ui = True
bpy.context.preferences.experimental.use_animation_baklava = True
def disable_experimental_animation_baklava():
bpy.context.preferences.view.show_developer_ui = False
bpy.context.preferences.experimental.use_animation_baklava = False
class AbstractNlaStripTest(unittest.TestCase):
""" Sets up a series of strips in one NLA track. """
@ -124,15 +114,6 @@ class NlaStripBoundaryTest(AbstractNlaStripTest):
class NLAStripActionSlotSelectionTest(AbstractNlaStripTest):
def setUp(self):
enable_experimental_animation_baklava()
return super().setUp()
def tearDown(self) -> None:
disable_experimental_animation_baklava()
return super().tearDown()
def test_two_strips_for_same_action(self):
action = bpy.data.actions.new("StripAction")
action.slots.new()

View file

@ -443,16 +443,6 @@ class CopyTransformsTest(AbstractConstraintTests):
class ActionConstraintTest(AbstractConstraintTests):
layer_collection = "Action"
def setUp(self):
bpy.context.preferences.view.show_developer_ui = True
bpy.context.preferences.experimental.use_animation_baklava = True
return super().setUp()
def tearDown(self) -> None:
bpy.context.preferences.view.show_developer_ui = False
bpy.context.preferences.experimental.use_animation_baklava = False
return super().tearDown()
def constraint(self) -> Constraint:
owner = bpy.context.scene.objects["Action.owner"]
constraint = owner.constraints["Action"]