diff --git a/doc/classes/Tween.xml b/doc/classes/Tween.xml
index 7e313c3d4c9..51efbd31d8c 100644
--- a/doc/classes/Tween.xml
+++ b/doc/classes/Tween.xml
@@ -501,6 +501,9 @@
The animation is interpolated backing out at ends.
+
+ The animation is interpolated like a spring towards the end.
+
The interpolation starts slowly and speeds up towards the end.
diff --git a/scene/animation/easing_equations.h b/scene/animation/easing_equations.h
index 1b9c378b4fe..91501917443 100644
--- a/scene/animation/easing_equations.h
+++ b/scene/animation/easing_equations.h
@@ -413,4 +413,33 @@ static real_t out_in(real_t t, real_t b, real_t c, real_t d) {
}
}; // namespace back
+namespace spring {
+static real_t out(real_t t, real_t b, real_t c, real_t d) {
+ t /= d;
+ real_t s = 1.0 - t;
+ t = (sin(t * Math_PI * (0.2 + 2.5 * t * t * t)) * pow(s, 2.2) + t) * (1.0 + (1.2 * s));
+ return c * t + b;
+}
+
+static real_t in(real_t t, real_t b, real_t c, real_t d) {
+ return c - out(d - t, 0, c, d) + b;
+}
+
+static real_t in_out(real_t t, real_t b, real_t c, real_t d) {
+ if (t < d / 2) {
+ return in(t * 2, b, c / 2, d);
+ }
+ real_t h = c / 2;
+ return out(t * 2 - d, b + h, h, d);
+}
+
+static real_t out_in(real_t t, real_t b, real_t c, real_t d) {
+ if (t < d / 2) {
+ return out(t * 2, b, c / 2, d);
+ }
+ real_t h = c / 2;
+ return in(t * 2 - d, b + h, h, d);
+}
+}; // namespace spring
+
#endif // EASING_EQUATIONS_H
diff --git a/scene/animation/tween.cpp b/scene/animation/tween.cpp
index 8266cfbd433..96e5da5a400 100644
--- a/scene/animation/tween.cpp
+++ b/scene/animation/tween.cpp
@@ -50,6 +50,7 @@ Tween::interpolater Tween::interpolaters[Tween::TRANS_MAX][Tween::EASE_MAX] = {
{ &circ::in, &circ::out, &circ::in_out, &circ::out_in },
{ &bounce::in, &bounce::out, &bounce::in_out, &bounce::out_in },
{ &back::in, &back::out, &back::in_out, &back::out_in },
+ { &spring::in, &spring::out, &spring::in_out, &spring::out_in },
};
void Tweener::set_tween(const Ref &p_tween) {
@@ -483,6 +484,7 @@ void Tween::_bind_methods() {
BIND_ENUM_CONSTANT(TRANS_CIRC);
BIND_ENUM_CONSTANT(TRANS_BOUNCE);
BIND_ENUM_CONSTANT(TRANS_BACK);
+ BIND_ENUM_CONSTANT(TRANS_SPRING);
BIND_ENUM_CONSTANT(EASE_IN);
BIND_ENUM_CONSTANT(EASE_OUT);
diff --git a/scene/animation/tween.h b/scene/animation/tween.h
index 67823da040e..10c7a272ef1 100644
--- a/scene/animation/tween.h
+++ b/scene/animation/tween.h
@@ -87,6 +87,7 @@ public:
TRANS_CIRC,
TRANS_BOUNCE,
TRANS_BACK,
+ TRANS_SPRING,
TRANS_MAX
};