[Bf-blender-cvs] [493a52aca4a] arcpatch-D8867_Nla_Merge_Strips: Feature: NLA Merge Strips

Wayde Moss noreply at git.blender.org
Wed Oct 21 06:26:02 CEST 2020


Commit: 493a52aca4a0702ab80c2d9fc8f1a74f253e6493
Author: Wayde Moss
Date:   Wed Oct 21 00:19:30 2020 -0400
Branches: arcpatch-D8867_Nla_Merge_Strips
https://developer.blender.org/rB493a52aca4a0702ab80c2d9fc8f1a74f253e6493

Feature: NLA Merge Strips

Todo: add media and example files

This patch is relative to {D8296} (which is relative to {D9247}. Apply {D9247} first then {D8296} then this one.

For user-facing design discussion: {T80235}
____

**Problem/Solution:**
Before, the only way to combine multiple Nla strips into a single strip is to execute a Bake operator. However, this will merge **all** strips into a replace strip with full influence. This patch creates a new operator "Resample Strips To New" which effectively allows merging a set of selected NlaStrips into a single strip of any blendmode and any nonzero influence. The old selected strips will be muted while preserving the whole Nla result. (I used the word "resample" because it's more g [...]

**Feature:** Nla add support for resampling selected strips into a new track. The more specific use is to support merging selected Nla strips into a single strip. The core resampling function is (anim_sys.c) //BKE_animsys_resample_selected_strips()//

(direct copy+paste of function comment)
```
/** Mute selected NLA strips and resample into a new track. The final Nla stack result will be
 * preserved when possible. New resampled strip will be selected. Previously selected strips will
 * be muted and deselected afterward.
 *
 * \param resample_blendmode: Resulting resampled strip's blend mode.
 * \param resample_influence: Resulting resampled strip's influence. above.
 * \param resample_insertion_nlt_index: NlaTrack to insert the resample track above or below.
 * \param insert_track_lower: Side of resample_insertion_nlt_index to place resample track.
 * \returns: The new resample track. Returns NULL and does nothing if in tweak mode, resample
 * influence zero, or no fcurves are involved in the resample.
 */
```

**Intended Uses:**

Merge Strips: User selects a block of NlaStrips and Resamples. Effectively, all selected strips will become muted and a new "merged" track will be created. Since the overall NLA stack result is preserved, the result is equivalent to a merge.

Convert Strip: User selects a single NlaStrip and Resamples with a different blendmode and/or influence.

**Potential improvements/changes:**

For frames where user had a keyframe, make them non-selected. Select non-user keys. This allows a follow-up op to do an Fcurve simplify or decimate of only the baked keyframes. Effectively it allows a follow-up Smart Bake that preserves user keys. Perhaps this can be done by the caller.

Allow user to somehow select channels to be resampled. Currently all channels found in all selected strips are resampled. Though a simple work around is to delete the undesired  channels after the resample.

**Limitations and potential problems:**

Design: When resample strip value not valid, what should we do? Currently we write a default value. Nothing we write will preserve the animation. This leaves the problem as a "Known Issue".

This operator will not properly resample outside of the resample bounds. Generally, it's not possible since multiple strips with non-None extend modes can not be represented by a single strip of any extend mode.. Maybe it's possible by properly setting the pre and post extrapolation for individual fcurves?

_____

**Some existing functions in (anim_sys.c) that had to be modified slightly for //BKE_animsys_resample_selected_strips()//:**

- changes (anim_sys.c) //nlastrip_evaluate()// and its nested calls to pass //allow_alloc_channels //to control whether NlaEvalChannels are allocated or to only blend existing channels. Flushing and keyframing require allocation. The new merging operator only needs to blend existing channels and requires no allocation.

There are potential areas for refactoring but haven't been implemented to keep the review simpler and more linear. It's an attempt to prevent introducing bugs that occur as a result of refactoring instead of the patch itself.

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

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

M	release/scripts/presets/keyconfig/keymap_data/blender_default.py
M	release/scripts/startup/bl_ui/space_nla.py
M	source/blender/blenkernel/BKE_animsys.h
M	source/blender/blenkernel/intern/anim_sys.c
M	source/blender/blenkernel/nla_private.h
M	source/blender/editors/space_nla/nla_edit.c
M	source/blender/editors/space_nla/nla_intern.h
M	source/blender/editors/space_nla/nla_ops.c
M	source/blender/makesrna/intern/rna_nla.c

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

diff --git a/release/scripts/presets/keyconfig/keymap_data/blender_default.py b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
index da85004664b..f315fd324bc 100644
--- a/release/scripts/presets/keyconfig/keymap_data/blender_default.py
+++ b/release/scripts/presets/keyconfig/keymap_data/blender_default.py
@@ -2248,6 +2248,7 @@ def km_nla_editor(params):
         ("nla.delete", {"type": 'X', "value": 'PRESS'}, None),
         ("nla.delete", {"type": 'DEL', "value": 'PRESS'}, None),
         ("nla.split", {"type": 'Y', "value": 'PRESS'}, None),
+        ("NLA_OT_resample_strips", {"type": 'M', "value":  'PRESS',"shift":True},None),
         ("nla.mute_toggle", {"type": 'H', "value": 'PRESS'}, None),
         ("nla.swap", {"type": 'F', "value": 'PRESS', "alt": True}, None),
         ("nla.move_up", {"type": 'PAGE_UP', "value": 'PRESS'}, None),
diff --git a/release/scripts/startup/bl_ui/space_nla.py b/release/scripts/startup/bl_ui/space_nla.py
index 44bea586dbc..8a851cc6199 100644
--- a/release/scripts/startup/bl_ui/space_nla.py
+++ b/release/scripts/startup/bl_ui/space_nla.py
@@ -165,6 +165,7 @@ class NLA_MT_edit(Menu):
         layout.separator()
         layout.operator("nla.duplicate", text="Duplicate").linked = False
         layout.operator("nla.duplicate", text="Linked Duplicate").linked = True
+        layout.operator("nla.resample_strips")
         layout.operator("nla.split")
         layout.operator("nla.delete")
         layout.operator("nla.tracks_delete")
@@ -270,6 +271,10 @@ class NLA_MT_context_menu(Menu):
 
         layout.separator()
 
+        col = layout.column()
+        col.operator_context="INVOKE_DEFAULT"
+        col.operator("nla.resample_strips")
+        
         layout.operator("nla.split")
         layout.operator("nla.delete")
 
diff --git a/source/blender/blenkernel/BKE_animsys.h b/source/blender/blenkernel/BKE_animsys.h
index ec0e42c0998..35583c52209 100644
--- a/source/blender/blenkernel/BKE_animsys.h
+++ b/source/blender/blenkernel/BKE_animsys.h
@@ -226,6 +226,15 @@ bool BKE_animsys_nla_remap_keyframe_values(struct NlaKeyframingContext *context,
                                            int index,
                                            bool *r_force_all);
 void BKE_animsys_free_nla_keyframing_context_cache(struct ListBase *cache);
+struct NlaTrack *BKE_animsys_resample_selected_strips(struct Main *main,
+                                                      struct Depsgraph *depsgraph,
+                                                      struct AnimData *adt,
+                                                      struct PointerRNA *id_ptr,
+                                                      char resample_name[],
+                                                      short resample_blendmode,
+                                                      float resample_influence,
+                                                      int resample_insertion_nlt_index,
+                                                      bool insert_track_lower);
 
 /* ************************************* */
 /* Evaluation API */
diff --git a/source/blender/blenkernel/intern/anim_sys.c b/source/blender/blenkernel/intern/anim_sys.c
index f5cbfdeb635..bd9eaae3323 100644
--- a/source/blender/blenkernel/intern/anim_sys.c
+++ b/source/blender/blenkernel/intern/anim_sys.c
@@ -2061,12 +2061,16 @@ static bool is_fcurve_evaluatable(FCurve *fcu)
   return true;
 }
 
-/** Evaluate action-clip strip and accumulate within snapshot. */
+/** Evaluate action-clip strip and accumulate within snapshot.
+ * \param allow_alloc_channels: If true, new NlaEvalChannels allocated and evaluated if needed.
+ * Otherwise only channels existing within the NlaEvalData are evaluated.
+ */
 static void nlastrip_evaluate_actionclip(PointerRNA *ptr,
                                          NlaEvalData *channels,
                                          ListBase *modifiers,
                                          NlaEvalStrip *nes,
-                                         NlaEvalSnapshot *snapshot)
+                                         NlaEvalSnapshot *snapshot,
+                                         bool allow_alloc_channels)
 {
   ListBase tmp_modifiers = {NULL, NULL};
   NlaStrip *strip = nes->strip;
@@ -2109,6 +2113,23 @@ static void nlastrip_evaluate_actionclip(PointerRNA *ptr,
       continue;
     }
 
+    /* Get an NLA evaluation channel to work with, and accumulate the evaluated value with the
+     * value(s) stored in this channel if it has been used already. */
+    NlaEvalChannel *nec = NULL;
+    if (allow_alloc_channels) {
+      /** Guarantees NlaEvalChannel. */
+      nec = nlaevalchan_verify(ptr, channels, fcu->rna_path);
+    }
+    else {
+      /** Only get NlaEvalChannel if it exists. */
+      nlaevalchan_try_get(channels, fcu->rna_path, &nec);
+    }
+
+    if (!nec) {
+      /** Skip since caller only wants to fill values for existing channels in snapshot. */
+      continue;
+    }
+
     /* Evaluate the F-Curve's value for the time given in the strip
      * NOTE: we use the modified time here, since strip's F-Curve Modifiers
      * are applied on top of this.
@@ -2121,11 +2142,6 @@ static void nlastrip_evaluate_actionclip(PointerRNA *ptr,
      */
     evaluate_value_fmodifiers(&storage, &tmp_modifiers, fcu, &value, strip->strip_time);
 
-    /* Get an NLA evaluation channel to work with,
-     * and accumulate the evaluated value with the value(s)
-     * stored in this channel if it has been used already. */
-    NlaEvalChannel *nec = nlaevalchan_verify(ptr, channels, fcu->rna_path);
-
     nlaeval_blend_value(&blend, nec, fcu->array_index, value);
   }
 
