diff options
Diffstat (limited to 'source/blender/editors/animation/keyframing.c')
-rw-r--r-- | source/blender/editors/animation/keyframing.c | 58 |
1 files changed, 56 insertions, 2 deletions
diff --git a/source/blender/editors/animation/keyframing.c b/source/blender/editors/animation/keyframing.c index 0a9f1a36a28..95d1ca1e7a6 100644 --- a/source/blender/editors/animation/keyframing.c +++ b/source/blender/editors/animation/keyframing.c @@ -35,6 +35,7 @@ #include "BLT_translation.h" +#include "DNA_action_types.h" #include "DNA_anim_types.h" #include "DNA_armature_types.h" #include "DNA_constraint_types.h" @@ -375,6 +376,43 @@ static eFCU_Cycle_Type remap_cyclic_keyframe_location(FCurve *fcu, float *px, fl return type; } +/* Used to make curves newly added to a cyclic Action cycle with the correct period. */ +static void make_new_fcurve_cyclic(const bAction *act, FCurve *fcu) +{ + /* The curve must contain one (newly-added) keyframe. */ + if (fcu->totvert != 1 || !fcu->bezt) { + return; + } + + const float period = act->frame_end - act->frame_start; + + if (period < 0.1f) { + return; + } + + /* Move the keyframe into the range. */ + const float frame_offset = fcu->bezt[0].vec[1][0] - act->frame_start; + const float fix = floorf(frame_offset / period) * period; + + fcu->bezt[0].vec[0][0] -= fix; + fcu->bezt[0].vec[1][0] -= fix; + fcu->bezt[0].vec[2][0] -= fix; + + /* Duplicate and offset the keyframe. */ + fcu->bezt = MEM_reallocN(fcu->bezt, sizeof(BezTriple) * 2); + fcu->totvert = 2; + + fcu->bezt[1] = fcu->bezt[0]; + fcu->bezt[1].vec[0][0] += period; + fcu->bezt[1].vec[1][0] += period; + fcu->bezt[1].vec[2][0] += period; + + /* Add the cycles modifier. */ + if (!fcu->modifiers.first) { + add_fmodifier(&fcu->modifiers, FMODIFIER_TYPE_CYCLES, fcu); + } +} + /* -------------- BezTriple Insertion -------------------- */ /* Change the Y position of a keyframe to match the input, adjusting handles. */ @@ -1352,8 +1390,10 @@ static bool insert_keyframe_fcurve_value(Main *bmain, /* we may not have a F-Curve when we're replacing only... */ if (fcu) { + const bool is_new_curve = (fcu->totvert == 0); + /* set color mode if the F-Curve is new (i.e. without any keyframes) */ - if ((fcu->totvert == 0) && (flag & INSERTKEY_XYZ2RGB)) { + if (is_new_curve && (flag & INSERTKEY_XYZ2RGB)) { /* for Loc/Rot/Scale and also Color F-Curves, the color of the F-Curve in the Graph Editor, * is determined by the array index for the F-Curve */ @@ -1366,12 +1406,26 @@ static bool insert_keyframe_fcurve_value(Main *bmain, } } + /* If the curve has only one key, make it cyclic if appropriate. */ + const bool is_cyclic_action = (flag & INSERTKEY_CYCLE_AWARE) && BKE_action_is_cyclic(act); + + if (is_cyclic_action && fcu->totvert == 1) { + make_new_fcurve_cyclic(act, fcu); + } + /* update F-Curve flags to ensure proper behavior for property type */ update_autoflags_fcurve_direct(fcu, prop); /* insert keyframe */ - return insert_keyframe_value( + const bool success = insert_keyframe_value( reports, ptr, prop, fcu, anim_eval_context, curval, keytype, flag); + + /* If the curve is new, make it cyclic if appropriate. */ + if (is_cyclic_action && is_new_curve) { + make_new_fcurve_cyclic(act, fcu); + } + + return success; } return false; |