Merge pull request #94858 from TokageItLab/early-break-loop-at-end
Determine `break_loop_at_end` 1 frame earlier using prediction by delta
This commit is contained in:
commit
7aba10b170
4 changed files with 9 additions and 13 deletions
|
@ -138,15 +138,11 @@ AnimationNode::NodeTimeInfo AnimationNodeAnimation::_process(const AnimationMixe
|
||||||
bool p_seek = p_playback_info.seeked;
|
bool p_seek = p_playback_info.seeked;
|
||||||
bool p_is_external_seeking = p_playback_info.is_external_seeking;
|
bool p_is_external_seeking = p_playback_info.is_external_seeking;
|
||||||
|
|
||||||
bool is_just_looped = false;
|
|
||||||
|
|
||||||
// 1. Progress for AnimationNode.
|
// 1. Progress for AnimationNode.
|
||||||
|
bool will_end = Animation::is_greater_or_equal_approx(cur_time + cur_delta, cur_len);
|
||||||
if (cur_loop_mode != Animation::LOOP_NONE) {
|
if (cur_loop_mode != Animation::LOOP_NONE) {
|
||||||
if (cur_loop_mode == Animation::LOOP_LINEAR) {
|
if (cur_loop_mode == Animation::LOOP_LINEAR) {
|
||||||
if (!Math::is_zero_approx(cur_len)) {
|
if (!Math::is_zero_approx(cur_len)) {
|
||||||
if (Animation::is_less_or_equal_approx(prev_time, cur_len) && Animation::is_greater_approx(cur_time, cur_len)) {
|
|
||||||
is_just_looped = true; // Don't break with negative timescale since remain will not be 0.
|
|
||||||
}
|
|
||||||
cur_time = Math::fposmod(cur_time, cur_len);
|
cur_time = Math::fposmod(cur_time, cur_len);
|
||||||
}
|
}
|
||||||
backward = false;
|
backward = false;
|
||||||
|
@ -156,7 +152,6 @@ AnimationNode::NodeTimeInfo AnimationNodeAnimation::_process(const AnimationMixe
|
||||||
backward = !backward;
|
backward = !backward;
|
||||||
} else if (Animation::is_less_or_equal_approx(prev_time, cur_len) && Animation::is_greater_approx(cur_time, cur_len)) {
|
} else if (Animation::is_less_or_equal_approx(prev_time, cur_len) && Animation::is_greater_approx(cur_time, cur_len)) {
|
||||||
backward = !backward;
|
backward = !backward;
|
||||||
is_just_looped = true; // Don't break with negative timescale since remain will not be 0.
|
|
||||||
}
|
}
|
||||||
cur_time = Math::pingpong(cur_time, cur_len);
|
cur_time = Math::pingpong(cur_time, cur_len);
|
||||||
}
|
}
|
||||||
|
@ -190,7 +185,7 @@ AnimationNode::NodeTimeInfo AnimationNodeAnimation::_process(const AnimationMixe
|
||||||
nti.position = cur_time;
|
nti.position = cur_time;
|
||||||
nti.delta = cur_delta;
|
nti.delta = cur_delta;
|
||||||
nti.loop_mode = cur_loop_mode;
|
nti.loop_mode = cur_loop_mode;
|
||||||
nti.is_just_looped = is_just_looped;
|
nti.will_end = will_end;
|
||||||
|
|
||||||
// 3. Progress for Animation.
|
// 3. Progress for Animation.
|
||||||
double prev_playback_time = prev_time + start_offset;
|
double prev_playback_time = prev_time + start_offset;
|
||||||
|
|
|
@ -804,7 +804,7 @@ AnimationNode::NodeTimeInfo AnimationNodeStateMachinePlayback::_process(const St
|
||||||
pi.weight = 0;
|
pi.weight = 0;
|
||||||
current_nti = p_state_machine->blend_node(p_state_machine->states[current].node, current, pi, AnimationNode::FILTER_IGNORE, true, true);
|
current_nti = p_state_machine->blend_node(p_state_machine->states[current].node, current, pi, AnimationNode::FILTER_IGNORE, true, true);
|
||||||
// Don't process first node if not necessary, insteads process next node.
|
// Don't process first node if not necessary, insteads process next node.
|
||||||
_transition_to_next_recursive(tree, p_state_machine, p_test_only);
|
_transition_to_next_recursive(tree, p_state_machine, p_delta, p_test_only);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check current node existence.
|
// Check current node existence.
|
||||||
|
@ -881,7 +881,7 @@ AnimationNode::NodeTimeInfo AnimationNodeStateMachinePlayback::_process(const St
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find next and see when to transition.
|
// Find next and see when to transition.
|
||||||
bool will_end = _transition_to_next_recursive(tree, p_state_machine, p_test_only) || current == AnimationNodeStateMachine::END_NODE;
|
bool will_end = _transition_to_next_recursive(tree, p_state_machine, p_delta, p_test_only) || current == AnimationNodeStateMachine::END_NODE;
|
||||||
|
|
||||||
// Predict remaining time.
|
// Predict remaining time.
|
||||||
if (will_end || ((p_state_machine->get_state_machine_type() == AnimationNodeStateMachine::STATE_MACHINE_TYPE_NESTED) && !p_state_machine->has_transition_from(current))) {
|
if (will_end || ((p_state_machine->get_state_machine_type() == AnimationNodeStateMachine::STATE_MACHINE_TYPE_NESTED) && !p_state_machine->has_transition_from(current))) {
|
||||||
|
@ -899,10 +899,11 @@ AnimationNode::NodeTimeInfo AnimationNodeStateMachinePlayback::_process(const St
|
||||||
return current_nti;
|
return current_nti;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AnimationNodeStateMachinePlayback::_transition_to_next_recursive(AnimationTree *p_tree, AnimationNodeStateMachine *p_state_machine, bool p_test_only) {
|
bool AnimationNodeStateMachinePlayback::_transition_to_next_recursive(AnimationTree *p_tree, AnimationNodeStateMachine *p_state_machine, double p_delta, bool p_test_only) {
|
||||||
_reset_request_for_fading_from = false;
|
_reset_request_for_fading_from = false;
|
||||||
|
|
||||||
AnimationMixer::PlaybackInfo pi;
|
AnimationMixer::PlaybackInfo pi;
|
||||||
|
pi.delta = p_delta;
|
||||||
NextInfo next;
|
NextInfo next;
|
||||||
Vector<StringName> transition_path;
|
Vector<StringName> transition_path;
|
||||||
transition_path.push_back(current);
|
transition_path.push_back(current);
|
||||||
|
|
|
@ -306,7 +306,7 @@ class AnimationNodeStateMachinePlayback : public Resource {
|
||||||
AnimationNode::NodeTimeInfo _process(const String &p_base_path, AnimationNodeStateMachine *p_state_machine, const AnimationMixer::PlaybackInfo p_playback_info, bool p_test_only);
|
AnimationNode::NodeTimeInfo _process(const String &p_base_path, AnimationNodeStateMachine *p_state_machine, const AnimationMixer::PlaybackInfo p_playback_info, bool p_test_only);
|
||||||
|
|
||||||
bool _check_advance_condition(const Ref<AnimationNodeStateMachine> p_state_machine, const Ref<AnimationNodeStateMachineTransition> p_transition) const;
|
bool _check_advance_condition(const Ref<AnimationNodeStateMachine> p_state_machine, const Ref<AnimationNodeStateMachineTransition> p_transition) const;
|
||||||
bool _transition_to_next_recursive(AnimationTree *p_tree, AnimationNodeStateMachine *p_state_machine, bool p_test_only);
|
bool _transition_to_next_recursive(AnimationTree *p_tree, AnimationNodeStateMachine *p_state_machine, double p_delta, bool p_test_only);
|
||||||
NextInfo _find_next(AnimationTree *p_tree, AnimationNodeStateMachine *p_state_machine) const;
|
NextInfo _find_next(AnimationTree *p_tree, AnimationNodeStateMachine *p_state_machine) const;
|
||||||
Ref<AnimationNodeStateMachineTransition> _check_group_transition(AnimationTree *p_tree, AnimationNodeStateMachine *p_state_machine, const AnimationNodeStateMachine::Transition &p_transition, Ref<AnimationNodeStateMachine> &r_state_machine, bool &r_bypass) const;
|
Ref<AnimationNodeStateMachineTransition> _check_group_transition(AnimationTree *p_tree, AnimationNodeStateMachine *p_state_machine, const AnimationNodeStateMachine::Transition &p_transition, Ref<AnimationNodeStateMachine> &r_state_machine, bool &r_bypass) const;
|
||||||
bool _can_transition_to_next(AnimationTree *p_tree, AnimationNodeStateMachine *p_state_machine, NextInfo p_next, bool p_test_only);
|
bool _can_transition_to_next(AnimationTree *p_tree, AnimationNodeStateMachine *p_state_machine, NextInfo p_next, bool p_test_only);
|
||||||
|
|
|
@ -74,7 +74,7 @@ public:
|
||||||
|
|
||||||
// Needs internally to estimate remain time, the previous frame values are not retained.
|
// Needs internally to estimate remain time, the previous frame values are not retained.
|
||||||
Animation::LoopMode loop_mode = Animation::LOOP_NONE;
|
Animation::LoopMode loop_mode = Animation::LOOP_NONE;
|
||||||
bool is_just_looped = false; // For breaking loop, it is true when just looped.
|
bool will_end = false; // For breaking loop, it is true when just looped.
|
||||||
bool is_infinity = false; // For unpredictable state machine's end.
|
bool is_infinity = false; // For unpredictable state machine's end.
|
||||||
|
|
||||||
bool is_looping() {
|
bool is_looping() {
|
||||||
|
@ -84,7 +84,7 @@ public:
|
||||||
if ((is_looping() && !p_break_loop) || is_infinity) {
|
if ((is_looping() && !p_break_loop) || is_infinity) {
|
||||||
return HUGE_LENGTH;
|
return HUGE_LENGTH;
|
||||||
}
|
}
|
||||||
if (p_break_loop && is_just_looped) {
|
if (is_looping() && p_break_loop && will_end) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
double remain = length - position;
|
double remain = length - position;
|
||||||
|
|
Loading…
Reference in a new issue