feat: Add Easing functions

This commit is contained in:
Qwreey 2022-12-28 06:37:07 +09:00
parent e10170958a
commit 3318270c3d
5 changed files with 235 additions and 92 deletions

View file

@ -0,0 +1,4 @@
라이브러리 사용법
...작성해야함

View file

@ -155,8 +155,17 @@ function module.init(shared)
local with = value.wfunc;
local tstore = value.store;
local rawKey = value.key;
local tween = value.tvalue;
local from = value.fvalue;
local add = value.avalue;
local set = tstore[rawKey];
if set ~= nil or (rawKey:match(",") and with) then
if add then
set = set + add;
end
if from then
set = from[set];
end
if with then
set = with(tstore,set,value.key,item);
end
@ -167,9 +176,6 @@ function module.init(shared)
setProperty(item,index,dset,ClassName);
end
end
local tween = value.tvalue;
local from = value.fvalue;
local add = value.avalue;
-- adding event function
local function regFn(_,newValue,key)

View file

@ -1,23 +1,5 @@
local EasingFunctions = {}
local function reverse(Index)
return 1 - Index
end
local Linear = {} do
Linear.Run = function(Index)
return Index
end
end
EasingFunctions["Linear"] = Linear
local Circle = {} do
Circle.Run = function(Index)
return 1-((1-Index)^2)
end
end
EasingFunctions["Circle"] = Circle
local Exp2 = {} do
local MinIndex = -4
local MaxIndex = 2
@ -25,13 +7,14 @@ local Exp2 = {} do
return Index * (MaxIndex - MinIndex) + MinIndex
end
local Min = math.exp(MinIndex)
local Max = math.exp(MaxIndex) - Min
local exp = math.exp
local Min = exp(MinIndex)
local Max = exp(MaxIndex) - Min
Exp2.Reverse = true
Exp2.Run = function(Index)
-- Index ; max = 1 min = 0
return (math.exp(GetIndex(Index)) - Min) / Max
return (exp(GetIndex(Index)) - Min) / Max
end
end
EasingFunctions["Exp2"] = Exp2
@ -43,33 +26,140 @@ local Exp4 = {} do
return Index * (MaxIndex - MinIndex) + MinIndex
end
local Min = math.exp(MinIndex)
local Max = math.exp(MaxIndex) - Min
local exp = math.exp
local Min = exp(MinIndex)
local Max = exp(MaxIndex) - Min
Exp4.Reverse = true
Exp4.Run = function(Index)
-- Index ; max = 1 min = 0
return (math.exp(GetIndex(Index)) - Min) / Max
return (exp(GetIndex(Index)) - Min) / Max
end
end
EasingFunctions["Exp4"] = Exp4
local Exp2Max4 = {} do
local MinIndex = -2
local MaxIndex = 4
local GetIndex = function(Index)
return Index * (MaxIndex - MinIndex) + MinIndex
end
local Min = math.exp(MinIndex)
local Max = math.exp(MaxIndex) - Min
Exp2Max4.Reverse = true
Exp2Max4.Run = function(Index)
-- Index ; max = 1 min = 0
return (math.exp(GetIndex(Index)) - Min) / Max
local Linear = {} do
Linear.Reverse = false
Linear.Run = function(Index)
return Index
end
end
EasingFunctions["Exp2Max4"] = Exp2Max4
EasingFunctions["Linear"] = Linear
local Expo = {} do
Expo.Reverse = false
Expo.Run = function(Index)
if Index == 1 then return 1 end
if Index == 0 then return 0 end
return 1 - 2^(-10 * Index)
end
end
EasingFunctions["Expo"] = Expo
local Quint = {} do
Quint.Reverse = false
Quint.Run = function(Index)
if Index == 1 then return 1 end
if Index == 0 then return 0 end
return 1 - ((1 - Index)^5)
end
end
EasingFunctions["Quint"] = Quint
local Quart = {} do
Quart.Reverse = false
Quart.Run = function(Index)
if Index == 1 then return 1 end
if Index == 0 then return 0 end
return 1 - ((1 - Index)^4)
end
end
EasingFunctions["Quart"] = Quart
local Cubic = {} do
Cubic.Reverse = false
Cubic.Run = function(Index)
if Index == 1 then return 1 end
if Index == 0 then return 0 end
return 1 - ((1 - Index)^3)
end
end
EasingFunctions["Cubic"] = Cubic
local Quad = {} do
Quad.Reverse = false
Quad.Run = function(Index)
if Index == 1 then return 1 end
if Index == 0 then return 0 end
return 1 - ((1 - Index)^2)
end
end
EasingFunctions["Quad"] = Quad
local Sin = {} do
local pi2 = math.pi/2
local sin = math.sin
Sin.Reverse = false
Sin.Run = function(Index)
if Index == 1 then return 1 end
if Index == 0 then return 0 end
return sin(Index * pi2);
end
end
EasingFunctions["Sin"] = Sin
local Circle = {} do
local sqrt = math.sqrt
Circle.Run = function(Index)
if Index == 1 then return 1 end
if Index == 0 then return 0 end
return sqrt(1-(1-Index)^2)
end
end
EasingFunctions["Circle"] = Circle
local Back = {} do
local c1 = 1.70158
local c3 = 2.70158
Back.Reverse = false
Back.Run = function(Index)
if Index == 1 then return 1 end
if Index == 0 then return 0 end
return 1 + c3 * (Index-1)^3 + c1 * (Index-1)^2
end
end
EasingFunctions["Back"] = Back
local Elastic = {} do
local sin = math.sin
local pi = math.pi
Elastic.Reverse = false
Elastic.Run = function(Index)
if Index == 1 then return 1 end
if Index == 0 then return 0 end
return (2^(-10*Index))*(sin((Index*10-0.75)*(2*pi/3)))+1
end
end
EasingFunctions["Elastic"] = Elastic
local Bounce = {} do
local n1 = 7.5625
local d1 = 2.75
Bounce.Reverse = false
Bounce.Run = function(Index)
if Index > 0.995 then return 1 end
if Index < 0.005 then return 0 end
if Index < 1 / d1 then
return n1 * Index^2
elseif Index < 2 / d1 then
return n1 * (Index - 1.5/d1)^2 + 0.75
elseif Index < 2.5 / d1 then
return n1 * (Index - 2.25/d1)^2 + 0.9375
else
return n1 * (Index - 2.625/d1)^2 + 0.984375
end
end
end
EasingFunctions["Bounce"] = Bounce
return EasingFunctions

View file

@ -9,15 +9,27 @@ local IsRoblox = version and version() or nil
local module = {}
function module.BindStep(StepFunction)
if IsRoblox then
if module.Connection then
error("Function was binded already")
end
local RunService = game:GetService("RunService")
if RunService:IsStudio() and (not RunService:IsRunning()) and RunService:IsEdit() then
RunService.Heartbeat:Connect(StepFunction)
module.Connection = RunService.Heartbeat:Connect(StepFunction)
else
RunService.Stepped:Connect(StepFunction)
-- RunService:BindToRenderStep("advancedTween",1,StepFunction)
module.Connection = RunService.RenderStepped:Connect(StepFunction)
end
else
-- do something here
end
end
function module.UnbindAll()
if not module.Connection then
error("Function was not binded yet")
end
module.Connection:Disconnect()
module.Connection = nil
end
return module

View file

@ -16,6 +16,7 @@ local EasingFunctions = require(script and script.EasingFunctions or "EasingFunc
local Stepped = require(script and script.Stepped or "Stepped")
local BindedFunctions = {} -- 애니메이션을 위해 프레임에 연결된 함수들
local FunctionTargetItem = setmetatable({},{__mode="kv"}) -- 함수가 타겟으로 하는 아이템
module.PlayIndex = setmetatable({},{__mode = "k"}) -- 애니메이션 실행 스택 저장하기
-- PlayIndex[Item][Property] = 0 or nil <= 트윈중이지 않은 속성
@ -25,12 +26,21 @@ module.PlayIndex = setmetatable({},{__mode = "k"}) -- 애니메이션 실행 스
-- Easing 스타일
------------------------------------
module.EasingFunctions = {
--// for Autocomplete
Linear = EasingFunctions.Linear; --// 직선
Circle = EasingFunctions.Circle; --// 사분원
Exp2 = EasingFunctions.Exp2; --// 덜 가파른 지수 그래프
Exp4 = EasingFunctions.Exp4; --// 더 가파른 지수 그래프
Exp2Max4 = EasingFunctions.Exp2Max4; --// 적당히 가파른 지수 그래프
Linear = EasingFunctions.Linear; ---직선, Linear. i=x, x=0 ~ 1
Quint = EasingFunctions.Quint; ---5제곱, Quint. (^5) i=1-(1-x)^5, x=0 ~ 1
Quart = EasingFunctions.Quart; ---4제곱, Quart. (^4) i=1-(1-x)^4, x=0 ~ 1
Cubic = EasingFunctions.Cubic; ---3제곱, Cubic. (^3) i=1-(1-x)^3, x=0 ~ 1
Quad = EasingFunctions.Quad; ---2제곱, Quad. (^2) i=1-(1-x)^2, x=0 ~ 1
Sin = EasingFunctions.Sin; ---사인파, Sin. i=sin(x*pi/2), x=0 ~ 1
Circle = EasingFunctions.Circle; ---사분원, Circle. i=sqrt(1-(1-x)^2), x=0 ~ 1
Expo = EasingFunctions.Expo; ---지수함수, Expo. i=1-2^(-10*x), x=0~1
Elastic = EasingFunctions.Elastic; ---튀어오름, Elastic.
Bounce = EasingFunctions.Bounce; ---통통거림, Bounce
-- Old things
Exp2 = EasingFunctions.Exp2; ---덜 가파른 지수. i=math.exp(x), x=-4 ~ 2
Exp4 = EasingFunctions.Exp4; ---더 가파른 지수. i=math.exp(x), x=-4 ~ 4
Exp2Max4 = EasingFunctions.Exp2; ---@deprecated
}
for i,v in pairs(EasingFunctions) do
module.EasingFunctions[i] = v
@ -78,21 +88,21 @@ function LerpProperties(Item,Old,New,Alpha,Setter)
)
)
elseif DefaultItems[Type] then
Item[Property] = Lerp(OldValue,NewValue,Alpha)
Value = Lerp(OldValue,NewValue,Alpha)
elseif Type == "UDim2" then
Item[Property] = UDim2.new(
Value = UDim2.new(
Lerp(OldValue.X.Scale ,NewValue.X.Scale ,Alpha),
Lerp(OldValue.X.Offset,NewValue.X.Offset,Alpha),
Lerp(OldValue.Y.Scale ,NewValue.Y.Scale ,Alpha),
Lerp(OldValue.Y.Offset,NewValue.Y.Offset,Alpha)
)
elseif Type == "UDim" then
Item[Property] = UDim.new(
Value = UDim.new(
Lerp(OldValue.Scale ,NewValue.Scale ),
Lerp(OldValue.Offset,NewValue.Offset)
)
elseif Type == "Color3" then
Item[Property] = Color3.fromRGB(
Value = Color3.fromRGB(
Lerp(OldValue.r*255,NewValue.r*255),
Lerp(OldValue.g*255,NewValue.g*255),
Lerp(OldValue.b*255,NewValue.b*255)
@ -108,7 +118,7 @@ function LerpProperties(Item,Old,New,Alpha,Setter)
)
end
if Setter then
Setter(Item,Property,NewValue)
Setter(Item,Property,Value)
else
Item[Property] = Value
end
@ -139,20 +149,32 @@ function module.RunTween(Item,Data,Properties,Ended,OnStepped,Setter,Getter,_)
local EndTime = clock() + Time
-- 플레이 인덱스 저장
local ThisPlayIndex = module.PlayIndex[Item] or {}
module.PlayIndex[Item] = ThisPlayIndex
-- 예전의 트윈을 덮어쓰고 현재 값을 저장함
local NowAnimationIndex = {}
local LastProperties = {}
for Property,_ in pairs(Properties) do
if Getter then
LastProperties[Property] = Getter(Property)
else
LastProperties[Property] = Item[Property]
local ItemPlayIndex = module.PlayIndex[Item]
if ItemPlayIndex then
for _,stepFunc in ipairs(BindedFunctions) do
if FunctionTargetItem[stepFunc] == Item then
stepFunc() -- 해당 애니메이션을 미리 계산해서 지금 위치를 저장
end
end
ThisPlayIndex[Property] = ThisPlayIndex[Property] ~= nil and ThisPlayIndex[Property] + 1 or 1
NowAnimationIndex[Property] = ThisPlayIndex[Property]
ItemPlayIndex = module.PlayIndex[Item]
end
if not ItemPlayIndex then
ItemPlayIndex = {}
module.PlayIndex[Item] = ItemPlayIndex
end
-- 예전의 트윈을 덮어쓰고 현재 값을 저장함 !이전 트윈은 파기됨
local ThisPlayIndex = {}
local LastProperties = {}
for PropertyName,_ in pairs(Properties) do
if Getter then
LastProperties[PropertyName] = Getter(Item,PropertyName)
else
LastProperties[PropertyName] = Item[PropertyName]
end
local PlayIndex = (ItemPlayIndex[PropertyName] or 0) + 1
ItemPlayIndex[PropertyName] = PlayIndex
ThisPlayIndex[PropertyName] = PlayIndex
end
-- 이징 효과 가져오기
@ -160,6 +182,10 @@ function module.RunTween(Item,Data,Properties,Ended,OnStepped,Setter,Getter,_)
local Easing do
local Data_Easing = Data.Easing or EasingFunctions.Exp2
local Data_EasingType = type(Data_Easing)
if Data_EasingType == "string" then
Data_Easing = EasingFunctions[Data_Easing]
Data_EasingType = "table"
end
Easing = (Data_EasingType == "function" and Data_Easing) or (Data_EasingType == "table" and Data_Easing.Run)
if Data_EasingType == "table" and Data_Easing.Reverse then
Direction = Direction == "Out" and "In" or "Out"
@ -171,11 +197,15 @@ function module.RunTween(Item,Data,Properties,Ended,OnStepped,Setter,Getter,_)
if CallBack then
for FncIndex,Fnc in pairs(CallBack) do
if type(Fnc) ~= "function" or (type(tonumber(FncIndex)) ~= "number" and FncIndex ~= "*") then
warn(("Unprocessable callback function got, Ignored.\n - key: %s value: %s"):format(tostring(Fnc),tostring(FncIndex)))
warn(
("Unprocessable callback function got, Ignored.\n - key: %s value: %s")
:format(tostring(Fnc),tostring(FncIndex))
)
CallBack[FncIndex] = nil
end
end
end
-- 스탭핑
local Step
Step = function()
@ -185,6 +215,18 @@ function module.RunTween(Item,Data,Properties,Ended,OnStepped,Setter,Getter,_)
return
end
-- 다른 트윈이 속성을 바꾸고 있다면(이후 트윈이) 그 속성을 건들지 않도록 없엠
local StopByOther = true
for PropertyName,PlayIndex in pairs(ThisPlayIndex) do
if PlayIndex ~= ItemPlayIndex[PropertyName] then
LastProperties[PropertyName] = nil
Properties[PropertyName] = nil
ThisPlayIndex[PropertyName] = nil
else
StopByOther = false
end
end
local Now = clock()
local Index = 1 - (EndTime - Now) / Time
local Alpha = Direction == "Out" and Easing(Index) or (1 - Easing(1 - Index))
@ -198,18 +240,6 @@ function module.RunTween(Item,Data,Properties,Ended,OnStepped,Setter,Getter,_)
Setter
)
-- 다른 트윈이 속성을 바꾸고 있다면(이후 트윈이) 그 속성을 건들지 않도록 없엠
local StopByOther = true
for Property,Index in pairs(NowAnimationIndex) do
if Index ~= ThisPlayIndex[Property] then
LastProperties[Property] = nil
Properties[Property] = nil
NowAnimationIndex[Property] = nil
else
StopByOther = false
end
end
-- 만약 다른 트윈이 지금 트윈하고 있는 속성을 모두 먹은경우 현재 트윈을 삭제함
if StopByOther then
remove(BindedFunctions,find(BindedFunctions,Step))
@ -219,15 +249,11 @@ function module.RunTween(Item,Data,Properties,Ended,OnStepped,Setter,Getter,_)
-- 끝남
if Now >= EndTime then
for Property,_ in pairs(Properties) do
ThisPlayIndex[Property] = 0
ItemPlayIndex[Property] = 0
end
local PlayIndexLen = 0
for _,_ in pairs(ThisPlayIndex) do
PlayIndexLen = PlayIndexLen + 1
end
if PlayIndexLen == 0 then
ThisPlayIndex = nil
if next(ItemPlayIndex) then
module.PlayIndex[Item] = nil
end
remove(BindedFunctions,find(BindedFunctions,Step))
@ -264,6 +290,7 @@ function module.RunTween(Item,Data,Properties,Ended,OnStepped,Setter,Getter,_)
-- 스캐줄에 등록
insert(BindedFunctions,Step)
FunctionTargetItem[Step] = Item
end
-- 여러개의 개체를 트윈시킴
@ -319,13 +346,17 @@ end
-- ./Stepped.lua 에서 연결점 편집 가능
-- roblox 는 이미 연결되어 있음
function module.Stepped()
if not BindedFunctions[1] then
return;
end
for _,Function in ipairs(BindedFunctions) do
Function()
if not FunctionTargetItem[Function] then
remove(BindedFunctions,find(BindedFunctions,Function))
else
Function()
end
end
end
Stepped.BindStep(module.Stepped)
script.Destroying:Connect(function()
Stepped.UnbindAll()
end)
return module