[Bf-blender-cvs] [f3f87db425e] temp-angavrilov: Animation: allow manually setting the intended playback range for actions.

Alexander Gavrilov noreply at git.blender.org
Thu Oct 21 20:41:00 CEST 2021


Commit: f3f87db425e5fd4d5d199de1baa59639ef2d84ad
Author: Alexander Gavrilov
Date:   Mon May 3 00:03:00 2021 +0300
Branches: temp-angavrilov
https://developer.blender.org/rBf3f87db425e5fd4d5d199de1baa59639ef2d84ad

Animation: allow manually setting the intended playback range for actions.

Some operations, e.g. adding a new action strip to NLA, require
knowing the active frame range of an action. However, currently it
can only be deduced by scanning the keyframes of the curves within
it. This is not ideal if e.g. curves are staggered for overlap.

As suggested by Nathan Vegdahl in comments to T54724, this patch adds
Action properties that allow manually specifying its active frame range.
The settings are exposed via a panel in the Dopesheet and Action Editor.
When enabled, the range is highlighted in the background using a striped
fill to distinguish it from the solid filled regular playback range.

When set, the frame range is used when adding or updating NLA tracks,
and by add-ons using `Action.frame_range`, e.g. FBX exporter.

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/anim_draw.c
M	source/blender/editors/include/ED_anim_api.h
M	source/blender/editors/space_action/action_data.c
M	source/blender/editors/space_action/action_draw.c
M	source/blender/editors/space_action/space_action.c
M	source/blender/editors/space_nla/nla_draw.c
M	source/blender/editors/space_nla/nla_edit.c
M	source/blender/makesdna/DNA_action_types.h
M	source/blender/makesrna/intern/rna_action.c

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

diff --git a/release/scripts/startup/bl_ui/space_dopesheet.py b/release/scripts/startup/bl_ui/space_dopesheet.py
index 781c430a752..1f37c7e98ca 100644
--- a/release/scripts/startup/bl_ui/space_dopesheet.py
+++ b/release/scripts/startup/bl_ui/space_dopesheet.py
@@ -688,6 +688,32 @@ class DOPESHEET_MT_snap_pie(Menu):
         pie.operator("action.snap", text="Selection to Nearest Marker").type = 'NEAREST_MARKER'
 
 
+class DOPESHEET_PT_action(Panel):
+    bl_space_type = 'DOPESHEET_EDITOR'
+    bl_region_type = 'UI'
+    bl_category = "Item"
+    bl_label = "Action"
+
+    @classmethod
+    def poll(cls, context):
+        return bool(context.selected_visible_actions)
+
+    def draw(self, context):
+        layout = self.layout
+        action = context.selected_visible_actions[0]
+
+        layout.label(text=action.name, icon='ACTION')
+
+        layout.prop(action, "use_frame_range")
+
+        col = layout.column()
+        col.active = action.use_frame_range
+
+        row = col.row(align=True)
+        row.prop(action, "frame_start", text="Start")
+        row.prop(action, "frame_end", text="End")
+
+
 class LayersDopeSheetPanel:
     bl_space_type = 'DOPESHEET_EDITOR'
     bl_region_type = 'UI'
