Anim: correctly auto-sync NLA strip length for slotted Action

When syncing the NLA strip length with the Action it uses, use the
length of the assigned action slot. Previously the entire Action was
considered when determining the length.

Pull Request: https://projects.blender.org/blender/blender/pulls/127573
This commit is contained in:
Sybren A. Stüvel
2024-09-13 15:10:46 +02:00
parent b952782a44
commit 7916a33be0
3 changed files with 45 additions and 3 deletions

View File

@@ -312,9 +312,21 @@ class Action : public ::bAction {
* or the result of a scan of all F-Curves for their first & last frames.
*
* \see get_frame_range_of_keys()
* \see get_frame_range_of_slot()
*/
float2 get_frame_range() const ATTR_WARN_UNUSED_RESULT;
/**
* Retrieve the intended playback frame range of a slot.
*
* \return a tuple (start frame, end frame). This is either the manually set range (if enabled)
* of the Action, or the result of a scan of all F-Curves of the slot for their first & last
* frames.
*
* \see get_frame_range()
*/
float2 get_frame_range_of_slot(slot_handle_t slot_handle) const ATTR_WARN_UNUSED_RESULT;
/**
* Calculate the extents of this Action.
*

View File

@@ -766,21 +766,51 @@ bool Action::is_cyclic() const
return (this->flag & ACT_FRAME_RANGE) && (this->flag & ACT_CYCLIC);
}
/** Return the frame range of the span of keys. */
static float2 get_frame_range_of_fcurves(Span<const FCurve *> fcurves, bool include_modifiers);
float2 Action::get_frame_range() const
{
if (this->flag & ACT_FRAME_RANGE) {
return {this->frame_start, this->frame_end};
}
return this->get_frame_range_of_keys(false);
Vector<const FCurve *> all_fcurves = fcurves_all(*this);
return get_frame_range_of_fcurves(all_fcurves, false);
}
float2 Action::get_frame_range_of_slot(const slot_handle_t slot_handle) const
{
if (this->flag & ACT_FRAME_RANGE) {
return {this->frame_start, this->frame_end};
}
Vector<const FCurve *> legacy_fcurves;
Span<const FCurve *> fcurves_to_consider;
if (this->is_action_layered()) {
fcurves_to_consider = fcurves_for_action_slot(*this, slot_handle);
}
else {
legacy_fcurves = fcurves_all(*this);
fcurves_to_consider = legacy_fcurves;
}
return get_frame_range_of_fcurves(fcurves_to_consider, false);
}
float2 Action::get_frame_range_of_keys(const bool include_modifiers) const
{
return get_frame_range_of_fcurves(fcurves_all(*this), include_modifiers);
}
static float2 get_frame_range_of_fcurves(Span<const FCurve *> fcurves,
const bool include_modifiers)
{
float min = 999999999.0f, max = -999999999.0f;
bool foundvert = false, foundmod = false;
for (const FCurve *fcu : fcurves_all(*this)) {
for (const FCurve *fcu : fcurves) {
/* if curve has keyframes, consider them first */
if (fcu->totvert) {
float nmin, nmax;

View File

@@ -1642,7 +1642,7 @@ void BKE_nlastrip_recalculate_bounds_sync_action(NlaStrip *strip)
prev_actstart = strip->actstart;
const float2 frame_range = strip->act->wrap().get_frame_range();
const float2 frame_range = strip->act->wrap().get_frame_range_of_slot(strip->action_slot_handle);
strip->actstart = frame_range[0];
strip->actend = frame_range[1];