[Bf-blender-cvs] [4e57b6ce77b] master: Animation: Sensible frame range for motion paths

Colin Marmond noreply at git.blender.org
Tue Apr 26 12:35:24 CEST 2022


Commit: 4e57b6ce77b15709d7a76382c2d185f9c845532c
Author: Colin Marmond
Date:   Tue Apr 26 12:29:22 2022 +0200
Branches: master
https://developer.blender.org/rB4e57b6ce77b15709d7a76382c2d185f9c845532c

Animation: Sensible frame range for motion paths

Motion paths can now be initialised to more sensible frame ranges,
rather than simply 1-250:

    - Scene Frame Range
    - Selected Keyframes
    - All Keyframes

Reviewed By: sybren, looch, dfelinto, pablico

Maniphest Tasks: T93047

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

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

M	release/scripts/startup/bl_ui/properties_animviz.py
M	source/blender/blenkernel/intern/anim_visualization.c
M	source/blender/editors/animation/anim_motion_paths.c
M	source/blender/editors/animation/keyframes_keylist.cc
M	source/blender/editors/armature/pose_edit.c
M	source/blender/editors/include/ED_anim_api.h
M	source/blender/editors/include/ED_keyframes_keylist.h
M	source/blender/editors/object/object_edit.c
M	source/blender/editors/object/object_intern.h
M	source/blender/editors/object/object_ops.c
M	source/blender/editors/space_nla/nla_draw.c
M	source/blender/makesdna/DNA_action_types.h
M	source/blender/makesrna/RNA_enum_items.h
M	source/blender/makesrna/intern/rna_animviz.c

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

diff --git a/release/scripts/startup/bl_ui/properties_animviz.py b/release/scripts/startup/bl_ui/properties_animviz.py
index 548ce72c429..9aac33eb5de 100644
--- a/release/scripts/startup/bl_ui/properties_animviz.py
+++ b/release/scripts/startup/bl_ui/properties_animviz.py
@@ -24,14 +24,9 @@ class MotionPathButtonsPanel:
         layout.use_property_split = True
         layout.use_property_decorate = False
 
-        row = layout.row(align=True)
-        row.prop(mps, "type")
-        if mps.type == 'RANGE':
-            if bones:
-                row.operator("pose.paths_range_update", text="", icon='TIME')
-            else:
-                row.operator("object.paths_range_update", text="", icon='TIME')
-
+        # Display Range
+        col = layout.column(align=True)
+        col.prop(mps, "type")
         if mps.type == 'CURRENT_FRAME':
             col = layout.column(align=True)
             col.prop(mps, "frame_before", text="Frame Range Before")
@@ -43,21 +38,28 @@ class MotionPathButtonsPanel:
             col.prop(mps, "frame_end", text="End")
             col.prop(mps, "frame_step", text="Step")
 
+        # Calculation Range
+        col = layout.column(align=True)
+        col.prop(mps, "range", text="Calculation Range")
+
         if mpath:
             col = layout.column(align=True)
-            col.enabled = False
-            if bones:
-                col.prop(mpath, "frame_start", text="Bone Cache From")
-            else:
-                col.prop(mpath, "frame_start", text="Cache From")
-            col.prop(mpath, "frame_end", text="To")
+            row = col.row(align=True)
+            row.enabled = False
+            row.prop(mpath, "frame_start", text="Cached Range")
+            row.prop(mpath, "frame_end", text="")
 
             col = layout.column(align=True)
-
             if bones:
-                col.operator("pose.paths_update", text="Update Paths", icon='BONE_DATA')
+                col.operator("pose.paths_update", text="Update Path", icon='BONE_DATA')
+                row = col.row(align=True)
+                row.operator("object.paths_update_visible", text="Update All Paths", icon='WORLD')
+                row.operator("pose.paths_clear", text="", icon='X')
             else:
-                col.operator("object.paths_update", text="Update Paths", icon='OBJECT_DATA')
+                col.operator("object.paths_update", text="Update Path", icon='OBJECT_DATA')
+                row = col.row(align=True)
+                row.operator("object.paths_update_visible", text="Update All Paths", icon='WORLD')
+                row.operator("object.paths_clear", text="", icon='X')
         else:
             col = layout.column(align=True)
             col.label(text="Nothing to show yet...", icon='ERROR')