@@ -779,6 +805,7 @@ classes = (
     DOPESHEET_MT_channel_context_menu,
     DOPESHEET_MT_snap_pie,
     DOPESHEET_PT_filters,
+    DOPESHEET_PT_action,
     DOPESHEET_PT_gpencil_mode,
     DOPESHEET_PT_gpencil_layer_masks,
     DOPESHEET_PT_gpencil_layer_transform,
diff --git a/source/blender/blenkernel/BKE_action.h b/source/blender/blenkernel/BKE_action.h
index 9f69c5e3976..d37f4e9e7ea 100644
--- a/source/blender/blenkernel/BKE_action.h
+++ b/source/blender/blenkernel/BKE_action.h
@@ -91,6 +91,10 @@ short action_get_item_transforms(struct bAction *act,
 /* Some kind of bounding box operation on the action */
 void calc_action_range(const struct bAction *act, float *start, float *end, short incl_modifiers);
 
+/* Retrieve the intended playback frame range, using the manually set range if available,
+ * or falling back to scanning F-Curves for their first & last frames otherwise. */
+void BKE_action_get_frame_range(const struct bAction *act, float *r_start, float *r_end);
+
 /* Does action have any motion data at all? */
 bool action_has_motion(const struct bAction *act);
 
diff --git a/source/blender/blenkernel/intern/action.c b/source/blender/blenkernel/intern/action.c
index 65900ec0f4b..1f6b9a47fbb 100644
--- a/source/blender/blenkernel/intern/action.c
+++ b/source/blender/blenkernel/intern/action.c
@@ -1506,6 +1506,24 @@ void calc_action_range(const bAction *act, float *start, float *end, short incl_
   }
 }
 
+/* Retrieve the intended playback frame range, using the manually set range if available,
+ * or falling back to scanning F-Curves for their first & last frames otherwise. */
+void BKE_action_get_frame_range(const struct bAction *act, float *r_start, float *r_end)
+{
+  if (act && (act->flag & ACT_FRAME_RANGE)) {
+    *r_start = act->frame_start;
+    *r_end = act->frame_end;
+  }
+  else {
+    calc_action_range(act, r_start, r_end, false);
+  }
+
+  /* Ensure that action is at least 1 frame long (for NLA strips to have a valid length). */
+  if (*r_start >= *r_end) {
+    *r_end = *r_start + 1.0f;
+  }
+}
+
 /* 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 487e925df79..310fee8620b 100644
--- a/source/blender/blenkernel/intern/nla.c
+++ b/source/blender/blenkernel/intern/nla.c
@@ -397,7 +397,7 @@ NlaStrip *BKE_nlastrip_new(bAction *act)
   /* determine initial range
    * - strip length cannot be 0... ever...
    */
-  calc_action_range(strip->act, &strip->actstart, &strip->actend, 0);
+  BKE_action_get_frame_range(strip->act, &strip->actstart, &strip->actend);
 
   strip->start = strip->actstart;
   strip->end = (IS_EQF(strip->actstart, strip->actend)) ? (strip->actstart + 1.0f) :
@@ -1444,7 +1444,7 @@ void BKE_nlastrip_recalculate_bounds_sync_action(NlaStrip *strip)
 
   prev_actstart = strip->actstart;
 
-  calc_action_range(strip->act, &strip->actstart, &strip->actend, 0);
+  BKE_action_get_frame_range(strip->act, &strip->actstart, &strip->actend);
 
   /* Set start such that key's do not visually move, to preserve the overall animation result. */
   strip->start += (strip->actstart - prev_actstart) * strip->scale;
diff --git a/source/blender/editors/animation/anim_draw.c b/source/blender/editors/animation/anim_draw.c
index 993d10cf303..f5a5609aa2e 100644
--- a/source/blender/editors/animation/anim_draw.c
+++ b/source/blender/editors/animation/anim_draw.c
@@ -168,6 +168,74 @@ void ANIM_draw_framerange(Scene *scene, View2D *v2d)
   immUnbindProgram();
 }
 
+/**
+ * Draw manually set intended playback frame range guides for the action in the background.
+ * Allows specifying a subset of the Y range of the view.
+ */
+void ANIM_draw_action_framerange(
+    AnimData *adt, bAction *action, View2D *v2d, float ymin, float ymax)
+{
+  if ((action->flag & ACT_FRAME_RANGE) == 0) {
+    return;
+  }
+
+  /* Compute the dimensions. */
+  CLAMP_MIN(ymin, v2d->cur.ymin);
+  CLAMP_MAX(ymax, v2d->cur.ymax);
+
+  if (ymin > ymax) {
+    return;
+  }
+
+  const float sfra = BKE_nla_tweakedit_remap(adt, action->frame_start, NLATIME_CONVERT_MAP);
+  const float efra = BKE_nla_tweakedit_remap(adt, action->frame_end, NLATIME_CONVERT_MAP);
+
+  /* Diagonal stripe filled area outside of the frame range. */
+  GPU_blend(GPU_BLEND_ALPHA);
+
+  GPUVertFormat *format = immVertexFormat();
+  uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
+
+  immBindBuiltinProgram(GPU_SHADER_2D_DIAG_STRIPES);
+
+  float color[4];
+  UI_GetThemeColorShadeAlpha4fv(TH_BACK, -40, -50, color);
+
+  immUniform4f("color1", color[0], color[1], color[2], color[3]);
+  immUniform4f("color2", 0.0f, 0.0f, 0.0f, 0.0f);
+  immUniform1i("size1", 2 * U.dpi_fac);
+  immUniform1i("size2", 4 * U.dpi_fac);
+
+  if (sfra < efra) {
+    immRectf(pos, v2d->cur.xmin, ymin, sfra, ymax);
+    immRectf(pos, efra, ymin, v2d->cur.xmax, ymax);
+  }
+  else {
+    immRectf(pos, v2d->cur.xmin, ymin, v2d->cur.xmax, ymax);
+  }
+
+  immUnbindProgram();
+
+  GPU_blend(GPU_BLEND_NONE);
+
+  /* Thin lines where the actual frames are. */
+  immBindBuiltinProgram(GPU_SHADER_2D_UNIFORM_COLOR);
+  immUniformThemeColorShade(TH_BACK, -60);
+
+  GPU_line_width(1.0f);
+
+  immBegin(GPU_PRIM_LINES, 4);
+
+  immVertex2f(pos, sfra, ymin);
+  immVertex2f(pos, sfra, ymax);
+
+  immVertex2f(pos, efra, ymin);
+  immVertex2f(pos, efra, ymax);
+
+  immEnd();
+  immUnbindProgram();
+}
+
 /* *************************************************** */
 /* NLA-MAPPING UTILITIES (required for drawing and also editing keyframes). */
 
