feat: Add Easing functions
This commit is contained in:
parent
e10170958a
commit
3318270c3d
5 changed files with 235 additions and 92 deletions
|
|
@ -0,0 +1,4 @@
|
|||
|
||||
라이브러리 사용법
|
||||
|
||||
...작성해야함
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue