Refactor: rename "Animation data-block" to "Action"
Rename "Animation data-block" to "Action" or "Layered Action", where appropriate. Some uses of the term actually refer to the `AnimData` struct, in which case they were left as-is. No real functional changes, just changing some messages & descriptions. Pull Request: https://projects.blender.org/blender/blender/pulls/124170
This commit is contained in:
parent
c0364efec0
commit
0aa75ab57b
@ -113,7 +113,7 @@ def _wm_selected_action_update(wm, context):
|
||||
|
||||
def register_props():
|
||||
# Due to this hackyness, the WindowManager will increase the user count of
|
||||
# the pointed-to Animation data-block.
|
||||
# the pointed-to Action.
|
||||
WindowManager.selected_action = PointerProperty(
|
||||
type=bpy.types.Action,
|
||||
name="Action",
|
||||
|
@ -101,7 +101,7 @@ class Action : public ::bAction {
|
||||
*/
|
||||
bool is_action_layered() const;
|
||||
|
||||
/* Animation Layers access. */
|
||||
/* Action Layers access. */
|
||||
blender::Span<const Layer *> layers() const;
|
||||
blender::MutableSpan<Layer *> layers();
|
||||
const Layer *layer(int64_t index) const;
|
||||
@ -110,7 +110,7 @@ class Action : public ::bAction {
|
||||
Layer &layer_add(StringRefNull name);
|
||||
|
||||
/**
|
||||
* Remove the layer from this animation.
|
||||
* Remove the layer from this Action.
|
||||
*
|
||||
* After this call, the passed reference is no longer valid, as the memory
|
||||
* will have been freed. Any strips on the layer will be freed too.
|
||||
@ -125,7 +125,7 @@ class Action : public ::bAction {
|
||||
*/
|
||||
void layer_ensure_at_least_one();
|
||||
|
||||
/* Animation Slot access. */
|
||||
/* Action Slot access. */
|
||||
blender::Span<const Slot *> slots() const;
|
||||
blender::MutableSpan<Slot *> slots();
|
||||
const Slot *slot(int64_t index) const;
|
||||
@ -146,8 +146,8 @@ class Action : public ::bAction {
|
||||
* Set the slot name, ensure it is unique, and propagate the new name to
|
||||
* all data-blocks that use it.
|
||||
*
|
||||
* This has to be done on the Animation level to ensure each slot has a
|
||||
* unique name within the Animation.
|
||||
* This has to be done on the Action level to ensure each slot has a
|
||||
* unique name within the Action.
|
||||
*
|
||||
* \note This does NOT ensure the first two characters match the ID type of
|
||||
* this slot. This is the caller's responsibility.
|
||||
@ -191,7 +191,7 @@ class Action : public ::bAction {
|
||||
/**
|
||||
* Create a new slot, named after the given ID, and limited to the ID's type.
|
||||
*
|
||||
* Note that this assigns neither this Animation nor the new Slot to the ID. This function
|
||||
* Note that this assigns neither this Action nor the new Slot to the ID. This function
|
||||
* merely initializes the Slot itself to suitable values to start animating this ID.
|
||||
*/
|
||||
Slot &slot_add_for_id(const ID &animated_id);
|
||||
@ -216,21 +216,21 @@ class Action : public ::bAction {
|
||||
*/
|
||||
Slot &slot_ensure_for_id(const ID &animated_id);
|
||||
|
||||
/** Assign this animation to the ID.
|
||||
/** Assign this Action to the ID.
|
||||
*
|
||||
* \param slot: The slot this ID should be animated by, may be nullptr if it is to be
|
||||
* assigned later. In that case, the ID will not actually receive any animation.
|
||||
* \param animated_id: The ID that should be animated by this Animation data-block.
|
||||
* \param animated_id: The ID that should be animated by this Action.
|
||||
*
|
||||
* \return whether the assignment was successful.
|
||||
*/
|
||||
bool assign_id(Slot *slot, ID &animated_id);
|
||||
|
||||
/**
|
||||
* Unassign this Animation from the animated ID.
|
||||
* Unassign this Action from the animated ID.
|
||||
*
|
||||
* \param animated_id: ID that is animated by this Animation. Calling this
|
||||
* function when this ID is _not_ animated by this Animation is not allowed,
|
||||
* \param animated_id: ID that is animated by this Action. Calling this
|
||||
* function when this ID is _not_ animated by this Action is not allowed,
|
||||
* and considered a bug.
|
||||
*/
|
||||
void unassign_id(ID &animated_id);
|
||||
@ -238,19 +238,19 @@ class Action : public ::bAction {
|
||||
/**
|
||||
* Find the slot that best matches the animated ID.
|
||||
*
|
||||
* If the ID is already animated by this Animation, by matching this
|
||||
* Animation's slots with (in order):
|
||||
* If the ID is already animated by this Action, by matching this
|
||||
* Action's slots with (in order):
|
||||
*
|
||||
* - `animated_id.adt->slot_handle`,
|
||||
* - `animated_id.adt->slot_name`,
|
||||
* - `animated_id.name`.
|
||||
*
|
||||
* Note that this is different from #slot_for_id, which does not use the
|
||||
* slot name, and only works when this Animation is already assigned. */
|
||||
* slot name, and only works when this Action is already assigned. */
|
||||
Slot *find_suitable_slot_for(const ID &animated_id);
|
||||
|
||||
/**
|
||||
* Return whether this Animation actually has any animation data for the given slot.
|
||||
* Return whether this Action actually has any animation data for the given slot.
|
||||
*/
|
||||
bool is_slot_animated(slot_handle_t slot_handle) const;
|
||||
|
||||
@ -264,7 +264,7 @@ class Action : public ::bAction {
|
||||
Layer *get_layer_for_keyframing();
|
||||
|
||||
protected:
|
||||
/** Return the layer's index, or -1 if not found in this animation. */
|
||||
/** Return the layer's index, or -1 if not found in this Action. */
|
||||
int64_t find_layer_index(const Layer &layer) const;
|
||||
|
||||
private:
|
||||
@ -283,7 +283,7 @@ class Action : public ::bAction {
|
||||
/**
|
||||
* Set the slot's ID type to that of the animated ID, ensure the name
|
||||
* prefix is set accordingly, and that the name is unique within the
|
||||
* Animation.
|
||||
* Action.
|
||||
*
|
||||
* \note This assumes that the slot has no ID type set yet. If it does, it
|
||||
* is considered a bug to call this function.
|
||||
@ -575,7 +575,7 @@ class Slot : public ::ActionSlot {
|
||||
/**
|
||||
* Ensure the first two characters of the name match the ID type.
|
||||
*
|
||||
* \note This does NOT ensure name uniqueness within the Animation. That is
|
||||
* \note This does NOT ensure name uniqueness within the Action. That is
|
||||
* the responsibility of the caller.
|
||||
*/
|
||||
void name_ensure_prefix();
|
||||
@ -677,7 +677,7 @@ static_assert(sizeof(ChannelBag) == sizeof(::ActionChannelBag),
|
||||
"DNA struct and its C++ wrapper must have the same size");
|
||||
|
||||
/**
|
||||
* Assign the animation to the ID.
|
||||
* Assign the Action to the ID.
|
||||
*
|
||||
* This will will make a best-effort guess as to which slot to use, in this
|
||||
* order;
|
||||
@ -691,9 +691,9 @@ static_assert(sizeof(ChannelBag) == sizeof(::ActionChannelBag),
|
||||
*
|
||||
* \return `false` if the assignment was not possible (for example the ID is of a type that cannot
|
||||
* be animated). If the above fall-through case of "no slot found" is reached, this function
|
||||
* will still return `true` as the Animation was successfully assigned.
|
||||
* will still return `true` as the Action was successfully assigned.
|
||||
*/
|
||||
bool assign_animation(Action &anim, ID &animated_id);
|
||||
bool assign_action(Action &action, ID &animated_id);
|
||||
|
||||
/**
|
||||
* Return whether the given Action can be assigned to the ID.
|
||||
@ -706,10 +706,10 @@ bool is_action_assignable_to(const bAction *dna_action, ID_Type id_code);
|
||||
/**
|
||||
* Ensure that this ID is no longer animated.
|
||||
*/
|
||||
void unassign_animation(ID &animated_id);
|
||||
void unassign_action(ID &animated_id);
|
||||
|
||||
/**
|
||||
* Clear the animation slot of this ID.
|
||||
* Clear the Action slot of this ID.
|
||||
*
|
||||
* `adt.slot_handle_name` is updated to reflect the current name of the
|
||||
* slot, before un-assigning. This is to ensure that the stored name reflects
|
||||
@ -717,14 +717,14 @@ void unassign_animation(ID &animated_id);
|
||||
*
|
||||
* \param animated_id: the animated ID.
|
||||
*
|
||||
* \note this does not clear the Animation pointer, just the slot handle.
|
||||
* \note this does not clear the Action pointer, just the slot handle.
|
||||
*/
|
||||
void unassign_slot(ID &animated_id);
|
||||
|
||||
/**
|
||||
* Return the Animation of this ID, or nullptr if it has none.
|
||||
* Return the Action of this ID, or nullptr if it has none.
|
||||
*/
|
||||
Action *get_animation(ID &animated_id);
|
||||
Action *get_action(ID &animated_id);
|
||||
|
||||
/**
|
||||
* Get the Action and the Slot that animate this ID.
|
||||
@ -740,33 +740,33 @@ std::optional<std::pair<Action *, Slot *>> get_action_slot_pair(ID &animated_id)
|
||||
/**
|
||||
* Return the F-Curves for this specific slot handle.
|
||||
*
|
||||
* This is just a utility function, that's intended to become obsolete when multi-layer animation
|
||||
* is introduced. However, since Blender currently only supports a single layer with a single
|
||||
* This is just a utility function, that's intended to become obsolete when multi-layer Actions
|
||||
* are introduced. However, since Blender currently only supports a single layer with a single
|
||||
* strip, of a single type, this function can be used.
|
||||
*
|
||||
* The use of this function is also an indicator for code that will have to be altered when
|
||||
* multi-layered animation is getting implemented.
|
||||
* multi-layered Actions are getting implemented.
|
||||
*/
|
||||
Span<FCurve *> fcurves_for_animation(Action &anim, slot_handle_t slot_handle);
|
||||
Span<const FCurve *> fcurves_for_animation(const Action &anim, slot_handle_t slot_handle);
|
||||
Span<FCurve *> fcurves_for_action_slot(Action &action, slot_handle_t slot_handle);
|
||||
Span<const FCurve *> fcurves_for_action_slot(const Action &action, slot_handle_t slot_handle);
|
||||
|
||||
/**
|
||||
* Return all F-Curves in the Action.
|
||||
*
|
||||
* This works for both legacy and layered Actions.
|
||||
*
|
||||
* This is a utility function whose purpose is unclear after multi-layer animation is introduced.
|
||||
* This is a utility function whose purpose is unclear after multi-layer Actions are introduced.
|
||||
* It might still be useful, it might not be.
|
||||
|
||||
* The use of this function is an indicator for code that might have to be altered when
|
||||
* multi-layered animation is getting implemented.
|
||||
* multi-layered Actions are getting implemented.
|
||||
*/
|
||||
Vector<const FCurve *> fcurves_all(const Action &action);
|
||||
Vector<FCurve *> fcurves_all(Action &action);
|
||||
|
||||
/**
|
||||
* Get (or add relevant data to be able to do so) F-Curve from the given Action,
|
||||
* for the given Animation Data block. This assumes that all the destinations are valid.
|
||||
* Get (or add relevant data to be able to do so) an F-Curve from the given Action,
|
||||
* for the given animated data-block. This assumes that all the destinations are valid.
|
||||
* \param ptr: can be a null pointer.
|
||||
*/
|
||||
FCurve *action_fcurve_ensure(Main *bmain,
|
||||
|
@ -5,7 +5,7 @@
|
||||
/** \file
|
||||
* \ingroup animrig
|
||||
*
|
||||
* \brief Animation data-block evaluation.
|
||||
* \brief Layered Action evaluation.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
@ -26,10 +26,10 @@ namespace blender::animrig {
|
||||
* \param flush_to_original: when true, look up the original data-block (assuming
|
||||
* the given one is an evaluated copy) and update that too.
|
||||
*/
|
||||
void evaluate_and_apply_animation(PointerRNA &animated_id_ptr,
|
||||
Action &animation,
|
||||
slot_handle_t slot_handle,
|
||||
const AnimationEvalContext &anim_eval_context,
|
||||
bool flush_to_original);
|
||||
void evaluate_and_apply_action(PointerRNA &animated_id_ptr,
|
||||
Action &action,
|
||||
slot_handle_t slot_handle,
|
||||
const AnimationEvalContext &anim_eval_context,
|
||||
bool flush_to_original);
|
||||
|
||||
} // namespace blender::animrig
|
||||
|
@ -52,7 +52,7 @@ namespace blender::animrig {
|
||||
|
||||
namespace {
|
||||
/**
|
||||
* Default name for animation slots. The first two characters in the name indicate the ID type
|
||||
* Default name for action slots. The first two characters in the name indicate the ID type
|
||||
* of whatever is animated by it.
|
||||
*
|
||||
* Since the ID type may not be determined when the slot is created, the prefix starts out at
|
||||
@ -95,7 +95,7 @@ template<typename T> static void grow_array(T **array, int *num, const int add_n
|
||||
BLI_assert(add_num > 0);
|
||||
const int new_array_num = *num + add_num;
|
||||
T *new_array = reinterpret_cast<T *>(
|
||||
MEM_cnew_array<T *>(new_array_num, "animrig::animation/grow_array"));
|
||||
MEM_cnew_array<T *>(new_array_num, "animrig::action/grow_array"));
|
||||
|
||||
blender::uninitialized_relocate_n(*array, *num, new_array);
|
||||
MEM_SAFE_FREE(*array);
|
||||
@ -123,7 +123,7 @@ template<typename T> static void shrink_array(T **array, int *num, const int shr
|
||||
*num = new_array_num;
|
||||
}
|
||||
|
||||
/* ----- Animation implementation ----------- */
|
||||
/* ----- Action implementation ----------- */
|
||||
|
||||
bool Action::is_empty() const
|
||||
{
|
||||
@ -262,19 +262,19 @@ const Slot *Action::slot_for_handle(const slot_handle_t handle) const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static void anim_slot_name_ensure_unique(Action &animation, Slot &slot)
|
||||
static void slot_name_ensure_unique(Action &action, Slot &slot)
|
||||
{
|
||||
/* Cannot capture parameters by reference in the lambda, as that would change its signature
|
||||
* and no longer be compatible with BLI_uniquename_cb(). That's why this struct is necessary. */
|
||||
struct DupNameCheckData {
|
||||
Action &anim;
|
||||
Action &action;
|
||||
Slot &slot;
|
||||
};
|
||||
DupNameCheckData check_data = {animation, slot};
|
||||
DupNameCheckData check_data = {action, slot};
|
||||
|
||||
auto check_name_is_used = [](void *arg, const char *name) -> bool {
|
||||
DupNameCheckData *data = static_cast<DupNameCheckData *>(arg);
|
||||
for (const Slot *slot : data->anim.slots()) {
|
||||
for (const Slot *slot : data->action.slots()) {
|
||||
if (slot == &data->slot) {
|
||||
/* Don't compare against the slot that's being renamed. */
|
||||
continue;
|
||||
@ -302,9 +302,9 @@ void Action::slot_name_set(Main &bmain, Slot &slot, const StringRefNull new_name
|
||||
void Action::slot_name_define(Slot &slot, const StringRefNull new_name)
|
||||
{
|
||||
BLI_assert_msg(StringRef(new_name).size() >= Slot::name_length_min,
|
||||
"Animation Slots must be large enough for a 2-letter ID code + the display name");
|
||||
"Action Slots must be large enough for a 2-letter ID code + the display name");
|
||||
STRNCPY_UTF8(slot.name, new_name.c_str());
|
||||
anim_slot_name_ensure_unique(*this, slot);
|
||||
slot_name_ensure_unique(*this, slot);
|
||||
}
|
||||
|
||||
void Action::slot_name_propagate(Main &bmain, const Slot &slot)
|
||||
@ -322,7 +322,7 @@ void Action::slot_name_propagate(Main &bmain, const Slot &slot)
|
||||
|
||||
AnimData *adt = BKE_animdata_from_id(id);
|
||||
if (!adt || adt->action != this) {
|
||||
/* Not animated by this Animation. */
|
||||
/* Not animated by this Action. */
|
||||
continue;
|
||||
}
|
||||
if (adt->slot_handle != slot.handle) {
|
||||
@ -352,7 +352,7 @@ Slot &Action::slot_allocate()
|
||||
{
|
||||
Slot &slot = *MEM_new<Slot>(__func__);
|
||||
this->last_slot_handle++;
|
||||
BLI_assert_msg(this->last_slot_handle > 0, "Animation Slot handle overflow");
|
||||
BLI_assert_msg(this->last_slot_handle > 0, "Action Slot handle overflow");
|
||||
slot.handle = this->last_slot_handle;
|
||||
|
||||
/* Set the default flags. These cannot be set via the 'DNA defaults' system,
|
||||
@ -373,7 +373,7 @@ Slot &Action::slot_add()
|
||||
/* Append the Slot to the Action. */
|
||||
grow_array_and_append<::ActionSlot *>(&this->slot_array, &this->slot_array_num, &slot);
|
||||
|
||||
anim_slot_name_ensure_unique(*this, slot);
|
||||
slot_name_ensure_unique(*this, slot);
|
||||
|
||||
/* If this is the first slot in this Action, it means that it could have
|
||||
* been used as a legacy Action before. As a result, this->idroot may be
|
||||
@ -444,7 +444,7 @@ bool Action::is_slot_animated(const slot_handle_t slot_handle) const
|
||||
return false;
|
||||
}
|
||||
|
||||
Span<const FCurve *> fcurves = fcurves_for_animation(*this, slot_handle);
|
||||
Span<const FCurve *> fcurves = fcurves_for_action_slot(*this, slot_handle);
|
||||
return !fcurves.is_empty();
|
||||
}
|
||||
|
||||
@ -468,7 +468,7 @@ bool Action::assign_id(Slot *slot, ID &animated_id)
|
||||
|
||||
if (adt->action && adt->action != this) {
|
||||
/* The caller should unassign the ID from its existing animation first, or
|
||||
* use the top-level function `assign_animation(anim, ID)`. */
|
||||
* use the top-level function `assign_action(anim, ID)`. */
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -520,7 +520,7 @@ bool Action::assign_id(Slot *slot, ID &animated_id)
|
||||
void Action::slot_name_ensure_prefix(Slot &slot)
|
||||
{
|
||||
slot.name_ensure_prefix();
|
||||
anim_slot_name_ensure_unique(*this, slot);
|
||||
slot_name_ensure_unique(*this, slot);
|
||||
}
|
||||
|
||||
void Action::slot_setup_for_id(Slot &slot, const ID &animated_id)
|
||||
@ -747,12 +747,12 @@ void Slot::users_invalidate(Main &bmain)
|
||||
|
||||
/* ----- Functions ----------- */
|
||||
|
||||
bool assign_animation(Action &anim, ID &animated_id)
|
||||
bool assign_action(Action &action, ID &animated_id)
|
||||
{
|
||||
unassign_animation(animated_id);
|
||||
unassign_action(animated_id);
|
||||
|
||||
Slot *slot = anim.find_suitable_slot_for(animated_id);
|
||||
return anim.assign_id(slot, animated_id);
|
||||
Slot *slot = action.find_suitable_slot_for(animated_id);
|
||||
return action.assign_id(slot, animated_id);
|
||||
}
|
||||
|
||||
bool is_action_assignable_to(const bAction *dna_action, const ID_Type id_code)
|
||||
@ -779,13 +779,13 @@ bool is_action_assignable_to(const bAction *dna_action, const ID_Type id_code)
|
||||
return true;
|
||||
}
|
||||
|
||||
void unassign_animation(ID &animated_id)
|
||||
void unassign_action(ID &animated_id)
|
||||
{
|
||||
Action *anim = get_animation(animated_id);
|
||||
if (!anim) {
|
||||
Action *action = get_action(animated_id);
|
||||
if (!action) {
|
||||
return;
|
||||
}
|
||||
anim->unassign_id(animated_id);
|
||||
action->unassign_id(animated_id);
|
||||
}
|
||||
|
||||
void unassign_slot(ID &animated_id)
|
||||
@ -809,7 +809,7 @@ void unassign_slot(ID &animated_id)
|
||||
}
|
||||
|
||||
/* TODO: rename to get_action(). */
|
||||
Action *get_animation(ID &animated_id)
|
||||
Action *get_action(ID &animated_id)
|
||||
{
|
||||
AnimData *adt = BKE_animdata_from_id(&animated_id);
|
||||
if (!adt) {
|
||||
@ -1179,14 +1179,14 @@ const FCurve *ChannelBag::fcurve_find(const StringRefNull rna_path, const int ar
|
||||
|
||||
/* Utility function implementations. */
|
||||
|
||||
static const animrig::ChannelBag *channelbag_for_animation(const Action &anim,
|
||||
const slot_handle_t slot_handle)
|
||||
static const animrig::ChannelBag *channelbag_for_action_slot(const Action &action,
|
||||
const slot_handle_t slot_handle)
|
||||
{
|
||||
if (slot_handle == Slot::unassigned) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (const animrig::Layer *layer : anim.layers()) {
|
||||
for (const animrig::Layer *layer : action.layers()) {
|
||||
for (const animrig::Strip *strip : layer->strips()) {
|
||||
switch (strip->type()) {
|
||||
case animrig::Strip::Type::Keyframe: {
|
||||
@ -1203,25 +1203,26 @@ static const animrig::ChannelBag *channelbag_for_animation(const Action &anim,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static animrig::ChannelBag *channelbag_for_animation(Action &anim, const slot_handle_t slot_handle)
|
||||
static animrig::ChannelBag *channelbag_for_action_slot(Action &action,
|
||||
const slot_handle_t slot_handle)
|
||||
{
|
||||
const animrig::ChannelBag *const_bag = channelbag_for_animation(const_cast<const Action &>(anim),
|
||||
slot_handle);
|
||||
const animrig::ChannelBag *const_bag = channelbag_for_action_slot(
|
||||
const_cast<const Action &>(action), slot_handle);
|
||||
return const_cast<animrig::ChannelBag *>(const_bag);
|
||||
}
|
||||
|
||||
Span<FCurve *> fcurves_for_animation(Action &anim, const slot_handle_t slot_handle)
|
||||
Span<FCurve *> fcurves_for_action_slot(Action &action, const slot_handle_t slot_handle)
|
||||
{
|
||||
animrig::ChannelBag *bag = channelbag_for_animation(anim, slot_handle);
|
||||
animrig::ChannelBag *bag = channelbag_for_action_slot(action, slot_handle);
|
||||
if (!bag) {
|
||||
return {};
|
||||
}
|
||||
return bag->fcurves();
|
||||
}
|
||||
|
||||
Span<const FCurve *> fcurves_for_animation(const Action &anim, const slot_handle_t slot_handle)
|
||||
Span<const FCurve *> fcurves_for_action_slot(const Action &action, const slot_handle_t slot_handle)
|
||||
{
|
||||
const animrig::ChannelBag *bag = channelbag_for_animation(anim, slot_handle);
|
||||
const animrig::ChannelBag *bag = channelbag_for_action_slot(action, slot_handle);
|
||||
if (!bag) {
|
||||
return {};
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ namespace blender::animrig::tests {
|
||||
class ActionLayersTest : public testing::Test {
|
||||
public:
|
||||
Main *bmain;
|
||||
Action *anim;
|
||||
Action *action;
|
||||
Object *cube;
|
||||
Object *suzanne;
|
||||
|
||||
@ -48,7 +48,7 @@ class ActionLayersTest : public testing::Test {
|
||||
void SetUp() override
|
||||
{
|
||||
bmain = BKE_main_new();
|
||||
anim = static_cast<Action *>(BKE_id_new(bmain, ID_AC, "ACÄnimåtië"));
|
||||
action = static_cast<Action *>(BKE_id_new(bmain, ID_AC, "ACÄnimåtië"));
|
||||
cube = BKE_object_add_only_object(bmain, OB_EMPTY, "Küüübus");
|
||||
suzanne = BKE_object_add_only_object(bmain, OB_EMPTY, "OBSuzanne");
|
||||
}
|
||||
@ -61,12 +61,12 @@ class ActionLayersTest : public testing::Test {
|
||||
|
||||
TEST_F(ActionLayersTest, add_layer)
|
||||
{
|
||||
Layer &layer = anim->layer_add("layer name");
|
||||
Layer &layer = action->layer_add("layer name");
|
||||
|
||||
EXPECT_EQ(anim->layer(0), &layer);
|
||||
EXPECT_EQ(action->layer(0), &layer);
|
||||
EXPECT_EQ("layer name", std::string(layer.name));
|
||||
EXPECT_EQ(1.0f, layer.influence) << "Expected DNA defaults to be used.";
|
||||
EXPECT_EQ(0, anim->layer_active_index)
|
||||
EXPECT_EQ(0, action->layer_active_index)
|
||||
<< "Expected newly added layer to become the active layer.";
|
||||
ASSERT_EQ(0, layer.strips().size()) << "Expected newly added layer to have no strip.";
|
||||
}
|
||||
@ -76,19 +76,20 @@ TEST_F(ActionLayersTest, add_layer__reset_idroot)
|
||||
/* An empty Action is a valid legacy Action, and thus can have its idroot set to a non-zero
|
||||
* value. If such an Action gets a layer, it no longer is a valid legacy Action, and thus its
|
||||
* idtype should be reset to zero. */
|
||||
anim->idroot = ID_CA; /* Fake that this was assigned to a camera data-block. */
|
||||
ASSERT_NE(0, anim->idroot) << "anim->idroot should not be zero at the start of this test.";
|
||||
action->idroot = ID_CA; /* Fake that this was assigned to a camera data-block. */
|
||||
ASSERT_NE(0, action->idroot) << "action->idroot should not be zero at the start of this test.";
|
||||
|
||||
anim->layer_add("layer name");
|
||||
action->layer_add("layer name");
|
||||
|
||||
EXPECT_EQ(0, anim->idroot) << "anim->idroot should get reset when the Action becomes layered.";
|
||||
EXPECT_EQ(0, action->idroot)
|
||||
<< "action->idroot should get reset when the Action becomes layered.";
|
||||
}
|
||||
|
||||
TEST_F(ActionLayersTest, remove_layer)
|
||||
{
|
||||
Layer &layer0 = anim->layer_add("Test Læür nul");
|
||||
Layer &layer1 = anim->layer_add("Test Læür één");
|
||||
Layer &layer2 = anim->layer_add("Test Læür twee");
|
||||
Layer &layer0 = action->layer_add("Test Læür nul");
|
||||
Layer &layer1 = action->layer_add("Test Læür één");
|
||||
Layer &layer2 = action->layer_add("Test Læür twee");
|
||||
|
||||
/* Add some strips to check that they are freed correctly too (implicitly by the
|
||||
* memory leak checker). */
|
||||
@ -99,27 +100,27 @@ TEST_F(ActionLayersTest, remove_layer)
|
||||
{ /* Test removing a layer that is not owned. */
|
||||
Action *other_anim = static_cast<Action *>(BKE_id_new(bmain, ID_AC, "ACOtherAnim"));
|
||||
Layer &other_layer = other_anim->layer_add("Another Layer");
|
||||
EXPECT_FALSE(anim->layer_remove(other_layer))
|
||||
<< "Removing a layer not owned by the animation should be gracefully rejected";
|
||||
EXPECT_FALSE(action->layer_remove(other_layer))
|
||||
<< "Removing a layer not owned by the Action should be gracefully rejected";
|
||||
BKE_id_free(bmain, &other_anim->id);
|
||||
}
|
||||
|
||||
EXPECT_TRUE(anim->layer_remove(layer1));
|
||||
EXPECT_EQ(2, anim->layers().size());
|
||||
EXPECT_STREQ(layer0.name, anim->layer(0)->name);
|
||||
EXPECT_STREQ(layer2.name, anim->layer(1)->name);
|
||||
EXPECT_TRUE(action->layer_remove(layer1));
|
||||
EXPECT_EQ(2, action->layers().size());
|
||||
EXPECT_STREQ(layer0.name, action->layer(0)->name);
|
||||
EXPECT_STREQ(layer2.name, action->layer(1)->name);
|
||||
|
||||
EXPECT_TRUE(anim->layer_remove(layer2));
|
||||
EXPECT_EQ(1, anim->layers().size());
|
||||
EXPECT_STREQ(layer0.name, anim->layer(0)->name);
|
||||
EXPECT_TRUE(action->layer_remove(layer2));
|
||||
EXPECT_EQ(1, action->layers().size());
|
||||
EXPECT_STREQ(layer0.name, action->layer(0)->name);
|
||||
|
||||
EXPECT_TRUE(anim->layer_remove(layer0));
|
||||
EXPECT_EQ(0, anim->layers().size());
|
||||
EXPECT_TRUE(action->layer_remove(layer0));
|
||||
EXPECT_EQ(0, action->layers().size());
|
||||
}
|
||||
|
||||
TEST_F(ActionLayersTest, add_strip)
|
||||
{
|
||||
Layer &layer = anim->layer_add("Test Læür");
|
||||
Layer &layer = action->layer_add("Test Læür");
|
||||
|
||||
Strip &strip = layer.strip_add(Strip::Type::Keyframe);
|
||||
ASSERT_EQ(1, layer.strips().size());
|
||||
@ -140,7 +141,7 @@ TEST_F(ActionLayersTest, add_strip)
|
||||
|
||||
/* Add some keys to check that also the strip data is freed correctly. */
|
||||
const KeyframeSettings settings = get_keyframe_settings(false);
|
||||
Slot &slot = anim->slot_add();
|
||||
Slot &slot = action->slot_add();
|
||||
strip.as<KeyframeStrip>().keyframe_insert(slot, {"location", 0}, {1.0f, 47.0f}, settings);
|
||||
another_strip.as<KeyframeStrip>().keyframe_insert(
|
||||
slot, {"location", 0}, {1.0f, 47.0f}, settings);
|
||||
@ -148,14 +149,14 @@ TEST_F(ActionLayersTest, add_strip)
|
||||
|
||||
TEST_F(ActionLayersTest, remove_strip)
|
||||
{
|
||||
Layer &layer = anim->layer_add("Test Læür");
|
||||
Layer &layer = action->layer_add("Test Læür");
|
||||
Strip &strip0 = layer.strip_add(Strip::Type::Keyframe);
|
||||
Strip &strip1 = layer.strip_add(Strip::Type::Keyframe);
|
||||
Strip &strip2 = layer.strip_add(Strip::Type::Keyframe);
|
||||
|
||||
/* Add some keys to check that also the strip data is freed correctly. */
|
||||
const KeyframeSettings settings = get_keyframe_settings(false);
|
||||
Slot &slot = anim->slot_add();
|
||||
Slot &slot = action->slot_add();
|
||||
strip0.as<KeyframeStrip>().keyframe_insert(slot, {"location", 0}, {1.0f, 47.0f}, settings);
|
||||
strip1.as<KeyframeStrip>().keyframe_insert(slot, {"location", 0}, {1.0f, 47.0f}, settings);
|
||||
strip2.as<KeyframeStrip>().keyframe_insert(slot, {"location", 0}, {1.0f, 47.0f}, settings);
|
||||
@ -173,7 +174,7 @@ TEST_F(ActionLayersTest, remove_strip)
|
||||
EXPECT_EQ(0, layer.strips().size());
|
||||
|
||||
{ /* Test removing a strip that is not owned. */
|
||||
Layer &other_layer = anim->layer_add("Another Layer");
|
||||
Layer &other_layer = action->layer_add("Another Layer");
|
||||
Strip &other_strip = other_layer.strip_add(Strip::Type::Keyframe);
|
||||
|
||||
EXPECT_FALSE(layer.strip_remove(other_strip))
|
||||
@ -183,7 +184,7 @@ TEST_F(ActionLayersTest, remove_strip)
|
||||
|
||||
TEST_F(ActionLayersTest, add_remove_strip_of_concrete_type)
|
||||
{
|
||||
Layer &layer = anim->layer_add("Test Læür");
|
||||
Layer &layer = action->layer_add("Test Læür");
|
||||
KeyframeStrip &key_strip = layer.strip_add<KeyframeStrip>();
|
||||
|
||||
/* key_strip is of type KeyframeStrip, but should be implicitly converted to a
|
||||
@ -194,8 +195,8 @@ TEST_F(ActionLayersTest, add_remove_strip_of_concrete_type)
|
||||
TEST_F(ActionLayersTest, add_slot)
|
||||
{
|
||||
{ /* Creating an 'unused' Slot should just be called 'Slot'. */
|
||||
Slot &slot = anim->slot_add();
|
||||
EXPECT_EQ(1, anim->last_slot_handle);
|
||||
Slot &slot = action->slot_add();
|
||||
EXPECT_EQ(1, action->last_slot_handle);
|
||||
EXPECT_EQ(1, slot.handle);
|
||||
|
||||
EXPECT_STREQ("XXSlot", slot.name);
|
||||
@ -203,8 +204,8 @@ TEST_F(ActionLayersTest, add_slot)
|
||||
}
|
||||
|
||||
{ /* Creating a Slot for a specific ID should name it after the ID. */
|
||||
Slot &slot = anim->slot_add_for_id(cube->id);
|
||||
EXPECT_EQ(2, anim->last_slot_handle);
|
||||
Slot &slot = action->slot_add_for_id(cube->id);
|
||||
EXPECT_EQ(2, action->last_slot_handle);
|
||||
EXPECT_EQ(2, slot.handle);
|
||||
|
||||
EXPECT_STREQ(cube->id.name, slot.name);
|
||||
@ -217,33 +218,34 @@ TEST_F(ActionLayersTest, add_slot__reset_idroot)
|
||||
/* An empty Action is a valid legacy Action, and thus can have its idroot set
|
||||
* to a non-zero value. If such an Action gets a slot, it no longer is a
|
||||
* valid legacy Action, and thus its idtype should be reset to zero. */
|
||||
anim->idroot = ID_CA; /* Fake that this was assigned to a camera data-block. */
|
||||
ASSERT_NE(0, anim->idroot) << "anim->idroot should not be zero at the start of this test.";
|
||||
action->idroot = ID_CA; /* Fake that this was assigned to a camera data-block. */
|
||||
ASSERT_NE(0, action->idroot) << "action->idroot should not be zero at the start of this test.";
|
||||
|
||||
anim->slot_add();
|
||||
action->slot_add();
|
||||
|
||||
EXPECT_EQ(0, anim->idroot) << "anim->idroot should get reset when the Action becomes layered.";
|
||||
EXPECT_EQ(0, action->idroot)
|
||||
<< "action->idroot should get reset when the Action becomes layered.";
|
||||
}
|
||||
|
||||
TEST_F(ActionLayersTest, add_slot_multiple)
|
||||
{
|
||||
Slot &bind_cube = anim->slot_add();
|
||||
Slot &bind_suzanne = anim->slot_add();
|
||||
EXPECT_TRUE(anim->assign_id(&bind_cube, cube->id));
|
||||
EXPECT_TRUE(anim->assign_id(&bind_suzanne, suzanne->id));
|
||||
Slot &bind_cube = action->slot_add();
|
||||
Slot &bind_suzanne = action->slot_add();
|
||||
EXPECT_TRUE(action->assign_id(&bind_cube, cube->id));
|
||||
EXPECT_TRUE(action->assign_id(&bind_suzanne, suzanne->id));
|
||||
|
||||
EXPECT_EQ(2, anim->last_slot_handle);
|
||||
EXPECT_EQ(2, action->last_slot_handle);
|
||||
EXPECT_EQ(1, bind_cube.handle);
|
||||
EXPECT_EQ(2, bind_suzanne.handle);
|
||||
}
|
||||
|
||||
TEST_F(ActionLayersTest, anim_assign_id)
|
||||
TEST_F(ActionLayersTest, action_assign_id)
|
||||
{
|
||||
/* Assign to the only, 'virgin' Slot, should always work. */
|
||||
Slot &slot_cube = anim->slot_add();
|
||||
Slot &slot_cube = action->slot_add();
|
||||
ASSERT_NE(nullptr, slot_cube.runtime);
|
||||
ASSERT_STREQ(slot_cube.name, "XXSlot");
|
||||
ASSERT_TRUE(anim->assign_id(&slot_cube, cube->id));
|
||||
ASSERT_TRUE(action->assign_id(&slot_cube, cube->id));
|
||||
EXPECT_EQ(slot_cube.handle, cube->adt->slot_handle);
|
||||
EXPECT_STREQ(slot_cube.name, "OBSlot");
|
||||
EXPECT_STREQ(slot_cube.name, cube->adt->slot_name)
|
||||
@ -253,7 +255,7 @@ TEST_F(ActionLayersTest, anim_assign_id)
|
||||
<< "Expecting Cube to be registered as animated by its slot.";
|
||||
|
||||
/* Assign another ID to the same Slot. */
|
||||
ASSERT_TRUE(anim->assign_id(&slot_cube, suzanne->id));
|
||||
ASSERT_TRUE(action->assign_id(&slot_cube, suzanne->id));
|
||||
EXPECT_STREQ(slot_cube.name, "OBSlot");
|
||||
EXPECT_STREQ(slot_cube.name, cube->adt->slot_name)
|
||||
<< "The slot name should be copied to the adt";
|
||||
@ -261,45 +263,45 @@ TEST_F(ActionLayersTest, anim_assign_id)
|
||||
EXPECT_TRUE(slot_cube.users(*bmain).contains(&cube->id))
|
||||
<< "Expecting Suzanne to be registered as animated by the Cube slot.";
|
||||
|
||||
{ /* Assign Cube to another animation+slot without unassigning first. */
|
||||
{ /* Assign Cube to another action+slot without unassigning first. */
|
||||
Action *another_anim = static_cast<Action *>(BKE_id_new(bmain, ID_AC, "ACOtherAnim"));
|
||||
Slot &another_slot = another_anim->slot_add();
|
||||
ASSERT_FALSE(another_anim->assign_id(&another_slot, cube->id))
|
||||
<< "Assigning animation (with this function) when already assigned should fail.";
|
||||
<< "Assigning Action (with this function) when already assigned should fail.";
|
||||
EXPECT_TRUE(slot_cube.users(*bmain).contains(&cube->id))
|
||||
<< "Expecting Cube to still be registered as animated by its slot.";
|
||||
}
|
||||
|
||||
{ /* Assign Cube to another slot of the same Animation, this should work. */
|
||||
const int user_count_pre = anim->id.us;
|
||||
Slot &slot_cube_2 = anim->slot_add();
|
||||
ASSERT_TRUE(anim->assign_id(&slot_cube_2, cube->id));
|
||||
ASSERT_EQ(anim->id.us, user_count_pre)
|
||||
<< "Assigning to a different slot of the same animation should _not_ change the user "
|
||||
"count of that Animation";
|
||||
{ /* Assign Cube to another slot of the same Action, this should work. */
|
||||
const int user_count_pre = action->id.us;
|
||||
Slot &slot_cube_2 = action->slot_add();
|
||||
ASSERT_TRUE(action->assign_id(&slot_cube_2, cube->id));
|
||||
ASSERT_EQ(action->id.us, user_count_pre)
|
||||
<< "Assigning to a different slot of the same Action should _not_ change the user "
|
||||
"count of that Action";
|
||||
EXPECT_FALSE(slot_cube.users(*bmain).contains(&cube->id))
|
||||
<< "Expecting Cube to no longer be registered as animated by the Cube slot.";
|
||||
EXPECT_TRUE(slot_cube_2.users(*bmain).contains(&cube->id))
|
||||
<< "Expecting Cube to be registered as animated by the 'cube_2' slot.";
|
||||
}
|
||||
|
||||
{ /* Unassign the animation. */
|
||||
const int user_count_pre = anim->id.us;
|
||||
anim->unassign_id(cube->id);
|
||||
ASSERT_EQ(anim->id.us, user_count_pre - 1)
|
||||
<< "Unassigning an animation should lower its user count";
|
||||
{ /* Unassign the Action. */
|
||||
const int user_count_pre = action->id.us;
|
||||
action->unassign_id(cube->id);
|
||||
ASSERT_EQ(action->id.us, user_count_pre - 1)
|
||||
<< "Unassigning an Action should lower its user count";
|
||||
|
||||
ASSERT_EQ(2, anim->slots().size()) << "Expecting the Action to have two Slots";
|
||||
EXPECT_FALSE(anim->slot(0)->users(*bmain).contains(&cube->id))
|
||||
ASSERT_EQ(2, action->slots().size()) << "Expecting the Action to have two Slots";
|
||||
EXPECT_FALSE(action->slot(0)->users(*bmain).contains(&cube->id))
|
||||
<< "Expecting Cube to no longer be registered as animated by any slot.";
|
||||
EXPECT_FALSE(anim->slot(1)->users(*bmain).contains(&cube->id))
|
||||
EXPECT_FALSE(action->slot(1)->users(*bmain).contains(&cube->id))
|
||||
<< "Expecting Cube to no longer be registered as animated by any slot.";
|
||||
}
|
||||
|
||||
/* Assign Cube to another 'virgin' slot. This should not cause a name
|
||||
* collision between the Slots. */
|
||||
Slot &another_slot_cube = anim->slot_add();
|
||||
ASSERT_TRUE(anim->assign_id(&another_slot_cube, cube->id));
|
||||
Slot &another_slot_cube = action->slot_add();
|
||||
ASSERT_TRUE(action->assign_id(&another_slot_cube, cube->id));
|
||||
EXPECT_EQ(another_slot_cube.handle, cube->adt->slot_handle);
|
||||
EXPECT_STREQ("OBSlot.002", another_slot_cube.name) << "The slot should be uniquely named";
|
||||
EXPECT_STREQ("OBSlot.002", cube->adt->slot_name) << "The slot name should be copied to the adt";
|
||||
@ -308,7 +310,7 @@ TEST_F(ActionLayersTest, anim_assign_id)
|
||||
|
||||
/* Create an ID of another type. This should not be assignable to this slot. */
|
||||
ID *mesh = static_cast<ID *>(BKE_id_new_nomain(ID_ME, "Mesh"));
|
||||
EXPECT_FALSE(anim->assign_id(&slot_cube, *mesh))
|
||||
EXPECT_FALSE(action->assign_id(&slot_cube, *mesh))
|
||||
<< "Mesh should not be animatable by an Object slot";
|
||||
EXPECT_FALSE(another_slot_cube.users(*bmain).contains(mesh))
|
||||
<< "Expecting Mesh to not be registered as animated by the 'slot_cube' slot.";
|
||||
@ -317,28 +319,28 @@ TEST_F(ActionLayersTest, anim_assign_id)
|
||||
|
||||
TEST_F(ActionLayersTest, rename_slot)
|
||||
{
|
||||
Slot &slot_cube = anim->slot_add();
|
||||
ASSERT_TRUE(anim->assign_id(&slot_cube, cube->id));
|
||||
Slot &slot_cube = action->slot_add();
|
||||
ASSERT_TRUE(action->assign_id(&slot_cube, cube->id));
|
||||
EXPECT_EQ(slot_cube.handle, cube->adt->slot_handle);
|
||||
EXPECT_STREQ("OBSlot", slot_cube.name);
|
||||
EXPECT_STREQ(slot_cube.name, cube->adt->slot_name)
|
||||
<< "The slot name should be copied to the adt";
|
||||
|
||||
anim->slot_name_define(slot_cube, "New Slot Name");
|
||||
action->slot_name_define(slot_cube, "New Slot Name");
|
||||
EXPECT_STREQ("New Slot Name", slot_cube.name);
|
||||
/* At this point the slot name will not have been copied to the cube
|
||||
* AnimData. However, I don't want to test for that here, as it's not exactly
|
||||
* desirable behavior, but more of a side-effect of the current
|
||||
* implementation. */
|
||||
|
||||
anim->slot_name_propagate(*bmain, slot_cube);
|
||||
action->slot_name_propagate(*bmain, slot_cube);
|
||||
EXPECT_STREQ("New Slot Name", cube->adt->slot_name);
|
||||
|
||||
/* Finally, do another rename, do NOT call the propagate function, then
|
||||
* unassign. This should still result in the correct slot name being stored
|
||||
* on the ADT. */
|
||||
anim->slot_name_define(slot_cube, "Even Newer Name");
|
||||
anim->unassign_id(cube->id);
|
||||
action->slot_name_define(slot_cube, "Even Newer Name");
|
||||
action->unassign_id(cube->id);
|
||||
EXPECT_STREQ("Even Newer Name", cube->adt->slot_name);
|
||||
}
|
||||
|
||||
@ -352,7 +354,7 @@ TEST_F(ActionLayersTest, slot_name_ensure_prefix)
|
||||
}
|
||||
};
|
||||
|
||||
Slot &raw_slot = anim->slot_add();
|
||||
Slot &raw_slot = action->slot_add();
|
||||
AccessibleSlot &slot = static_cast<AccessibleSlot &>(raw_slot);
|
||||
ASSERT_STREQ("XXSlot", slot.name);
|
||||
ASSERT_EQ(0, slot.idtype);
|
||||
@ -367,7 +369,7 @@ TEST_F(ActionLayersTest, slot_name_ensure_prefix)
|
||||
EXPECT_STREQ("CASlot", slot.name);
|
||||
|
||||
/* idtype ME, explicit name of other idtype. */
|
||||
anim->slot_name_define(slot, "CANewName");
|
||||
action->slot_name_define(slot, "CANewName");
|
||||
slot.idtype = ID_ME;
|
||||
slot.name_ensure_prefix();
|
||||
EXPECT_STREQ("MENewName", slot.name);
|
||||
@ -380,7 +382,7 @@ TEST_F(ActionLayersTest, slot_name_ensure_prefix)
|
||||
|
||||
TEST_F(ActionLayersTest, slot_name_prefix)
|
||||
{
|
||||
Slot &slot = anim->slot_add();
|
||||
Slot &slot = action->slot_add();
|
||||
EXPECT_EQ("XX", slot.name_prefix_for_idtype());
|
||||
|
||||
slot.idtype = ID_CA;
|
||||
@ -389,11 +391,11 @@ TEST_F(ActionLayersTest, slot_name_prefix)
|
||||
|
||||
TEST_F(ActionLayersTest, rename_slot_name_collision)
|
||||
{
|
||||
Slot &slot1 = anim->slot_add();
|
||||
Slot &slot2 = anim->slot_add();
|
||||
Slot &slot1 = action->slot_add();
|
||||
Slot &slot2 = action->slot_add();
|
||||
|
||||
anim->slot_name_define(slot1, "New Slot Name");
|
||||
anim->slot_name_define(slot2, "New Slot Name");
|
||||
action->slot_name_define(slot1, "New Slot Name");
|
||||
action->slot_name_define(slot2, "New Slot Name");
|
||||
EXPECT_STREQ("New Slot Name", slot1.name);
|
||||
EXPECT_STREQ("New Slot Name.001", slot2.name);
|
||||
}
|
||||
@ -402,25 +404,25 @@ TEST_F(ActionLayersTest, find_suitable_slot)
|
||||
{
|
||||
/* ===
|
||||
* Empty case, no slots exist yet and the ID doesn't even have an AnimData. */
|
||||
EXPECT_EQ(nullptr, anim->find_suitable_slot_for(cube->id));
|
||||
EXPECT_EQ(nullptr, action->find_suitable_slot_for(cube->id));
|
||||
|
||||
/* ===
|
||||
* Slot exists with the same name & type as the ID, but the ID doesn't have any AnimData yet.
|
||||
* These should nevertheless be matched up. */
|
||||
Slot &slot = anim->slot_add();
|
||||
Slot &slot = action->slot_add();
|
||||
slot.handle = 327;
|
||||
STRNCPY_UTF8(slot.name, "OBKüüübus");
|
||||
slot.idtype = GS(cube->id.name);
|
||||
EXPECT_EQ(&slot, anim->find_suitable_slot_for(cube->id));
|
||||
EXPECT_EQ(&slot, action->find_suitable_slot_for(cube->id));
|
||||
|
||||
/* ===
|
||||
* Slot exists with the same name & type as the ID, and the ID has an AnimData with the same
|
||||
* slot name, but a different slot_handle. Since the Animation has not yet been
|
||||
* slot name, but a different slot_handle. Since the Action has not yet been
|
||||
* assigned to this ID, the slot_handle should be ignored, and the slot name used for
|
||||
* matching. */
|
||||
|
||||
/* Create a slot with a handle that should be ignored.*/
|
||||
Slot &other_slot = anim->slot_add();
|
||||
Slot &other_slot = action->slot_add();
|
||||
other_slot.handle = 47;
|
||||
|
||||
AnimData *adt = BKE_animdata_ensure_id(&cube->id);
|
||||
@ -428,28 +430,28 @@ TEST_F(ActionLayersTest, find_suitable_slot)
|
||||
/* Configure adt to use the handle of one slot, and the name of the other. */
|
||||
adt->slot_handle = other_slot.handle;
|
||||
STRNCPY_UTF8(adt->slot_name, slot.name);
|
||||
EXPECT_EQ(&slot, anim->find_suitable_slot_for(cube->id));
|
||||
EXPECT_EQ(&slot, action->find_suitable_slot_for(cube->id));
|
||||
|
||||
/* ===
|
||||
* Same situation as above (AnimData has name of one slot, but the handle of another),
|
||||
* except that the animation data-block has already been assigned. In this case the handle
|
||||
* should take precedence. */
|
||||
adt->action = anim;
|
||||
id_us_plus(&anim->id);
|
||||
EXPECT_EQ(&other_slot, anim->find_suitable_slot_for(cube->id));
|
||||
* except that the Action has already been assigned. In this case the handle should take
|
||||
* precedence. */
|
||||
adt->action = action;
|
||||
id_us_plus(&action->id);
|
||||
EXPECT_EQ(&other_slot, action->find_suitable_slot_for(cube->id));
|
||||
|
||||
/* ===
|
||||
* A slot exists, but doesn't match anything in the anim data of the cube. This should fall
|
||||
* A slot exists, but doesn't match anything in the action data of the cube. This should fall
|
||||
* back to using the ID name. */
|
||||
adt->slot_handle = 161;
|
||||
STRNCPY_UTF8(adt->slot_name, "¿¿What's this??");
|
||||
EXPECT_EQ(&slot, anim->find_suitable_slot_for(cube->id));
|
||||
EXPECT_EQ(&slot, action->find_suitable_slot_for(cube->id));
|
||||
}
|
||||
|
||||
TEST_F(ActionLayersTest, strip)
|
||||
{
|
||||
constexpr float inf = std::numeric_limits<float>::infinity();
|
||||
Layer &layer0 = anim->layer_add("Test Læür nul");
|
||||
Layer &layer0 = action->layer_add("Test Læür nul");
|
||||
Strip &strip = layer0.strip_add(Strip::Type::Keyframe);
|
||||
|
||||
strip.resize(-inf, inf);
|
||||
@ -486,9 +488,9 @@ TEST_F(ActionLayersTest, strip)
|
||||
|
||||
TEST_F(ActionLayersTest, KeyframeStrip__keyframe_insert)
|
||||
{
|
||||
Slot &slot = anim->slot_add();
|
||||
EXPECT_TRUE(anim->assign_id(&slot, cube->id));
|
||||
Layer &layer = anim->layer_add("Kübus layer");
|
||||
Slot &slot = action->slot_add();
|
||||
EXPECT_TRUE(action->assign_id(&slot, cube->id));
|
||||
Layer &layer = action->layer_add("Kübus layer");
|
||||
|
||||
Strip &strip = layer.strip_add(Strip::Type::Keyframe);
|
||||
KeyframeStrip &key_strip = strip.as<KeyframeStrip>();
|
||||
@ -533,38 +535,38 @@ TEST_F(ActionLayersTest, is_action_assignable_to)
|
||||
EXPECT_TRUE(is_action_assignable_to(nullptr, ID_CA))
|
||||
<< "nullptr Actions should be assignable to any type.";
|
||||
|
||||
EXPECT_TRUE(is_action_assignable_to(anim, ID_OB))
|
||||
EXPECT_TRUE(is_action_assignable_to(action, ID_OB))
|
||||
<< "Empty Actions should be assignable to any type.";
|
||||
EXPECT_TRUE(is_action_assignable_to(anim, ID_CA))
|
||||
EXPECT_TRUE(is_action_assignable_to(action, ID_CA))
|
||||
<< "Empty Actions should be assignable to any type.";
|
||||
|
||||
/* Make the Action a legacy one. */
|
||||
FCurve fake_fcurve;
|
||||
BLI_addtail(&anim->curves, &fake_fcurve);
|
||||
ASSERT_FALSE(anim->is_empty());
|
||||
ASSERT_TRUE(anim->is_action_legacy());
|
||||
ASSERT_EQ(0, anim->idroot);
|
||||
BLI_addtail(&action->curves, &fake_fcurve);
|
||||
ASSERT_FALSE(action->is_empty());
|
||||
ASSERT_TRUE(action->is_action_legacy());
|
||||
ASSERT_EQ(0, action->idroot);
|
||||
|
||||
EXPECT_TRUE(is_action_assignable_to(anim, ID_OB))
|
||||
EXPECT_TRUE(is_action_assignable_to(action, ID_OB))
|
||||
<< "Legacy Actions with idroot=0 should be assignable to any type.";
|
||||
EXPECT_TRUE(is_action_assignable_to(anim, ID_CA))
|
||||
EXPECT_TRUE(is_action_assignable_to(action, ID_CA))
|
||||
<< "Legacy Actions with idroot=0 should be assignable to any type.";
|
||||
|
||||
/* Set the legacy idroot. */
|
||||
anim->idroot = ID_CA;
|
||||
EXPECT_FALSE(is_action_assignable_to(anim, ID_OB))
|
||||
action->idroot = ID_CA;
|
||||
EXPECT_FALSE(is_action_assignable_to(action, ID_OB))
|
||||
<< "Legacy Actions with idroot=ID_CA should NOT be assignable to ID_OB.";
|
||||
EXPECT_TRUE(is_action_assignable_to(anim, ID_CA))
|
||||
EXPECT_TRUE(is_action_assignable_to(action, ID_CA))
|
||||
<< "Legacy Actions with idroot=CA should be assignable to ID_CA.";
|
||||
|
||||
/* Make the Action a layered one. */
|
||||
BLI_poptail(&anim->curves);
|
||||
anim->layer_add("layer");
|
||||
ASSERT_EQ(0, anim->idroot) << "Adding a layer should clear the idroot.";
|
||||
BLI_poptail(&action->curves);
|
||||
action->layer_add("layer");
|
||||
ASSERT_EQ(0, action->idroot) << "Adding a layer should clear the idroot.";
|
||||
|
||||
EXPECT_TRUE(is_action_assignable_to(anim, ID_OB))
|
||||
EXPECT_TRUE(is_action_assignable_to(action, ID_OB))
|
||||
<< "Layered Actions should be assignable to any type.";
|
||||
EXPECT_TRUE(is_action_assignable_to(anim, ID_CA))
|
||||
EXPECT_TRUE(is_action_assignable_to(action, ID_CA))
|
||||
<< "Layered Actions should be assignable to any type.";
|
||||
}
|
||||
|
||||
|
@ -127,7 +127,7 @@ void animdata_fcurve_delete(bAnimContext *ac, AnimData *adt, FCurve *fcu)
|
||||
animdata_remove_empty_action(adt);
|
||||
}
|
||||
else {
|
||||
/* TODO: support deleting FCurves from Animation data-blocks. */
|
||||
/* TODO: support deleting FCurves from layered Actions. */
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -200,7 +200,7 @@ const FCurve *fcurve_find_by_rna_path(const AnimData &adt,
|
||||
|
||||
const Slot *slot = action.slot_for_handle(adt.slot_handle);
|
||||
if (!slot) {
|
||||
/* No need to inspect anything if this ID does not have an animation Slot. */
|
||||
/* No need to inspect anything if this ID does not have an Action Slot. */
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
@ -35,15 +35,15 @@ void apply_evaluation_result(const EvaluationResult &evaluation_result,
|
||||
PointerRNA &animated_id_ptr,
|
||||
bool flush_to_original);
|
||||
|
||||
static EvaluationResult evaluate_animation(PointerRNA &animated_id_ptr,
|
||||
Action &animation,
|
||||
const slot_handle_t slot_handle,
|
||||
const AnimationEvalContext &anim_eval_context)
|
||||
static EvaluationResult evaluate_action(PointerRNA &animated_id_ptr,
|
||||
Action &action,
|
||||
const slot_handle_t slot_handle,
|
||||
const AnimationEvalContext &anim_eval_context)
|
||||
{
|
||||
EvaluationResult last_result;
|
||||
|
||||
/* Evaluate each layer in order. */
|
||||
for (Layer *layer : animation.layers()) {
|
||||
for (Layer *layer : action.layers()) {
|
||||
if (layer->influence <= 0.0f) {
|
||||
/* Don't bother evaluating layers without influence. */
|
||||
continue;
|
||||
@ -69,14 +69,14 @@ static EvaluationResult evaluate_animation(PointerRNA &animated_id_ptr,
|
||||
return last_result;
|
||||
}
|
||||
|
||||
void evaluate_and_apply_animation(PointerRNA &animated_id_ptr,
|
||||
Action &animation,
|
||||
const slot_handle_t slot_handle,
|
||||
const AnimationEvalContext &anim_eval_context,
|
||||
const bool flush_to_original)
|
||||
void evaluate_and_apply_action(PointerRNA &animated_id_ptr,
|
||||
Action &action,
|
||||
const slot_handle_t slot_handle,
|
||||
const AnimationEvalContext &anim_eval_context,
|
||||
const bool flush_to_original)
|
||||
{
|
||||
EvaluationResult evaluation_result = evaluate_animation(
|
||||
animated_id_ptr, animation, slot_handle, anim_eval_context);
|
||||
EvaluationResult evaluation_result = evaluate_action(
|
||||
animated_id_ptr, action, slot_handle, anim_eval_context);
|
||||
if (!evaluation_result) {
|
||||
return;
|
||||
}
|
||||
|
@ -54,7 +54,7 @@ class AnimatedProperty {
|
||||
}
|
||||
};
|
||||
|
||||
/* Evaluated FCurves for some animation slot.
|
||||
/* Evaluated FCurves for some action slot.
|
||||
* Mapping from property identifier to its float value.
|
||||
*
|
||||
* Can be fed to the evaluation of the next layer, mixed with another strip, or
|
||||
|
@ -33,7 +33,7 @@ using namespace blender::animrig::internal;
|
||||
class AnimationEvaluationTest : public testing::Test {
|
||||
protected:
|
||||
Main *bmain;
|
||||
Action *anim;
|
||||
Action *action;
|
||||
Object *cube;
|
||||
Slot *slot;
|
||||
Layer *layer;
|
||||
@ -60,13 +60,13 @@ class AnimationEvaluationTest : public testing::Test {
|
||||
void SetUp() override
|
||||
{
|
||||
bmain = BKE_main_new();
|
||||
anim = static_cast<Action *>(BKE_id_new(bmain, ID_AC, "ACÄnimåtië"));
|
||||
action = static_cast<Action *>(BKE_id_new(bmain, ID_AC, "ACÄnimåtië"));
|
||||
|
||||
cube = BKE_object_add_only_object(bmain, OB_EMPTY, "Küüübus");
|
||||
|
||||
slot = &anim->slot_add();
|
||||
anim->assign_id(slot, cube->id);
|
||||
layer = &anim->layer_add("Kübus layer");
|
||||
slot = &action->slot_add();
|
||||
action->assign_id(slot, cube->id);
|
||||
layer = &action->layer_add("Kübus layer");
|
||||
|
||||
/* Make it easier to predict test values. */
|
||||
settings.interpolation = BEZT_IPO_LIN;
|
||||
|
@ -163,7 +163,7 @@ void CombinedKeyingResult::generate_reports(ReportList *reports, const eReportTy
|
||||
if (this->get_count(SingleKeyingResult::NO_VALID_SLOT) > 0) {
|
||||
const int error_count = this->get_count(SingleKeyingResult::NO_VALID_SLOT);
|
||||
errors.append(fmt::format(RPT_("Inserting keys on {:d} data-block(s) has been skipped because "
|
||||
"of missing animation slots."),
|
||||
"of missing action slots."),
|
||||
error_count));
|
||||
}
|
||||
|
||||
|
@ -307,7 +307,7 @@ int BKE_fcurves_filter(ListBase *dst, ListBase *src, const char *dataPrefix, con
|
||||
* \note Return pointer parameters (`r_action`, `r_driven` and `r_special`) are all optional and
|
||||
* may be NULL.
|
||||
*
|
||||
* \note since Animation data-blocks may have multiple layers all containing an F-Curve for this
|
||||
* \note since Actions may have multiple layers all containing an F-Curve for this
|
||||
* property, what is returned is a best-effort guess. The topmost layer has priority, and it is
|
||||
* assumed that when it has a strip, it's infinite.
|
||||
*/
|
||||
|
@ -396,13 +396,13 @@ static void read_keyframe_strip(BlendDataReader *reader, animrig::KeyframeStrip
|
||||
}
|
||||
}
|
||||
|
||||
static void read_layers(BlendDataReader *reader, animrig::Action &anim)
|
||||
static void read_layers(BlendDataReader *reader, animrig::Action &action)
|
||||
{
|
||||
BLO_read_pointer_array(reader, reinterpret_cast<void **>(&anim.layer_array));
|
||||
BLO_read_pointer_array(reader, reinterpret_cast<void **>(&action.layer_array));
|
||||
|
||||
for (int layer_idx = 0; layer_idx < anim.layer_array_num; layer_idx++) {
|
||||
BLO_read_struct(reader, ActionLayer, &anim.layer_array[layer_idx]);
|
||||
ActionLayer *layer = anim.layer_array[layer_idx];
|
||||
for (int layer_idx = 0; layer_idx < action.layer_array_num; layer_idx++) {
|
||||
BLO_read_struct(reader, ActionLayer, &action.layer_array[layer_idx]);
|
||||
ActionLayer *layer = action.layer_array[layer_idx];
|
||||
|
||||
BLO_read_pointer_array(reader, reinterpret_cast<void **>(&layer->strip_array));
|
||||
for (int strip_idx = 0; strip_idx < layer->strip_array_num; strip_idx++) {
|
||||
@ -419,13 +419,13 @@ static void read_layers(BlendDataReader *reader, animrig::Action &anim)
|
||||
}
|
||||
}
|
||||
|
||||
static void read_slots(BlendDataReader *reader, animrig::Action &anim)
|
||||
static void read_slots(BlendDataReader *reader, animrig::Action &action)
|
||||
{
|
||||
BLO_read_pointer_array(reader, reinterpret_cast<void **>(&anim.slot_array));
|
||||
BLO_read_pointer_array(reader, reinterpret_cast<void **>(&action.slot_array));
|
||||
|
||||
for (int i = 0; i < anim.slot_array_num; i++) {
|
||||
BLO_read_struct(reader, ActionSlot, &anim.slot_array[i]);
|
||||
anim.slot_array[i]->wrap().blend_read_post();
|
||||
for (int i = 0; i < action.slot_array_num; i++) {
|
||||
BLO_read_struct(reader, ActionSlot, &action.slot_array[i]);
|
||||
action.slot_array[i]->wrap().blend_read_post();
|
||||