T54233: NLA "Push Down" discards Blend Mode, Extrapolation, and Influence
authorJoshua Leung <aligorith@gmail.com>
Thu, 8 Mar 2018 03:49:33 +0000 (16:49 +1300)
committerJoshua Leung <aligorith@gmail.com>
Thu, 8 Mar 2018 04:15:33 +0000 (17:15 +1300)
Each AnimData block has a set of Blend/Extrapolation/Influence settings
that can be used to control how the active action is blended with the
NLA stack. However, these settings were not getting copied over to the
newly created strips (as the push-down code existed long before these
settings were added).

This commit solves this in several ways:
* Active Action Blend/Extrapolation/Influence settings now get copied
  to the new strips when adding them to the NLA stack via Push Down.

  Note: This doesn't happen when there are no existing NLA tracks,
        as these settings don't get used in that case.

* Strip Influence will be copied across when inf < 1.0 (i.e. when a
  non-default value is used), to maintain the effect. To make this work,
  the influence value will get added as a keyframe to the strip's
  "Influence" Control FCurve.

  - See code comments for an alternative approach and why that was not chosen
  - Strip Time still doesn't get keyframes added automatically yet.

* To ensure the "extrapolation mode" settings don't get always overwritten,
  I've put in place a compromise: the extrapolation will only get changed
  if the chosen setting will cause problmes (i.e. hold forward & back -> hold forward
  if there are other tracks before it already).

Not safe for backporting to 2.79[x] stable releases.

source/blender/blenkernel/intern/nla.c

index 2363eb5..6a0effd 100644 (file)
@@ -1392,7 +1392,12 @@ void BKE_nlastrip_validate_fcurves(NlaStrip *strip)
                        /* store path - make copy, and store that */
                        fcu->rna_path = BLI_strdupn("influence", 9);
                        
-                       /* TODO: insert a few keyframes to ensure default behavior? */
+                       /* insert keyframe to ensure current value stays on first refresh */
+                       fcu->bezt = MEM_callocN(sizeof(BezTriple), "nlastrip influence bezt");
+                       fcu->totvert = 1;
+                       
+                       fcu->bezt->vec[1][0] = strip->start;
+                       fcu->bezt->vec[1][1] = strip->influence;
                }
        }
        
@@ -1760,7 +1765,8 @@ bool BKE_nla_action_stash(AnimData *adt)
 void BKE_nla_action_pushdown(AnimData *adt)
 {
        NlaStrip *strip;
-
+       const bool is_first = (adt) && (adt->nla_tracks.first == NULL);
+       
        /* sanity checks */
        /* TODO: need to report the error for this */
        if (ELEM(NULL, adt, adt->action))
@@ -1784,6 +1790,32 @@ void BKE_nla_action_pushdown(AnimData *adt)
                id_us_min(&adt->action->id);
                adt->action = NULL;
                
+               /* copy current "action blending" settings from adt to the strip,
+                * as it was keyframed with these settings, so omitting them will
+                * change the effect  [T54233]
+                *
+                * NOTE: We only do this when there are no tracks
+                */
+               if (is_first == false) {
+                       strip->blendmode = adt->act_blendmode;
+                       strip->influence = adt->act_influence;
+                       strip->extendmode = adt->act_extendmode;
+                       
+                       if (adt->act_influence < 1.0f) {
+                               /* enable "user-controlled" influence (which will insert a default keyframe)
+                                * so that the influence doesn't get lost on the new update
+                                *
+                                * NOTE: An alternative way would have been to instead hack the influence
+                                * to not get always get reset to full strength if NLASTRIP_FLAG_USR_INFLUENCE
+                                * is disabled but auto-blending isn't being used. However, that approach
+                                * is a bit hacky/hard to discover, and may cause backwards compatability issues,
+                                * so it's better to just do it this way.
+                                */
+                               strip->flag |= NLASTRIP_FLAG_USR_INFLUENCE;
+                               BKE_nlastrip_validate_fcurves(strip);
+                       }
+               }
+               
                /* if the strip is the first one in the track it lives in, check if there
                 * are strips in any other tracks that may be before this, and set the extend
                 * mode accordingly
@@ -1793,7 +1825,8 @@ void BKE_nla_action_pushdown(AnimData *adt)
                         * so that it doesn't override strips in previous tracks
                         */
                        /* FIXME: this needs to be more automated, since user can rearrange strips */
-                       strip->extendmode = NLASTRIP_EXTEND_HOLD_FORWARD;
+                       if (strip->extendmode == NLASTRIP_EXTEND_HOLD)
+                               strip->extendmode = NLASTRIP_EXTEND_HOLD_FORWARD;
                }
                
                /* make strip the active one... */