Refactor: move code related to fcurve keyframe insertion

No functional changes.

Move the functions
`insert_vert_fcurve` and
`insert_bezt_fcurve`
from `ED_keyframing.hh` / `keyframing.cc`
to `ANIM_fcurve.hh` / `fcurve.cc`
in animrig

Pull Request: https://projects.blender.org/blender/blender/pulls/114570
This commit is contained in:
Christoph Lendenfeld
2023-11-07 14:33:52 +01:00
committed by Christoph Lendenfeld
parent 160111c318
commit 69a3c5c7fc
15 changed files with 352 additions and 327 deletions

View File

@@ -8,6 +8,7 @@
* \brief Functions to modify FCurves.
*/
#include "DNA_anim_types.h"
struct AnimData;
struct FCurve;
@@ -18,4 +19,36 @@ namespace blender::animrig {
*/
bool delete_keyframe_fcurve(AnimData *adt, FCurve *fcu, float cfra);
/**
* \brief Lesser Key-framing API call.
*
* Use this when validation of necessary animation data isn't necessary as it already
* exists, and there is a #BezTriple that can be directly copied into the array.
*
* This function adds a given #BezTriple to an F-Curve. It will allocate
* memory for the array if needed, and will insert the #BezTriple into a
* suitable place in chronological order.
*
* \note any recalculate of the F-Curve that needs to be done will need to be done by the caller.
*/
int insert_bezt_fcurve(FCurve *fcu, const BezTriple *bezt, eInsertKeyFlags flag);
/**
* \brief Main Key-framing API call.
*
* Use this when validation of necessary animation data isn't necessary as it
* already exists. It will insert a keyframe using the current value being keyframed.
* Returns the index at which a keyframe was added (or -1 if failed).
*
* This function is a wrapper for #insert_bezt_fcurve(), and should be used when
* adding a new keyframe to a curve, when the keyframe doesn't exist anywhere else yet.
* It returns the index at which the keyframe was added.
*
* \param keyframe_type: The type of keyframe (#eBezTriple_KeyframeType).
* \param flag: Optional flags (#eInsertKeyFlags) for controlling how keys get added
* and/or whether updates get done.
*/
int insert_vert_fcurve(
FCurve *fcu, float x, float y, eBezTriple_KeyframeType keyframe_type, eInsertKeyFlags flag);
} // namespace blender::animrig

View File

