diff options
Diffstat (limited to 'source')
-rw-r--r-- | source/blender/blenkernel/BKE_action.h | 3 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/action.c | 6 | ||||
-rw-r--r-- | source/blender/blenkernel/intern/nla.c | 5 | ||||
-rw-r--r-- | source/blender/editors/animation/keyframing.c | 58 | ||||
-rw-r--r-- | source/blender/makesdna/DNA_action_types.h | 2 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_action.c | 10 | ||||
-rw-r--r-- | source/blender/makesrna/intern/rna_scene.c | 3 |
7 files changed, 84 insertions, 3 deletions
diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h index 6d457ed32f0..b5e94793658 100644 --- a/source/blender/blenkernel/BKE_action.h +++ b/source/blender/blenkernel/BKE_action.h @@ -98,6 +98,9 @@ void BKE_action_get_frame_range(const struct bAction *act, float *r_start, float /* Does action have any motion data at all? */ bool action_has_motion(const struct bAction *act); +/* Is the action configured as cyclic. */ +bool BKE_action_is_cyclic(const struct bAction *act); + /* Action Groups API ----------------- */ /* Get the active action-group for an Action */ diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c index 47db5183e76..408a0b3065e 100644 --- a/source/blender/blenkernel/intern/action.c +++ b/source/blender/blenkernel/intern/action.c @@ -1591,6 +1591,12 @@ void BKE_action_get_frame_range(const struct bAction *act, float *r_start, float } } +/* Is the action configured as cyclic. */ +bool BKE_action_is_cyclic(const struct bAction *act) +{ + return act && (act->flag & ACT_FRAME_RANGE) && (act->flag & ACT_CYCLIC); +} + /* Return flags indicating which transforms the given object/posechannel has * - if 'curves' is provided, a list of links to these curves are also returned */ diff --git a/source/blender/blenkernel/intern/nla.c b/source/blender/blenkernel/intern/nla.c index 0666c1dfc53..8f2a60358e7 100644 --- a/source/blender/blenkernel/intern/nla.c +++ b/source/blender/blenkernel/intern/nla.c @@ -395,6 +395,11 @@ NlaStrip *BKE_nlastrip_new(bAction *act) strip->flag &= ~NLASTRIP_FLAG_SYNC_LENGTH; } + /* Enable cyclic time for known cyclic actions. */ + if (BKE_action_is_cyclic(act)) { + strip->flag |= NLASTRIP_FLAG_USR_TIME_CYCLIC; + } + /* assign the action reference */ strip->act = act; id_us_plus(&act->id); 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; diff --git a/source/blender/makesdna/DNA_action_types.h b/source/blender/makesdna/DNA_action_types.h index 9d1de4c0c36..8e7551e1703 100644 --- a/source/blender/makesdna/DNA_action_types.h +++ b/source/blender/makesdna/DNA_action_types.h @@ -701,6 +701,8 @@ typedef enum eAction_Flags { /* ACT_DISABLED = (1 << 11), */ /* UNUSED */ /** The action has a manually set intended playback frame range. */ ACT_FRAME_RANGE = (1 << 12), + /** The action is intended to be a cycle (requires ACT_FRAME_RANGE). */ + ACT_CYCLIC = (1 << 13), } eAction_Flags; /* ************************************************ */ diff --git a/source/blender/makesrna/intern/rna_action.c b/source/blender/makesrna/intern/rna_action.c index db2c415c918..96e37dfebbb 100644 --- a/source/blender/makesrna/intern/rna_action.c +++ b/source/blender/makesrna/intern/rna_action.c @@ -893,6 +893,16 @@ static void rna_def_action(BlenderRNA *brna) "(this range is used by some tools, but does not affect animation evaluation)"); RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); + prop = RNA_def_property(srna, "use_cyclic", PROP_BOOLEAN, PROP_NONE); + RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); + RNA_def_property_boolean_sdna(prop, NULL, "flag", ACT_CYCLIC); + RNA_def_property_ui_text( + prop, + "Cyclic Animation", + "The action is intended to be used as a cycle looping over its manually set " + "playback frame range (enabling this doesn't automatically make it loop)"); + RNA_def_property_update(prop, NC_ANIMATION | ND_ANIMCHAN | NA_EDITED, NULL); + prop = RNA_def_property(srna, "frame_start", PROP_FLOAT, PROP_TIME); RNA_def_property_clear_flag(prop, PROP_ANIMATABLE); RNA_def_property_float_sdna(prop, NULL, "frame_start"); diff --git a/source/blender/makesrna/intern/rna_scene.c b/source/blender/makesrna/intern/rna_scene.c index c69a69290f9..d05f2a13c4b 100644 --- a/source/blender/makesrna/intern/rna_scene.c +++ b/source/blender/makesrna/intern/rna_scene.c @@ -3425,7 +3425,8 @@ static void rna_def_tool_settings(BlenderRNA *brna) prop, "Cycle-Aware Keying", "For channels with cyclic extrapolation, keyframe insertion is automatically " - "remapped inside the cycle time range, and keeps ends in sync"); + "remapped inside the cycle time range, and keeps ends in sync. Curves newly added to " + "actions with a Manual Frame Range and Cyclic Animation are automatically made cyclic"); /* Keyframing */ prop = RNA_def_property(srna, "keyframe_type", PROP_ENUM, PROP_NONE); |