mirror of
https://github.com/blender/blender
synced 2026-09-29 04:37:17 +03:00
Refactor: remove remaining legacy action code
This removes the remaining legacy action code, that includes any unit tests for legacy actions. The only place that still deals with legacy actions is the versioning code. I left the RNA functions `is_action_legacy` and `is_action_layered` in place to not cause a breaking change for addons. However the functions are now just hardcoded to return false and true respectively. Part of #150644 Pull Request: https://projects.blender.org/blender/blender/pulls/152526
This commit is contained in:
parent
95355b4afb
commit
12e628ea43
22 changed files with 39 additions and 578 deletions
|
|
@ -713,9 +713,6 @@ class ANIM_OT_slot_new_for_id(Operator):
|
|||
if not animated_id.animation_data or not animated_id.animation_data.action:
|
||||
cls.poll_message_set("An action slot can only be created when an action is assigned")
|
||||
return False
|
||||
if not animated_id.animation_data.action.is_action_layered:
|
||||
cls.poll_message_set("Action slots are only supported by layered Actions. Upgrade this Action first")
|
||||
return False
|
||||
if not animated_id.animation_data.action.is_editable:
|
||||
cls.poll_message_set("Creating a new Slot is not possible on a linked Action")
|
||||
return False
|
||||
|
|
|
|||
|
|
@ -21,15 +21,13 @@ def draw_action_and_slot_selector_for_id(layout, animated_id):
|
|||
if not adt or not adt.action:
|
||||
return
|
||||
|
||||
# Only show the slot selector when a layered Action is assigned.
|
||||
if adt.action.is_action_layered:
|
||||
layout.context_pointer_set("animated_id", animated_id)
|
||||
layout.template_search(
|
||||
adt, "action_slot",
|
||||
adt, "action_suitable_slots",
|
||||
new="anim.slot_new_for_id",
|
||||
unlink="anim.slot_unassign_from_id",
|
||||
)
|
||||
layout.context_pointer_set("animated_id", animated_id)
|
||||
layout.template_search(
|
||||
adt, "action_slot",
|
||||
adt, "action_suitable_slots",
|
||||
new="anim.slot_new_for_id",
|
||||
unlink="anim.slot_unassign_from_id",
|
||||
)
|
||||
|
||||
|
||||
class ANIM_MT_keyframe_insert_pie(Menu):
|
||||
|
|
|
|||
|
|
@ -1175,7 +1175,7 @@ class ConstraintButtonsSubPanel:
|
|||
|
||||
col = layout.column(align=True)
|
||||
col.prop(con, "action")
|
||||
if con.action and con.action.is_action_layered:
|
||||
if con.action:
|
||||
col.context_pointer_set("animated_id", con.id_data)
|
||||
col.template_search(
|
||||
con, "action_slot",
|
||||
|
|
|
|||
|
|
@ -322,7 +322,7 @@ class DOPESHEET_HT_editor_buttons:
|
|||
row.template_action(animated_id, new="action.new", unlink="action.unlink")
|
||||
|
||||
adt = animated_id and animated_id.animation_data
|
||||
if not adt or not adt.action or not adt.action.is_action_layered:
|
||||
if not adt or not adt.action:
|
||||
return
|
||||
|
||||
# Store the animated ID in the context, so that the new/unlink operators
|
||||
|
|
|
|||
|
|
@ -78,16 +78,7 @@ class Slot;
|
|||
*
|
||||
* \note This wrapper class for the `bAction` DNA struct only has functionality
|
||||
* for the layered animation data. The legacy F-Curves (in `bAction::curves`)
|
||||
* and their groups (in `bAction::groups`) are not managed here.
|
||||
*
|
||||
* To continue supporting legacy actions at runtime, there are
|
||||
* `Action::is_action_legacy()` and `Action::is_action_layered()` that report
|
||||
* whether an Action uses that legacy F-Curve data or is instead a layered
|
||||
* Action. These methods will eventually be removed when runtime support for
|
||||
* legacy actions is fully removed. For code in blend file loading and
|
||||
* versioning, which will stick around for the long-term, use
|
||||
* `animrig::versioning::action_is_layered()` instead. (Note that an empty
|
||||
* Action is considered both a valid legacy *and* layered action.)
|
||||
* and their groups (in `bAction::groups`) are not managed here. See animrig::versioning.
|
||||
*
|
||||
* \see #AnimData::action
|
||||
* \see #AnimData::slot_handle
|
||||
|
|
@ -103,50 +94,12 @@ class Action : public bAction {
|
|||
*/
|
||||
Action(const Action &other) = delete;
|
||||
|
||||
/* Discriminators for 'legacy' and 'layered' Actions.
|
||||
*
|
||||
* Note: `is_action_legacy()` and `is_action_layered()` are transitional APIs,
|
||||
* and should eventually be removed. See their documentation below for
|
||||
* details.
|
||||
*/
|
||||
/**
|
||||
* Return whether this Action has any data at all.
|
||||
*
|
||||
* \return true when `bAction::layer_array` and `bAction::slot_array` are empty.
|
||||
*/
|
||||
bool is_empty() const;
|
||||
/**
|
||||
* Return whether this is a legacy Action.
|
||||
*
|
||||
* - Animation data is stored in `bAction::curves`.
|
||||
* - Evaluated equally for all data-blocks that reference this Action.
|
||||
* - Slot handle is ignored.
|
||||
*
|
||||
* \note An empty Action is valid as both a legacy and layered Action. Code that only supports
|
||||
* layered Actions should assert on `is_action_layered()`.
|
||||
*
|
||||
* \note This method will be removed when runtime support for legacy Actions
|
||||
* is removed, so only use it in such runtime code. See
|
||||
* `animrig::versioning::action_is_layered()` for uses that should stick
|
||||
* around for the long term, such as blend file loading and versioning.
|
||||
*
|
||||
* \see #animrig::versioning::action_is_layered()
|
||||
*/
|
||||
bool is_action_legacy() const;
|
||||
/**
|
||||
* Return whether this is a layered Action.
|
||||
*
|
||||
* - Animation data is stored in `bAction::layer_array`.
|
||||
* - Evaluated for data-blocks based on their slot handle.
|
||||
*
|
||||
* \note This method will be removed when runtime support for legacy Actions
|
||||
* is removed, so only use it in such runtime code. See
|
||||
* `animrig::versioning::action_is_layered()` for uses that should stick
|
||||
* around for the long term, such as blend file loading and versioning.
|
||||
*
|
||||
* \see #animrig::versioning::action_is_layered()
|
||||
*/
|
||||
bool is_action_layered() const;
|
||||
|
||||
/* Action Layers access. */
|
||||
Span<const Layer *> layers() const;
|
||||
|
|
@ -1914,12 +1867,6 @@ void assert_baklava_phase_1_invariants(const Layer &layer);
|
|||
/** \copydoc assert_baklava_phase_1_invariants(const Action &) */
|
||||
void assert_baklava_phase_1_invariants(const Strip &strip);
|
||||
|
||||
/**
|
||||
* Creates a new `Action` that matches the old action but is converted to have layers.
|
||||
* Returns a nullptr if the action is empty or already layered.
|
||||
*/
|
||||
Action *convert_to_layered_action(Main &bmain, const Action &legacy_action);
|
||||
|
||||
/**
|
||||
* Move the given slot from `from_action` to `to_action`.
|
||||
* The slot identifier might not be exactly the same if the identifier already exists in the slots
|
||||
|
|
|
|||
|
|
@ -125,15 +125,6 @@ Vector<bActionGroup *> channel_groups_all(bAction *action);
|
|||
*/
|
||||
Vector<bActionGroup *> channel_groups_for_assigned_slot(AnimData *adt);
|
||||
|
||||
/**
|
||||
* Determine whether to treat this Action as a legacy Action or not.
|
||||
*
|
||||
* - empty Action: returns the value of the 'Slotted Actions' experimental feature.
|
||||
* - layered Action: always returns false.
|
||||
* - legacy Action: always returns true.
|
||||
*/
|
||||
bool action_treat_as_legacy(const bAction &action);
|
||||
|
||||
/**
|
||||
* Remove all F-Curves whose RNA path starts with the given prefix from an Action Slot.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -29,13 +29,6 @@ namespace animrig::versioning {
|
|||
* This will return false for both Animato and pre-Animato actions. It is used
|
||||
* during file read and versioning to determine how forward-compatible and
|
||||
* legacy data should be handled.
|
||||
*
|
||||
* NOTE: this is semi-duplicated from `Action::is_action_layered()`, but with
|
||||
* tweaks to also recognize ultra-legacy (pre-Animato) data. Because this needs access to
|
||||
* deprecated DNA fields, which is ok here in the versioning code, the other "is this legacy or
|
||||
* layered?" functions do not check for pre-Animato data.
|
||||
*
|
||||
* \see Action::is_action_layered()
|
||||
*/
|
||||
bool action_is_layered(const bAction &dna_action);
|
||||
|
||||
|
|
|
|||
|
|
@ -224,18 +224,6 @@ bool Action::is_empty() const
|
|||
return this->layer_array_num == 0 && this->slot_array_num == 0 &&
|
||||
BLI_listbase_is_empty(&this->curves) && BLI_listbase_is_empty(&this->groups);
|
||||
}
|
||||
bool Action::is_action_legacy() const
|
||||
{
|
||||
/* This is a valid legacy Action only if there is no layered info. */
|
||||
return this->layer_array_num == 0 && this->slot_array_num == 0;
|
||||
}
|
||||
bool Action::is_action_layered() const
|
||||
{
|
||||
/* This is a valid layered Action if there is ANY layered info (because that
|
||||
* takes precedence) or when there is no legacy info. */
|
||||
return this->layer_array_num > 0 || this->slot_array_num > 0 ||
|
||||
(BLI_listbase_is_empty(&this->curves) && BLI_listbase_is_empty(&this->groups));
|
||||
}
|
||||
|
||||
Span<const Layer *> Action::layers() const
|
||||
{
|
||||
|
|
@ -2443,15 +2431,8 @@ void Channelbag::restore_channel_group_invariants()
|
|||
}
|
||||
}
|
||||
|
||||
bool ChannelGroup::is_legacy() const
|
||||
{
|
||||
return this->channelbag == nullptr;
|
||||
}
|
||||
|
||||
Span<FCurve *> ChannelGroup::fcurves()
|
||||
{
|
||||
BLI_assert(!this->is_legacy());
|
||||
|
||||
if (this->fcurve_range_length == 0) {
|
||||
return {};
|
||||
}
|
||||
|
|
@ -2462,8 +2443,6 @@ Span<FCurve *> ChannelGroup::fcurves()
|
|||
|
||||
Span<const FCurve *> ChannelGroup::fcurves() const
|
||||
{
|
||||
BLI_assert(!this->is_legacy());
|
||||
|
||||
if (this->fcurve_range_length == 0) {
|
||||
return {};
|
||||
}
|
||||
|
|
@ -2952,57 +2931,6 @@ void assert_baklava_phase_1_invariants(const Strip &strip)
|
|||
BLI_assert(strip.frame_offset == 0.0);
|
||||
}
|
||||
|
||||
Action *convert_to_layered_action(Main &bmain, const Action &legacy_action)
|
||||
{
|
||||
if (!legacy_action.is_action_legacy()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::string suffix = "_layered";
|
||||
/* In case the legacy action has a long name it is shortened to make space for the suffix. */
|
||||
char legacy_name[MAX_ID_NAME - 10];
|
||||
/* Offsetting the id.name to remove the ID prefix (AC) which gets added back later. */
|
||||
STRNCPY_UTF8(legacy_name, legacy_action.id.name + 2);
|
||||
|
||||
const std::string layered_action_name = std::string(legacy_name) + suffix;
|
||||
bAction *dna_action = BKE_action_add(&bmain, layered_action_name.c_str());
|
||||
|
||||
Action &converted_action = dna_action->wrap();
|
||||
Slot &slot = converted_action.slot_add();
|
||||
Layer &layer = converted_action.layer_add(legacy_action.id.name);
|
||||
Strip &strip = layer.strip_add(converted_action, Strip::Type::Keyframe);
|
||||
BLI_assert(strip.data<StripKeyframeData>(converted_action).channelbag_array_num == 0);
|
||||
Channelbag *bag = &strip.data<StripKeyframeData>(converted_action).channelbag_for_slot_add(slot);
|
||||
|
||||
const int fcu_count = BLI_listbase_count(&legacy_action.curves);
|
||||
bag->fcurve_array = MEM_calloc_arrayN<FCurve *>(fcu_count, "Convert to layered action");
|
||||
bag->fcurve_array_num = fcu_count;
|
||||
|
||||
Map<const FCurve *, FCurve *> old_new_fcurve_map;
|
||||
for (auto [i, fcu] : legacy_action.curves.enumerate()) {
|
||||
bag->fcurve_array[i] = BKE_fcurve_copy(&fcu);
|
||||
bag->fcurve_array[i]->grp = nullptr;
|
||||
old_new_fcurve_map.add(&fcu, bag->fcurve_array[i]);
|
||||
}
|
||||
|
||||
for (bActionGroup &group : legacy_action.groups) {
|
||||
/* The resulting group might not have the same name, because the legacy system allowed
|
||||
* duplicate names while the new system ensures uniqueness. */
|
||||
bActionGroup &converted_group = bag->channel_group_create(group.name);
|
||||
for (FCurve &fcu : group.channels) {
|
||||
if (fcu.grp != &group) {
|
||||
/* Since the group listbase points to the action listbase, it won't stop iterating when
|
||||
* reaching the end of the group but iterate to the end of the action FCurves. */
|
||||
break;
|
||||
}
|
||||
FCurve *new_fcurve = old_new_fcurve_map.lookup(&fcu);
|
||||
bag->fcurve_assign_to_channel_group(*new_fcurve, converted_group);
|
||||
}
|
||||
}
|
||||
|
||||
return &converted_action;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone information from the given slot into this slot while retaining important info like the
|
||||
* slot handle and runtime data. This copies the identifier which might clash with other
|
||||
|
|
|
|||
|
|
@ -54,7 +54,6 @@ TEST_F(ActionIteratorsTest, iterate_all_fcurves_of_slot)
|
|||
{
|
||||
Slot &cube_slot = action->slot_add();
|
||||
Slot &monkey_slot = action->slot_add();
|
||||
EXPECT_TRUE(action->is_action_layered());
|
||||
|
||||
/* Try iterating an empty action. */
|
||||
Vector<FCurve *> no_fcurves;
|
||||
|
|
|
|||
|
|
@ -242,16 +242,6 @@ Vector<bActionGroup *> channel_groups_for_assigned_slot(AnimData *adt)
|
|||
return slot_groups;
|
||||
}
|
||||
|
||||
bool action_treat_as_legacy(const bAction &action)
|
||||
{
|
||||
/* 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,
|
||||
const slot_handle_t slot_handle,
|
||||
const StringRefNull rna_path_prefix)
|
||||
|
|
|
|||
|
|
@ -32,151 +32,6 @@
|
|||
|
||||
namespace blender::animrig::tests {
|
||||
|
||||
static bActionGroup *action_groups_add_new(bAction *act, const char name[])
|
||||
{
|
||||
if (ELEM(nullptr, act, name)) {
|
||||
return nullptr;
|
||||
}
|
||||
BLI_assert(act->wrap().is_action_legacy());
|
||||
bActionGroup *agrp = MEM_new_for_free<bActionGroup>("bActionGroup");
|
||||
agrp->flag = AGRP_SELECTED;
|
||||
STRNCPY_UTF8(agrp->name, name[0] ? name : "Group");
|
||||
BLI_addtail(&act->groups, agrp);
|
||||
BLI_uniquename(
|
||||
&act->groups, agrp, "Group", '.', offsetof(bActionGroup, name), sizeof(agrp->name));
|
||||
|
||||
return agrp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add given channel into (active) group
|
||||
* - assumes that channel is not linked to anything anymore
|
||||
* - always adds at the end of the group
|
||||
*
|
||||
* \note Only for unit testing since this function only works on legacy actions.
|
||||
*/
|
||||
static void action_groups_add_channel(bAction *act, bActionGroup *agrp, FCurve *fcurve)
|
||||
{
|
||||
if (ELEM(nullptr, act, agrp, fcurve)) {
|
||||
return;
|
||||
}
|
||||
BLI_assert(act->wrap().is_action_legacy());
|
||||
/* If no channels anywhere, just add to two lists at the same time. */
|
||||
if (BLI_listbase_is_empty(&act->curves)) {
|
||||
fcurve->next = fcurve->prev = nullptr;
|
||||
agrp->channels.first = agrp->channels.last = fcurve;
|
||||
act->curves.first = act->curves.last = fcurve;
|
||||
}
|
||||
/* If the group already has channels, the F-Curve can simply be added to the list
|
||||
* (i.e. as the last channel in the group).
|
||||
*/
|
||||
else if (agrp->channels.first) {
|
||||
if (agrp->channels.last == act->curves.last) {
|
||||
act->curves.last = fcurve;
|
||||
}
|
||||
BLI_insertlinkafter(&agrp->channels, agrp->channels.last, fcurve);
|
||||
}
|
||||
/* Otherwise, need to find the nearest F-Curve in group before/after current to link with */
|
||||
else {
|
||||
bActionGroup *grp;
|
||||
agrp->channels.first = agrp->channels.last = fcurve;
|
||||
for (grp = agrp->prev; grp; grp = grp->prev) {
|
||||
if (grp->channels.last) {
|
||||
BLI_insertlinkafter(&act->curves, grp->channels.last, fcurve);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (grp == nullptr) {
|
||||
BLI_insertlinkbefore(&act->curves, act->curves.first, fcurve);
|
||||
}
|
||||
}
|
||||
|
||||
fcurve->grp = agrp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure an FCurve exists for a legacy action. Only useful for unit tests since legacy actions can
|
||||
* no longer be created and are versioned to layered actions.
|
||||
*/
|
||||
static FCurve *action_fcurve_ensure_legacy(Main *bmain,
|
||||
bAction *act,
|
||||
const char group[],
|
||||
PointerRNA *ptr,
|
||||
const FCurveDescriptor &fcurve_descriptor)
|
||||
{
|
||||
if (!act) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
BLI_assert(act->wrap().is_empty() || act->wrap().is_action_legacy());
|
||||
|
||||
/* Try to find f-curve matching for this setting.
|
||||
* - add if not found and allowed to add one
|
||||
* TODO: add auto-grouping support? how this works will need to be resolved
|
||||
*/
|
||||
FCurve *fcu = BKE_fcurve_find(
|
||||
&act->curves, fcurve_descriptor.rna_path.c_str(), fcurve_descriptor.array_index);
|
||||
|
||||
if (fcu != nullptr) {
|
||||
return fcu;
|
||||
}
|
||||
|
||||
/* Determine the property (sub)type if we can. */
|
||||
std::optional<PropertyType> prop_type = std::nullopt;
|
||||
std::optional<PropertySubType> prop_subtype = std::nullopt;
|
||||
if (ptr != nullptr) {
|
||||
PropertyRNA *resolved_prop;
|
||||
PointerRNA resolved_ptr;
|
||||
PointerRNA id_ptr = RNA_id_pointer_create(ptr->owner_id);
|
||||
const bool resolved = RNA_path_resolve_property(
|
||||
&id_ptr, fcurve_descriptor.rna_path.c_str(), &resolved_ptr, &resolved_prop);
|
||||
if (resolved) {
|
||||
prop_type = RNA_property_type(resolved_prop);
|
||||
prop_subtype = RNA_property_subtype(resolved_prop);
|
||||
}
|
||||
}
|
||||
|
||||
BLI_assert_msg(!fcurve_descriptor.prop_type.has_value(),
|
||||
"Did not expect a prop_type to be passed in. This is fine, but does need some "
|
||||
"changes to action_fcurve_ensure_legacy() to deal with it");
|
||||
BLI_assert_msg(!fcurve_descriptor.prop_subtype.has_value(),
|
||||
"Did not expect a prop_subtype to be passed in. This is fine, but does need some "
|
||||
"changes to action_fcurve_ensure_legacy() to deal with it");
|
||||
fcu = create_fcurve_for_channel(
|
||||
{fcurve_descriptor.rna_path, fcurve_descriptor.array_index, prop_type, prop_subtype});
|
||||
|
||||
if (BLI_listbase_is_empty(&act->curves)) {
|
||||
fcu->flag |= FCURVE_ACTIVE;
|
||||
}
|
||||
|
||||
if (group) {
|
||||
bActionGroup *agrp = static_cast<bActionGroup *>(
|
||||
BLI_findstring(&act->groups, group, offsetof(bActionGroup, name)));
|
||||
|
||||
if (agrp == nullptr) {
|
||||
agrp = action_groups_add_new(act, group);
|
||||
|
||||
/* Sync bone group colors if applicable. */
|
||||
if (ptr && (ptr->type == &RNA_PoseBone) && ptr->data) {
|
||||
const bPoseChannel *pchan = static_cast<const bPoseChannel *>(ptr->data);
|
||||
action_group_colors_set_from_posebone(agrp, pchan);
|
||||
}
|
||||
}
|
||||
|
||||
action_groups_add_channel(act, agrp, fcu);
|
||||
}
|
||||
else {
|
||||
BLI_addtail(&act->curves, fcu);
|
||||
}
|
||||
|
||||
/* New f-curve was added, meaning it's possible that it affects
|
||||
* dependency graph component which wasn't previously animated.
|
||||
*/
|
||||
DEG_relations_tag_update(bmain);
|
||||
|
||||
return fcu;
|
||||
}
|
||||
|
||||
TEST(action, low_level_initialisation)
|
||||
{
|
||||
bAction *action = BKE_id_new_nomain<bAction>("NewAction");
|
||||
|
|
@ -1160,9 +1015,6 @@ TEST_F(ActionLayersTest, action_slot_get_id_for_keying__layered_action)
|
|||
{
|
||||
Slot &slot = action->slot_add();
|
||||
|
||||
/* Double-check that the action is considered layered for the test. */
|
||||
EXPECT_TRUE(action->is_action_layered());
|
||||
|
||||
/* A slot with no users should never return a user. */
|
||||
EXPECT_EQ(nullptr, action_slot_get_id_for_keying(*bmain, *action, slot.handle, nullptr));
|
||||
EXPECT_EQ(nullptr, action_slot_get_id_for_keying(*bmain, *action, slot.handle, &cube->id));
|
||||
|
|
@ -1183,117 +1035,6 @@ TEST_F(ActionLayersTest, action_slot_get_id_for_keying__layered_action)
|
|||
EXPECT_EQ(nullptr, action_slot_get_id_for_keying(*bmain, *action, slot.handle, &bob->id));
|
||||
}
|
||||
|
||||
TEST_F(ActionLayersTest, conversion_to_layered)
|
||||
{
|
||||
EXPECT_TRUE(action->is_empty());
|
||||
FCurve *legacy_fcu_0 = action_fcurve_ensure_legacy(
|
||||
bmain, action, "Test", nullptr, {"location", 0});
|
||||
FCurve *legacy_fcu_1 = action_fcurve_ensure_legacy(
|
||||
bmain, action, "Test", nullptr, {"location", 1});
|
||||
|
||||
KeyframeSettings settings;
|
||||
settings.handle = HD_AUTO;
|
||||
settings.interpolation = BEZT_IPO_BEZ;
|
||||
settings.keyframe_type = BEZT_KEYTYPE_KEYFRAME;
|
||||
insert_vert_fcurve(legacy_fcu_0, {0, 0}, settings, INSERTKEY_NOFLAGS);
|
||||
insert_vert_fcurve(legacy_fcu_0, {1, 1}, settings, INSERTKEY_NOFLAGS);
|
||||
add_fmodifier(&legacy_fcu_1->modifiers, FMODIFIER_TYPE_NOISE, legacy_fcu_1);
|
||||
|
||||
Action *converted = convert_to_layered_action(*bmain, *action);
|
||||
ASSERT_TRUE(converted != action);
|
||||
EXPECT_STREQ(converted->id.name, "ACACÄnimåtië_layered");
|
||||
Strip *strip = converted->layer(0)->strip(0);
|
||||
StripKeyframeData &strip_data = strip->data<StripKeyframeData>(*converted);
|
||||
Channelbag *bag = strip_data.channelbag(0);
|
||||
ASSERT_EQ(bag->fcurve_array_num, 2);
|
||||
ASSERT_EQ(bag->fcurve_array[0]->totvert, 2);
|
||||
|
||||
ASSERT_EQ(BLI_listbase_count(&action->groups), 1);
|
||||
ASSERT_EQ(BLI_listbase_count(&converted->groups), 0);
|
||||
|
||||
ASSERT_EQ(bag->channel_groups().size(), 1);
|
||||
bActionGroup *group = bag->channel_group(0);
|
||||
ASSERT_EQ(group->fcurve_range_length, 2);
|
||||
ASSERT_STREQ(group->name, "Test");
|
||||
|
||||
ASSERT_TRUE(bag->fcurve_array[0]->modifiers.first == nullptr);
|
||||
ASSERT_TRUE(bag->fcurve_array[1]->modifiers.first != nullptr);
|
||||
|
||||
constexpr char id_name_max[] =
|
||||
"name_for_an_action_that_is_exactly_255_bytes_MAX_ID_NAME-3______"
|
||||
"name_for_an_action_that_is_exactly_255_bytes_MAX_ID_NAME-3______"
|
||||
"name_for_an_action_that_is_exactly_255_bytes_MAX_ID_NAME-3______"
|
||||
"name_for_an_action_that_is_exactly_255_bytes_MAX_ID_NAME-3_____";
|
||||
BLI_STATIC_ASSERT(std::string::traits_type::length(id_name_max) == MAX_ID_NAME - 2 - 1,
|
||||
"Wrong 'max length' name");
|
||||
Action *long_name_action = BKE_id_new<Action>(bmain, id_name_max);
|
||||
action_fcurve_ensure_legacy(bmain, long_name_action, "Long", nullptr, {"location", 0});
|
||||
/* The long name is shortened to make space for "_layered". */
|
||||
constexpr char id_name_max_converted[] =
|
||||
"name_for_an_action_that_is_exactly_255_bytes_MAX_ID_NAME-3______"
|
||||
"name_for_an_action_that_is_exactly_255_bytes_MAX_ID_NAME-3______"
|
||||
"name_for_an_action_that_is_exactly_255_bytes_MAX_ID_NAME-3______"
|
||||
"name_for_an_action_that_is_exactly_255_bytes_MAX_ID_NAM_layered";
|
||||
BLI_STATIC_ASSERT(std::string::traits_type::length(id_name_max_converted) == MAX_ID_NAME - 2 - 1,
|
||||
"Wrong 'max length' name");
|
||||
converted = convert_to_layered_action(*bmain, *long_name_action);
|
||||
EXPECT_STREQ(BKE_id_name(converted->id), id_name_max_converted);
|
||||
}
|
||||
|
||||
TEST_F(ActionLayersTest, conversion_to_layered_action_groups)
|
||||
{
|
||||
EXPECT_TRUE(action->is_empty());
|
||||
action_fcurve_ensure_legacy(bmain, action, "Test", nullptr, {"location", 0});
|
||||
action_fcurve_ensure_legacy(bmain, action, "Test", nullptr, {"rotation_euler", 1});
|
||||
action_fcurve_ensure_legacy(bmain, action, "Test_Two", nullptr, {"scale", 1});
|
||||
action_fcurve_ensure_legacy(bmain, action, "Test_Three", nullptr, {"show_name", 1});
|
||||
action_fcurve_ensure_legacy(bmain, action, "Test_Rename", nullptr, {"show_axis", 1});
|
||||
|
||||
bActionGroup *rename_group = static_cast<bActionGroup *>(BLI_findlink(&action->groups, 3));
|
||||
ASSERT_NE(rename_group, nullptr);
|
||||
ASSERT_STREQ(rename_group->name, "Test_Rename");
|
||||
/* Forcing a duplicate name which was allowed by legacy actions. */
|
||||
STRNCPY_UTF8(rename_group->name, "Test");
|
||||
|
||||
Action *converted = convert_to_layered_action(*bmain, *action);
|
||||
Strip *strip = converted->layer(0)->strip(0);
|
||||
StripKeyframeData &strip_data = strip->data<StripKeyframeData>(*converted);
|
||||
Channelbag *bag = strip_data.channelbag(0);
|
||||
|
||||
ASSERT_EQ(BLI_listbase_count(&converted->groups), 0);
|
||||
ASSERT_EQ(bag->channel_groups().size(), 4);
|
||||
|
||||
bActionGroup *test_group = bag->channel_group(0);
|
||||
EXPECT_STREQ(test_group->name, "Test");
|
||||
EXPECT_EQ(test_group->fcurve_range_length, 2);
|
||||
|
||||
bActionGroup *test_two_group = bag->channel_group(1);
|
||||
EXPECT_STREQ(test_two_group->name, "Test_Two");
|
||||
EXPECT_EQ(test_two_group->fcurve_range_length, 1);
|
||||
EXPECT_STREQ(bag->fcurve_array[test_two_group->fcurve_range_start]->rna_path, "scale");
|
||||
|
||||
bActionGroup *test_three_group = bag->channel_group(2);
|
||||
EXPECT_STREQ(test_three_group->name, "Test_Three");
|
||||
EXPECT_EQ(test_three_group->fcurve_range_length, 1);
|
||||
EXPECT_STREQ(bag->fcurve_array[test_three_group->fcurve_range_start]->rna_path, "show_name");
|
||||
|
||||
bActionGroup *test_rename_group = bag->channel_group(3);
|
||||
EXPECT_STREQ(test_rename_group->name, "Test.001");
|
||||
EXPECT_EQ(test_rename_group->fcurve_range_length, 1);
|
||||
EXPECT_STREQ(bag->fcurve_array[test_rename_group->fcurve_range_start]->rna_path, "show_axis");
|
||||
|
||||
ASSERT_NE(converted, action);
|
||||
}
|
||||
|
||||
TEST_F(ActionLayersTest, empty_to_layered)
|
||||
{
|
||||
ASSERT_TRUE(action->is_empty());
|
||||
Action *converted = convert_to_layered_action(*bmain, *action);
|
||||
ASSERT_TRUE(converted != action);
|
||||
ASSERT_TRUE(converted->is_action_layered());
|
||||
ASSERT_FALSE(converted->is_action_legacy());
|
||||
}
|
||||
|
||||
TEST_F(ActionLayersTest, action_move_slot)
|
||||
{
|
||||
Action *action_2 = BKE_id_new<Action>(bmain, "Action 2");
|
||||
|
|
@ -2436,14 +2177,8 @@ TEST_F(ActionFCurveMoveTest, test_fcurve_move_layered)
|
|||
|
||||
cbag_dst.fcurve_ensure(this->bmain, {"dest_prop", 0});
|
||||
|
||||
ASSERT_TRUE(action_src.is_action_layered());
|
||||
ASSERT_TRUE(action_dst.is_action_layered());
|
||||
|
||||
action_fcurve_move(action_dst, slot_dst.handle, action_src, fcurve_to_move);
|
||||
|
||||
EXPECT_TRUE(action_src.is_action_layered());
|
||||
EXPECT_TRUE(action_dst.is_action_layered());
|
||||
|
||||
EXPECT_EQ(nullptr, cbag_src.fcurve_find({fcurve_to_move.rna_path, fcurve_to_move.array_index}))
|
||||
<< "F-Curve should no longer exist in source Action";
|
||||
EXPECT_EQ(&fcurve_to_move,
|
||||
|
|
|
|||
|
|
@ -74,7 +74,9 @@ void convert_legacy_animato_actions(Main &bmain)
|
|||
void convert_legacy_animato_action(bAction &dna_action)
|
||||
{
|
||||
Action &action = dna_action.wrap();
|
||||
BLI_assert(action.is_action_legacy());
|
||||
/* Check that this is a legacy action.
|
||||
* Cannot use `!action_is_layered` because that would be false on empty actions. */
|
||||
BLI_assert(action.layer_array_num == 0 && action.slot_array_num == 0);
|
||||
|
||||
/* Store this ahead of time, because adding the slot sets the action's idroot
|
||||
* to 0. We also set the action's idroot to 0 manually, just to be defensive
|
||||
|
|
@ -268,7 +270,9 @@ void action_groups_reconstruct(bAction *act)
|
|||
if (!act) {
|
||||
return;
|
||||
}
|
||||
BLI_assert(act->wrap().is_action_legacy());
|
||||
/* Check that this is a legacy action.
|
||||
* Cannot use `!action_is_layered` because that would be false on empty actions. */
|
||||
BLI_assert(act->layer_array_num == 0 && act->slot_array_num == 0);
|
||||
/* Clear out all group channels. Channels that are actually in use are
|
||||
* reconstructed below; this step is necessary to clear out unused groups. */
|
||||
for (bActionGroup &group : act->groups) {
|
||||
|
|
|
|||
|
|
@ -795,8 +795,6 @@ void animsys_evaluate_action_group(PointerRNA *ptr,
|
|||
bActionGroup *agrp,
|
||||
const AnimationEvalContext *anim_eval_context)
|
||||
{
|
||||
FCurve *fcu;
|
||||
|
||||
/* check if mapper is appropriate for use here (we set to nullptr if it's inappropriate) */
|
||||
if (ELEM(nullptr, act, agrp)) {
|
||||
return;
|
||||
|
|
@ -819,16 +817,6 @@ void animsys_evaluate_action_group(PointerRNA *ptr,
|
|||
};
|
||||
|
||||
animrig::ChannelGroup channel_group = agrp->wrap();
|
||||
if (channel_group.is_legacy()) {
|
||||
/* calculate then execute each curve */
|
||||
for (fcu = static_cast<FCurve *>(agrp->channels.first); (fcu) && (fcu->grp == agrp);
|
||||
fcu = fcu->next)
|
||||
{
|
||||
visit_fcurve(fcu);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (FCurve *fcurve : channel_group.fcurves()) {
|
||||
visit_fcurve(fcurve);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1684,18 +1684,6 @@ void DepsgraphRelationBuilder::build_animdata_fcurve_target(
|
|||
}
|
||||
}
|
||||
|
||||
void DepsgraphRelationBuilder::build_animdata_curves_targets(ID *id,
|
||||
ComponentKey &adt_key,
|
||||
OperationNode *operation_from,
|
||||
ListBaseT<FCurve> *curves)
|
||||
{
|
||||
/* Iterate over all curves and build relations. */
|
||||
PointerRNA id_ptr = RNA_id_pointer_create(id);
|
||||
for (FCurve &fcu : *curves) {
|
||||
build_animdata_fcurve_target(id, id_ptr, adt_key, operation_from, &fcu);
|
||||
}
|
||||
}
|
||||
|
||||
void DepsgraphRelationBuilder::build_animdata_action_targets(ID *id,
|
||||
const int32_t slot_handle,
|
||||
ComponentKey &adt_key,
|
||||
|
|
@ -1710,10 +1698,6 @@ void DepsgraphRelationBuilder::build_animdata_action_targets(ID *id,
|
|||
if (action.is_empty()) {
|
||||
return;
|
||||
}
|
||||
if (action.is_action_legacy()) {
|
||||
build_animdata_curves_targets(id, adt_key, operation_from, &action.curves);
|
||||
return;
|
||||
}
|
||||
|
||||
const animrig::Slot *slot = action.slot_for_handle(slot_handle);
|
||||
if (slot == nullptr) {
|
||||
|
|
|
|||
|
|
@ -170,10 +170,6 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder {
|
|||
ComponentKey &adt_key,
|
||||
OperationNode *operation_from,
|
||||
FCurve *fcu);
|
||||
virtual void build_animdata_curves_targets(ID *id,
|
||||
ComponentKey &adt_key,
|
||||
OperationNode *operation_from,
|
||||
ListBaseT<FCurve> *curves);
|
||||
virtual void build_animdata_action_targets(ID *id,
|
||||
int32_t slot_handle,
|
||||
ComponentKey &adt_key,
|
||||
|
|
|
|||
|
|
@ -156,18 +156,6 @@ static short agrp_keyframes_loop(KeyframeEditData *ked,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Legacy actions. */
|
||||
if (agrp->wrap().is_legacy()) {
|
||||
for (FCurve &fcu : agrp->channels) {
|
||||
if (fcu.grp == agrp) {
|
||||
if (ANIM_fcurve_keyframes_loop(ked, &fcu, key_ok, key_cb, fcu_cb)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Layered actions. */
|
||||
animrig::Channelbag &channelbag = agrp->channelbag->wrap();
|
||||
Span<FCurve *> fcurves = channelbag.fcurves().slice(agrp->fcurve_range_start,
|
||||
|
|
|
|||
|
|
@ -1355,17 +1355,6 @@ void action_group_to_keylist(
|
|||
return;
|
||||
}
|
||||
|
||||
/* Legacy actions. */
|
||||
if (agrp->wrap().is_legacy()) {
|
||||
for (FCurve &fcu : agrp->channels) {
|
||||
if (fcu.grp != agrp) {
|
||||
break;
|
||||
}
|
||||
fcurve_to_keylist(adt, &fcu, keylist, saction_flag, range, true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* Layered actions. */
|
||||
animrig::Channelbag &channelbag = agrp->channelbag->wrap();
|
||||
Span<FCurve *> fcurves = channelbag.fcurves().slice(agrp->fcurve_range_start,
|
||||
|
|
|
|||
|
|
@ -199,14 +199,6 @@ static ActionSlot *rna_Action_slots_new(
|
|||
{
|
||||
animrig::Action &action = dna_action->wrap();
|
||||
|
||||
if (!action.is_action_layered()) {
|
||||
BKE_reportf(reports,
|
||||
RPT_ERROR,
|
||||
"Cannot add slots to a legacy Action '%s'. Convert it to a layered Action first.",
|
||||
action.id.name + 2);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (name[0] == 0) {
|
||||
BKE_reportf(reports, RPT_ERROR, "Invalid slot name '%s': name must not be empty.", name);
|
||||
return nullptr;
|
||||
|
|
@ -255,14 +247,6 @@ static ActionLayer *rna_Action_layers_new(bAction *dna_action,
|
|||
{
|
||||
animrig::Action &action = dna_action->wrap();
|
||||
|
||||
if (!action.is_action_layered()) {
|
||||
BKE_reportf(reports,
|
||||
RPT_ERROR,
|
||||
"Cannot add layers to a legacy Action '%s'. Convert it to a layered Action first.",
|
||||
action.id.name + 2);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (action.layers().size() >= 1) {
|
||||
/* Not allowed to have more than one layer, for now. This limitation is in
|
||||
* place until working with multiple animated IDs is fleshed out better. */
|
||||
|
|
@ -861,20 +845,6 @@ static void rna_ActionGroup_channels_begin(CollectionPropertyIterator *iter, Poi
|
|||
|
||||
iter->internal.custom = custom_iter;
|
||||
|
||||
/* We handle both the listbase (legacy action) and array (layered action)
|
||||
* cases below. The code for each is based on the code in
|
||||
* `rna_iterator_listbase_begin()` and `rna_iterator_array_begin()`,
|
||||
* respectively. */
|
||||
|
||||
/* Group from a legacy action. */
|
||||
if (group->wrap().is_legacy()) {
|
||||
custom_iter->tag = ActionGroupChannelsIterator::LISTBASE;
|
||||
custom_iter->listbase.link = static_cast<Link *>(group->channels.first);
|
||||
|
||||
iter->valid = custom_iter->listbase.link != nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Group from a layered action. */
|
||||
animrig::Channelbag &cbag = group->channelbag->wrap();
|
||||
|
||||
|
|
@ -1019,11 +989,14 @@ static bool rna_Action_is_empty_get(PointerRNA *ptr)
|
|||
}
|
||||
static bool rna_Action_is_action_legacy_get(PointerRNA *ptr)
|
||||
{
|
||||
return rna_action(ptr).is_action_legacy();
|
||||
/* All actions are versioned so legacy actions no longer exist. This RNA function should be
|
||||
* removed at the next opportunity. */
|
||||
return rna_action(ptr).is_empty();
|
||||
}
|
||||
static bool rna_Action_is_action_layered_get(PointerRNA *ptr)
|
||||
static bool rna_Action_is_action_layered_get(PointerRNA * /* ptr */)
|
||||
{
|
||||
return rna_action(ptr).is_action_layered();
|
||||
/*All actions are layered through versioning. */
|
||||
return true;
|
||||
}
|
||||
|
||||
static void rna_Action_frame_range_get(PointerRNA *ptr, float *r_values)
|
||||
|
|
@ -1133,31 +1106,16 @@ static FCurve *rna_Action_fcurve_ensure_for_datablock(bAction *_self,
|
|||
* Used to check if an action (value pointer)
|
||||
* is suitable to be assigned to the ID-block that is ptr.
|
||||
*/
|
||||
bool rna_Action_id_poll(PointerRNA *ptr, PointerRNA value)
|
||||
bool rna_Action_id_poll(PointerRNA * /* ptr */, PointerRNA value)
|
||||
{
|
||||
ID *srcId = ptr->owner_id;
|
||||
bAction *dna_action = id_cast<bAction *>(value.owner_id);
|
||||
|
||||
if (!dna_action) {
|
||||
return false;
|
||||
}
|
||||
|
||||
animrig::Action &action = dna_action->wrap();
|
||||
if (animrig::legacy::action_treat_as_legacy(action)) {
|
||||
/* there can still be actions that will have undefined id-root
|
||||
* (i.e. floating "action-library" members) which we will not
|
||||
* be able to resolve an idroot for automatically, so let these through
|
||||
*/
|
||||
if (action.idroot == 0) {
|
||||
return true;
|
||||
}
|
||||
if (srcId) {
|
||||
return GS(srcId->name) == action.idroot;
|
||||
}
|
||||
}
|
||||
|
||||
/* Layered Actions can always be assigned. */
|
||||
BLI_assert(action.idroot == 0);
|
||||
BLI_assert(dna_action->idroot == 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -2444,13 +2402,11 @@ static void rna_def_action(BlenderRNA *brna)
|
|||
|
||||
prop = RNA_def_property(srna, "is_action_legacy", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_clear_flag(prop, PROP_EDITABLE);
|
||||
RNA_def_property_ui_text(
|
||||
prop,
|
||||
"Is Legacy Action",
|
||||
"Return whether this is a legacy Action. Legacy Actions have no layers or slots. An "
|
||||
"empty Action is considered as both a 'legacy' and a 'layered' Action. Since Blender 4.4 "
|
||||
"actions are automatically updated to layered actions, and thus this will only return True "
|
||||
"when the action is empty");
|
||||
RNA_def_property_ui_text(prop,
|
||||
"Is Legacy Action",
|
||||
"Return whether this is a legacy Action. Legacy Actions have no layers "
|
||||
"or slots. Since Blender 4.4 actions are automatically updated to "
|
||||
"layered actions. This will only return true on empty actions");
|
||||
RNA_def_property_boolean_funcs(prop, "rna_Action_is_action_legacy_get", nullptr);
|
||||
|
||||
prop = RNA_def_property(srna, "is_action_layered", PROP_BOOLEAN, PROP_NONE);
|
||||
|
|
@ -2458,8 +2414,8 @@ static void rna_def_action(BlenderRNA *brna)
|
|||
RNA_def_property_ui_text(
|
||||
prop,
|
||||
"Is Layered Action",
|
||||
"Return whether this is a layered Action. An empty Action is considered "
|
||||
"as both a 'legacy' and a 'layered' Action.");
|
||||
"Return whether this is a layered Action. At this point all actions "
|
||||
"are layered through versioning and this function will always return true");
|
||||
RNA_def_property_boolean_funcs(prop, "rna_Action_is_action_layered_get", nullptr);
|
||||
|
||||
/* Collection properties. */
|
||||
|
|
|
|||
|
|
@ -95,11 +95,8 @@ void animation_backup_original(Scene *scene, AnimationBackup *backup)
|
|||
|
||||
assert_baklava_phase_1_invariants(action);
|
||||
|
||||
if (action.is_action_legacy()) {
|
||||
BLI_movelisttolist(&backup->curves, &scene->adt->action->curves);
|
||||
}
|
||||
else if (animrig::Channelbag *channelbag = animrig::channelbag_for_action_slot(
|
||||
action, scene->adt->slot_handle))
|
||||
if (animrig::Channelbag *channelbag = animrig::channelbag_for_action_slot(
|
||||
action, scene->adt->slot_handle))
|
||||
{
|
||||
animrig::channelbag_fcurves_move(backup->channelbag, *channelbag);
|
||||
}
|
||||
|
|
@ -119,18 +116,13 @@ void animation_restore_original(Scene *scene, AnimationBackup *backup)
|
|||
|
||||
assert_baklava_phase_1_invariants(action);
|
||||
|
||||
if (action.is_action_legacy()) {
|
||||
BLI_movelisttolist(&scene->adt->action->curves, &backup->curves);
|
||||
}
|
||||
else {
|
||||
animrig::Channelbag *channelbag = animrig::channelbag_for_action_slot(
|
||||
action, scene->adt->slot_handle);
|
||||
/* The channel bag should exist if we got here, because otherwise the
|
||||
* backup channel bag would have been empty. */
|
||||
BLI_assert(channelbag != nullptr);
|
||||
animrig::Channelbag *channelbag = animrig::channelbag_for_action_slot(action,
|
||||
scene->adt->slot_handle);
|
||||
/* The channel bag should exist if we got here, because otherwise the
|
||||
* backup channel bag would have been empty. */
|
||||
BLI_assert(channelbag != nullptr);
|
||||
|
||||
animrig::channelbag_fcurves_move(*channelbag, backup->channelbag);
|
||||
}
|
||||
animrig::channelbag_fcurves_move(*channelbag, backup->channelbag);
|
||||
}
|
||||
|
||||
if (!BLI_listbase_is_empty(&backup->drivers)) {
|
||||
|
|
|
|||
|
|
@ -578,7 +578,6 @@ class VersioningTest(unittest.TestCase):
|
|||
def test_nla_conversion(self):
|
||||
nla_object = bpy.data.objects["nla_object"]
|
||||
nla_anim_data = nla_object.animation_data
|
||||
self.assertTrue(nla_anim_data.action.is_action_layered)
|
||||
self.assertNotEqual(nla_anim_data.action_slot_handle, 0)
|
||||
|
||||
# The action that is not pushed into an NLA strip.
|
||||
|
|
@ -590,19 +589,15 @@ class VersioningTest(unittest.TestCase):
|
|||
self.assertEqual(fcurve.array_index, fcurve_index)
|
||||
|
||||
self.assertEqual(len(nla_anim_data.nla_tracks), 2)
|
||||
self.assertTrue(nla_anim_data.nla_tracks[0].strips[0].action.is_action_layered)
|
||||
self.assertNotEqual(nla_anim_data.nla_tracks[0].strips[0].action_slot_handle, 0)
|
||||
|
||||
self.assertTrue(nla_anim_data.nla_tracks[1].strips[0].action.is_action_layered)
|
||||
self.assertNotEqual(nla_anim_data.nla_tracks[1].strips[0].action_slot_handle, 0)
|
||||
|
||||
def test_multi_use_action(self):
|
||||
object_a = bpy.data.objects["multi_user_object_a"]
|
||||
object_b = bpy.data.objects["multi_user_object_b"]
|
||||
self.assertTrue(object_a.animation_data.action.is_action_layered)
|
||||
self.assertNotEqual(object_a.animation_data.action_slot_handle, 0)
|
||||
|
||||
self.assertTrue(object_b.animation_data.action.is_action_layered)
|
||||
self.assertNotEqual(object_b.animation_data.action_slot_handle, 0)
|
||||
|
||||
self.assertEqual(object_a.animation_data.action, object_b.animation_data.action)
|
||||
|
|
@ -620,12 +615,10 @@ class VersioningTest(unittest.TestCase):
|
|||
def test_action_constraint(self):
|
||||
constrained_object = bpy.data.objects["action_constraint_constrained"]
|
||||
action_constraint = constrained_object.constraints[0]
|
||||
self.assertTrue(action_constraint.action.is_action_layered)
|
||||
self.assertNotEqual(action_constraint.action_slot_handle, 0)
|
||||
|
||||
action_owner_object = bpy.data.objects["action_constraint_action_owner"]
|
||||
action = action_owner_object.animation_data.action
|
||||
self.assertTrue(action.is_action_layered)
|
||||
self.assertEqual(action, action_constraint.action)
|
||||
self.assertEqual(action_owner_object.animation_data.action_slot_handle, action_constraint.action_slot_handle)
|
||||
strip = action.layers[0].strips[0]
|
||||
|
|
@ -638,7 +631,6 @@ class VersioningTest(unittest.TestCase):
|
|||
def test_armature_action_conversion(self):
|
||||
armature_object = bpy.data.objects["armature_object"]
|
||||
action = armature_object.animation_data.action
|
||||
self.assertTrue(action.is_action_layered)
|
||||
strip = action.layers[0].strips[0]
|
||||
self.assertEqual(len(strip.channelbags[0].groups), 2)
|
||||
self.assertEqual(strip.channelbags[0].groups[0].name, "Bone")
|
||||
|
|
|
|||
|
|
@ -711,7 +711,6 @@ 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"
|
||||
|
|
@ -721,7 +720,6 @@ 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"
|
||||
|
|
@ -730,7 +728,6 @@ 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
|
||||
|
||||
|
|
|
|||
|
|
@ -122,7 +122,6 @@ class NLAStripActionSlotSelectionTest(AbstractNlaStripTest):
|
|||
def test_two_strips_for_same_action(self):
|
||||
action = bpy.data.actions.new("StripAction")
|
||||
action.slots.new('OBJECT', "Slot")
|
||||
self.assertTrue(action.is_action_layered)
|
||||
self.assertEqual(1, len(action.slots))
|
||||
|
||||
track = self.nla_tracks.new()
|
||||
|
|
@ -137,12 +136,10 @@ class NLAStripActionSlotSelectionTest(AbstractNlaStripTest):
|
|||
def test_switch_action_via_assignment(self):
|
||||
action1 = bpy.data.actions.new("StripAction 1")
|
||||
action1.slots.new('OBJECT', "Slot")
|
||||
self.assertTrue(action1.is_action_layered)
|
||||
self.assertEqual(1, len(action1.slots))
|
||||
|
||||
action2 = bpy.data.actions.new("StripAction 2")
|
||||
action2.slots.new('OBJECT', "Slot")
|
||||
self.assertTrue(action2.is_action_layered)
|
||||
self.assertEqual(1, len(action2.slots))
|
||||
|
||||
track = self.nla_tracks.new()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue