From 038977a985722036d4e2e7f90e0b477225955d80 Mon Sep 17 00:00:00 2001
From: kobewi <kobewi4e@gmail.com>
Date: Fri, 28 Jan 2022 22:58:54 +0100
Subject: [PATCH] Better handle infinite Tween loops

---
 doc/classes/Tween.xml     |  2 +-
 scene/animation/tween.cpp | 10 ++++++++++
 2 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/doc/classes/Tween.xml b/doc/classes/Tween.xml
index 1cba9953664..a1b53346d87 100644
--- a/doc/classes/Tween.xml
+++ b/doc/classes/Tween.xml
@@ -146,7 +146,7 @@
 			<description>
 				Sets the number of times the tweening sequence will be repeated, i.e. [code]set_loops(2)[/code] will run the animation twice.
 				Calling this method without arguments will make the [Tween] run infinitely, until it is either killed by [method kill] or by freeing bound node, or all the animated objects have been freed (which makes further animation impossible).
-				[b]Warning:[/b] Make sure to always add some duration/delay when using infinite loops. 0-duration looped animations (e.g. single [CallbackTweener] with no delay) are equivalent to infinite [code]while[/code] loops and will freeze your game.
+				[b]Warning:[/b] Make sure to always add some duration/delay when using infinite loops. 0-duration looped animations (e.g. single [CallbackTweener] with no delay or [PropertyTweener] with invalid node) are equivalent to infinite [code]while[/code] loops and will freeze your game. If a [Tween]'s lifetime depends on some node, always use [method bind_node].
 			</description>
 		</method>
 		<method name="set_parallel">
diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp
index 53ff3eeeae1..a2fed718bee 100644
--- a/scene/animation/tween.cpp
+++ b/scene/animation/tween.cpp
@@ -283,6 +283,10 @@ bool Tween::step(float p_delta) {
 		float step_delta = rem_delta;
 		step_active = false;
 
+#ifdef DEBUG_ENABLED
+		float prev_delta = rem_delta;
+#endif
+
 		for (Ref<Tweener> &tweener : tweeners.write[current_step]) {
 			// Modified inside Tweener.step().
 			float temp_delta = rem_delta;
@@ -312,6 +316,12 @@ bool Tween::step(float p_delta) {
 				start_tweeners();
 			}
 		}
+
+#ifdef DEBUG_ENABLED
+		if (Math::is_equal_approx(rem_delta, prev_delta) && running && loops <= 0) {
+			ERR_FAIL_V_MSG(false, "Infinite loop detected. Check set_loops() description for more info.");
+		}
+#endif
 	}
 
 	return true;