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. @@
_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs