From 77b8578d04763398a60d372afcc834e05bc5fe77 Mon Sep 17 00:00:00 2001
From: Jaime Ita Passos <jp6781615@gmail.com>
Date: Mon, 19 Apr 2021 21:42:00 -0300
Subject: [PATCH] Add ease Lua library

---
 src/lua_mathlib.c | 119 +++++++++++++++++++++++++++++++++++++++++++++-
 src/m_easing.c    |  63 +++++++++++++++++-------
 src/m_easing.h    |  52 +++++++++++---------
 3 files changed, 193 insertions(+), 41 deletions(-)

diff --git a/src/lua_mathlib.c b/src/lua_mathlib.c
index b6046ab53b..1b7113b369 100644
--- a/src/lua_mathlib.c
+++ b/src/lua_mathlib.c
@@ -16,6 +16,7 @@
 #include "p_local.h"
 #include "doomstat.h" // for ALL7EMERALDS
 #include "r_main.h" // for R_PointToDist2
+#include "m_easing.h"
 
 #include "lua_script.h"
 #include "lua_libs.h"
@@ -185,7 +186,7 @@ static int lib_coloropposite(lua_State *L)
 	return 2;
 }
 
-static luaL_Reg lib[] = {
+static luaL_Reg lib_math[] = {
 	{"abs", lib_abs},
 	{"min", lib_min},
 	{"max", lib_max},
@@ -223,9 +224,123 @@ static luaL_Reg lib[] = {
 	{NULL, NULL}
 };
 
+//
+// Easing functions
+//
+
+#define EASINGFUNC(easetype) \
+{ \
+	fixed_t start = 0; \
+	fixed_t end = FRACUNIT; \
+	fixed_t t = luaL_checkfixed(L, 1); \
+	int n = lua_gettop(L); \
+	if (n == 2) \
+		end = luaL_checkfixed(L, 2); \
+	else if (n >= 3) \
+	{ \
+		start = luaL_checkfixed(L, 2); \
+		end = luaL_checkfixed(L, 3); \
+	} \
+	lua_pushfixed(L, (Easing_ ## easetype)(t, start, end)); \
+	return 1; \
+} \
+
+static int lib_easelinear(lua_State *L) { EASINGFUNC(Linear) }
+
+static int lib_easeinsine(lua_State *L) { EASINGFUNC(InSine) }
+static int lib_easeoutsine(lua_State *L) { EASINGFUNC(OutSine) }
+static int lib_easeinoutsine(lua_State *L) { EASINGFUNC(InOutSine) }
+
+static int lib_easeinquad(lua_State *L) { EASINGFUNC(InQuad) }
+static int lib_easeoutquad(lua_State *L) { EASINGFUNC(OutQuad) }
+static int lib_easeinoutquad(lua_State *L) { EASINGFUNC(InOutQuad) }
+
+static int lib_easeincubic(lua_State *L) { EASINGFUNC(InCubic) }
+static int lib_easeoutcubic(lua_State *L) { EASINGFUNC(OutCubic) }
+static int lib_easeinoutcubic(lua_State *L) { EASINGFUNC(InOutCubic) }
+
+static int lib_easeinquart(lua_State *L) { EASINGFUNC(InQuart) }
+static int lib_easeoutquart(lua_State *L) { EASINGFUNC(OutQuart) }
+static int lib_easeinoutquart(lua_State *L) { EASINGFUNC(InOutQuart) }
+
+static int lib_easeinquint(lua_State *L) { EASINGFUNC(InQuint) }
+static int lib_easeoutquint(lua_State *L) { EASINGFUNC(OutQuint) }
+static int lib_easeinoutquint(lua_State *L) { EASINGFUNC(InOutQuint) }
+
+static int lib_easeinexpo(lua_State *L) { EASINGFUNC(InExpo) }
+static int lib_easeoutexpo(lua_State *L) { EASINGFUNC(OutExpo) }
+static int lib_easeinoutexpo(lua_State *L) { EASINGFUNC(InOutExpo) }
+
+#undef EASINGFUNC
+
+#define EASINGFUNC(easetype) \
+{ \
+	boolean useparam = false; \
+	fixed_t param = 0; \
+	fixed_t start = 0; \
+	fixed_t end = FRACUNIT; \
+	fixed_t t = luaL_checkfixed(L, 1); \
+	int n = lua_gettop(L); \
+	if (n == 2) \
+		end = luaL_checkfixed(L, 2); \
+	else if (n >= 3) \
+	{ \
+		start = (fixed_t)luaL_optinteger(L, 2, start); \
+		end = (fixed_t)luaL_optinteger(L, 3, end); \
+		if ((n >= 4) && (useparam = (!lua_isnil(L, 4)))) \
+			param = luaL_checkfixed(L, 4); \
+	} \
+	if (useparam) \
+		lua_pushfixed(L, (Easing_ ## easetype ## Parameterized)(t, start, end, param)); \
+	else \
+		lua_pushfixed(L, (Easing_ ## easetype)(t, start, end)); \
+	return 1; \
+} \
+
+static int lib_easeinback(lua_State *L) { EASINGFUNC(InBack) }
+static int lib_easeoutback(lua_State *L) { EASINGFUNC(OutBack) }
+static int lib_easeinoutback(lua_State *L) { EASINGFUNC(InOutBack) }
+
+#undef EASINGFUNC
+
+static luaL_Reg lib_ease[] = {
+	{"linear", lib_easelinear},
+
+	{"insine", lib_easeinsine},
+	{"outsine", lib_easeoutsine},
+	{"inoutsine", lib_easeinoutsine},
+
+	{"inquad", lib_easeinquad},
+	{"outquad", lib_easeoutquad},
+	{"inoutquad", lib_easeinoutquad},
+
+	{"incubic", lib_easeincubic},
+	{"outcubic", lib_easeoutcubic},
+	{"inoutcubic", lib_easeinoutcubic},
+
+	{"inquart", lib_easeinquart},
+	{"outquart", lib_easeoutquart},
+	{"inoutquart", lib_easeinoutquart},
+
+	{"inquint", lib_easeinquint},
+	{"outquint", lib_easeoutquint},
+	{"inoutquint", lib_easeinoutquint},
+
+	{"inexpo", lib_easeinexpo},
+	{"outexpo", lib_easeoutexpo},
+	{"inoutexpo", lib_easeinoutexpo},
+
+	{"inback", lib_easeinback},
+	{"outback", lib_easeoutback},
+	{"inoutback", lib_easeinoutback},
+
+	{NULL, NULL}
+};
+
 int LUA_MathLib(lua_State *L)
 {
 	lua_pushvalue(L, LUA_GLOBALSINDEX);
-	luaL_register(L, NULL, lib);
+	luaL_register(L, NULL, lib_math);
+	luaL_register(L, "ease", lib_ease);
 	return 0;
 }
diff --git a/src/m_easing.c b/src/m_easing.c
index b3ea8842fd..c871d3106e 100644
--- a/src/m_easing.c
+++ b/src/m_easing.c
@@ -144,7 +144,11 @@ static INT32 fixexp(fixed_t a)
 #define fixintdiv(x, y) FixedDiv(x, (y) * FRACUNIT)
 #define fixinterp(start, end, t) FixedMul((FRACUNIT - (t)), start) + FixedMul(t, end)
 
-#define EASINGFUNC(type) fixed_t Easing_ ## type (fixed_t start, fixed_t end, fixed_t t)
+// ==================
+//  EASING FUNCTIONS
+// ==================
+
+#define EASINGFUNC(type) fixed_t Easing_ ## type (fixed_t t, fixed_t start, fixed_t end)
 
 //
 // Linear
@@ -327,17 +331,20 @@ EASINGFUNC(InOutExpo)
 #define EASEBACKCONST1 111514 // 1.70158
 #define EASEBACKCONST2 99942 // 1.525
 
-EASINGFUNC(InBack)
+static fixed_t EaseInBack(fixed_t t, fixed_t start, fixed_t end, fixed_t c1)
 {
-	const fixed_t c1 = EASEBACKCONST1;
 	const fixed_t c3 = c1 + FRACUNIT;
 	fixed_t x = FixedMul(FixedMul(t, t), FixedMul(c3, t) - c1);
 	return fixinterp(start, end, x);
 }
 
-EASINGFUNC(OutBack)
+EASINGFUNC(InBack)
+{
+	return EaseInBack(t, start, end, EASEBACKCONST1);
+}
+
+static fixed_t EaseOutBack(fixed_t t, fixed_t start, fixed_t end, fixed_t c1)
 {
-	const fixed_t c1 = EASEBACKCONST1;
 	const fixed_t c3 = c1 + FRACUNIT;
 	fixed_t x;
 	t -= FRACUNIT;
@@ -345,32 +352,56 @@ EASINGFUNC(OutBack)
 	return fixinterp(start, end, x);
 }
 
-static fixed_t DoEaseInOutBack(fixed_t start, fixed_t end, fixed_t t, fixed_t c2)
+EASINGFUNC(OutBack)
 {
-	fixed_t x;
+	return EaseOutBack(t, start, end, EASEBACKCONST1);
+}
 
-	c2 += FRACUNIT;
+static fixed_t EaseInOutBack(fixed_t t, fixed_t start, fixed_t end, fixed_t c2)
+{
+	fixed_t x, y;
+	const fixed_t f2 = 2*FRACUNIT;
 
 	if (t < FRACUNIT / 2)
 	{
-		x = fixintmul(7, t) - c2;
-		x = fixintmul(2, x);
-		x = FixedMul(FixedMul(t, t), x);
+		x = fixpow(FixedMul(t, f2), f2);
+		y = FixedMul(c2 + FRACUNIT, FixedMul(t, f2));
+		x = FixedMul(x, y - c2);
 	}
 	else
 	{
-		t -= FRACUNIT;
-		x = fixintmul(2, fixintmul(7, t) + c2);
-		x = FixedMul(FixedMul(t, t), x);
-		x = FRACUNIT + x;
+		x = fixpow(-(FixedMul(t, f2) - f2), f2);
+		y = FixedMul(c2 + FRACUNIT, FixedMul(t, f2) - f2);
+		x = FixedMul(x, y + c2);
+		x += f2;
 	}
 
+	x /= 2;
+
 	return fixinterp(start, end, x);
 }
 
 EASINGFUNC(InOutBack)
 {
-	return DoEaseInOutBack(start, end, t, EASEBACKCONST2);
+	return EaseInOutBack(t, start, end, EASEBACKCONST2);
+}
+
+#undef EASINGFUNC
+#define EASINGFUNC(type) fixed_t Easing_ ## type (fixed_t t, fixed_t start, fixed_t end, fixed_t param)
+
+EASINGFUNC(InBackParameterized)
+{
+	return EaseInBack(t, start, end, param);
+}
+
+EASINGFUNC(OutBackParameterized)
+{
+	return EaseOutBack(t, start, end, param);
+}
+
+EASINGFUNC(InOutBackParameterized)
+{
+	return EaseInOutBack(t, start, end, param);
 }
 
 #undef EASINGFUNC
diff --git a/src/m_easing.h b/src/m_easing.h
index e5571ece37..435ad35e7a 100644
--- a/src/m_easing.h
+++ b/src/m_easing.h
@@ -56,40 +56,46 @@ extern easingfunc_t easing_funclist[EASE_MAX];
 extern const char *easing_funcnames[EASE_MAX];
 
 #define EASINGFUNCLIST(sep) \
-	EASINGFUNC(Linear) sep \
+	EASINGFUNC(Linear) sep /* Easing_Linear */ \
  \
-	EASINGFUNC(InSine) sep \
-	EASINGFUNC(OutSine) sep \
-	EASINGFUNC(InOutSine) sep \
+	EASINGFUNC(InSine) sep /* Easing_InSine */ \
+	EASINGFUNC(OutSine) sep /* Easing_OutSine */ \
+	EASINGFUNC(InOutSine) sep /* Easing_InOutSine */ \
  \
-	EASINGFUNC(InQuad) sep \
-	EASINGFUNC(OutQuad) sep \
-	EASINGFUNC(InOutQuad) sep \
+	EASINGFUNC(InQuad) sep /* Easing_InQuad */ \
+	EASINGFUNC(OutQuad) sep /* Easing_OutQuad */ \
+	EASINGFUNC(InOutQuad) sep /* Easing_InOutQuad */ \
  \
-	EASINGFUNC(InCubic) sep \
-	EASINGFUNC(OutCubic) sep \
-	EASINGFUNC(InOutCubic) sep \
+	EASINGFUNC(InCubic) sep /* Easing_InCubic */ \
+	EASINGFUNC(OutCubic) sep /* Easing_OutCubic */ \
+	EASINGFUNC(InOutCubic) sep /* Easing_InOutCubic */ \
  \
-	EASINGFUNC(InQuart) sep \
-	EASINGFUNC(OutQuart) sep \
-	EASINGFUNC(InOutQuart) sep \
+	EASINGFUNC(InQuart) sep /* Easing_InQuart */ \
+	EASINGFUNC(OutQuart) sep /* Easing_OutQuart */ \
+	EASINGFUNC(InOutQuart) sep /* Easing_InOutQuart */ \
  \
-	EASINGFUNC(InQuint) sep \
-	EASINGFUNC(OutQuint) sep \
-	EASINGFUNC(InOutQuint) sep \
+	EASINGFUNC(InQuint) sep /* Easing_InQuint */ \
+	EASINGFUNC(OutQuint) sep /* Easing_OutQuint */ \
+	EASINGFUNC(InOutQuint) sep /* Easing_InOutQuint */ \
  \
-	EASINGFUNC(InExpo) sep \
-	EASINGFUNC(OutExpo) sep \
-	EASINGFUNC(InOutExpo) sep \
+	EASINGFUNC(InExpo) sep /* Easing_InExpo */ \
+	EASINGFUNC(OutExpo) sep /* Easing_OutExpo */ \
+	EASINGFUNC(InOutExpo) sep /* Easing_InOutExpo */ \
  \
-	EASINGFUNC(InBack) sep \
-	EASINGFUNC(OutBack) sep \
-	EASINGFUNC(InOutBack) sep
+	EASINGFUNC(InBack) sep /* Easing_InBack */ \
+	EASINGFUNC(OutBack) sep /* Easing_OutBack */ \
+	EASINGFUNC(InOutBack) sep /* Easing_InOutBack */
 
-#define EASINGFUNC(type) fixed_t Easing_ ## type (fixed_t start, fixed_t end, fixed_t t);
+#define EASINGFUNC(type) fixed_t Easing_ ## type (fixed_t t, fixed_t start, fixed_t end);
 
 EASINGFUNCLIST()
 
 #undef EASINGFUNC
+#define EASINGFUNC(type) fixed_t Easing_ ## type (fixed_t t, fixed_t start, fixed_t end, fixed_t param);
 
+EASINGFUNC(InBackParameterized) /* Easing_InBackParameterized */
+EASINGFUNC(OutBackParameterized) /* Easing_OutBackParameterized */
+EASINGFUNC(InOutBackParameterized) /* Easing_InOutBackParameterized */
+
+#undef EASINGFUNC
 #endif
-- 
GitLab