diff --git a/README.md b/README.md index e69de29..ea3c29c 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,4 @@ + +라이브러리 사용법 + +...작성해야함 diff --git a/src/class.lua b/src/class.lua index 461ac34..e99151e 100644 --- a/src/class.lua +++ b/src/class.lua @@ -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) diff --git a/src/libs/AdvancedTween/EasingFunctions.lua b/src/libs/AdvancedTween/EasingFunctions.lua index 74fd386..e616ef8 100644 --- a/src/libs/AdvancedTween/EasingFunctions.lua +++ b/src/libs/AdvancedTween/EasingFunctions.lua @@ -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 diff --git a/src/libs/AdvancedTween/Stepped.lua b/src/libs/AdvancedTween/Stepped.lua index 00190af..f9d3e22 100644 --- a/src/libs/AdvancedTween/Stepped.lua +++ b/src/libs/AdvancedTween/Stepped.lua @@ -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 diff --git a/src/libs/AdvancedTween/init.lua b/src/libs/AdvancedTween/init.lua index cd5da51..24f31b6 100644 --- a/src/libs/AdvancedTween/init.lua +++ b/src/libs/AdvancedTween/init.lua @@ -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