From 8323c3891d87782c40db5b65be8a4ba0f27d7d94 Mon Sep 17 00:00:00 2001
From: "Silc Lizard (Tokage) Renew"
 <61938263+TokageItLab@users.noreply.github.com>
Date: Thu, 1 Aug 2024 23:57:47 +0900
Subject: [PATCH] Snap current position to the edge on animation finished

---
 scene/animation/animation_blend_tree.cpp | 1 +
 scene/animation/animation_player.cpp     | 5 ++++-
 2 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/scene/animation/animation_blend_tree.cpp b/scene/animation/animation_blend_tree.cpp
index a27da73b8931..e4baae1afbc5 100644
--- a/scene/animation/animation_blend_tree.cpp
+++ b/scene/animation/animation_blend_tree.cpp
@@ -237,6 +237,7 @@ AnimationNode::NodeTimeInfo AnimationNodeAnimation::_process(const AnimationMixe
 			}
 			// Finished.
 			if (Animation::is_less_approx(prev_playback_time, anim_size) && Animation::is_greater_or_equal_approx(cur_playback_time, anim_size)) {
+				cur_playback_time = anim_size;
 				process_state->tree->call_deferred(SNAME("emit_signal"), SceneStringName(animation_finished), animation);
 			}
 		}
diff --git a/scene/animation/animation_player.cpp b/scene/animation/animation_player.cpp
index 19229f405a4e..24b777e2eb8a 100644
--- a/scene/animation/animation_player.cpp
+++ b/scene/animation/animation_player.cpp
@@ -204,19 +204,20 @@ void AnimationPlayer::_process_playback_data(PlaybackData &cd, double p_delta, f
 	}
 
 	double prev_pos = cd.pos; // The animation may be changed during process, so it is safer that the state is changed before process.
-	cd.pos = next_pos;
 
 	// End detection.
 	if (p_is_current) {
 		if (cd.from->animation->get_loop_mode() == Animation::LOOP_NONE) {
 			if (!backwards && Animation::is_less_or_equal_approx(prev_pos, len) && Math::is_equal_approx(next_pos, len)) {
 				// Playback finished.
+				next_pos = len; // Snap to the edge.
 				end_reached = true;
 				end_notify = Animation::is_less_approx(prev_pos, len); // Notify only if not already at the end.
 				p_blend = 1.0;
 			}
 			if (backwards && Animation::is_greater_or_equal_approx(prev_pos, 0) && Math::is_equal_approx(next_pos, 0)) {
 				// Playback finished.
+				next_pos = 0; // Snap to the edge.
 				end_reached = true;
 				end_notify = Animation::is_greater_approx(prev_pos, 0); // Notify only if not already at the beginning.
 				p_blend = 1.0;
@@ -224,6 +225,8 @@ void AnimationPlayer::_process_playback_data(PlaybackData &cd, double p_delta, f
 		}
 	}
 
+	cd.pos = next_pos;
+
 	PlaybackInfo pi;
 	if (p_started) {
 		pi.time = prev_pos;