Refactor: centralize responsibility for "Only Insert Needed" #121525
@ -6,12 +6,14 @@
|
||||
* \ingroup animrig
|
||||
*/
|
||||
|
||||
#include <cfloat>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
|
||||
#include "ANIM_animdata.hh"
|
||||
#include "ANIM_fcurve.hh"
|
||||
#include "BKE_fcurve.hh"
|
||||
#include "BLI_math_base.h"
|
||||
#include "BLI_math_vector_types.hh"
|
||||
#include "BLI_string.h"
|
||||
#include "DNA_anim_types.h"
|
||||
@ -271,11 +273,57 @@ void initialize_bezt(BezTriple *beztr,
|
||||
beztr->period = 4.1f;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return whether the given fcurve already evaluates to the same value as the
|
||||
* proposed keyframe at the keyframe's time.
|
||||
*
|
||||
* This is a helper function for determining whether to insert a keyframe or not
|
||||
* when "only insert needed" is enabled.
|
||||
*
|
||||
* Note: this does *not* determine whether inserting the keyframe would change
|
||||
* the fcurve at points other than the keyframe itself. For example, even if
|
||||
* inserting the key wouldn't change the fcurve's value at the time of the
|
||||
* keyframe, the resulting changes to bezier interpolation could change the
|
||||
* fcurve on either side of it. This function intentionally does not account for
|
||||
* that, since that's not how the "only insert needed" feature is supposed to
|
||||
* work.
|
||||
*/
|
||||
static bool new_key_needed(FCurve &fcu, const float frame, const float value)
|
||||
{
|
||||
if (fcu.totvert == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool replace;
|
||||
const int bezt_index = BKE_fcurve_bezt_binarysearch_index(
|
||||
fcu.bezt, frame, fcu.totvert, &replace);
|
||||
|
||||
if (replace) {
|
||||
/* If there is already a key, we only need to modify it if the proposed value is different. */
|
||||
return fcu.bezt[bezt_index].vec[1][1] != value;
|
||||
}
|
||||
|
||||
const int diff_ulp = 32;
|
||||
const float fcu_eval = evaluate_fcurve(&fcu, frame);
|
||||
/* No need to insert a key if the same value is already the value of the FCurve at that point. */
|
||||
if (compare_ff_relative(fcu_eval, value, FLT_EPSILON, diff_ulp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
SingleKeyingResult insert_vert_fcurve(FCurve *fcu,
|
||||
const float2 position,
|
||||
const KeyframeSettings &settings,
|
||||
eInsertKeyFlags flag)
|
||||
{
|
||||
BLI_assert(fcu != nullptr);
|
||||
|
||||
if ((flag & INSERTKEY_NEEDED) && !new_key_needed(*fcu, position[0], position[1])) {
|
||||
nathanvegdahl marked this conversation as resolved
Outdated
|
||||
return SingleKeyingResult::NO_KEY_NEEDED;
|
||||
}
|
||||
|
||||
BezTriple beztr = {{{0}}};
|
||||
initialize_bezt(&beztr, position, settings, eFCurve_Flags(fcu->flag));
|
||||
|
||||
@ -494,7 +542,7 @@ void bake_fcurve_segments(FCurve *fcu)
|
||||
/* Add keyframes with these, tagging as 'breakdowns'. */
|
||||
for (n = 1, fp = value_cache; n < range && fp; n++, fp++) {
|
||||
blender::animrig::insert_vert_fcurve(
|
||||
fcu, {fp->frame, fp->val}, settings, eInsertKeyFlags(1));
|
||||
fcu, {fp->frame, fp->val}, settings, INSERTKEY_NOFLAGS);
|
||||
}
|
||||
Nathan Vegdahl
commented
Note to reviewers: this is changed to This same change is elsewhere in this PR as well, for the same reason. Note to reviewers: this is changed to `INSERTKEY_NOFLAGS` because the flag previously passed was actually not used by `insert_vert_fcurve()`, but now is. So this actually preserves the previous behavior.
This same change is elsewhere in this PR as well, for the same reason.
|
||||
|
||||
MEM_freeN(value_cache);
|
||||
|
@ -6,7 +6,6 @@
|
||||
* \ingroup animrig
|
||||
*/
|
||||
|
||||
#include <cfloat>
|
||||
#include <cmath>
|
||||
#include <string>
|
||||
|
||||
@ -425,38 +424,6 @@ static eFCU_Cycle_Type remap_cyclic_keyframe_location(FCurve *fcu, float *px, fl
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* This helper function determines whether a new keyframe is needed.
|
||||
* A keyframe doesn't get added when the FCurve already has the proposed value.
|
||||
*/
|
||||
static bool new_key_needed(FCurve *fcu, const float frame, const float value)
|
||||
{
|
||||
if (fcu == nullptr) {
|
||||
return true;
|
||||
}
|
||||
if (fcu->totvert == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool replace;
|
||||
const int bezt_index = BKE_fcurve_bezt_binarysearch_index(
|
||||
fcu->bezt, frame, fcu->totvert, &replace);
|
||||
|
||||
if (replace) {
|
||||
/* If there is already a key, we only need to modify it if the proposed value is different. */
|
||||
return fcu->bezt[bezt_index].vec[1][1] != value;
|
||||
}
|
||||
|
||||
const int diff_ulp = 32;
|
||||
const float fcu_eval = evaluate_fcurve(fcu, frame);
|
||||
/* No need to insert a key if the same value is already the value of the FCurve at that point. */
|
||||
if (compare_ff_relative(fcu_eval, value, FLT_EPSILON, diff_ulp)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static float nla_time_remap(const AnimationEvalContext *anim_eval_context,
|
||||
PointerRNA *id_ptr,
|
||||
AnimData *adt,
|
||||
@ -496,15 +463,7 @@ static SingleKeyingResult insert_keyframe_value(
|
||||
KeyframeSettings settings = get_keyframe_settings((flag & INSERTKEY_NO_USERPREF) == 0);
|
||||
settings.keyframe_type = keytype;
|
||||
|
||||
if ((flag & INSERTKEY_NEEDED) && !new_key_needed(fcu, cfra, curval)) {
|
||||
return SingleKeyingResult::NO_KEY_NEEDED;
|
||||
}
|
||||
|
||||
if (insert_vert_fcurve(fcu, {cfra, curval}, settings, flag) != SingleKeyingResult::SUCCESS) {
|
||||
return SingleKeyingResult::FCURVE_NOT_KEYFRAMEABLE;
|
||||
}
|
||||
|
||||
return SingleKeyingResult::SUCCESS;
|
||||
return insert_vert_fcurve(fcu, {cfra, curval}, settings, flag);
|
||||
}
|
||||
nathanvegdahl marked this conversation as resolved
Outdated
Nathan Vegdahl
commented
Here's where I goofed. This inhibiting of the flag, and the whole note along with it, is wrong. And that's because this is the very function where "Only Insert Needed" was previously handled. I removed the old code that handled the flag here while moving the changes over from the other PR. And then I did a separate pass after committing that code to see where the flag needed to be ignored due to the changes to Here's where I goofed. This inhibiting of the flag, and the whole note along with it, is wrong. And that's because this is the very function where "Only Insert Needed" was previously handled.
I removed the old code that handled the flag here while moving the changes over from the other PR. And then I did a separate pass after committing that code to see where the flag needed to be ignored due to the changes to `insert_vert_fcurve()`. Hence how I ended up here.
|
||||
|
||||
bool insert_keyframe_direct(ReportList *reports,
|
||||
|
@ -1714,7 +1714,7 @@ static void propagate_curve_values(ListBase /*tPChanFCurveLink*/ *pflinks,
|
||||
const float current_fcu_value = evaluate_fcurve(fcu, source_frame);
|
||||
LISTBASE_FOREACH (FrameLink *, target_frame, target_frames) {
|
||||
insert_vert_fcurve(
|
||||
fcu, {target_frame->frame, current_fcu_value}, settings, INSERTKEY_NEEDED);
|
||||
nathanvegdahl marked this conversation as resolved
Outdated
I expected this to change behavior but it doesn't seem to do that I expected this to change behavior but it doesn't seem to do that
Nathan Vegdahl
commented
It doesn't change behavior for the same reason as the comment I left further above:
In other words, It doesn't change behavior for the same reason as the comment I left further above:
> Note to reviewers: this is changed to `INSERTKEY_NOFLAGS` because the flag previously passed was actually not used by `insert_vert_fcurve()`, but now is. So this actually preserves the previous behavior.
>
> This same change is elsewhere in this PR as well, for the same reason.
In other words, `insert_vert_fcurve()` previously completely ignored `INSERTKEY_NEEDED`, so the fact that it was passed that flag in a couple of places (including here) was meaningless before. But now it's actually used, so to preserve behavior we have to change to `INSERTKEY_NOFLAGS`.
|
||||
fcu, {target_frame->frame, current_fcu_value}, settings, INSERTKEY_NOFLAGS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Add parentheses around
(flag & INSERTKEY_NEEDED)
Gah! Thanks.