Browse Source

Determine break_loop_at_end 1 frame earlier using prediction by delta

Silc Lizard (Tokage) Renew 1 year ago
parent
commit
4de79fed45

+ 2 - 7
scene/animation/animation_blend_tree.cpp

@@ -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;

+ 4 - 3
scene/animation/animation_node_state_machine.cpp

@@ -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);

+ 1 - 1
scene/animation/animation_node_state_machine.h

@@ -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);

+ 2 - 2
scene/animation/animation_tree.h

@@ -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;