@@ -6,10 +6,14 @@
* \ingroup animrig
*/
#include <cmath>
#include <string.h>
#include "ANIM_fcurve.hh"
#include "BKE_fcurve.h"
#include "DNA_anim_types.h"
#include "ED_anim_api.hh"
#include "MEM_guardedalloc.h"
namespace blender::animrig {
@@ -33,4 +37,270 @@ bool delete_keyframe_fcurve(AnimData *adt, FCurve *fcu, float cfra)
return true;
}
/* ************************************************** */
/* KEYFRAME INSERTION */
/* -------------- BezTriple Insertion -------------------- */
/* Change the Y position of a keyframe to match the input, adjusting handles. */
static void replace_bezt_keyframe_ypos(BezTriple *dst, const BezTriple *bezt)
{
/* just change the values when replacing, so as to not overwrite handles */
float dy = bezt->vec[1][1] - dst->vec[1][1];
/* just apply delta value change to the handle values */
dst->vec[0][1] += dy;
dst->vec[1][1] += dy;
dst->vec[2][1] += dy;
dst->f1 = bezt->f1;
dst->f2 = bezt->f2;
dst->f3 = bezt->f3;
/* TODO: perform some other operations? */
}
int insert_bezt_fcurve(FCurve *fcu, const BezTriple *bezt, eInsertKeyFlags flag)
{
int i = 0;
/* are there already keyframes? */
if (fcu->bezt) {
bool replace;
i = BKE_fcurve_bezt_binarysearch_index(fcu->bezt, bezt->vec[1][0], fcu->totvert, &replace);
/* replace an existing keyframe? */
if (replace) {
/* sanity check: 'i' may in rare cases exceed arraylen */
if ((i >= 0) && (i < fcu->totvert)) {
if (flag & INSERTKEY_OVERWRITE_FULL) {
fcu->bezt[i] = *bezt;
}
else {
replace_bezt_keyframe_ypos(&fcu->bezt[i], bezt);
}
if (flag & INSERTKEY_CYCLE_AWARE) {
/* If replacing an end point of a cyclic curve without offset,
* modify the other end too. */
if (ELEM(i, 0, fcu->totvert - 1) && BKE_fcurve_get_cycle_type(fcu) == FCU_CYCLE_PERFECT)
{
replace_bezt_keyframe_ypos(&fcu->bezt[i == 0 ? fcu->totvert - 1 : 0], bezt);
}
}
}
}
/* Keyframing modes allow not replacing the keyframe. */
else if ((flag & INSERTKEY_REPLACE) == 0) {
/* insert new - if we're not restricted to replacing keyframes only */
BezTriple *newb = static_cast<BezTriple *>(
MEM_callocN((fcu->totvert + 1) * sizeof(BezTriple), "beztriple"));
/* Add the beztriples that should occur before the beztriple to be pasted
* (originally in fcu). */
if (i > 0) {
memcpy(newb, fcu->bezt, i * sizeof(BezTriple));
}
/* add beztriple to paste at index i */
*(newb + i) = *bezt;
/* add the beztriples that occur after the beztriple to be pasted (originally in fcu) */
if (i < fcu->totvert) {
memcpy(newb + i + 1, fcu->bezt + i, (fcu->totvert - i) * sizeof(BezTriple));
}
/* replace (+ free) old with new, only if necessary to do so */
MEM_freeN(fcu->bezt);
fcu->bezt = newb;
fcu->totvert++;
}
else {
return -1;
}
}
/* no keyframes already, but can only add if...
* 1) keyframing modes say that keyframes can only be replaced, so adding new ones won't know
* 2) there are no samples on the curve
* NOTE: maybe we may want to allow this later when doing samples -> bezt conversions,
* but for now, having both is asking for trouble
*/
else if ((flag & INSERTKEY_REPLACE) == 0 && (fcu->fpt == nullptr)) {
/* create new keyframes array */
fcu->bezt = static_cast<BezTriple *>(MEM_callocN(sizeof(BezTriple), "beztriple"));
*(fcu->bezt) = *bezt;
fcu->totvert = 1;
}
/* cannot add anything */
else {
/* return error code -1 to prevent any misunderstandings */
return -1;
}
/* we need to return the index, so that some tools which do post-processing can
* detect where we added the BezTriple in the array
*/
return i;
}
/**
* Update the FCurve to allow insertion of `bezt` without modifying the curve shape.
*
* Checks whether it is necessary to apply Bezier subdivision due to involvement of non-auto
* handles. If necessary, changes `bezt` handles from Auto to Aligned.
*
* \param bezt: key being inserted
* \param prev: keyframe before that key
* \param next: keyframe after that key
*/
static void subdivide_nonauto_handles(const FCurve *fcu,
BezTriple *bezt,
BezTriple *prev,
BezTriple *next)
{
if (prev->ipo != BEZT_IPO_BEZ || bezt->ipo != BEZT_IPO_BEZ) {
return;
}
/* Don't change Vector handles, or completely auto regions. */
const bool bezt_auto = BEZT_IS_AUTOH(bezt) || (bezt->h1 == HD_VECT && bezt->h2 == HD_VECT);
const bool prev_auto = BEZT_IS_AUTOH(prev) || (prev->h2 == HD_VECT);
const bool next_auto = BEZT_IS_AUTOH(next) || (next->h1 == HD_VECT);
if (bezt_auto && prev_auto && next_auto) {
return;
}
/* Subdivide the curve. */
float delta;
if (!BKE_fcurve_bezt_subdivide_handles(bezt, prev, next, &delta)) {
return;
}
/* Decide when to force auto to manual. */
if (!BEZT_IS_AUTOH(bezt)) {
return;
}
if ((prev_auto || next_auto) && fcu->auto_smoothing == FCURVE_SMOOTH_CONT_ACCEL) {
const float hx = bezt->vec[1][0] - bezt->vec[0][0];
const float dx = bezt->vec[1][0] - prev->vec[1][0];
/* This mode always uses 1/3 of key distance for handle x size. */
const bool auto_works_well = fabsf(hx - dx / 3.0f) < 0.001f;
if (auto_works_well) {
return;
}
}
/* Turn off auto mode. */
bezt->h1 = bezt->h2 = HD_ALIGN;
}
int insert_vert_fcurve(
FCurve *fcu, float x, float y, eBezTriple_KeyframeType keyframe_type, eInsertKeyFlags flag)
{
BezTriple beztr = {{{0}}};
uint oldTot = fcu->totvert;
int a;
/* set all three points, for nicer start position
* NOTE: +/- 1 on vec.x for left and right handles is so that 'free' handles work ok...
*/
beztr.vec[0][0] = x - 1.0f;
beztr.vec[0][1] = y;
beztr.vec[1][0] = x;
beztr.vec[1][1] = y;
beztr.vec[2][0] = x + 1.0f;
beztr.vec[2][1] = y;
beztr.f1 = beztr.f2 = beztr.f3 = SELECT;
/* set default handle types and interpolation mode */
if (flag & INSERTKEY_NO_USERPREF) {
/* for Py-API, we want scripts to have predictable behavior,
* hence the option to not depend on the userpref defaults
*/
beztr.h1 = beztr.h2 = HD_AUTO_ANIM;
beztr.ipo = BEZT_IPO_BEZ;
}
else {
/* For UI usage - defaults should come from the user-preferences and/or tool-settings. */
beztr.h1 = beztr.h2 = U.keyhandles_new; /* use default handle type here */
/* use default interpolation mode, with exceptions for int/discrete values */
beztr.ipo = U.ipo_new;
}
/* interpolation type used is constrained by the type of values the curve can take */
if (fcu->flag & FCURVE_DISCRETE_VALUES) {
beztr.ipo = BEZT_IPO_CONST;
}
else if ((beztr.ipo == BEZT_IPO_BEZ) && (fcu->flag & FCURVE_INT_VALUES)) {
beztr.ipo = BEZT_IPO_LIN;
}
/* set keyframe type value (supplied), which should come from the scene settings in most cases */
BEZKEYTYPE(&beztr) = keyframe_type;
/* set default values for "easing" interpolation mode settings
* NOTE: Even if these modes aren't currently used, if users switch
* to these later, we want these to work in a sane way out of
* the box.
*/
/* "back" easing - this value used to be used when overshoot=0, but that
* introduced discontinuities in how the param worked. */
beztr.back = 1.70158f;
/* "elastic" easing - values here were hand-optimized for a default duration of
* ~10 frames (typical mograph motion length) */
beztr.amplitude = 0.8f;
beztr.period = 4.1f;
/* add temp beztriple to keyframes */
a = insert_bezt_fcurve(fcu, &beztr, flag);
BKE_fcurve_active_keyframe_set(fcu, &fcu->bezt[a]);
/* what if 'a' is a negative index?
* for now, just exit to prevent any segfaults
*/
if (a < 0) {
return -1;
}
/* Set handle-type and interpolation. */
if ((fcu->totvert > 2) && (flag & INSERTKEY_REPLACE) == 0) {
BezTriple *bezt = (fcu->bezt + a);
/* Set interpolation from previous (if available),
* but only if we didn't just replace some keyframe:
* - Replacement is indicated by no-change in number of verts.
* - When replacing, the user may have specified some interpolation that should be kept.
*/
if (fcu->totvert > oldTot) {
if (a > 0) {
bezt->ipo = (bezt - 1)->ipo;
}
else if (a < fcu->totvert - 1) {
bezt->ipo = (bezt + 1)->ipo;
}
if (0 < a && a < (fcu->totvert - 1) && (flag & INSERTKEY_OVERWRITE_FULL) == 0) {
subdivide_nonauto_handles(fcu, bezt, bezt - 1, bezt + 1);
}
}
}
/* don't recalculate handles if fast is set
* - this is a hack to make importers faster
* - we may calculate twice (due to auto-handle needing to be calculated twice)
*/
if ((flag & INSERTKEY_FAST) == 0) {
BKE_fcurve_handles_recalc(fcu);
}
/* return the index at which the keyframe was added */
return a;
}
} // namespace blender::animrig