@@ -2311,7 +2327,8 @@ static void nlastrip_evaluate_transition(PointerRNA *ptr,
                                          NlaEvalStrip *nes,
                                          NlaEvalSnapshot *snapshot,
                                          const AnimationEvalContext *anim_eval_context,
-                                         const bool flush_to_original)
+                                         const bool flush_to_original,
+                                         bool allow_alloc_channels)
 {
   ListBase tmp_modifiers = {NULL, NULL};
   NlaEvalSnapshot snapshot1, snapshot2;
@@ -2353,16 +2370,28 @@ static void nlastrip_evaluate_transition(PointerRNA *ptr,
   tmp_nes.strip = s1;
   tmp_nes.strip_time = s1->strip_time;
   nlaeval_snapshot_init(&snapshot1, channels, snapshot);
-  nlastrip_evaluate(
-      ptr, channels, &tmp_modifiers, &tmp_nes, &snapshot1, anim_eval_context, flush_to_original);
+  nlastrip_evaluate(ptr,
+                    channels,
+                    &tmp_modifiers,
+                    &tmp_nes,
+                    &snapshot1,
+                    anim_eval_context,
+                    flush_to_original,
+                    allow_alloc_channels);
 
   /* second strip */
   tmp_nes.strip_mode = NES_TIME_TRANSITION_END;
   tmp_nes.strip = s2;
   tmp_nes.strip_time = s2->strip_time;
   nlaeval_snapshot_init(&snapshot2, channels, snapshot);
-  nlastrip_evaluate(
-      ptr, channels, &tmp_modifiers, &tmp_nes, &snapshot2, anim_eval_context, flush_to_original);
+  nlastrip_evaluate(ptr,
+                    channels,
+                    &tmp_modifiers,
+                    &tmp_nes,
+                    &snapshot2,
+                    anim_eval_context,
+                    flush_to_original,
+                    allow_alloc_channels);
 
   /* accumulate temp-buffer and full-buffer, using the 'real' strip */
   nlaeval_snapshot_mix_and_free(channels, snapshot, &snapshot1, &snapshot2, nes->strip_time);
@@ -2757,7 +2786,8 @@ static void nlastrip_evaluate_meta(PointerRNA *ptr,
                                    NlaEvalStrip *nes,
                                    NlaEvalSnapshot *snapshot,
                                    const AnimationEvalContext *anim_eval_context,
-                                   const bool flush_to_original)
+                                   const bool flush_to_original,
+                                   bool allow_alloc_channels)
 {
   ListBase tmp_modifiers = {NULL, NULL};
   NlaStrip *strip = nes->strip;
@@ -2785,8 +2815,14 @@ static void nlastrip_evaluate_meta(PointerRNA *ptr,
    * - there's no need to use a temporary buffer (as it causes issues [T40082])
    */
   if (tmp_nes) {
-    nlastrip_evaluate(
-        ptr, channels, &tmp_modifiers, tmp_nes, snapshot, &child_context, flush_to_original);
+    nlastrip_evaluate(ptr,
+                      channels,
+                      &tmp_modifiers,
+                      tmp_nes,
+                      snapshot,
+                      &child_context,
+                      flush_to_original,
+                      allow_alloc_channels);
 
     /* free temp eval-strip */
     MEM_freeN(tmp_nes);
@@ -2903,7 +2939,8 @@ void nlastrip_evaluate(PointerRNA *ptr,
                        NlaEvalStrip *nes,
                        NlaEvalSnapshot *snapshot,
                        const AnimationEvalContext *anim_eval_context,
-                       const bool flush_to_original)
+                       const bool flush_to_original,
+                       bool allow_alloc_channels)
 {
   NlaStrip *strip = nes->strip;
 
@@ -2922,15 +2959,27 @@ void nlastrip_evaluate(PointerRNA *ptr,
   /* actions to take depend on the type of strip */
   switch (strip->type) {
     case NLASTRIP_TYPE_CLIP: /* action-clip */
-      nlastrip_evaluate_actionclip(ptr, channels, modifiers, nes, snapshot);
+      nlastrip_evaluate_actionclip(ptr, channels, modifiers, nes, snapshot, allow_alloc_channels);
       break;
     case NLASTRIP_TYPE_TRANSITION: /* transition */
-      nlastrip_evaluate_transition(
-          ptr, channels, modifiers, nes, snapshot, anim_eval_context, flush_to_original);
+      nlastrip_evaluate_transition(ptr,
+                                   channels,
+                                   modifiers,
+                                   nes,
+                                   snapshot,
+                                   anim_eval_context,
+                                   flush_to_original,
+                                   allow_al

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list