* AnimationTreePlayer (_process_node): remove switched argument.

The _process_node function (which recurses through the blend tree
generating blend values and the active animation list) had an argument
named `switched` which would loop an animation back to the beginning if
it had reached the end (regardless of whether or not it was supposed to
be a looping animation).

This argument was only used in four places: two of them were overridden
by a seek-to-zero, and I believe the other two are bugs.

In OneShot, it was used to reset the oneshot animation to the beginning
when fired. But this would fail if the oneshot node was fired before it
had completed its previous run. While this *could* be a valid way for
oneshot to work (firing does nothing if it's already running), the code
currently resets the fade-in, so I believe that it is intended to reset.
I replaced this usage with seek-to-0.

In Transition, it was used on the previous (fading out) animation when
seeking the Transition node, which I believe is incorrect: why would you
want to loop a non-looping animation instead of simply fading out from
the end? Also it will never happen unless you seek the Transition node
twice during one cross-fade.

The other two uses are in Transition and _process_animation, where it is
used along with a seek-to-zero which overrides it.
This commit is contained in:
Josh Grams 2016-03-27 07:19:05 -04:00
parent 15d1fca061
commit 8920ab0fbf
2 changed files with 41 additions and 43 deletions

View File

@ -432,7 +432,7 @@ void AnimationTreePlayer::_notification(int p_what) {
}
float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode **r_prev_anim,float p_weight, float p_time, bool switched, bool p_seek,const HashMap<NodePath,bool> *p_filter, float p_reverse_weight) {
float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode **r_prev_anim,float p_weight, float p_time, bool p_seek,const HashMap<NodePath,bool> *p_filter, float p_reverse_weight) {
ERR_FAIL_COND_V(!node_map.has(p_node), 0);
NodeBase *nb=node_map[p_node];
@ -445,7 +445,7 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode
case NODE_OUTPUT: {
NodeOut *on = static_cast<NodeOut*>(nb);
return _process_node(on->inputs[0].node,r_prev_anim,p_weight,p_time,switched,p_seek);
return _process_node(on->inputs[0].node,r_prev_anim,p_weight,p_time,p_seek);
} break;
case NODE_ANIMATION: {
@ -479,9 +479,6 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode
an->time=anim_size;
}
if (switched && an->time >= anim_size) {
an->time = 0.0;
}
an->skip=true;
for (List<AnimationNode::TrackRef>::Element *E=an->tref.front();E;E=E->next()) {
@ -523,13 +520,17 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode
if (!osn->active) {
//make it as if this node doesn't exist, pass input 0 by.
return _process_node(osn->inputs[0].node,r_prev_anim,p_weight,p_time,switched,p_seek,p_filter,p_reverse_weight);
return _process_node(osn->inputs[0].node,r_prev_anim,p_weight,p_time,p_seek,p_filter,p_reverse_weight);
}
float os_seek = p_seek;
if (p_seek)
osn->time=p_time;
if (osn->start)
if (osn->start) {
osn->time=0;
os_seek = true;
}
float blend;
@ -554,13 +555,13 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode
if (!osn->filter.empty()) {
main_rem = _process_node(osn->inputs[0].node,r_prev_anim,(osn->mix?p_weight:p_weight*(1.0-blend)),p_time,switched,p_seek,&osn->filter,p_weight);
os_rem = _process_node(osn->inputs[1].node,r_prev_anim,p_weight*blend,p_time,osn->start,p_seek,&osn->filter,-1);
main_rem = _process_node(osn->inputs[0].node,r_prev_anim,(osn->mix?p_weight:p_weight*(1.0-blend)),p_time,p_seek,&osn->filter,p_weight);
os_rem = _process_node(osn->inputs[1].node,r_prev_anim,p_weight*blend,p_time,os_seek,&osn->filter,-1);
} else {
main_rem = _process_node(osn->inputs[0].node,r_prev_anim,(osn->mix?p_weight:p_weight*(1.0-blend)),p_time,switched,p_seek);
os_rem = _process_node(osn->inputs[1].node,r_prev_anim,p_weight*blend,p_time,osn->start,p_seek);
main_rem = _process_node(osn->inputs[0].node,r_prev_anim,(osn->mix?p_weight:p_weight*(1.0-blend)),p_time,p_seek);
os_rem = _process_node(osn->inputs[1].node,r_prev_anim,p_weight*blend,p_time,os_seek);
}
if (osn->start) {
@ -581,8 +582,8 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode
MixNode *mn = static_cast<MixNode*>(nb);
float rem = _process_node(mn->inputs[0].node,r_prev_anim,p_weight,p_time,switched,p_seek,p_filter,p_reverse_weight);
_process_node(mn->inputs[1].node,r_prev_anim,p_weight*mn->amount,p_time,switched,p_seek,p_filter,p_reverse_weight);
float rem = _process_node(mn->inputs[0].node,r_prev_anim,p_weight,p_time,p_seek,p_filter,p_reverse_weight);
_process_node(mn->inputs[1].node,r_prev_anim,p_weight*mn->amount,p_time,p_seek,p_filter,p_reverse_weight);
return rem;
} break;
@ -593,12 +594,12 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode
float rem;
if (!bn->filter.empty()) {
rem = _process_node(bn->inputs[0].node,r_prev_anim,p_weight*(1.0-bn->value),p_time,switched,p_seek,&bn->filter,p_weight);
_process_node(bn->inputs[1].node,r_prev_anim,p_weight*bn->value,p_time,switched,p_seek,&bn->filter,-1);
rem = _process_node(bn->inputs[0].node,r_prev_anim,p_weight*(1.0-bn->value),p_time,p_seek,&bn->filter,p_weight);
_process_node(bn->inputs[1].node,r_prev_anim,p_weight*bn->value,p_time,p_seek,&bn->filter,-1);
} else {
rem = _process_node(bn->inputs[0].node,r_prev_anim,p_weight*(1.0-bn->value),p_time,switched,p_seek,p_filter,p_reverse_weight*(1.0-bn->value));
_process_node(bn->inputs[1].node,r_prev_anim,p_weight*bn->value,p_time,switched,p_seek,p_filter,p_reverse_weight*bn->value);
rem = _process_node(bn->inputs[0].node,r_prev_anim,p_weight*(1.0-bn->value),p_time,p_seek,p_filter,p_reverse_weight*(1.0-bn->value));
_process_node(bn->inputs[1].node,r_prev_anim,p_weight*bn->value,p_time,p_seek,p_filter,p_reverse_weight*bn->value);
}
return rem;
@ -618,19 +619,19 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode
upper_blend = bn->value;
}
rem = _process_node(bn->inputs[1].node,r_prev_anim,p_weight*blend,p_time,switched,p_seek,p_filter,p_reverse_weight*blend);
_process_node(bn->inputs[2].node,r_prev_anim,p_weight*upper_blend,p_time,switched,p_seek,p_filter,p_reverse_weight*upper_blend);
_process_node(bn->inputs[0].node,r_prev_anim,p_weight*lower_blend,p_time,switched,p_seek,p_filter,p_reverse_weight*lower_blend);
rem = _process_node(bn->inputs[1].node,r_prev_anim,p_weight*blend,p_time,p_seek,p_filter,p_reverse_weight*blend);
_process_node(bn->inputs[2].node,r_prev_anim,p_weight*upper_blend,p_time,p_seek,p_filter,p_reverse_weight*upper_blend);
_process_node(bn->inputs[0].node,r_prev_anim,p_weight*lower_blend,p_time,p_seek,p_filter,p_reverse_weight*lower_blend);
return rem;
} break;
case NODE_BLEND4: {
Blend4Node *bn = static_cast<Blend4Node*>(nb);
float rem = _process_node(bn->inputs[0].node,r_prev_anim,p_weight*(1.0-bn->value.x),p_time,switched,p_seek,p_filter,p_reverse_weight*(1.0-bn->value.x));
_process_node(bn->inputs[1].node,r_prev_anim,p_weight*bn->value.x,p_time,switched,p_seek,p_filter,p_reverse_weight*bn->value.x);
float rem2 = _process_node(bn->inputs[2].node,r_prev_anim,p_weight*(1.0-bn->value.y),p_time,switched,p_seek,p_filter,p_reverse_weight*(1.0-bn->value.y));
_process_node(bn->inputs[3].node,r_prev_anim,p_weight*bn->value.y,p_time,switched,p_seek,p_filter,p_reverse_weight*bn->value.y);
float rem = _process_node(bn->inputs[0].node,r_prev_anim,p_weight*(1.0-bn->value.x),p_time,p_seek,p_filter,p_reverse_weight*(1.0-bn->value.x));
_process_node(bn->inputs[1].node,r_prev_anim,p_weight*bn->value.x,p_time,p_seek,p_filter,p_reverse_weight*bn->value.x);
float rem2 = _process_node(bn->inputs[2].node,r_prev_anim,p_weight*(1.0-bn->value.y),p_time,p_seek,p_filter,p_reverse_weight*(1.0-bn->value.y));
_process_node(bn->inputs[3].node,r_prev_anim,p_weight*bn->value.y,p_time,p_seek,p_filter,p_reverse_weight*bn->value.y);
return MAX(rem,rem2);
@ -639,9 +640,9 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode
TimeScaleNode *tsn = static_cast<TimeScaleNode*>(nb);
float rem;
if (p_seek)
rem = _process_node(tsn->inputs[0].node,r_prev_anim,p_weight,p_time,switched,true,p_filter,p_reverse_weight);
rem = _process_node(tsn->inputs[0].node,r_prev_anim,p_weight,p_time,true,p_filter,p_reverse_weight);
else
rem = _process_node(tsn->inputs[0].node,r_prev_anim,p_weight,p_time*tsn->scale,switched,false,p_filter,p_reverse_weight);
rem = _process_node(tsn->inputs[0].node,r_prev_anim,p_weight,p_time*tsn->scale,false,p_filter,p_reverse_weight);
if (tsn->scale == 0)
return INFINITY;
else
@ -653,21 +654,21 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode
TimeSeekNode *tsn = static_cast<TimeSeekNode*>(nb);
if (tsn->seek_pos>=0) {
float res = _process_node(tsn->inputs[0].node,r_prev_anim,p_weight,tsn->seek_pos,switched,true,p_filter,p_reverse_weight);
float res = _process_node(tsn->inputs[0].node,r_prev_anim,p_weight,tsn->seek_pos,true,p_filter,p_reverse_weight);
tsn->seek_pos=-1;
return res;
} else
return _process_node(tsn->inputs[0].node,r_prev_anim,p_weight,p_time,switched,p_seek);
return _process_node(tsn->inputs[0].node,r_prev_anim,p_weight,p_time,p_seek);
} break;
case NODE_TRANSITION: {
TransitionNode *tn = static_cast<TransitionNode*>(nb);
if (tn->prev<0) {
if (tn->prev<0) { // process current animation, check for transition
float rem = _process_node(tn->inputs[tn->current].node,r_prev_anim,p_weight,p_time,switched,p_seek,p_filter,p_reverse_weight);
float rem = _process_node(tn->inputs[tn->current].node,r_prev_anim,p_weight,p_time,p_seek,p_filter,p_reverse_weight);
if (p_seek)
tn->time=p_time;
else
@ -687,32 +688,29 @@ float AnimationTreePlayer::_process_node(const StringName& p_node,AnimationNode
return rem;
} else {
} else { // cross-fading from tn->prev to tn->current
float blend = tn->xfade? (tn->prev_xfading/tn->xfade) : 1;
float rem;
if (!p_seek && tn->switched) { //just switched
if (!p_seek && tn->switched) { //just switched, seek to start of current
rem = _process_node(tn->inputs[tn->current].node,r_prev_anim,p_weight*(1.0-blend),0,true,true,p_filter,p_reverse_weight*(1.0-blend));
rem = _process_node(tn->inputs[tn->current].node,r_prev_anim,p_weight*(1.0-blend),0,true,p_filter,p_reverse_weight*(1.0-blend));
} else {
rem = _process_node(tn->inputs[tn->current].node,r_prev_anim,p_weight*(1.0-blend),p_time,switched,p_seek,p_filter,p_reverse_weight*(1.0-blend));
rem = _process_node(tn->inputs[tn->current].node,r_prev_anim,p_weight*(1.0-blend),p_time,p_seek,p_filter,p_reverse_weight*(1.0-blend));
}
tn->switched=false;
//if (!p_seek)
if (p_seek) {
_process_node(tn->inputs[tn->prev].node,r_prev_anim,p_weight*blend,0,true,false,p_filter,p_reverse_weight*blend);
if (p_seek) { // don't seek prev animation
_process_node(tn->inputs[tn->prev].node,r_prev_anim,p_weight*blend,0,false,p_filter,p_reverse_weight*blend);
tn->time=p_time;
} else {
_process_node(tn->inputs[tn->prev].node,r_prev_anim,p_weight*blend,p_time,switched,false,p_filter,p_reverse_weight*blend);
_process_node(tn->inputs[tn->prev].node,r_prev_anim,p_weight*blend,p_time,false,p_filter,p_reverse_weight*blend);
tn->time+=p_time;
tn->prev_xfading-=p_time;
if (tn->prev_xfading<0) {
@ -749,10 +747,10 @@ void AnimationTreePlayer::_process_animation(float p_delta) {
AnimationNode *prev=NULL;
if (reset_request) {
_process_node(out_name,&prev, 1.0, 0, true, true );
_process_node(out_name,&prev, 1.0, 0, true);
reset_request=false;
} else
_process_node(out_name,&prev, 1.0, p_delta, false, false );
_process_node(out_name,&prev, 1.0, p_delta);
if (dirty_caches) {
//some animation changed.. ignore this pass

View File

@ -267,7 +267,7 @@ private:
Map<StringName,NodeBase*> node_map;
// return time left to finish animation
float _process_node(const StringName& p_node,AnimationNode **r_prev_anim, float p_weight,float p_step, bool switched, bool p_seek=false,const HashMap<NodePath,bool> *p_filter=NULL, float p_reverse_weight=0);
float _process_node(const StringName& p_node,AnimationNode **r_prev_anim, float p_weight,float p_step, bool p_seek=false,const HashMap<NodePath,bool> *p_filter=NULL, float p_reverse_weight=0);
void _process_animation(float p_delta);
bool reset_request;