diff --git a/source/blender/editors/include/ED_anim_api.h b/source/blender/editors/include/ED_anim_api.h
index 5d5d9140a24..cab4c18211d 100644
--- a/source/blender/editors/include/ED_anim_api.h
+++ b/source/blender/editors/include/ED_anim_api.h
@@ -676,6 +676,10 @@ void ANIM_draw_previewrange(const struct bContext *C, struct View2D *v2d, int en
 /* main call to draw normal frame range indicators */
 void ANIM_draw_framerange(struct Scene *scene, struct View2D *v2d);
 
+/* Draw manually set intended playback frame range indicators for the action. */
+void ANIM_draw_action_framerange(
+    struct AnimData *adt, struct bAction *action, struct View2D *v2d, float ymin, float ymax);
+
 /* ************************************************* */
 /* F-MODIFIER TOOLS */
 
@@ -864,7 +868,8 @@ void ED_operatormacros_action(void);
 /* XXX: Should we be doing these here, or at all? */
 
 /* Action Editor - Action Management */
-struct AnimData *ED_actedit_animdata_from_context(struct bContext *C, struct ID **r_adt_id_owner);
+struct AnimData *ED_actedit_animdata_from_context(const struct bContext *C,
+                                                  struct ID **r_adt_id_owner);
 void ED_animedit_unlink_action(struct bContext *C,
                                struct ID *id,
                                struct AnimData *adt,
diff --git a/source/blender/editors/space_action/action_data.c b/source/blender/editors/space_action/action_data.c
index a4fd2d81778..fd1829c8cb6 100644
--- a/source/blender/editors/space_action/action_data.c
+++ b/source/blender/editors/space_action/action_data.c
@@ -71,7 +71,7 @@
 /* ACTION CREATION */
 
 /* Helper function to find the active AnimData block from the Action Editor context */
-AnimData *ED_actedit_animdata_from_context(bContext *C, ID **r_adt_id_owner)
+AnimData *ED_actedit_animdata_from_context(const bContext *C, ID **r_adt_id_owner)
 {
   SpaceAction *saction = (SpaceAction *)CTX_wm_space_data(C);
   Object *ob = CTX_data_active_object(C);
diff --git a/source/blender/editors/space_action/action_draw.c b/source/blender/editors/space_action/action_draw.c
index 6f1a90e56a5..bc13b7f2b1b 100644
--- a/source/blender/editors/space_action/action_draw.c
+++ b/source/blender/editors/space_action/action_draw.c
@@ -131,6 +131,54 @@ void draw_channel_names(bContext *C, bAnimContext *ac, ARegion *region)
 /* extra padding for lengths (to go under scrollers) */
 #define EXTRA_SCROLL_PAD 100.0f
 
+/* Draw manually set intended playback frame ranges for actions. */
+static void draw_channel_action_ranges(bAnimContext *ac, ListBase *anim_data, View2D *v2d)
+{
+  /* Variables for coalescing the Y region of one action. */
+  bAction *cur_action = NULL;
+  AnimData *cur_adt = NULL;
+  float cur_ymax;
+
+  /* Walk through channels, grouping contiguous spans referencing the same action. */
+  float ymax = ACHANNEL_FIRST_TOP(ac) + ACHANNEL_SKIP / 2;
+  float ystep = ACHANNEL_STEP(ac);
+  float ymin = ymax - ystep;
+
+  for (bAnimListElem *ale = anim_data->first; ale; ale = ale->next, ymax = ymin, ymin -= ystep) {
+    bAction *action = NULL;
+    AnimData *adt = NULL;
+
+    /* check if visible */
+    if (IN_RANGE(ymin, v2d->cur.ymin, v2d->cur.ymax) ||
+        IN_RANGE(ymax, v2d->cur.ymin, v2d->cur.ymax)) {
+      /* check if anything to show for this channel 

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list