Fix #126140: Cycle aware keying not working
The issue was that the code path for layered actions never hit the function `remap_cyclic_keyframe_location`. The solution is to move that logic into `insert_vert_fcurve`. My reason for why this is the correct solution is that the remapping happens on a per FCurve basis, so it should be within `fcurve.cc`. Doing so ensures that the layered actions also hit that code. Pull Request: https://projects.blender.org/blender/blender/pulls/126399
This commit is contained in:
committed by
Christoph Lendenfeld
parent
5e88a1466c
commit
ff0c097fa1
@@ -365,6 +365,48 @@ static bool new_key_needed(const FCurve &fcu, const float frame, const float val
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the point where a key is about to be inserted to be inside the main cycle range.
|
||||
* Returns the type of the cycle if it is enabled and valid.
|
||||
*/
|
||||
static float2 remap_cyclic_keyframe_location(const FCurve &fcu,
|
||||
const eFCU_Cycle_Type type,
|
||||
float2 position)
|
||||
{
|
||||
if (fcu.totvert < 2 || !fcu.bezt) {
|
||||
return position;
|
||||
}
|
||||
|
||||
if (type == FCU_CYCLE_NONE) {
|
||||
return position;
|
||||
}
|
||||
|
||||
BezTriple *first = &fcu.bezt[0], *last = &fcu.bezt[fcu.totvert - 1];
|
||||
const float start = first->vec[1][0], end = last->vec[1][0];
|
||||
|
||||
if (start >= end) {
|
||||
return position;
|
||||
}
|
||||
|
||||
if (position.x < start || position.x > end) {
|
||||
const float period = end - start;
|
||||
const float step = floorf((position.x - start) / period);
|
||||
position.x -= step * period;
|
||||
|
||||
if (type == FCU_CYCLE_OFFSET) {
|
||||
/* Nasty check to handle the case when the modes are different better. */
|
||||
FMod_Cycles *data = static_cast<FMod_Cycles *>(((FModifier *)fcu.modifiers.first)->data);
|
||||
short mode = (step >= 0) ? data->after_mode : data->before_mode;
|
||||
|
||||
if (mode == FCM_EXTRAPOLATE_CYCLIC_OFFSET) {
|
||||
position.y -= step * (last->vec[1][1] - first->vec[1][1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return position;
|
||||
}
|
||||
|
||||
SingleKeyingResult insert_vert_fcurve(FCurve *fcu,
|
||||
const float2 position,
|
||||
const KeyframeSettings &settings,
|
||||
@@ -372,12 +414,24 @@ SingleKeyingResult insert_vert_fcurve(FCurve *fcu,
|
||||
{
|
||||
BLI_assert(fcu != nullptr);
|
||||
|
||||
if ((flag & INSERTKEY_NEEDED) && !new_key_needed(*fcu, position[0], position[1])) {
|
||||
float2 remapped_position = position;
|
||||
/* Adjust coordinates for cycle aware insertion. */
|
||||
if (flag & INSERTKEY_CYCLE_AWARE) {
|
||||
eFCU_Cycle_Type type = BKE_fcurve_get_cycle_type(fcu);
|
||||
remapped_position = remap_cyclic_keyframe_location(*fcu, type, position);
|
||||
if (type != FCU_CYCLE_PERFECT) {
|
||||
/* Inhibit action from insert_bezt_fcurve unless it's a perfect cycle. */
|
||||
flag &= ~INSERTKEY_CYCLE_AWARE;
|
||||
}
|
||||
}
|
||||
|
||||
if ((flag & INSERTKEY_NEEDED) && !new_key_needed(*fcu, remapped_position.x, remapped_position.y))
|
||||
{
|
||||
return SingleKeyingResult::NO_KEY_NEEDED;
|
||||
}
|
||||
|
||||
BezTriple beztr = {{{0}}};
|
||||
initialize_bezt(&beztr, position, settings, eFCurve_Flags(fcu->flag));
|
||||
initialize_bezt(&beztr, remapped_position, settings, eFCurve_Flags(fcu->flag));
|
||||
|
||||
uint oldTot = fcu->totvert;
|
||||
int a;
|
||||
|
||||
@@ -386,48 +386,6 @@ static BitVector<> nla_map_keyframe_values_and_generate_reports(
|
||||
return successful_remaps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the point where a key is about to be inserted to be inside the main cycle range.
|
||||
* Returns the type of the cycle if it is enabled and valid.
|
||||
*/
|
||||
static eFCU_Cycle_Type remap_cyclic_keyframe_location(FCurve *fcu, float *px, float *py)
|
||||
{
|
||||
if (fcu->totvert < 2 || !fcu->bezt) {
|
||||
return FCU_CYCLE_NONE;
|
||||
}
|
||||
|
||||
eFCU_Cycle_Type type = BKE_fcurve_get_cycle_type(fcu);
|
||||
|
||||
if (type == FCU_CYCLE_NONE) {
|
||||
return FCU_CYCLE_NONE;
|
||||
}
|
||||
|
||||
BezTriple *first = &fcu->bezt[0], *last = &fcu->bezt[fcu->totvert - 1];
|
||||
const float start = first->vec[1][0], end = last->vec[1][0];
|
||||
|
||||
if (start >= end) {
|
||||
return FCU_CYCLE_NONE;
|
||||
}
|
||||
|
||||
if (*px < start || *px > end) {
|
||||
float period = end - start;
|
||||
float step = floorf((*px - start) / period);
|
||||
*px -= step * period;
|
||||
|
||||
if (type == FCU_CYCLE_OFFSET) {
|
||||
/* Nasty check to handle the case when the modes are different better. */
|
||||
FMod_Cycles *data = static_cast<FMod_Cycles *>(((FModifier *)fcu->modifiers.first)->data);
|
||||
short mode = (step >= 0) ? data->after_mode : data->before_mode;
|
||||
|
||||
if (mode == FCM_EXTRAPOLATE_CYCLIC_OFFSET) {
|
||||
*py -= step * (last->vec[1][1] - first->vec[1][1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
static float nla_time_remap(float time,
|
||||
const AnimationEvalContext *anim_eval_context,
|
||||
PointerRNA *id_ptr,
|
||||
@@ -456,14 +414,6 @@ static SingleKeyingResult insert_keyframe_value(
|
||||
return SingleKeyingResult::FCURVE_NOT_KEYFRAMEABLE;
|
||||
}
|
||||
|
||||
/* Adjust coordinates for cycle aware insertion. */
|
||||
if (flag & INSERTKEY_CYCLE_AWARE) {
|
||||
if (remap_cyclic_keyframe_location(fcu, &cfra, &curval) != FCU_CYCLE_PERFECT) {
|
||||
/* Inhibit action from insert_vert_fcurve unless it's a perfect cycle. */
|
||||
flag &= ~INSERTKEY_CYCLE_AWARE;
|
||||
}
|
||||
}
|
||||
|
||||
KeyframeSettings settings = get_keyframe_settings((flag & INSERTKEY_NO_USERPREF) == 0);
|
||||
settings.keyframe_type = keytype;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user