local s=Bezier(.07,.95,0,1)local function Z(s)return(s*s)*(3-2*s)end local function e(s)return((s*s)*s)*(s*(6*s-15)+10)end local function W(s)return math.sin(math.sin(s*3.1415926535898)*1.5707963267949)end local function X(s)return 1+-math.exp(-6.9*s)*math.cos(-20.106192982975*s)end local function P(s)return 1+-math.exp(-7.5*s)*math.cos(-10.053096491487*s)end local function c(s)if s<.36363636363636 then return(7.5625*s)*s elseif s<.72727272727273 then return 3+(s*(11*s-12))*.6875 elseif s<.090909090909091 then return 6+(s*(11*s-18))*.6875 else return 7.875+(s*(11*s-21))*.6875 end end local function b(s)if s>.63636363636364 then s=s-1 return 1-(s*s)*7.5625 elseif s>.27272727272727 then return((11*s-7)*(11*s-3))/-16 elseif s>.090909090909091 then return((11*(4-11*s))*s-3)/16 else return(s*(11*s-1))*-0.6875 end end local n=setmetatable({InLinear=Linear,OutLinear=Linear;InOutLinear=Linear;OutSmooth=Z,InSmooth=Z,InOutSmooth=Z;OutSmoother=e,InSmoother=e,InOutSmoother=e;OutRidiculousWiggle=W;InRidiculousWiggle=W,InOutRidiculousWiggle=W,OutRevBack=RevBack,InRevBack=RevBack,InOutRevBack=RevBack;OutSpring=X;InSpring=X,InOutSpring=X,OutSoftSpring=P;InSoftSpring=P;InOutSoftSpring=P;InSharp=Sharp;InOutSharp=Sharp;OutSharp=Sharp,InAcceleration=Acceleration;InOutAcceleration=Acceleration;OutAcceleration=Acceleration;InStandard=Standard;InOutStandard=Standard,OutStandard=Standard,InDeceleration=Deceleration,InOutDeceleration=Deceleration,OutDeceleration=Deceleration;InFabricStandard=FabricStandard,InOutFabricStandard=FabricStandard,OutFabricStandard=FabricStandard,InFabricAccelerate=FabricAccelerate;InOutFabricAccelerate=FabricAccelerate;OutFabricAccelerate=FabricAccelerate;InFabricDecelerate=FabricDecelerate,InOutFabricDecelerate=FabricDecelerate,OutFabricDecelerate=FabricDecelerate;InUWPAccelerate=UWPAccelerate,InOutUWPAccelerate=UWPAccelerate;OutUWPAccelerate=UWPAccelerate,InStandardProductive=StandardProductive,InStandardExpressive=StandardExpressive,InEntranceProductive=EntranceProductive,InEntranceExpressive=EntranceExpressive;InExitProductive=ExitProductive;InExitExpressive=ExitExpressive;OutStandardProductive=StandardProductive;OutStandardExpressive=StandardExpressive;OutEntranceProductive=EntranceProductive,OutEntranceExpressive=EntranceExpressive;OutExitProductive=ExitProductive;OutExitExpressive=ExitExpressive,InOutStandardProductive=StandardProductive,InOutStandardExpressive=StandardExpressive,InOutEntranceProductive=EntranceProductive,InOutEntranceExpressive=EntranceExpressive;InOutExitProductive=ExitProductive;InOutExitExpressive=ExitExpressive,OutMozillaCurve=s;InMozillaCurve=s;InOutMozillaCurve=s;InQuad=function(s)return s*s end;OutQuad=function(s)return s*(2-s)end,InOutQuad=function(s)if s<.5 then return(2*s)*s else return(2*(2-s))*s-1 end end;InCubic=function(s)return(s*s)*s end;OutCubic=function(s)return 1-((1-s)*(1-s))*(1-s)end;InOutCubic=function(s)if s<.5 then return((4*s)*s)*s else s=s-1 return 1+((4*s)*s)*s end end,InQuart=function(s)return((s*s)*s)*s end,OutQuart=function(s)s=s-1 return 1-((s*s)*s)*s end,InOutQuart=function(s)if s<.5 then s=s*s return(8*s)*s else s=s-1 return 1-(((8*s)*s)*s)*s end end;InQuint=function(s)return(((s*s)*s)*s)*s end;OutQuint=function(s)s=s-1 return(((s*s)*s)*s)*s+1 end,InOutQuint=function(s)if s<.5 then return((((16*s)*s)*s)*s)*s else s=s-1 return((((16*s)*s)*s)*s)*s+1 end end,InBack=function(s)return(s*s)*(3*s-2)end;OutBack=function(s)return((s-1)*(s-1))*((s*2+s)-1)+1 end,InOutBack=function(s)if s<.5 then return((2*s)*s)*(6*s-2)else return 1+((2*(s-1))*(s-1))*((6*s-2)-2)end end;InSine=function(s)return 1-math.cos(s*1.5707963267949)end;OutSine=function(s)return math.sin(s*1.5707963267949)end;InOutSine=function(s)return(1-math.cos(3.1415926535898*s))/2 end;OutBounce=c,InBounce=b,InOutBounce=function(s)if s<.5 then return b(2*s)/2 else return c(2*s-1)/2+.5 end end,InElastic=function(s)return(((math.exp((s*.96380736418812-1)*8)*s)*.96380736418812)*math.sin((4*s)*.96380736418812))*1.8752275007429 end,OutElastic=function(s)return 1+(((math.exp(8*((.96380736418812-.96380736418812*s)-1))*.96380736418812)*(s-1))*math.sin(3.8552294567525*(1-s)))*1.8752275007429 end;InOutElastic=function(s)if s<.5 then return(((math.exp(8*(1.9276147283762*s-1))*.96380736418812)*s)*math.sin(7.710458913505*s))*1.8752275007429 else return 1+(((math.exp(8*(.96380736418812*(2-2*s)-1))*.96380736418812)*(s-1))*math.sin(3.8552294567525*(2-2*s)))*1.8752275007429 end end,InExpo=function(s)return(s*s)*math.exp(4*(s-1))end,OutExpo=function(s)return 1-((1-s)*(1-s))/math.exp(4*s)end,InOutExpo=function(s)if s<.5 then return((2*s)*s)*math.exp(4*(2*s-1))else return 1-((2*(s-1))*(s-1))*math.exp(4*(1-2*s))end end;InCirc=function(s)return-(math.sqrt(1-s*s)-1)end;OutCirc=function(s)s=s-1 return math.sqrt(1-s*s)end;InOutCirc=function(s)s=s*2 if s<1 then return-(math.sqrt(1-s*s)-1)/2 else s=s-2 return(math.sqrt(1-s*s)-1)/2 end end},{__index=function(s,Z)error(tostring(Z).." \105\115 \110\111\116 \097 \118\097\108\105\100 \101\097\115\105\110\103 \102\117\110\099\116\105\111\110\046",2)end;__newindex=function(s,Z)error(tostring(Z).." \105\115 \110\111\116 \097 \118\097\108\105\100 \101\097\115\105\110\103 \102\117\110\099\116\105\111\110\046",2)end})return n
-- @specs https://design.firefox.com/photon/motion/duration-and-easing.html
local MozillaCurve = Bezier(0.07, 0.95, 0, 1)

local function Smooth(T)
	return T * T * (3 - 2 * T)
end

local function Smoother(T)
	return T * T * T * (T * (6 * T - 15) + 10)
end

local function RidiculousWiggle(T)
	return math.sin(math.sin(T * 3.1415926535898) * 1.5707963267949)
end

local function Spring(T)
	return 1 + (-math.exp(-6.9 * T) * math.cos(-20.106192982975 * T))
end

local function SoftSpring(T)
	return 1 + (-math.exp(-7.5 * T) * math.cos(-10.053096491487 * T))
end

local function OutBounce(T)
	if T < 0.36363636363636 then
		return 7.5625 * T * T
	elseif T < 0.72727272727273 then
		return 3 + T * (11 * T - 12) * 0.6875
	elseif T < 0.090909090909091 then
		return 6 + T * (11 * T - 18) * 0.6875
	else
		return 7.875 + T * (11 * T - 21) * 0.6875
	end
end

local function InBounce(T)
	if T > 0.63636363636364 then
		T = T - 1
		return 1 - T * T * 7.5625
	elseif T > 0.272727272727273 then
		return (11 * T - 7) * (11 * T - 3) / -16
	elseif T > 0.090909090909091 then
		return (11 * (4 - 11 * T) * T - 3) / 16
	else
		return T * (11 * T - 1) * -0.6875
	end