@@ -67,12 +69,12 @@ class MotionPathButtonsPanel:
             else:
                 col.operator("object.paths_calculate", text="Calculate...", icon='OBJECT_DATA')
 
-        row = col.row(align=True)
-        row.operator("object.paths_update_visible", text="Update All Paths", icon='WORLD')
-        if bones:
-            row.operator("pose.paths_clear", text="", icon='X')
-        else:
-            row.operator("object.paths_clear", text="", icon='X')
+            row = col.row(align=True)
+            row.operator("object.paths_update_visible", text="Update All Paths", icon='WORLD')
+            if bones:
+                row.operator("pose.paths_clear", text="", icon='X')
+            else:
+                row.operator("object.paths_clear", text="", icon='X')
 
 
 class MotionPathButtonsPanel_display:
diff --git a/source/blender/blenkernel/intern/anim_visualization.c b/source/blender/blenkernel/intern/anim_visualization.c
index 53a3a7e3712..799845cbce8 100644
--- a/source/blender/blenkernel/intern/anim_visualization.c
+++ b/source/blender/blenkernel/intern/anim_visualization.c
@@ -153,6 +153,8 @@ bMotionPath *animviz_verify_motionpaths(ReportList *reports,
     if ((mpath->start_frame != mpath->end_frame) && (mpath->length > 0)) {
       /* outer check ensures that we have some curve data for this path */
       if (mpath->length == expected_length) {
+        mpath->start_frame = avs->path_sf;
+        mpath->end_frame = avs->path_ef;
         /* return/use this as it is already valid length */
         return mpath;
       }
diff --git a/source/blender/editors/animation/anim_motion_paths.c b/source/blender/editors/animation/anim_motion_paths.c
index 539227933cf..b15bd3db678 100644
--- a/source/blender/editors/animation/anim_motion_paths.c
+++ b/source/blender/editors/animation/anim_motion_paths.c
@@ -340,6 +340,43 @@ static void motionpath_free_free_tree_data(ListBase *targets)
   }
 }
 
+void animviz_motionpath_compute_range(Object *ob, Scene *scene)
+{
+  bAnimVizSettings *avs = ob->mode == OB_MODE_POSE ? &ob->pose->avs : &ob->avs;
+
+  const bool has_action = ob->adt && ob->adt->action;
+  if (avs->path_range == MOTIONPATH_RANGE_SCENE || !has_action ||
+      BLI_listbase_is_empty(&ob->adt->action->curves)) {
+    avs->path_sf = PSFRA;
+    avs->path_ef = PEFRA;
+    return;
+  }
+
+  struct AnimKeylist *keylist = ED_keylist_create();
+  LISTBASE_FOREACH (FCurve *, fcu, &ob->adt->action->curves) {
+    fcurve_to_keylist(ob->adt, fcu, keylist, 0);
+  }
+
+  Range2f frame_range;
+  switch (avs->path_range) {
+    case MOTIONPATH_RANGE_KEYS_SELECTED:
+      if (ED_keylist_selected_keys_frame_range(keylist, &frame_range)) {
+        break;
+      }
+      ATTR_FALLTHROUGH;  // Fall through if there were no selected keys found.
+    case MOTIONPATH_RANGE_KEYS_ALL:
+      ED_keylist_all_keys_frame_range(keylist, &frame_range);
+      break;
+    case MOTIONPATH_RANGE_SCENE:
+      BLI_assert_msg(false, "This should not happen, function should have exited earlier.");
+  };
+
+  avs->path_sf = frame_range.min;
+  avs->path_ef = frame_range.max;
+
+  ED_keylist_free(keylist);
+}
+
 void animviz_calc_motionpaths(Depsgraph *depsgraph,
                               Main *bmain,
                               Scene *scene,
diff --git a/source/blender/editors/animation/keyframes_keylist.cc b/source/blender/editors/animation/keyframes_keylist.cc
index 9ee047fafff..3356ef4d47d 100644
--- a/source/blender/editors/animation/keyframes_keylist.cc
+++ b/source/blender/editors/animation/keyframes_keylist.cc
@@ -304,7 +304,21 @@ const struct ListBase *ED_keylist_listbase(const AnimKeylist *keylist)
   return &keylist->key_columns;
 }
 
