|
|
|
|
@@ -979,6 +979,19 @@ NlaEvalStrip *nlastrips_ctime_get_strip(ListBase *list,
|
|
|
|
|
return nes;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static NlaEvalStrip *nlastrips_ctime_get_strip_single(
|
|
|
|
|
ListBase *dst_list,
|
|
|
|
|
NlaStrip *single_strip,
|
|
|
|
|
const AnimationEvalContext *anim_eval_context,
|
|
|
|
|
const bool flush_to_original)
|
|
|
|
|
{
|
|
|
|
|
ListBase single_tracks_list;
|
|
|
|
|
single_tracks_list.first = single_tracks_list.last = single_strip;
|
|
|
|
|
|
|
|
|
|
return nlastrips_ctime_get_strip(
|
|
|
|
|
dst_list, &single_tracks_list, -1, anim_eval_context, flush_to_original);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* ---------------------- */
|
|
|
|
|
|
|
|
|
|
/* Initialize a valid mask, allocating memory if necessary. */
|
|
|
|
|
@@ -2212,177 +2225,226 @@ static void animsys_evaluate_nla_domain(PointerRNA *ptr, NlaEvalData *channels,
|
|
|
|
|
|
|
|
|
|
/* ---------------------- */
|
|
|
|
|
|
|
|
|
|
/** Tweaked strip is evaluated differently from other strips. Adjacent strips are ignored
|
|
|
|
|
* and includes a workaround for when user is not editing in place. */
|
|
|
|
|
static void animsys_create_tweak_strip(const AnimData *adt,
|
|
|
|
|
const bool keyframing_to_strip,
|
|
|
|
|
NlaStrip *r_tweak_strip)
|
|
|
|
|
|
|
|
|
|
{
|
|
|
|
|
/* Copy active strip so we can modify how it evaluates without affecting user data. */
|
|
|
|
|
memcpy(r_tweak_strip, adt->actstrip, sizeof(NlaStrip));
|
|
|
|
|
r_tweak_strip->next = r_tweak_strip->prev = NULL;
|
|
|
|
|
|
|
|
|
|
/* If tweaked strip is syncing action length, then evaluate using action length. */
|
|
|
|
|
if (r_tweak_strip->flag & NLASTRIP_FLAG_SYNC_LENGTH) {
|
|
|
|
|
BKE_nlastrip_recalculate_bounds_sync_action(r_tweak_strip);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Strips with a user-defined time curve don't get properly remapped for editing
|
|
|
|
|
* at the moment, so mapping them just for display may be confusing. */
|
|
|
|
|
const bool is_inplace_tweak = !(adt->flag & ADT_NLA_EDIT_NOMAP) &&
|
|
|
|
|
!(adt->actstrip->flag & NLASTRIP_FLAG_USR_TIME);
|
|
|
|
|
|
|
|
|
|
if (!is_inplace_tweak) {
|
|
|
|
|
/* Use Hold due to no proper remapping yet (the note above). */
|
|
|
|
|
r_tweak_strip->extendmode = NLASTRIP_EXTEND_HOLD;
|
|
|
|
|
|
|
|
|
|
/* Disable range. */
|
|
|
|
|
r_tweak_strip->flag |= NLASTRIP_FLAG_NO_TIME_MAP;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Controls whether able to keyframe outside range of tweaked strip. */
|
|
|
|
|
if (keyframing_to_strip) {
|
|
|
|
|
r_tweak_strip->extendmode = (is_inplace_tweak &&
|
|
|
|
|
!(r_tweak_strip->flag & NLASTRIP_FLAG_SYNC_LENGTH)) ?
|
|
|
|
|
NLASTRIP_EXTEND_NOTHING :
|
|
|
|
|
NLASTRIP_EXTEND_HOLD;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Action track and strip are associated with the non-pushed action. */
|
|
|
|
|
static void animsys_create_action_track_strip(const AnimData *adt,
|
|
|
|
|
const bool keyframing_to_strip,
|
|
|
|
|
NlaStrip *r_action_strip)
|
|
|
|
|
{
|
|
|
|
|
memset(r_action_strip, 0, sizeof(NlaStrip));
|
|
|
|
|
|
|
|
|
|
bAction *action = adt->action;
|
|
|
|
|
|
|
|
|
|
if ((adt->flag & ADT_NLA_EDIT_ON)) {
|
|
|
|
|
action = adt->tmpact;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Set settings of dummy NLA strip from AnimData settings. */
|
|
|
|
|
r_action_strip->act = action;
|
|
|
|
|
|
|
|
|
|
/* Action range is calculated taking F-Modifiers into account
|
|
|
|
|
* (which making new strips doesn't do due to the troublesome nature of that). */
|
|
|
|
|
calc_action_range(r_action_strip->act, &r_action_strip->actstart, &r_action_strip->actend, 1);
|
|
|
|
|
r_action_strip->start = r_action_strip->actstart;
|
|
|
|
|
r_action_strip->end = (IS_EQF(r_action_strip->actstart, r_action_strip->actend)) ?
|
|
|
|
|
(r_action_strip->actstart + 1.0f) :
|
|
|
|
|
(r_action_strip->actend);
|
|
|
|
|
|
|
|
|
|
r_action_strip->blendmode = adt->act_blendmode;
|
|
|
|
|
r_action_strip->extendmode = adt->act_extendmode;
|
|
|
|
|
r_action_strip->influence = adt->act_influence;
|
|
|
|
|
|
|
|
|
|
/* NOTE: must set this, or else the default setting overrides,
|
|
|
|
|
* and this setting doesn't work. */
|
|
|
|
|
r_action_strip->flag |= NLASTRIP_FLAG_USR_INFLUENCE;
|
|
|
|
|
|
|
|
|
|
/* Unless extendmode is Nothing (might be useful for flattening NLA evaluation), disable range.
|
|
|
|
|
* Extendmode Nothing and Hold will behave as normal. Hold Forward will behave just like Hold.
|
|
|
|
|
*/
|
|
|
|
|
if (r_action_strip->extendmode != NLASTRIP_EXTEND_NOTHING) {
|
|
|
|
|
r_action_strip->flag |= NLASTRIP_FLAG_NO_TIME_MAP;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const bool tweaking = (adt->flag & ADT_NLA_EDIT_ON) != 0;
|
|
|
|
|
const bool soloing = (adt->flag & ADT_NLA_SOLO_TRACK) != 0;
|
|
|
|
|
const bool actionstrip_evaluated = r_action_strip->act && !soloing && !tweaking;
|
|
|
|
|
if (!actionstrip_evaluated) {
|
|
|
|
|
r_action_strip->flag |= NLASTRIP_FLAG_MUTED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** If we're keyframing, then we must allow keyframing outside fcurve bounds. */
|
|
|
|
|
if (keyframing_to_strip) {
|
|
|
|
|
r_action_strip->extendmode = NLASTRIP_EXTEND_HOLD;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool is_nlatrack_evaluatable(const AnimData *adt, const NlaTrack *nlt)
|
|
|
|
|
{
|
|
|
|
|
/* Skip disabled tracks unless it contains the tweaked strip. */
|
|
|
|
|
const bool contains_tweak_strip = (adt->flag & ADT_NLA_EDIT_ON) &&
|
|
|
|
|
(nlt->index == adt->act_track->index);
|
|
|
|
|
if ((nlt->flag & NLATRACK_DISABLED) && !contains_tweak_strip) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Solo and muting are mutually exclusive. */
|
|
|
|
|
if (adt->flag & ADT_NLA_SOLO_TRACK) {
|
|
|
|
|
/* Skip if there is a solo track, but this isn't it. */
|
|
|
|
|
if ((nlt->flag & NLATRACK_SOLO) == 0) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* Skip track if muted. */
|
|
|
|
|
if (nlt->flag & NLATRACK_MUTED) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Check for special case of non-pushed action being evaluated with no NLA influence (off and no
|
|
|
|
|
* strips evaluated) nor NLA interference (ensure NLA not soloing). */
|
|
|
|
|
static bool is_action_track_evaluated_without_nla(const AnimData *adt,
|
|
|
|
|
const bool any_strip_evaluated)
|
|
|
|
|
{
|
|
|
|
|
if (adt->action == NULL) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (any_strip_evaluated) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** NLA settings interference. */
|
|
|
|
|
if ((adt->flag & (ADT_NLA_SOLO_TRACK | ADT_NLA_EDIT_ON)) == 0) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Allow action track to evaluate as if there isn't any NLA data. */
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** XXX Wayde Moss: BKE_nlatrack_find_tweaked() exists within nla.c, but it doesn't appear to
|
|
|
|
|
* work as expected. From animsys_evaluate_nla_for_flush(), it returns NULL in tweak mode. I'm not
|
|
|
|
|
* sure why. Preferably, it would be as simple as checking for (adt->act_Track == nlt) but that
|
|
|
|
|
* doesn't work either, neither does comparing indices.
|
|
|
|
|
*
|
|
|
|
|
* This function is a temporary work around. The first disabled track is always the tweaked track.
|
|
|
|
|
*/
|
|
|
|
|
static NlaTrack *nlatrack_find_tweaked(const AnimData *adt)
|
|
|
|
|
{
|
|
|
|
|
NlaTrack *nlt;
|
|
|
|
|
|
|
|
|
|
if (adt == NULL) {
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Since the track itself gets disabled, we want the first disabled. */
|
|
|
|
|
for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next) {
|
|
|
|
|
if (nlt->flag & NLATRACK_DISABLED) {
|
|
|
|
|
return nlt;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* NLA Evaluation function - values are calculated and stored in temporary "NlaEvalChannels"
|
|
|
|
|
*
|
|
|
|
|
* \param[out] echannels: Evaluation channels with calculated values
|
|
|
|
|
* \param[out] r_context: If not NULL,
|
|
|
|
|
* data about the currently edited strip is stored here and excluded from value calculation.
|
|
|
|
|
* \return false if NLA evaluation isn't actually applicable.
|
|
|
|
|
*/
|
|
|
|
|
static bool animsys_evaluate_nla(NlaEvalData *echannels,
|
|
|
|
|
PointerRNA *ptr,
|
|
|
|
|
AnimData *adt,
|
|
|
|
|
const AnimationEvalContext *anim_eval_context,
|
|
|
|
|
const bool flush_to_original,
|
|
|
|
|
NlaKeyframingContext *r_context)
|
|
|
|
|
static bool animsys_evaluate_nla_for_flush(NlaEvalData *echannels,
|
|
|
|
|
PointerRNA *ptr,
|
|
|
|
|
const AnimData *adt,
|
|
|
|
|
const AnimationEvalContext *anim_eval_context,
|
|
|
|
|
const bool flush_to_original)
|
|
|
|
|
{
|
|
|
|
|
NlaTrack *nlt;
|
|
|
|
|
short track_index = 0;
|
|
|
|
|
bool has_strips = false;
|
|
|
|
|
|
|
|
|
|
ListBase estrips = {NULL, NULL};
|
|
|
|
|
NlaEvalStrip *nes;
|
|
|
|
|
NlaStrip dummy_strip_buf;
|
|
|
|
|
|
|
|
|
|
/* dummy strip for active action */
|
|
|
|
|
NlaStrip *dummy_strip = r_context ? &r_context->strip : &dummy_strip_buf;
|
|
|
|
|
NlaStrip tweak_strip;
|
|
|
|
|
|
|
|
|
|
memset(dummy_strip, 0, sizeof(*dummy_strip));
|
|
|
|
|
NlaTrack *tweaked_track = nlatrack_find_tweaked(adt);
|
|
|
|
|
|
|
|
|
|
/* 1. get the stack of strips to evaluate at current time (influence calculated here) */
|
|
|
|
|
/* Get the stack of strips to evaluate at current time (influence calculated here). */
|
|
|
|
|
for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next, track_index++) {
|
|
|
|
|
/* stop here if tweaking is on and this strip is the tweaking track
|
|
|
|
|
* (it will be the first one that's 'disabled')... */
|
|
|
|
|
if ((adt->flag & ADT_NLA_EDIT_ON) && (nlt->flag & NLATRACK_DISABLED)) {
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if (!is_nlatrack_evaluatable(adt, nlt)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* solo and muting are mutually exclusive... */
|
|
|
|
|
if (adt->flag & ADT_NLA_SOLO_TRACK) {
|
|
|
|
|
/* skip if there is a solo track, but this isn't it */
|
|
|
|
|
if ((nlt->flag & NLATRACK_SOLO) == 0) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
/* else - mute doesn't matter */
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* no solo tracks - skip track if muted */
|
|
|
|
|
if (nlt->flag & NLATRACK_MUTED) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* if this track has strips (but maybe they won't be suitable), set has_strips
|
|
|
|
|
* - used for mainly for still allowing normal action evaluation...
|
|
|
|
|
*/
|
|
|
|
|
if (nlt->strips.first) {
|
|
|
|
|
has_strips = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* otherwise, get strip to evaluate for this channel */
|
|
|
|
|
nes = nlastrips_ctime_get_strip(
|
|
|
|
|
&estrips, &nlt->strips, track_index, anim_eval_context, flush_to_original);
|
|
|
|
|
/** Append strip to evaluate for this track. */
|
|
|
|
|
if (nlt == tweaked_track) {
|
|
|
|
|
/** Tweaked strip is evaluated differently. */
|
|
|
|
|
animsys_create_tweak_strip(adt, false, &tweak_strip);
|
|
|
|
|
nes = nlastrips_ctime_get_strip_single(
|
|
|
|
|
&estrips, &tweak_strip, anim_eval_context, flush_to_original);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
nes = nlastrips_ctime_get_strip(
|
|
|
|
|
&estrips, &nlt->strips, track_index, anim_eval_context, flush_to_original);
|
|
|
|
|
}
|
|
|
|
|
if (nes) {
|
|
|
|
|
nes->track = nlt;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* add 'active' Action (may be tweaking track) as last strip to evaluate in NLA stack
|
|
|
|
|
* - only do this if we're not exclusively evaluating the 'solo' NLA-track
|
|
|
|
|
* - however, if the 'solo' track houses the current 'tweaking' strip,
|
|
|
|
|
* then we should allow this to play, otherwise nothing happens
|
|
|
|
|
*/
|
|
|
|
|
if ((adt->action) && ((adt->flag & ADT_NLA_SOLO_TRACK) == 0 || (adt->flag & ADT_NLA_EDIT_ON))) {
|
|
|
|
|
/* if there are strips, evaluate action as per NLA rules */
|
|
|
|
|
if ((has_strips) || (adt->actstrip)) {
|
|
|
|
|
/* make dummy NLA strip, and add that to the stack */
|
|
|
|
|
ListBase dummy_trackslist;
|
|
|
|
|
|
|
|
|
|
dummy_trackslist.first = dummy_trackslist.last = dummy_strip;
|
|
|
|
|
|
|
|
|
|
/* Strips with a user-defined time curve don't get properly remapped for editing
|
|
|
|
|
* at the moment, so mapping them just for display may be confusing. */
|
|
|
|
|
bool is_inplace_tweak = (nlt) && !(adt->flag & ADT_NLA_EDIT_NOMAP) &&
|
|
|
|
|
!(adt->actstrip->flag & NLASTRIP_FLAG_USR_TIME);
|
|
|
|
|
|
|
|
|
|
if (is_inplace_tweak) {
|
|
|
|
|
/* edit active action in-place according to its active strip, so copy the data */
|
|
|
|
|
memcpy(dummy_strip, adt->actstrip, sizeof(NlaStrip));
|
|
|
|
|
/* Prevents nla eval from considering active strip's adj strips.
|
|
|
|
|
* For user, this means entering tweak mode on a strip ignores evaluating adjacent strips
|
|
|
|
|
* in the same track. */
|
|
|
|
|
dummy_strip->next = dummy_strip->prev = NULL;
|
|
|
|
|
|
|
|
|
|
/* If tweaked strip is syncing action length, then evaluate using action length. */
|
|
|
|
|
if (dummy_strip->flag & NLASTRIP_FLAG_SYNC_LENGTH) {
|
|
|
|
|
BKE_nlastrip_recalculate_bounds_sync_action(dummy_strip);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* set settings of dummy NLA strip from AnimData settings */
|
|
|
|
|
dummy_strip->act = adt->action;
|
|
|
|
|
|
|
|
|
|
/* action range is calculated taking F-Modifiers into account
|
|
|
|
|
* (which making new strips doesn't do due to the troublesome nature of that) */
|
|
|
|
|
calc_action_range(dummy_strip->act, &dummy_strip->actstart, &dummy_strip->actend, 1);
|
|
|
|
|
dummy_strip->start = dummy_strip->actstart;
|
|
|
|
|
dummy_strip->end = (IS_EQF(dummy_strip->actstart, dummy_strip->actend)) ?
|
|
|
|
|
(dummy_strip->actstart + 1.0f) :
|
|
|
|
|
(dummy_strip->actend);
|
|
|
|
|
|
|
|
|
|
/* Always use the blend mode of the strip in tweak mode, even if not in-place. */
|
|
|
|
|
if (nlt && adt->actstrip) {
|
|
|
|
|
dummy_strip->blendmode = adt->actstrip->blendmode;
|
|
|
|
|
dummy_strip->extendmode = NLASTRIP_EXTEND_HOLD;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
dummy_strip->blendmode = adt->act_blendmode;
|
|
|
|
|
dummy_strip->extendmode = adt->act_extendmode;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Unless extend-mode is Nothing (might be useful for flattening NLA evaluation),
|
|
|
|
|
* disable range. */
|
|
|
|
|
if (dummy_strip->extendmode != NLASTRIP_EXTEND_NOTHING) {
|
|
|
|
|
dummy_strip->flag |= NLASTRIP_FLAG_NO_TIME_MAP;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dummy_strip->influence = adt->act_influence;
|
|
|
|
|
|
|
|
|
|
/* NOTE: must set this, or else the default setting overrides,
|
|
|
|
|
* and this setting doesn't work. */
|
|
|
|
|
dummy_strip->flag |= NLASTRIP_FLAG_USR_INFLUENCE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* add this to our list of evaluation strips */
|
|
|
|
|
if (r_context == NULL) {
|
|
|
|
|
nlastrips_ctime_get_strip(
|
|
|
|
|
&estrips, &dummy_trackslist, -1, anim_eval_context, flush_to_original);
|
|
|
|
|
}
|
|
|
|
|
/* If computing the context for keyframing, store data there instead of the list. */
|
|
|
|
|
else {
|
|
|
|
|
/* The extend mode here effectively controls
|
|
|
|
|
* whether it is possible to key-frame beyond the ends.*/
|
|
|
|
|
dummy_strip->extendmode = (is_inplace_tweak &&
|
|
|
|
|
!(dummy_strip->flag & NLASTRIP_FLAG_SYNC_LENGTH)) ?
|
|
|
|
|
NLASTRIP_EXTEND_NOTHING :
|
|
|
|
|
NLASTRIP_EXTEND_HOLD;
|
|
|
|
|
|
|
|
|
|
r_context->eval_strip = nes = nlastrips_ctime_get_strip(
|
|
|
|
|
NULL, &dummy_trackslist, -1, anim_eval_context, flush_to_original);
|
|
|
|
|
|
|
|
|
|
/* These setting combinations require no data from strips below, so exit immediately. */
|
|
|
|
|
if ((nes == NULL) ||
|
|
|
|
|
(dummy_strip->blendmode == NLASTRIP_MODE_REPLACE && dummy_strip->influence == 1.0f)) {
|
|
|
|
|
BLI_freelistN(&estrips);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
/* special case - evaluate as if there isn't any NLA data */
|
|
|
|
|
BLI_freelistN(&estrips);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (is_action_track_evaluated_without_nla(adt, has_strips)) {
|
|
|
|
|
BLI_freelistN(&estrips);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* only continue if there are strips to evaluate */
|
|
|
|
|
if (BLI_listbase_is_empty(&estrips)) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
NlaStrip action_strip = {0};
|
|
|
|
|
animsys_create_action_track_strip(adt, false, &action_strip);
|
|
|
|
|
nlastrips_ctime_get_strip_single(&estrips, &action_strip, anim_eval_context, flush_to_original);
|
|
|
|
|
|
|
|
|
|
/* 2. for each strip, evaluate then accumulate on top of existing channels,
|
|
|
|
|
* but don't set values yet. */
|
|
|
|
|
/* Per strip, evaluate and accumulate on top of existing channels. */
|
|
|
|
|
for (nes = estrips.first; nes; nes = nes->next) {
|
|
|
|
|
nlastrip_evaluate(ptr,
|
|
|
|
|
echannels,
|
|
|
|
|
@@ -2393,11 +2455,116 @@ static bool animsys_evaluate_nla(NlaEvalData *echannels,
|
|
|
|
|
flush_to_original);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 3. free temporary evaluation data that's not used elsewhere */
|
|
|
|
|
/* Free temporary evaluation data that's not used elsewhere. */
|
|
|
|
|
BLI_freelistN(&estrips);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Lower blended values are calculated and accumulated into r_context->lower_eval_data. */
|
|
|
|
|
static void animsys_evaluate_nla_for_keyframing(PointerRNA *ptr,
|
|
|
|
|
const AnimData *adt,
|
|
|
|
|
const AnimationEvalContext *anim_eval_context,
|
|
|
|
|
NlaKeyframingContext *r_context)
|
|
|
|
|
{
|
|
|
|
|
if (!r_context) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Early out. If NLA track is soloing and tweaked action isn't it, then don't allow keyframe
|
|
|
|
|
* insertion. */
|
|
|
|
|
if (adt->flag & ADT_NLA_SOLO_TRACK) {
|
|
|
|
|
if (!(adt->act_track && (adt->act_track->flag & NLATRACK_SOLO))) {
|
|
|
|
|
r_context->eval_strip = NULL;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NlaTrack *nlt;
|
|
|
|
|
short track_index = 0;
|
|
|
|
|
bool has_strips = false;
|
|
|
|
|
|
|
|
|
|
ListBase lower_estrips = {NULL, NULL};
|
|
|
|
|
NlaEvalStrip *nes;
|
|
|
|
|
|
|
|
|
|
NlaTrack *tweaked_track = nlatrack_find_tweaked(adt);
|
|
|
|
|
|
|
|
|
|
/* Get the lower stack of strips to evaluate at current time (influence calculated here). */
|
|
|
|
|
for (nlt = adt->nla_tracks.first; nlt; nlt = nlt->next, track_index++) {
|
|
|
|
|
|
|
|
|
|
if (!is_nlatrack_evaluatable(adt, nlt)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Tweaked strip effect should not be stored in any snapshot. */
|
|
|
|
|
if (nlt == tweaked_track) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (nlt->strips.first) {
|
|
|
|
|
has_strips = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Get strip to evaluate for this channel. */
|
|
|
|
|
nes = nlastrips_ctime_get_strip(
|
|
|
|
|
&lower_estrips, &nlt->strips, track_index, anim_eval_context, false);
|
|
|
|
|
if (nes) {
|
|
|
|
|
nes->track = nlt;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** Note: Although we early out, we can still keyframe to the non-pushed action since the
|
|
|
|
|
* keyframe remap function detects (r_context->strip.act == NULL) and will keyframe without
|
|
|
|
|
* remapping.
|
|
|
|
|
*/
|
|
|
|
|
if (is_action_track_evaluated_without_nla(adt, has_strips)) {
|
|
|
|
|
BLI_freelistN(&lower_estrips);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Write r_context->eval_strip. */
|
|
|
|
|
if (adt->flag & ADT_NLA_EDIT_ON) {
|
|
|
|
|
|
|
|
|
|
NlaStrip *tweak_strip = &r_context->strip;
|
|
|
|
|
animsys_create_tweak_strip(adt, true, tweak_strip);
|
|
|
|
|
r_context->eval_strip = nlastrips_ctime_get_strip_single(
|
|
|
|
|
NULL, tweak_strip, anim_eval_context, false);
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
|
|
|
|
|
NlaStrip *action_strip = &r_context->strip;
|
|
|
|
|
animsys_create_action_track_strip(adt, true, action_strip);
|
|
|
|
|
r_context->eval_strip = nlastrips_ctime_get_strip_single(
|
|
|
|
|
NULL, action_strip, anim_eval_context, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If NULL, then keyframing will fail. No need to do any more processing. */
|
|
|
|
|
if (!r_context->eval_strip) {
|
|
|
|
|
BLI_freelistN(&lower_estrips);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If tweak strip is full REPLACE, then lower strips not needed. */
|
|
|
|
|
if (r_context->strip.blendmode == NLASTRIP_MODE_REPLACE &&
|
|
|
|
|
IS_EQF(r_context->strip.influence, 1.0f)) {
|
|
|
|
|
BLI_freelistN(&lower_estrips);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* For each strip, evaluate then accumulate on top of existing channels. */
|
|
|
|
|
for (nes = lower_estrips.first; nes; nes = nes->next) {
|
|
|
|
|
nlastrip_evaluate(ptr,
|
|
|
|
|
&r_context->lower_eval_data,
|
|
|
|
|
NULL,
|
|
|
|
|
nes,
|
|
|
|
|
&r_context->lower_eval_data.eval_snapshot,
|
|
|
|
|
anim_eval_context,
|
|
|
|
|
false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Free temporary evaluation data that's not used elsewhere. */
|
|
|
|
|
BLI_freelistN(&lower_estrips);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* NLA Evaluation function (mostly for use through do_animdata)
|
|
|
|
|
* - All channels that will be affected are not cleared anymore. Instead, we just evaluate into
|
|
|
|
|
* some temp channels, where values can be accumulated in one go.
|
|
|
|
|
@@ -2412,7 +2579,7 @@ static void animsys_calculate_nla(PointerRNA *ptr,
|
|
|
|
|
nlaeval_init(&echannels);
|
|
|
|
|
|
|
|
|
|
/* evaluate the NLA stack, obtaining a set of values to flush */
|
|
|
|
|
if (animsys_evaluate_nla(&echannels, ptr, adt, anim_eval_context, flush_to_original, NULL)) {
|
|
|
|
|
if (animsys_evaluate_nla_for_flush(&echannels, ptr, adt, anim_eval_context, flush_to_original)) {
|
|
|
|
|
/* reset any channels touched by currently inactive actions to default value */
|
|
|
|
|
animsys_evaluate_nla_domain(ptr, &echannels, adt);
|
|
|
|
|
|
|
|
|
|
@@ -2448,8 +2615,7 @@ NlaKeyframingContext *BKE_animsys_get_nla_keyframing_context(
|
|
|
|
|
struct ListBase *cache,
|
|
|
|
|
struct PointerRNA *ptr,
|
|
|
|
|
struct AnimData *adt,
|
|
|
|
|
const AnimationEvalContext *anim_eval_context,
|
|
|
|
|
const bool flush_to_original)
|
|
|
|
|
const AnimationEvalContext *anim_eval_context)
|
|
|
|
|
{
|
|
|
|
|
/* No remapping needed if NLA is off or no action. */
|
|
|
|
|
if ((adt == NULL) || (adt->action == NULL) || (adt->nla_tracks.first == NULL) ||
|
|
|
|
|
@@ -2472,8 +2638,7 @@ NlaKeyframingContext *BKE_animsys_get_nla_keyframing_context(
|
|
|
|
|
ctx->adt = adt;
|
|
|
|
|
|
|
|
|
|
nlaeval_init(&ctx->lower_eval_data);
|
|
|
|
|
animsys_evaluate_nla(
|
|
|
|
|
&ctx->lower_eval_data, ptr, adt, anim_eval_context, flush_to_original, ctx);
|
|
|
|
|
animsys_evaluate_nla_for_keyframing(ptr, adt, anim_eval_context, ctx);
|
|
|
|
|
|
|
|
|
|
BLI_assert(ELEM(ctx->strip.act, NULL, adt->action));
|
|
|
|
|
BLI_addtail(cache, ctx);
|
|
|
|
|
|