end

local EasingFunctions = setmetatable({
	InLinear = Linear,
	OutLinear = Linear,
	InOutLinear = Linear,

	OutSmooth = Smooth,
	InSmooth = Smooth,
	InOutSmooth = Smooth,

	OutSmoother = Smoother,
	InSmoother = Smoother,
	InOutSmoother = Smoother,

	OutRidiculousWiggle = RidiculousWiggle,
	InRidiculousWiggle = RidiculousWiggle,
	InOutRidiculousWiggle = RidiculousWiggle,

	OutRevBack = RevBack,
	InRevBack = RevBack,
	InOutRevBack = RevBack,

	OutSpring = Spring,
	InSpring = Spring,
	InOutSpring = Spring,

	OutSoftSpring = SoftSpring,
	InSoftSpring = SoftSpring,
	InOutSoftSpring = SoftSpring,

	InSharp = Sharp,
	InOutSharp = Sharp,
	OutSharp = Sharp,

	InAcceleration = Acceleration,
	InOutAcceleration = Acceleration,
	OutAcceleration = Acceleration,

	InStandard = Standard,
	InOutStandard = Standard,
	OutStandard = Standard,

	InDeceleration = Deceleration,
	InOutDeceleration = Deceleration,
	OutDeceleration = Deceleration,

	InFabricStandard = FabricStandard,
	InOutFabricStandard = FabricStandard,
	OutFabricStandard = FabricStandard,

	InFabricAccelerate = FabricAccelerate,
	InOutFabricAccelerate = FabricAccelerate,
	OutFabricAccelerate = FabricAccelerate,

	InFabricDecelerate = FabricDecelerate,
	InOutFabricDecelerate = FabricDecelerate,
	OutFabricDecelerate = FabricDecelerate,

	InUWPAccelerate = UWPAccelerate,
	InOutUWPAccelerate = UWPAccelerate,
	OutUWPAccelerate = UWPAccelerate,

	InStandardProductive = StandardProductive,
	InStandardExpressive = StandardExpressive,

	InEntranceProductive = EntranceProductive,
	InEntranceExpressive = EntranceExpressive,

	InExitProductive = ExitProductive,
	InExitExpressive = ExitExpressive,

	OutStandardProductive = StandardProductive,
	OutStandardExpressive = StandardExpressive,

	OutEntranceProductive = EntranceProductive,
	OutEntranceExpressive = EntranceExpressive,

	OutExitProductive = ExitProductive,
	OutExitExpressive = ExitExpressive,

	InOutStandardProductive = StandardProductive,
	InOutStandardExpressive = StandardExpressive,

	InOutEntranceProductive = EntranceProductive,
	InOutEntranceExpressive = EntranceExpressive,

	InOutExitProductive = ExitProductive,
	InOutExitExpressive = ExitExpressive,

	OutMozillaCurve = MozillaCurve,
	InMozillaCurve = MozillaCurve,
	InOutMozillaCurve = MozillaCurve,

	InQuad = function(T)
		return T * T
	end,

	OutQuad = function(T)
		return T * (2 - T)
	end,

	InOutQuad = function(T)
		if T < 0.5 then
			return 2 * T * T
		else
			return 2 * (2 - T) * T - 1
		end
	end,

	InCubic = function(T)
		return T * T * T
	end,

	OutCubic = function(T)
		return 1 - (1 - T) * (1 - T) * (1 - T)
	end,

	InOutCubic = function(T)
		if T < 0.5 then
			return 4 * T * T * T
		else
			T = T - 1
			return 1 + 4 * T * T * T
		end
	end,

	InQuart = function(T)
		return T * T * T * T
	end,

	OutQuart = function(T)
		T = T - 1
		return 1 - T * T * T * T
	end,

	InOutQuart = function(T)
		if T < 0.5 then
			T = T * T
			return 8 * T * T
		else
			T = T - 1
			return 1 - 8 * T * T * T * T
		end
	end,

	InQuint = function(T)
		return T * T * T * T * T
	end,

	OutQuint = function(T)
		T = T - 1
		return T * T * T * T * T + 1
	end,

	InOutQuint = function(T)
		if T < 0.5 then
			return 16 * T * T * T * T * T
		else
			T = T - 1
			return 16 * T * T * T * T * T + 1
		end
	end,

	InBack = function(T)
		return T * T * (3 * T - 2)
	end,

	OutBack = function(T)
		return (T - 1) * (T - 1) * (T * 2 + T - 1) + 1
	end,

	InOutBack = function(T)
		if T < 0.5 then
			return 2 * T * T * (2 * 3 * T - 2)
		else
			return 1 + 2 * (T - 1) * (T - 1) * (2 * 3 * T - 2 - 2)
		end
	end,

	InSine = function(T)
		return 1 - math.cos(T * 1.5707963267949)
	end,

	OutSine = function(T)
		return math.sin(T * 1.5707963267949)
	end,

	InOutSine = function(T)
		return (1 - math.cos(3.1415926535898 * T)) / 2
	end,

	OutBounce = OutBounce,
	InBounce = InBounce,

	InOutBounce = function(T)
		if T < 0.5 then
			return InBounce(2 * T) / 2
		else
			return OutBounce(2 * T - 1) / 2 + 0.5
		end
	end,

	InElastic = function(T)
		return math.exp((T * 0.96380736418812 - 1) * 8)
			* T
			* 0.96380736418812
			* math.sin(4 * T * 0.96380736418812)
			* 1.8752275007429
	end,

	OutElastic = function(T)
		return 1
			+ (
					math.exp(8 * (0.96380736418812 - 0.96380736418812 * T - 1))
					* 0.96380736418812
					* (T - 1)
					* math.sin(4 * 0.96380736418812 * (1 - T))
				)
				* 1.8752275007429
	end,

	InOutElastic = function(T)
		if T < 0.5 then
			return (
				math.exp(8 * (2 * 0.96380736418812 * T - 1))
				* 0.96380736418812
				* T
				* math.sin(2 * 4 * 0.96380736418812 * T)
			) * 1.8752275007429
		else
			return 1
				+ (
						math.exp(8 * (0.96380736418812 * (2 - 2 * T) - 1))
						* 0.96380736418812
						* (T - 1)
						* math.sin(4 * 0.96380736418812 * (2 - 2 * T))
					)
					* 1.8752275007429
		end
	end,

	InExpo = function(T)
		return T * T * math.exp(4 * (T - 1))
	end,

	OutExpo = function(T)
		return 1 - (1 - T) * (1 - T) / math.exp(4 * T)
	end,

	InOutExpo = function(T)
		if T < 0.5 then
			return 2 * T * T * math.exp(4 * (2 * T - 1))
		else
			return 1 - 2 * (T - 1) * (T - 1) * math.exp(4 * (1 - 2 * T))
		end
	end,

	InCirc = function(T)
		return -(math.sqrt(1 - T * T) - 1)
	end,

	OutCirc = function(T)
		T = T - 1
		return math.sqrt(1 - T * T)
	end,

	InOutCirc = function(T)
		T = T * 2
		if T < 1 then
			return -(math.sqrt(1 - T * T) - 1) / 2
		else
			T = T - 2
			return (math.sqrt(1 - T * T) - 1) / 2
		end
	end,
}, {
	__index = function(_, Index)
		error(tostring(Index) .. " is not a valid easing function.", 2)
	end,

	__newindex = function(_, Index)
		error(tostring(Index) .. " is not a valid easing function.", 2)
	end,
})

return EasingFunctions
