Adding advanced tween module for tweening objects and fixed some bukket error
This commit is contained in:
parent
f8bde6f4e8
commit
921af23d66
10 changed files with 529 additions and 91 deletions
|
|
@ -7,6 +7,15 @@
|
||||||
"Quad": {
|
"Quad": {
|
||||||
"$path": "src"
|
"$path": "src"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"StarterGui": {
|
||||||
|
"$className": "StarterGui",
|
||||||
|
"QuadTesting": {
|
||||||
|
"$className": "ScreenGui",
|
||||||
|
"testScript": {
|
||||||
|
"$path": "testScript.client.lua"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
67
readme.lua
Normal file
67
readme.lua
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
-- 이렇게 모듈을 부를 수 있다, 뒤에 if 가 붇은것은 자동완성이 뜨도록 하기 위해서 사용된다
|
||||||
|
---@module "src/init.lua"
|
||||||
|
local quad = require(game.ReplicatedStorage:WaitForChild "Quad");
|
||||||
|
local render = quad.init();
|
||||||
|
-- init 함수를 이용해 여러 스크립트가 이 모듈을 호출해도 완전히 별계의
|
||||||
|
-- 환경에서 실행될 수 있도록 만든다, init 를 호출하면 완전히 새로운 store 와 style
|
||||||
|
-- 등을 가진 모듈을 새로 생성한다
|
||||||
|
|
||||||
|
-- 하위 모듈을 이렇게 부른다
|
||||||
|
local class = render.class;
|
||||||
|
local mount = render.mount;
|
||||||
|
local store = render.store;
|
||||||
|
|
||||||
|
-- 오브젝트를 이렇게 불러온다
|
||||||
|
local frame = class "Frame"; -- 이렇게 원하는 오브젝트를 불러올 수 있다
|
||||||
|
local text = class "TextLabel";
|
||||||
|
text.TextSize = 17; -- 이렇게 오브젝트의 기본값도 정할 수 있다
|
||||||
|
text.Size = UDim2.new(1,0,0,30);
|
||||||
|
local titleText = class "TextLabel";
|
||||||
|
-- 당연 이렇게 똑같은 className 을 가진 오브젝트를 여러번 import 도 된다
|
||||||
|
-- 다른 임포트에서 설정한 기본값은 여기에 적용되지 않는다
|
||||||
|
|
||||||
|
local gui = script.Parent;
|
||||||
|
local app = mount(gui,frame "testFrame" { -- mount 로 트리를 마운트한다, 이후 app 에서 unmount 호출가능
|
||||||
|
Size = UDim2.fromOffset(120,60);
|
||||||
|
Position = UDim2.fromScale(0.5,0.5);
|
||||||
|
AnchorPoint = Vector2.new(0.5,0.5);
|
||||||
|
text "texts" { -- 이렇게 단순히 child 개체를 만들 수 있다
|
||||||
|
Text = "We can make ui like this";
|
||||||
|
};
|
||||||
|
text "texts" {
|
||||||
|
Position = UDim2.fromOffset(0,30);
|
||||||
|
Text = "qweiufnwlqef";
|
||||||
|
};
|
||||||
|
titleText { -- 아이디를 명명하지 않아도 오브젝트를 바로 만들 수 있다
|
||||||
|
Text = "test";
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
print(store.getObject("texts"));
|
||||||
|
-- getObject 를 호출하면 해당 id 로 명명된 오브젝트중
|
||||||
|
-- 가장 처음으로 생성된 객체를 반환한다
|
||||||
|
store.getObjects("texts"):each(function(index,this)
|
||||||
|
this.Text = "이렇게 모든 택스트를 한꺼번에 바꿀 수도 있습니다";
|
||||||
|
end);
|
||||||
|
-- getObjects 를 이용하면 해당 id 로 명명된 오브젝트가 담긴 array 를 가져온다
|
||||||
|
-- for 을 돌릴 수 있지만 each 를 이용해 async 된 작업을 수행할 수 있다
|
||||||
|
store.getObjects("texts"):eachSync(function(index,this)
|
||||||
|
this.Text = "또한, 기본적으로 Aync 를 이용하기 때문에 순차적인 실행이 필요한 경우 Sync 를 붇여야합니다";
|
||||||
|
end);
|
||||||
|
-- sync 를 하면 일반 스크립트를 실행하는것 처럼 순차적으로 실행되도록 만들 수도 있다
|
||||||
|
-- 이 때 순서는 먼저 생생된 순서이다, 항상 같음을 유지한다는 보장이 없으므로 순서가 중요한경우
|
||||||
|
-- 직접 for 을 이용해 순서 검증을 한 뒤 task 를 수행해야한다
|
||||||
|
|
||||||
|
-- 이렇게 어떤 오브젝트를 가지고 task 수행하는 thread 를 만들 수 있다
|
||||||
|
do local this = store.getObject("testFrame");
|
||||||
|
spawn(function ()
|
||||||
|
local flip = false;
|
||||||
|
while wait(0.5) do
|
||||||
|
flip = not flip;
|
||||||
|
this.BackgroundTransparency = flip and 1 or 0;
|
||||||
|
end
|
||||||
|
end);
|
||||||
|
end
|
||||||
|
|
||||||
|
app.unmount(); -- 트리의 객체들을 모두 파기한다, 플러그인에서 unload 같은곳에 쓰는 함수
|
||||||
|
return app;
|
||||||
|
|
@ -13,11 +13,14 @@ local module = {};
|
||||||
|
|
||||||
function module.init(shared)
|
function module.init(shared)
|
||||||
local new = {};
|
local new = {};
|
||||||
local bind = shared.event.bind;
|
local event = shared.event; ---@module "src.event"
|
||||||
local addObject = shared.store.addObject;
|
local bind = event.bind;
|
||||||
local storeNew = shared.store.new;
|
local store = shared.store; ---@module "src.store"
|
||||||
local mount = shared.mount;
|
local addObject = store.addObject;
|
||||||
local getHolder = shared.mount.getHolder;
|
local storeNew = store.new;
|
||||||
|
local mount = shared.mount; ---@module "src.mount"
|
||||||
|
local getHolder = mount.getHolder;
|
||||||
|
local advancedTween = shared.advancedTween; ---@module "src.libs.AdvancedTween"
|
||||||
|
|
||||||
-- make object that from instance, class and more
|
-- make object that from instance, class and more
|
||||||
function new.make(ClassName,...) -- render object
|
function new.make(ClassName,...) -- render object
|
||||||
|
|
@ -89,15 +92,26 @@ function module.init(shared)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local tween = value.tvalue;
|
local tween = value.tvalue;
|
||||||
|
local from = value.fvalue;
|
||||||
|
|
||||||
-- adding event function
|
-- adding event function
|
||||||
local function regFn(newValue,store)
|
local function regFn(newValue,store)
|
||||||
|
if from then
|
||||||
|
newValue = from[newValue];
|
||||||
|
end
|
||||||
if with then
|
if with then
|
||||||
newValue = with(newValue,item,store);
|
newValue = with(newValue,item,store);
|
||||||
end
|
end
|
||||||
|
if tween then
|
||||||
|
if not advancedTween then
|
||||||
|
return wran "module 'AdvancedTween' needs to be loaded for tween properties but it is not founded on 'src.libs'. you should adding that to src.libs directory";
|
||||||
|
end
|
||||||
|
advancedTween.RunTween(item,tween,{[index] = newValue});
|
||||||
|
else
|
||||||
item[index] = newValue;
|
item[index] = newValue;
|
||||||
end
|
end
|
||||||
value.register(regFn);
|
end
|
||||||
|
value:register(regFn);
|
||||||
|
|
||||||
-- this is using hacky of roblox instance
|
-- this is using hacky of roblox instance
|
||||||
-- this is will keep reference from week table until
|
-- this is will keep reference from week table until
|
||||||
|
|
@ -208,7 +222,7 @@ function module.init(shared)
|
||||||
if child then
|
if child then
|
||||||
for _,v in pairs(child) do
|
for _,v in pairs(child) do
|
||||||
if v then
|
if v then
|
||||||
((type(v) == table and rawget(v,"__object") or v).Parent = object;
|
((type(v) == "table") and rawget(v,"__object") or v).Parent = object;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
10
src/init.lua
10
src/init.lua
|
|
@ -24,15 +24,17 @@ frame{
|
||||||
]]
|
]]
|
||||||
|
|
||||||
local require = require(script.require);
|
local require = require(script.require);
|
||||||
local event = require("event"); ---@module "src.event"
|
local event = require "event"; ---@module "src.event"
|
||||||
local store = require("store"); ---@module "src.store"
|
local store = require "store"; ---@module "src.store"
|
||||||
--local style = require("style");
|
--local style = require("style");
|
||||||
local class = require("class"); ---@module "src.class"
|
local class = require "class"; ---@module "src.class"
|
||||||
local mount = require("mount"); ---@module "src.mount"
|
local mount = require "mount"; ---@module "src.mount"
|
||||||
|
local _,advancedTween = pcall(require,"src.libs.AdvancedTween"); ---@module "src.libs.AdvancedTween"
|
||||||
|
|
||||||
function module.init()
|
function module.init()
|
||||||
local this = {items = {}};
|
local this = {items = {}};
|
||||||
|
|
||||||
|
this.advancedTween = type(advancedTween) == "table" and advancedTween;
|
||||||
this.event = event.init(this);
|
this.event = event.init(this);
|
||||||
this.store = store.init(this);
|
this.store = store.init(this);
|
||||||
--this.style = style.init(this);
|
--this.style = style.init(this);
|
||||||
|
|
|
||||||
23
src/libs/AdvancedTween/BezierCurves.lua
Normal file
23
src/libs/AdvancedTween/BezierCurves.lua
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
local module = {}
|
||||||
|
|
||||||
|
function Lerp(Alpha,Point1,Point2)
|
||||||
|
return Point1 + ( (Point2 - Point1) * Alpha )
|
||||||
|
end
|
||||||
|
|
||||||
|
function module.Bezier(Alpha,...)
|
||||||
|
local New = {}
|
||||||
|
local Len = #{...}
|
||||||
|
|
||||||
|
for i = 1,Len do
|
||||||
|
if i ~= 1 then
|
||||||
|
New[#New+1] = Lerp(Alpha,select(...,i-1),select(...,i))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if Len <= 2 then
|
||||||
|
return New[1]
|
||||||
|
end
|
||||||
|
return module.Bezier(Alpha,unpack(New))
|
||||||
|
end
|
||||||
|
|
||||||
|
return module
|
||||||
75
src/libs/AdvancedTween/EasingFunctions.lua
Normal file
75
src/libs/AdvancedTween/EasingFunctions.lua
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
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
|
||||||
|
local GetIndex = function(Index)
|
||||||
|
return Index * (MaxIndex - MinIndex) + MinIndex
|
||||||
|
end
|
||||||
|
|
||||||
|
local Min = math.exp(MinIndex)
|
||||||
|
local Max = math.exp(MaxIndex) - Min
|
||||||
|
|
||||||
|
Exp2.Reverse = true
|
||||||
|
Exp2.Run = function(Index)
|
||||||
|
-- Index ; max = 1 min = 0
|
||||||
|
return (math.exp(GetIndex(Index)) - Min) / Max
|
||||||
|
end
|
||||||
|
end
|
||||||
|
EasingFunctions["Exp2"] = Exp2
|
||||||
|
|
||||||
|
local Exp4 = {} do
|
||||||
|
local MinIndex = -4
|
||||||
|
local MaxIndex = 4
|
||||||
|
local GetIndex = function(Index)
|
||||||
|
return Index * (MaxIndex - MinIndex) + MinIndex
|
||||||
|
end
|
||||||
|
|
||||||
|
local Min = math.exp(MinIndex)
|
||||||
|
local Max = math.exp(MaxIndex) - Min
|
||||||
|
|
||||||
|
Exp4.Reverse = true
|
||||||
|
Exp4.Run = function(Index)
|
||||||
|
-- Index ; max = 1 min = 0
|
||||||
|
return (math.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
|
||||||
|
end
|
||||||
|
end
|
||||||
|
EasingFunctions["Exp2Max4"] = Exp2Max4
|
||||||
|
|
||||||
|
return EasingFunctions
|
||||||
23
src/libs/AdvancedTween/Stepped.lua
Normal file
23
src/libs/AdvancedTween/Stepped.lua
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
local IsRoblox = version and version() or nil
|
||||||
|
|
||||||
|
-- 로블록스 이외의 다른 lua 플렛폼을 위한 바인드 스탭,
|
||||||
|
-- 여기에다 프레임 앞에 실행되는 이벤트를 핸들링해서 StepFunction 을
|
||||||
|
-- 연동해주면 됨,
|
||||||
|
|
||||||
|
-- 이 함수는 한 프레임마다 트윈들을 가져와서 실행시켜줌, (만약 트윈 효과가 하나도 없으면 그냥 건너뜀)
|
||||||
|
|
||||||
|
local module = {}
|
||||||
|
function module.BindStep(StepFunction)
|
||||||
|
if IsRoblox then
|
||||||
|
local RunService = game:GetService("RunService")
|
||||||
|
if RunService:IsStudio() and (not RunService:IsRunning()) and RunService:IsEdit() then
|
||||||
|
RunService.Heartbeat:Connect(StepFunction)
|
||||||
|
else
|
||||||
|
RunService.Stepped:Connect(StepFunction)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- do something here
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return module
|
||||||
280
src/libs/AdvancedTween/init.lua
Normal file
280
src/libs/AdvancedTween/init.lua
Normal file
|
|
@ -0,0 +1,280 @@
|
||||||
|
local module = {}
|
||||||
|
|
||||||
|
------------------------------------
|
||||||
|
-- 기본함수, 필요 모듈 가져오기
|
||||||
|
------------------------------------
|
||||||
|
local type = typeof or type
|
||||||
|
local clock = os.clock
|
||||||
|
local tonumber = tonumber
|
||||||
|
|
||||||
|
local script = script
|
||||||
|
local EasingFunctions = require(script and script.EasingFunctions or "EasingFunctions")
|
||||||
|
local Stepped = require(script and script.Stepped or "Stepped")
|
||||||
|
|
||||||
|
local BindedFunctions = {} -- 애니메이션을 위해 프레임에 연결된 함수들
|
||||||
|
|
||||||
|
module.PlayIndex = setmetatable({},{__mode = "k"}) -- 애니메이션 실행 스택 저장하기
|
||||||
|
-- PlayIndex[Item][Property] = 0 or nil <= 트윈중이지 않은 속성
|
||||||
|
-- PlayIndex[Item][Property] = 1... <= 트윈중인 속성
|
||||||
|
|
||||||
|
------------------------------------
|
||||||
|
-- Easing 스타일
|
||||||
|
------------------------------------
|
||||||
|
module.EasingFunctions = {
|
||||||
|
--// for Autocomplete
|
||||||
|
Linear = EasingFunctions.Linear; --// 직선
|
||||||
|
Circle = EasingFunctions.Circle; --// 사분원
|
||||||
|
Exp2 = EasingFunctions.Exp2; --// 덜 가파른 지수 그래프
|
||||||
|
Exp4 = EasingFunctions.Exp4; --// 더 가파른 지수 그래프
|
||||||
|
Exp2Max4 = EasingFunctions.Exp2Max4; --// 적당히 가파른 지수 그래프
|
||||||
|
}
|
||||||
|
for i,v in pairs(EasingFunctions) do
|
||||||
|
module.EasingFunctions[i] = v
|
||||||
|
end
|
||||||
|
|
||||||
|
module.EasingDirection = {
|
||||||
|
Out = "Out"; -- 반전된 방향
|
||||||
|
In = "In" ; -- 기본방향
|
||||||
|
}
|
||||||
|
|
||||||
|
------------------------------------
|
||||||
|
-- Lerp 함수
|
||||||
|
------------------------------------
|
||||||
|
-- 이중 선형, Alpha 를 받아서 값을 구해옴
|
||||||
|
function Lerp(start,goal,alpha)
|
||||||
|
return start + ((goal - start) * alpha)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 기본적으로 로블록스에 있는 클래스중, + - * / 과 같은 연산자 처리 메타 인덱스가 있는것들
|
||||||
|
local DefaultItems = {
|
||||||
|
["Vector2"] = true;
|
||||||
|
["Vector3"] = true;
|
||||||
|
["CFrame" ] = true;
|
||||||
|
["number" ] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
-- 예전 값,목표 값,알파를 주고 각각 해당하는 속성에 입력해줌
|
||||||
|
-- 기본적으로 모든 속성값 적용은 여기에서 이루워짐
|
||||||
|
function LerpProperties(Item,Old,New,Alpha)
|
||||||
|
for Property,OldValue in pairs(Old) do
|
||||||
|
local NewValue = New[Property]
|
||||||
|
if NewValue ~= nil then
|
||||||
|
local Type = type(OldValue)
|
||||||
|
if DefaultItems[Type] then
|
||||||
|
Item[Property] = Lerp(OldValue,NewValue,Alpha)
|
||||||
|
elseif Type == "UDim2" then
|
||||||
|
Item[Property] = 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(
|
||||||
|
Lerp(OldValue.Scale ,NewValue.Scale ),
|
||||||
|
Lerp(OldValue.Offset,NewValue.Offset)
|
||||||
|
)
|
||||||
|
elseif Type == "Color3" then
|
||||||
|
Item[Property] = Color3.fromRGB(
|
||||||
|
Lerp(OldValue.r*255,NewValue.r*255),
|
||||||
|
Lerp(OldValue.g*255,NewValue.g*255),
|
||||||
|
Lerp(OldValue.b*255,NewValue.b*255)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
------------------------------------
|
||||||
|
-- 모듈 함수 지정
|
||||||
|
------------------------------------
|
||||||
|
-- 트윈 메서드 지정, 트윈을 만들게 됨
|
||||||
|
-- Item : 트윈할 인스턴트
|
||||||
|
-- Data : 트윈 정보들 (태이블)
|
||||||
|
--Data.Time (in seconds, you can use 0.5 .. etc)
|
||||||
|
--Data.Easing (function)
|
||||||
|
--Data.Direction ("Out" , "In")
|
||||||
|
--Data.CallBack 콜백 함수들(태이블), 예시 :
|
||||||
|
--Data.CallBack[0.5] = function() end 다음과 같이 쓰면 인덱스가 정확히 0.5 가 되는 순간(시간이 아니라 이징 함수에 의해 나온 값이 같아지는 순간)
|
||||||
|
--해당 함수가 실행됨
|
||||||
|
--Properties : 트윈할 속성과 목표값 예시 :
|
||||||
|
--Data.Properties.Position = UDim2.new(1,0,1,0) 처럼 하면 Position 속성의 목표를 1,0,1,0 으로 지정
|
||||||
|
function module.RunTween(Item,Data,Properties,Ended)
|
||||||
|
-- 시간 저장
|
||||||
|
local Time = Data.Time or 1
|
||||||
|
local EndTime = clock() + Time
|
||||||
|
|
||||||
|
-- 플레이 인덱스 저장
|
||||||
|
local ThisPlayIndex = module.PlayIndex[Item] or {}
|
||||||
|
module.PlayIndex[Item] = ThisPlayIndex
|
||||||
|
|
||||||
|
-- 예전의 트윈을 덮어쓰고 현재 값을 저장함
|
||||||
|
local NowAnimationIndex = {}
|
||||||
|
local LastProperties = {}
|
||||||
|
for Property,_ in pairs(Properties) do
|
||||||
|
LastProperties[Property] = Item[Property]
|
||||||
|
ThisPlayIndex[Property] = ThisPlayIndex[Property] ~= nil and ThisPlayIndex[Property] + 1 or 1
|
||||||
|
NowAnimationIndex[Property] = ThisPlayIndex[Property]
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 이징 효과 가져오기
|
||||||
|
local Direction = Data.Direction or "Out"
|
||||||
|
local Easing do
|
||||||
|
local Data_Easing = Data.Easing or EasingFunctions.Exp2
|
||||||
|
local Data_EasingType = type(Data_Easing)
|
||||||
|
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"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 중간중간 실행되는 함수 확인
|
||||||
|
local CallBack = Data.CallBack
|
||||||
|
if CallBack then
|
||||||
|
for FncIndex,Fnc in pairs(CallBack) do
|
||||||
|
if type(Fnc) ~= "function" or type(tonumber(FncIndex)) ~= "number" then
|
||||||
|
CallBack[FncIndex] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- 스탭핑
|
||||||
|
local Step
|
||||||
|
Step = function()
|
||||||
|
-- 아에 멈추게 되는 경우
|
||||||
|
if module.PlayIndex[Item] == nil then
|
||||||
|
table.remove(BindedFunctions,table.find(BindedFunctions,Step))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
local Now = clock()
|
||||||
|
local Index = 1 - (EndTime - Now) / Time
|
||||||
|
|
||||||
|
-- 속성 Lerp 수행
|
||||||
|
if Direction == "Out" then
|
||||||
|
LerpProperties(
|
||||||
|
Item,
|
||||||
|
LastProperties,
|
||||||
|
Properties,
|
||||||
|
Easing(Index)
|
||||||
|
)
|
||||||
|
else
|
||||||
|
LerpProperties(
|
||||||
|
Item,
|
||||||
|
LastProperties,
|
||||||
|
Properties,
|
||||||
|
1 - Easing(1 - Index)
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 다른 트윈이 속성을 바꾸고 있다면(이후 트윈이) 그 속성을 건들지 않도록 없엠
|
||||||
|
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
|
||||||
|
table.remove(BindedFunctions,table.find(BindedFunctions,Step))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 끝남
|
||||||
|
if Now >= EndTime then
|
||||||
|
for Property,_ in pairs(Properties) do
|
||||||
|
ThisPlayIndex[Property] = 0
|
||||||
|
end
|
||||||
|
|
||||||
|
local PlayIndexLen = 0
|
||||||
|
for _,_ in pairs(ThisPlayIndex) do
|
||||||
|
PlayIndexLen = PlayIndexLen + 1
|
||||||
|
end
|
||||||
|
if PlayIndexLen == 0 then
|
||||||
|
ThisPlayIndex = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
table.remove(BindedFunctions,table.find(BindedFunctions,Step))
|
||||||
|
Index = 1
|
||||||
|
if Ended then
|
||||||
|
Ended()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 중간 중간 함수 배정된것 실행
|
||||||
|
if CallBack then
|
||||||
|
for FncIndex,Fnc in pairs(CallBack) do
|
||||||
|
if tonumber(FncIndex) <= Index then
|
||||||
|
Fnc()
|
||||||
|
CallBack[FncIndex] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 스캐줄에 등록
|
||||||
|
table.insert(BindedFunctions,Step)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 여러개의 개체를 트윈시킴
|
||||||
|
function module.RunTweens(Items,Data,Properties,Ended)
|
||||||
|
local First = true
|
||||||
|
for _,Item in pairs(Items) do
|
||||||
|
module.RunTween(Item,Data,Properties,First and Ended)
|
||||||
|
First = false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 트윈 멈추기
|
||||||
|
function module.StopTween(Item)
|
||||||
|
module.PlayIndex[Item] = nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 해당 개체가 트윈중인지 반환
|
||||||
|
function module.IsTweening(Item)
|
||||||
|
if module.PlayIndex[Item] == nil then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
for Property,Index in pairs(module.PlayIndex[Item]) do
|
||||||
|
if Index ~= 0 then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 해당 개체의 해당 프로퍼티가 트윈중인지 반환
|
||||||
|
function module.IsPropertyTweening(Item,PropertyName)
|
||||||
|
if module.PlayIndex[Item] == nil then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
if module.PlayIndex[Item][PropertyName] == nil then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
return module.PlayIndex[Item][PropertyName] ~= 0
|
||||||
|
end
|
||||||
|
|
||||||
|
------------------------------------
|
||||||
|
-- 프레임 연결
|
||||||
|
------------------------------------
|
||||||
|
-- 1 프레임마다 실행되도록 해야되는 함수
|
||||||
|
-- ./Stepped.lua 에서 연결점 편집 가능
|
||||||
|
-- roblox 는 이미 연결되어 있음
|
||||||
|
function module.Stepped()
|
||||||
|
if not BindedFunctions[1] then
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
for _,Function in ipairs(BindedFunctions) do
|
||||||
|
Function()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
Stepped.BindStep(module.Stepped)
|
||||||
|
|
||||||
|
return module
|
||||||
|
|
@ -84,6 +84,25 @@ function module.init(shared)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local registerMt = {
|
||||||
|
register = function (s,efunc)
|
||||||
|
insert(s.event,efunc);
|
||||||
|
end;
|
||||||
|
with = function (s,efunc)
|
||||||
|
return setmetatable({wfunc = efunc},{__index = s});
|
||||||
|
end;
|
||||||
|
default = function (s,value)
|
||||||
|
return setmetatable({dvalue = value},{__index = s});
|
||||||
|
end;
|
||||||
|
tween = function (s,value)
|
||||||
|
return setmetatable({tvalue = value},{__index = s});
|
||||||
|
end;
|
||||||
|
from = function (s,value)
|
||||||
|
return setmetatable({fvalue = value},{__index = s});
|
||||||
|
end;
|
||||||
|
};
|
||||||
|
registerMt.__index = registerMt;
|
||||||
|
|
||||||
-- bindable store object
|
-- bindable store object
|
||||||
local store = {};
|
local store = {};
|
||||||
function store:__index(key)
|
function store:__index(key)
|
||||||
|
|
@ -103,23 +122,12 @@ function module.init(shared)
|
||||||
if not register then
|
if not register then
|
||||||
local event = setmetatable({},week);
|
local event = setmetatable({},week);
|
||||||
self.__evt[key] = event;
|
self.__evt[key] = event;
|
||||||
register = {
|
register = setmetatable({
|
||||||
register = function (efunc)
|
event = event;
|
||||||
insert(event,efunc);
|
|
||||||
end;
|
|
||||||
with = function (s,efunc)
|
|
||||||
return setmetatable({wfunc = efunc},{__index = s});
|
|
||||||
end;
|
|
||||||
default = function (s,value)
|
|
||||||
return setmetatable({dvalue = value},{__index = s});
|
|
||||||
end;
|
|
||||||
tween = function (s,value)
|
|
||||||
return setmetatable({tvalue = value},{__index = s});
|
|
||||||
end;
|
|
||||||
key = key;
|
key = key;
|
||||||
store = self;
|
store = self;
|
||||||
t = "reg";
|
t = "reg";
|
||||||
};
|
},registerMt);
|
||||||
self.__reg[key] = register;
|
self.__reg[key] = register;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,67 +1,4 @@
|
||||||
-- 이렇게 모듈을 부를 수 있다, 뒤에 if 가 붇은것은 자동완성이 뜨도록 하기 위해서 사용된다
|
local Quad = require(game.ReplicatedStorage:WaitForChild "Quad"); ---@module "src"
|
||||||
---@module "src/init.lua"
|
local _ = Quad.init(); local class,mount,store,event,advancedTween = _.class,_.mount,_.store,_.event,_.advancedTween;
|
||||||
local quad = require(game.ReplicatedStorage:WaitForChild "Quad");
|
|
||||||
local render = quad.init();
|
|
||||||
-- init 함수를 이용해 여러 스크립트가 이 모듈을 호출해도 완전히 별계의
|
|
||||||
-- 환경에서 실행될 수 있도록 만든다, init 를 호출하면 완전히 새로운 store 와 style
|
|
||||||
-- 등을 가진 모듈을 새로 생성한다
|
|
||||||
|
|
||||||
-- 하위 모듈을 이렇게 부른다
|
|
||||||
local class = render.class;
|
|
||||||
local mount = render.mount;
|
|
||||||
local store = render.store;
|
|
||||||
|
|
||||||
-- 오브젝트를 이렇게 불러온다
|
|
||||||
local frame = class "Frame"; -- 이렇게 원하는 오브젝트를 불러올 수 있다
|
|
||||||
local text = class "TextLabel";
|
|
||||||
text.TextSize = 17; -- 이렇게 오브젝트의 기본값도 정할 수 있다
|
|
||||||
text.Size = UDim2.new(1,0,0,30);
|
|
||||||
local titleText = class "TextLabel";
|
|
||||||
-- 당연 이렇게 똑같은 className 을 가진 오브젝트를 여러번 import 도 된다
|
|
||||||
-- 다른 임포트에서 설정한 기본값은 여기에 적용되지 않는다
|
|
||||||
|
|
||||||
local gui = script.Parent;
|
|
||||||
local app = mount(gui,frame "testFrame" { -- mount 로 트리를 마운트한다, 이후 app 에서 unmount 호출가능
|
|
||||||
Size = UDim2.fromOffset(120,60);
|
|
||||||
Position = UDim2.fromScale(0.5,0.5);
|
|
||||||
AnchorPoint = Vector2.new(0.5,0.5);
|
|
||||||
text "texts" { -- 이렇게 단순히 child 개체를 만들 수 있다
|
|
||||||
Text = "We can make ui like this";
|
|
||||||
};
|
|
||||||
text "texts" {
|
|
||||||
Position = UDim2.fromOffset(0,30);
|
|
||||||
Text = "qweiufnwlqef";
|
|
||||||
};
|
|
||||||
titleText { -- 아이디를 명명하지 않아도 오브젝트를 바로 만들 수 있다
|
|
||||||
Text = "test";
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
print(store.getObject("texts"));
|
|
||||||
-- getObject 를 호출하면 해당 id 로 명명된 오브젝트중
|
|
||||||
-- 가장 처음으로 생성된 객체를 반환한다
|
|
||||||
store.getObjects("texts"):each(function(index,this)
|
|
||||||
this.Text = "이렇게 모든 택스트를 한꺼번에 바꿀 수도 있습니다";
|
|
||||||
end);
|
|
||||||
-- getObjects 를 이용하면 해당 id 로 명명된 오브젝트가 담긴 array 를 가져온다
|
|
||||||
-- for 을 돌릴 수 있지만 each 를 이용해 async 된 작업을 수행할 수 있다
|
|
||||||
store.getObjects("texts"):eachSync(function(index,this)
|
|
||||||
this.Text = "또한, 기본적으로 Aync 를 이용하기 때문에 순차적인 실행이 필요한 경우 Sync 를 붇여야합니다";
|
|
||||||
end);
|
|
||||||
-- sync 를 하면 일반 스크립트를 실행하는것 처럼 순차적으로 실행되도록 만들 수도 있다
|
|
||||||
-- 이 때 순서는 먼저 생생된 순서이다, 항상 같음을 유지한다는 보장이 없으므로 순서가 중요한경우
|
|
||||||
-- 직접 for 을 이용해 순서 검증을 한 뒤 task 를 수행해야한다
|
|
||||||
|
|
||||||
-- 이렇게 어떤 오브젝트를 가지고 task 수행하는 thread 를 만들 수 있다
|
|
||||||
do local this = store.getObject("testFrame");
|
|
||||||
spawn(function ()
|
|
||||||
local flip = false;
|
|
||||||
while wait(0.5) do
|
|
||||||
flip = not flip;
|
|
||||||
this.BackgroundTransparency = flip and 1 or 0;
|
|
||||||
end
|
|
||||||
end);
|
|
||||||
end
|
|
||||||
|
|
||||||
app.unmount(); -- 트리의 객체들을 모두 파기한다, 플러그인에서 unload 같은곳에 쓰는 함수
|
|
||||||
return app;
|
|
||||||
Loading…
Reference in a new issue