-bool ED_keylist_frame_range(const struct AnimKeylist *keylist, Range2f *r_frame_range)
+static void keylist_first_last(const struct AnimKeylist *keylist,
+                               const struct ActKeyColumn **first_column,
+                               const struct ActKeyColumn **last_column)
+{
+  if (keylist->is_runtime_initialized) {
+    *first_column = &keylist->runtime.key_columns[0];
+    *last_column = &keylist->runtime.key_columns[keylist->column_len - 1];
+  }
+  else {
+    *first_column = static_cast<const ActKeyColumn *>(keylist->key_columns.first);
+    *last_column = static_cast<const ActKeyColumn *>(keylist->key_columns.last);
+  }
+}
+
+bool ED_keylist_all_keys_frame_range(const struct AnimKeylist *keylist, Range2f *r_frame_range)
 {
   BLI_assert(r_frame_range);
 
@@ -314,13 +328,33 @@ bool ED_keylist_frame_range(const struct AnimKeylist *keylist, Range2f *r_frame_
 
   const ActKeyColumn *first_column;
   const ActKeyColumn *last_column;
-  if (keylist->is_runtime_initialized) {
-    first_column = &keylist->runtime.key_columns[0];
-    last_column = &keylist->runtime.key_columns[keylist->column_len - 1];
+  keylist_first_last(keylist, &first_column, &last_column);
+  r_frame_range->min = first_column->cfra;
+  r_frame_range->max = last_column->cfra;
+
+  return true;
+}
+
+bool ED_keylist_selected_keys_frame_range(const struct AnimKeylist *keylist,
+                                          Range2f *r_frame_range)
+{
+  BLI_assert(r_frame_range);
+
+  if (ED_keylist_is_empty(keylist)) {
+    return false;
   }
-  else {
-    first_column = static_cast<const ActKeyColumn *>(keylist->key_columns.first);
-    last_column = static_cast<const ActKeyColumn *>(keylist->key_columns.last);
+
+  const ActKeyColumn *first_column;
+  const ActKeyColumn *last_column;
+  keylist_first_last(keylist, &first_column, &last_column);
+  while (first_column && !(first_column->sel & SELECT)) {
+    first_column = first_column->next;
+  }
+  while (last_column && !(last_column->sel & SELECT)) {
+    last_column = last_column->prev;
+  }
+  if (!first_column || !last_column || first_column == last_column) {
+    return false;
   }
   r_frame_range->min = first_column->cfra;
   r_frame_range->max = last_column->cfra;
diff --git a/source/blender/editors/armature/pose_edit.c b/source/blender/editors/armature/pose_edit.c
index 2ad7a373012..cec83ffa0f0 100644
--- a/source/blender/editors/armature/pose_edit.c
+++ b/source/blender/editors/armature/pose_edit.c
@@ -222,16 +222,15 @@ static int pose_calculate_paths_invoke(bContext *C, wmOperator *op, const wmEven
     bAnimVizSettings *avs = &ob->pose->avs;
     PointerRNA avs_ptr;
 
-    RNA_int_set(op->ptr, "start_frame", avs->path_sf);
-    RNA_int_set(op->ptr, "end_frame", avs->path_ef);
-
     RNA_pointer_create(NULL, &RNA_AnimVizMotionPaths, avs, &avs_ptr);
+    RNA_enum_set(op->ptr, "display_type", RNA_enum_get(&avs_ptr, "type"));
+    RNA_enum_set(op->ptr, "range", RNA_enum_get(&avs_ptr, "range"));
     RNA_enum_set(op->ptr, "bake_location", RNA_enum_get(&avs_ptr, "bake_location"));
   }
 
   /* show popup dialog to allow editing of range... */
   /* FIXME: hard-coded dimensions here are just arbitrary. */
-  return WM_operator_props_dialog_popup(C, op, 200);
+  return WM_operator_props_dialog_popup(C, op, 270);
 }
 
 /* For the object with pose/action: create path curves for selected bones
@@ -251,8 +250,9 @@ static int pose_calculate_paths_exec(bContext *C, wmOperator *op)
     bAnimVizSettings *avs = &ob->pose->avs;
     PointerRNA avs_ptr;
 
-    avs->path_sf = RNA_int_get(op->ptr, "start_frame");
-    avs->path_ef = RNA_int_get(op->ptr, "end_frame");
+    avs->path_type = RNA_enum_get(op->ptr, "display_type");
+    avs->path_range

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list