View File

@@ -43,6 +43,8 @@
#include "RNA_path.hh"
#include "RNA_prototypes.h"
#include "ANIM_fcurve.hh"
#include "anim_intern.h"
/* ************************************************** */
@@ -122,9 +124,9 @@ FCurve *alloc_driver_fcurve(const char rna_path[],
* - These are configured to 0,0 and 1,1 to give a 1-1 mapping
* which can be easily tweaked from there.
*/
insert_vert_fcurve(
blender::animrig::insert_vert_fcurve(
fcu, 0.0f, 0.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_FAST | INSERTKEY_NO_USERPREF);
insert_vert_fcurve(
blender::animrig::insert_vert_fcurve(
fcu, 1.0f, 1.0f, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_FAST | INSERTKEY_NO_USERPREF);
fcu->extend = FCURVE_EXTRAPOLATE_LINEAR;
BKE_fcurve_handles_recalc(fcu);

View File

@@ -38,6 +38,8 @@
#include "ED_keyframes_edit.hh"
#include "ED_keyframing.hh"
#include "ANIM_fcurve.hh"
/* This file contains code for various keyframe-editing tools which are 'destructive'
* (i.e. they will modify the order of the keyframes, and change the size of the array).
* While some of these tools may eventually be moved out into blenkernel, for now, it is
@@ -117,7 +119,7 @@ void clean_fcurve(bAnimContext *ac,
/* now insert first keyframe, as it should be ok */
bezt = old_bezts;
insert_bezt_fcurve(fcu, bezt, eInsertKeyFlags(0));
blender::animrig::insert_bezt_fcurve(fcu, bezt, eInsertKeyFlags(0));
if (!(bezt->f2 & SELECT)) {
lastb = fcu->bezt;
lastb->f1 = lastb->f2 = lastb->f3 = 0;
@@ -149,7 +151,7 @@ void clean_fcurve(bAnimContext *ac,
cur[1] = bezt->vec[1][1];
if (only_selected_keys && !(bezt->f2 & SELECT)) {
insert_bezt_fcurve(fcu, bezt, eInsertKeyFlags(0));
blender::animrig::insert_bezt_fcurve(fcu, bezt, eInsertKeyFlags(0));
lastb = (fcu->bezt + (fcu->totvert - 1));
lastb->f1 = lastb->f2 = lastb->f3 = 0;
continue;
@@ -166,7 +168,7 @@ void clean_fcurve(bAnimContext *ac,
if (cur[1] > next[1]) {
if (IS_EQT(cur[1], prev[1], thresh) == 0) {
/* add new keyframe */
insert_bezt_fcurve(fcu, bezt, eInsertKeyFlags(0));
blender::animrig::insert_bezt_fcurve(fcu, bezt, eInsertKeyFlags(0));
}
}
}
@@ -174,7 +176,7 @@ void clean_fcurve(bAnimContext *ac,
/* only add if values are a considerable distance apart */
if (IS_EQT(cur[1], prev[1], thresh) == 0) {
/* add new keyframe */
insert_bezt_fcurve(fcu, bezt, eInsertKeyFlags(0));
blender::animrig::insert_bezt_fcurve(fcu, bezt, eInsertKeyFlags(0));
}
}
}
@@ -184,18 +186,18 @@ void clean_fcurve(bAnimContext *ac,
/* does current have same value as previous and next? */
if (IS_EQT(cur[1], prev[1], thresh) == 0) {
/* add new keyframe */
insert_bezt_fcurve(fcu, bezt, eInsertKeyFlags(0));
blender::animrig::insert_bezt_fcurve(fcu, bezt, eInsertKeyFlags(0));
}
else if (IS_EQT(cur[1], next[1], thresh) == 0) {
/* add new keyframe */
insert_bezt_fcurve(fcu, bezt, eInsertKeyFlags(0));
blender::animrig::insert_bezt_fcurve(fcu, bezt, eInsertKeyFlags(0));
}
}
else {
/* add if value doesn't equal that of previous */
if (IS_EQT(cur[1], prev[1], thresh) == 0) {
/* add new keyframe */
insert_bezt_fcurve(fcu, bezt, eInsertKeyFlags(0));
blender::animrig::insert_bezt_fcurve(fcu, bezt, eInsertKeyFlags(0));
}
}
}
@@ -1077,7 +1079,7 @@ bool decimate_fcurve(bAnimListElem *ale, float remove_ratio, float error_sq_max)
BezTriple *bezt = (old_bezts + i);
bezt->f2 &= ~BEZT_FLAG_IGNORE_TAG;
if ((bezt->f2 & BEZT_FLAG_TEMP_TAG) == 0) {
insert_bezt_fcurve(fcu, bezt, eInsertKeyFlags(0));
blender::animrig::insert_bezt_fcurve(fcu, bezt, eInsertKeyFlags(0));
}
}
/* now free the memory used by the old BezTriples */
@@ -1270,7 +1272,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++) {
insert_vert_fcurve(
blender::animrig::insert_vert_fcurve(
fcu, fp->frame, fp->val, BEZT_KEYTYPE_BREAKDOWN, eInsertKeyFlags(1));
}
@@ -1712,7 +1714,7 @@ static void paste_animedit_keys_fcurve(
* NOTE: we do not want to inherit handles from existing keyframes in this case!
*/
insert_bezt_fcurve(fcu, bezt, INSERTKEY_OVERWRITE_FULL);
blender::animrig::insert_bezt_fcurve(fcu, bezt, INSERTKEY_OVERWRITE_FULL);
/* un-apply offset from src beztriple after copying */
sub_v2_v2(bezt->vec[0], offset);

View File

@@ -212,271 +212,6 @@ void update_autoflags_fcurve(FCurve *fcu, bContext *C, ReportList *reports, Poin
}
}
/* ************************************************** */
/* KEYFRAME INSERTION */
/* -------------- BezTriple Insertion -------------------- */
/* Change the Y position of a keyframe to match the input, adjusting handles. */
static void replace_bezt_keyframe_ypos(BezTriple *dst, const BezTriple *bezt)
{
/* just change the values when replacing, so as to not overwrite handles */
float dy = bezt->vec[1][1] - dst->vec[1][1];
/* just apply delta value change to the handle values */
dst->vec[0][1] += dy;
dst->vec[1][1] += dy;
dst->vec[2][1] += dy;
dst->f1 = bezt->f1;
dst->f2 = bezt->f2;
dst->f3 = bezt->f3;
/* TODO: perform some other operations? */
}
int insert_bezt_fcurve(FCurve *fcu, const BezTriple *bezt, eInsertKeyFlags flag)
{
int i = 0;
/* are there already keyframes? */
if (fcu->bezt) {
bool replace;
i = BKE_fcurve_bezt_binarysearch_index(fcu->bezt, bezt->vec[1][0], fcu->totvert, &replace);
/* replace an existing keyframe? */
if (replace) {
/* sanity check: 'i' may in rare cases exceed arraylen */
if ((i >= 0) && (i < fcu->totvert)) {
if (flag & INSERTKEY_OVERWRITE_FULL) {
fcu->bezt[i] = *bezt;
}
else {
replace_bezt_keyframe_ypos(&fcu->bezt[i], bezt);
}
if (flag & INSERTKEY_CYCLE_AWARE) {
/* If replacing an end point of a cyclic curve without offset,
* modify the other end too. */
if (ELEM(i, 0, fcu->totvert - 1) && BKE_fcurve_get_cycle_type(fcu) == FCU_CYCLE_PERFECT)
{
replace_bezt_keyframe_ypos(&fcu->bezt[i == 0 ? fcu->totvert - 1 : 0], bezt);
}
}
}
}
/* Keyframing modes allow not replacing the keyframe. */
else if ((flag & INSERTKEY_REPLACE) == 0) {
/* insert new - if we're not restricted to replacing keyframes only */
BezTriple *newb = static_cast<BezTriple *>(
MEM_callocN((fcu->totvert + 1) * sizeof(BezTriple), "beztriple"));
/* Add the beztriples that should occur before the beztriple to be pasted
* (originally in fcu). */
if (i > 0) {
memcpy(newb, fcu->bezt, i * sizeof(BezTriple));
}
/* add beztriple to paste at index i */
*(newb + i) = *bezt;
/* add the beztriples that occur after the beztriple to be pasted (originally in fcu) */
if (i < fcu->totvert) {
memcpy(newb + i + 1, fcu->bezt + i, (fcu->totvert - i) * sizeof(BezTriple));
}
/* replace (+ free) old with new, only if necessary to do so */
MEM_freeN(fcu->bezt);
fcu->bezt = newb;
fcu->totvert++;
}
else {
return -1;
}
}
/* no keyframes already, but can only add if...
* 1) keyframing modes say that keyframes can only be replaced, so adding new ones won't know
* 2) there are no samples on the curve
* NOTE: maybe we may want to allow this later when doing samples -> bezt conversions,
* but for now, having both is asking for trouble
*/
else if ((flag & INSERTKEY_REPLACE) == 0 && (fcu->fpt == nullptr)) {
/* create new keyframes array */
fcu->bezt = static_cast<BezTriple *>(MEM_callocN(sizeof(BezTriple), "beztriple"));
*(fcu->bezt) = *bezt;
fcu->totvert = 1;
}
/* cannot add anything */
else {
/* return error code -1 to prevent any misunderstandings */
return -1;
}
/* we need to return the index, so that some tools which do post-processing can
* detect where we added the BezTriple in the array
*/
return i;
}
/**
* Update the FCurve to allow insertion of `bezt` without modifying the curve shape.
*
* Checks whether it is necessary to apply Bezier subdivision due to involvement of non-auto
* handles. If necessary, changes `bezt` handles from Auto to Aligned.
*
* \param bezt: key being inserted
* \param prev: keyframe before that key
* \param next: keyframe after that key
*/
static void subdivide_nonauto_handles(const FCurve *fcu,
BezTriple *bezt,
BezTriple *prev,
BezTriple *next)
{
if (prev->ipo != BEZT_IPO_BEZ || bezt->ipo != BEZT_IPO_BEZ) {
return;
}
/* Don't change Vector handles, or completely auto regions. */
const bool bezt_auto = BEZT_IS_AUTOH(bezt) || (bezt->h1 == HD_VECT && bezt->h2 == HD_VECT);
const bool prev_auto = BEZT_IS_AUTOH(prev) || (prev->h2 == HD_VECT);
const bool next_auto = BEZT_IS_AUTOH(next) || (next->h1 == HD_VECT);
if (bezt_auto && prev_auto && next_auto) {
return;
}
/* Subdivide the curve. */
float delta;
if (!BKE_fcurve_bezt_subdivide_handles(bezt, prev, next, &delta)) {
return;
}
/* Decide when to force auto to manual. */
if (!BEZT_IS_AUTOH(bezt)) {
return;
}
if ((prev_auto || next_auto) && fcu->auto_smoothing == FCURVE_SMOOTH_CONT_ACCEL) {
const float hx = bezt->vec[1][0] - bezt->vec[0][0];
const float dx = bezt->vec[1][0] - prev->vec[1][0];
/* This mode always uses 1/3 of key distance for handle x size. */
const bool auto_works_well = fabsf(hx - dx / 3.0f) < 0.001f;
if (auto_works_well) {
return;
}
}
/* Turn off auto mode. */
bezt->h1 = bezt->h2 = HD_ALIGN;
}
int insert_vert_fcurve(
FCurve *fcu, float x, float y, eBezTriple_KeyframeType keyframe_type, eInsertKeyFlags flag)
{
BezTriple beztr = {{{0}}};
uint oldTot = fcu->totvert;
int a;
/* set all three points, for nicer start position
* NOTE: +/- 1 on vec.x for left and right handles is so that 'free' handles work ok...
*/
beztr.vec[0][0] = x - 1.0f;
beztr.vec[0][1] = y;
beztr.vec[1][0] = x;
beztr.vec[1][1] = y;
beztr.vec[2][0] = x + 1.0f;
beztr.vec[2][1] = y;
beztr.f1 = beztr.f2 = beztr.f3 = SELECT;
/* set default handle types and interpolation mode */
if (flag & INSERTKEY_NO_USERPREF) {
/* for Py-API, we want scripts to have predictable behavior,
* hence the option to not depend on the userpref defaults
*/
beztr.h1 = beztr.h2 = HD_AUTO_ANIM;
beztr.ipo = BEZT_IPO_BEZ;
}
else {
/* For UI usage - defaults should come from the user-preferences and/or tool-settings. */
beztr.h1 = beztr.h2 = U.keyhandles_new; /* use default handle type here */
/* use default interpolation mode, with exceptions for int/discrete values */
beztr.ipo = U.ipo_new;
}
/* interpolation type used is constrained by the type of values the curve can take */
if (fcu->flag & FCURVE_DISCRETE_VALUES) {
beztr.ipo = BEZT_IPO_CONST;
}
else if ((beztr.ipo == BEZT_IPO_BEZ) && (fcu->flag & FCURVE_INT_VALUES)) {
beztr.ipo = BEZT_IPO_LIN;
}
/* set keyframe type value (supplied), which should come from the scene settings in most cases */
BEZKEYTYPE(&beztr) = keyframe_type;
/* set default values for "easing" interpolation mode settings
* NOTE: Even if these modes aren't currently used, if users switch
* to these later, we want these to work in a sane way out of
* the box.
*/
/* "back" easing - this value used to be used when overshoot=0, but that
* introduced discontinuities in how the param worked. */
beztr.back = 1.70158f;
/* "elastic" easing - values here were hand-optimized for a default duration of
* ~10 frames (typical mograph motion length) */
beztr.amplitude = 0.8f;
beztr.period = 4.1f;
/* add temp beztriple to keyframes */
a = insert_bezt_fcurve(fcu, &beztr, flag);
BKE_fcurve_active_keyframe_set(fcu, &fcu->bezt[a]);
/* what if 'a' is a negative index?
* for now, just exit to prevent any segfaults
*/
if (a < 0) {
return -1;
}
/* Set handle-type and interpolation. */
if ((fcu->totvert > 2) && (flag & INSERTKEY_REPLACE) == 0) {
BezTriple *bezt = (fcu->bezt + a);
/* Set interpolation from previous (if available),
* but only if we didn't just replace some keyframe:
* - Replacement is indicated by no-change in number of verts.
* - When replacing, the user may have specified some interpolation that should be kept.
*/
if (fcu->totvert > oldTot) {
if (a > 0) {
bezt->ipo = (bezt - 1)->ipo;
}
else if (a < fcu->totvert - 1) {
bezt->ipo = (bezt + 1)->ipo;
}
if (0 < a && a < (fcu->totvert - 1) && (flag & INSERTKEY_OVERWRITE_FULL) == 0) {
subdivide_nonauto_handles(fcu, bezt, bezt - 1, bezt + 1);
}
}
}
/* don't recalculate handles if fast is set
* - this is a hack to make importers faster
* - we may calculate twice (due to auto-handle needing to be calculated twice)
*/
if ((flag & INSERTKEY_FAST) == 0) {
BKE_fcurve_handles_recalc(fcu);
}
/* return the index at which the keyframe was added */
return a;
}
/* ------------------------- Insert Key API ------------------------- */
void ED_keyframes_add(FCurve *fcu, int num_keys_to_add)

View File

@@ -67,13 +67,14 @@
#include "ED_armature.hh"
#include "ED_keyframes_edit.hh"
#include "ED_keyframes_keylist.hh"
#include "ED_keyframing.hh"
#include "ED_markers.hh"
#include "ED_numinput.hh"
#include "ED_screen.hh"
#include "ED_space_api.hh"
#include "ED_util.hh"
#include "ANIM_fcurve.hh"
#include "GPU_immediate.h"
#include "GPU_immediate_util.h"
#include "GPU_matrix.h"
@@ -1740,7 +1741,7 @@ static void propagate_curve_values(ListBase /*tPChanFCurveLink*/ *pflinks,
FCurve *fcu = (FCurve *)ld->data;
const float current_fcu_value = evaluate_fcurve(fcu, source_frame);
LISTBASE_FOREACH (FrameLink *, target_frame, target_frames) {
insert_vert_fcurve(
blender::animrig::insert_vert_fcurve(
fcu, target_frame->frame, current_fcu_value, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NEEDED);
}
}

View File

@@ -67,38 +67,6 @@ void update_autoflags_fcurve_direct(FCurve *fcu, PropertyRNA *prop);
/* -------- */
/**
* \brief Lesser Key-framing API call.
*
* Use this when validation of necessary animation data isn't necessary as it already
* exists, and there is a #BezTriple that can be directly copied into the array.
*
* This function adds a given #BezTriple to an F-Curve. It will allocate
* memory for the array if needed, and will insert the #BezTriple into a
* suitable place in chronological order.
*
* \note any recalculate of the F-Curve that needs to be done will need to be done by the caller.
*/
int insert_bezt_fcurve(FCurve *fcu, const BezTriple *bezt, eInsertKeyFlags flag);
/**
* \brief Main Key-framing API call.
*
* Use this when validation of necessary animation data isn't necessary as it
* already exists. It will insert a keyframe using the current value being keyframed.
* Returns the index at which a keyframe was added (or -1 if failed).
*
* This function is a wrapper for #insert_bezt_fcurve(), and should be used when
* adding a new keyframe to a curve, when the keyframe doesn't exist anywhere else yet.
* It returns the index at which the keyframe was added.
*
* \param keyframe_type: The type of keyframe (#eBezTriple_KeyframeType).
* \param flag: Optional flags (#eInsertKeyFlags) for controlling how keys get added
* and/or whether updates get done.
*/
int insert_vert_fcurve(
FCurve *fcu, float x, float y, eBezTriple_KeyframeType keyframe_type, eInsertKeyFlags flag);
/**
* Add the given number of keyframes to the FCurve. Their coordinates are
* uninitialized, so the curve should not be used without further attention.

View File

@@ -43,6 +43,7 @@
#include "UI_view2d.hh"
#include "ANIM_fcurve.hh"
#include "ANIM_keyframing.hh"
#include "ED_anim_api.hh"
#include "ED_gpencil_legacy.hh"
@@ -859,7 +860,7 @@ static void insert_fcurve_key(bAnimContext *ac,
}
const float curval = evaluate_fcurve(fcu, cfra);
insert_vert_fcurve(
blender::animrig::insert_vert_fcurve(
fcu, cfra, curval, eBezTriple_KeyframeType(ts->keyframe_type), eInsertKeyFlags(0));
}

View File

@@ -47,6 +47,7 @@
#include "UI_interface.hh"
#include "UI_view2d.hh"
#include "ANIM_fcurve.hh"
#include "ANIM_keyframing.hh"
#include "ED_anim_api.hh"
#include "ED_keyframes_edit.hh"
@@ -179,7 +180,7 @@ static void insert_graph_keys(bAnimContext *ac, eGraphKeys_InsertKey_Types mode)
}
/* Insert keyframe directly into the F-Curve. */
insert_vert_fcurve(
blender::animrig::insert_vert_fcurve(
fcu, x, y, eBezTriple_KeyframeType(ts->keyframe_type), eInsertKeyFlags(0));
ale->update |= ANIM_UPDATE_DEFAULT;
@@ -228,7 +229,7 @@ static void insert_graph_keys(bAnimContext *ac, eGraphKeys_InsertKey_Types mode)
}
const float curval = evaluate_fcurve_only_curve(fcu, cfra);
insert_vert_fcurve(
blender::animrig::insert_vert_fcurve(
fcu, cfra, curval, eBezTriple_KeyframeType(ts->keyframe_type), eInsertKeyFlags(0));
}
@@ -345,7 +346,7 @@ static int graphkeys_click_insert_exec(bContext *C, wmOperator *op)
val = val * scale - offset;
/* Insert keyframe on the specified frame + value. */
insert_vert_fcurve(
blender::animrig::insert_vert_fcurve(
fcu, frame, val, eBezTriple_KeyframeType(ts->keyframe_type), eInsertKeyFlags(0));
ale->update |= ANIM_UPDATE_DEPS;

View File

@@ -15,6 +15,8 @@
#include "ED_keyframing.hh"
#include "ANIM_fcurve.hh"
#include "BLI_listbase.h"
#include "BLI_math_matrix.h"
#include "BLI_string.h"
@@ -65,7 +67,7 @@ void AnimationImporter::add_bezt(FCurve *fcu,
bez.ipo = ipo; /* use default interpolation mode here... */
bez.f1 = bez.f2 = bez.f3 = SELECT;
bez.h1 = bez.h2 = HD_AUTO;
insert_bezt_fcurve(fcu, &bez, INSERTKEY_NOFLAGS);
blender::animrig::insert_bezt_fcurve(fcu, &bez, INSERTKEY_NOFLAGS);
BKE_fcurve_handles_recalc(fcu);
}
@@ -132,7 +134,7 @@ void AnimationImporter::animation_to_fcurves(COLLADAFW::AnimationCurve *curve)
#endif
bez.f1 = bez.f2 = bez.f3 = SELECT;
insert_bezt_fcurve(fcu, &bez, INSERTKEY_NOFLAGS);
blender::animrig::insert_bezt_fcurve(fcu, &bez, INSERTKEY_NOFLAGS);
}
BKE_fcurve_handles_recalc(fcu);

View File

@@ -103,7 +103,7 @@ void BCAnimationCurve::create_bezt(float frame, float output)
bez.ipo = U.ipo_new; /* use default interpolation mode here... */
bez.f1 = bez.f2 = bez.f3 = SELECT;
bez.h1 = bez.h2 = HD_AUTO;
insert_bezt_fcurve(fcu, &bez, INSERTKEY_NOFLAGS);
blender::animrig::insert_bezt_fcurve(fcu, &bez, INSERTKEY_NOFLAGS);
BKE_fcurve_handles_recalc(fcu);
}
@@ -315,7 +315,8 @@ void BCAnimationCurve::clean_handles()
BezTriple *bezt = &old_bezts[i];
float x = bezt->vec[1][0];
float y = bezt->vec[1][1];
insert_vert_fcurve(fcurve, x, y, (eBezTriple_KeyframeType)BEZKEYTYPE(bezt), INSERTKEY_NOFLAGS);
blender::animrig::insert_vert_fcurve(
fcurve, x, y, (eBezTriple_KeyframeType)BEZKEYTYPE(bezt), INSERTKEY_NOFLAGS);
BezTriple *lastb = fcurve->bezt + (fcurve->totvert - 1);
lastb->f1 = lastb->f2 = lastb->f3 = 0;
}
@@ -380,7 +381,8 @@ void BCAnimationCurve::add_value(const float val, const int frame_index)
{
FCurve *fcu = get_edit_fcurve();
fcu->auto_smoothing = U.auto_smoothing_new;
insert_vert_fcurve(fcu, frame_index, val, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NOFLAGS);
blender::animrig::insert_vert_fcurve(
fcu, frame_index, val, BEZT_KEYTYPE_KEYFRAME, INSERTKEY_NOFLAGS);
if (fcu->totvert == 1) {
init_range(val);

View File

@@ -15,7 +15,8 @@
#include "ED_anim_api.hh"
#include "ED_keyframes_edit.hh"
#include "ED_keyframing.hh"
#include "ANIM_fcurve.hh"
typedef float(TangentPoint)[2];

View File

@@ -186,6 +186,7 @@ set(LIB
bf_blenkernel
PRIVATE bf::blenlib
PRIVATE bf::dna
PRIVATE bf::animrig
bf_imbuf
PRIVATE bf::intern::guardedalloc
bf_io_common

View File

@@ -41,6 +41,8 @@
#include "ED_keyframing.hh"
#include "ED_mesh.hh"
#include "ANIM_fcurve.hh"
#include "WM_api.hh"
#include <iostream>
@@ -93,7 +95,7 @@ void add_bezt(FCurve *fcu,
bez.ipo = ipo; /* use default interpolation mode here... */
bez.f1 = bez.f2 = bez.f3 = SELECT;
bez.h1 = bez.h2 = HD_AUTO;
insert_bezt_fcurve(fcu, &bez, INSERTKEY_NOFLAGS);
blender::animrig::insert_bezt_fcurve(fcu, &bez, INSERTKEY_NOFLAGS);
}
/**

View File

@@ -30,6 +30,10 @@
#include "ED_keyframes_edit.hh"
#include "ED_keyframing.hh"
#ifdef RNA_RUNTIME
# include "ANIM_fcurve.hh"
#endif
const EnumPropertyItem rna_enum_fmodifier_type_items[] = {
{FMODIFIER_TYPE_NULL, "nullptr", 0, "Invalid", ""},
{FMODIFIER_TYPE_GENERATOR,
@@ -1051,11 +1055,11 @@ static void rna_FModifierStepped_frame_end_set(PointerRNA *ptr, float value)
static BezTriple *rna_FKeyframe_points_insert(
ID *id, FCurve *fcu, Main *bmain, float frame, float value, int keyframe_type, int flag)
{
int index = insert_vert_fcurve(fcu,
frame,
value,
eBezTriple_KeyframeType(keyframe_type),
eInsertKeyFlags(flag) | INSERTKEY_NO_USERPREF);
int index = blender::animrig::insert_vert_fcurve(fcu,
frame,
value,
eBezTriple_KeyframeType(keyframe_type),
eInsertKeyFlags(flag) | INSERTKEY_NO_USERPREF);
if ((fcu->bezt) && (index >= 0)) {
rna_tag_animation_update(bmain, id);