[Bf-blender-cvs] [72acce43bc3] master: Animation: allow marking actions as cyclic for Cycle-Aware Keying.

Alexander Gavrilov noreply at git.blender.org
Wed Nov 24 13:58:49 CET 2021


Commit: 72acce43bc34e5e9569606e08ee536b02cab088b
Author: Alexander Gavrilov
Date:   Tue Jul 27 10:39:52 2021 +0300
Branches: master
https://developer.blender.org/rB72acce43bc34e5e9569606e08ee536b02cab088b

Animation: allow marking actions as cyclic for Cycle-Aware Keying.

When a manual frame range is set, allow marking an action as having
Cyclic Animation. This does not affect how the action is evaluated,
but the Cycle-Aware Keying option will automatically make any newly
added F-Curves cyclic. This allows using the option from the start
to build the cycle, rather than only for tweaking an existing loop.

The curves are made cyclic when they have only one key, either
after inserting the first key, or before adding the second one.
The latter case avoids the need to manually make the first added
curve cyclic after marking a newly added action cyclic.

Differential Revision: https://developer.blender.org/D11803

===================================================================

M	release/scripts/startup/bl_ui/space_dopesheet.py
M	source/blender/blenkernel/BKE_action.h
M	source/blender/blenkernel/intern/action.c
M	source/blender/blenkernel/intern/nla.c
M	source/blender/editors/animation/keyframing.c
M	source/blender/makesdna/DNA_action_types.h
M	source/blender/makesrna/intern/rna_action.c
M	source/blender/makesrna/intern/rna_scene.c

===================================================================

diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py
index 6e5eba7b734..3c90e0c96cc 100644
--- a/release/scripts/startup/bl_ui/space_dopesheet.py
+++ b/release/scripts/startup/bl_ui/space_dopesheet.py
@@ -556,6 +556,8 @@ class DopesheetActionPanelBase:
         row.prop(action, "frame_start", text="Start")
         row.prop(action, "frame_end", text="End")
 
+        col.prop(action, "use_cyclic")
+
 
 class DOPESHEET_PT_action(DopesheetActionPanelBase, Panel):
     bl_space_type = 'DOPESHEET_EDITOR'
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);



More information about the Bf-blender-cvs mailing list