From 921af23d66774eecc45a6163e3da280b1b864f74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=84=B8=EC=A0=A4=EA=B7=80=20=EA=B3=A0=EC=96=91=EC=9D=B4?= =?UTF-8?q?=EB=93=A4?= <46598063+qwreey75@users.noreply.github.com> Date: Fri, 24 Dec 2021 18:11:11 +0900 Subject: [PATCH] Adding advanced tween module for tweening objects and fixed some bukket error --- default.project.json | 9 + readme.lua | 67 +++++ src/class.lua | 30 ++- src/init.lua | 10 +- src/libs/AdvancedTween/BezierCurves.lua | 23 ++ src/libs/AdvancedTween/EasingFunctions.lua | 75 ++++++ src/libs/AdvancedTween/Stepped.lua | 23 ++ src/libs/AdvancedTween/init.lua | 280 +++++++++++++++++++++ src/store.lua | 36 +-- testScript.client.lua | 67 +---- 10 files changed, 529 insertions(+), 91 deletions(-) create mode 100644 readme.lua create mode 100644 src/libs/AdvancedTween/BezierCurves.lua create mode 100644 src/libs/AdvancedTween/EasingFunctions.lua create mode 100644 src/libs/AdvancedTween/Stepped.lua create mode 100644 src/libs/AdvancedTween/init.lua diff --git a/default.project.json b/default.project.json index b9f71b6..5c9d7da 100644 --- a/default.project.json +++ b/default.project.json @@ -7,6 +7,15 @@ "Quad": { "$path": "src" } + }, + "StarterGui": { + "$className": "StarterGui", + "QuadTesting": { + "$className": "ScreenGui", + "testScript": { + "$path": "testScript.client.lua" + } + } } } } \ No newline at end of file diff --git a/readme.lua b/readme.lua new file mode 100644 index 0000000..687781d --- /dev/null +++ b/readme.lua @@ -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; \ No newline at end of file diff --git a/src/class.lua b/src/class.lua index 44ffb2c..03a4e3d 100644 --- a/src/class.lua +++ b/src/class.lua @@ -13,11 +13,14 @@ local module = {}; function module.init(shared) local new = {}; - local bind = shared.event.bind; - local addObject = shared.store.addObject; - local storeNew = shared.store.new; - local mount = shared.mount; - local getHolder = shared.mount.getHolder; + local event = shared.event; ---@module "src.event" + local bind = event.bind; + local store = shared.store; ---@module "src.store" + local addObject = store.addObject; + 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 function new.make(ClassName,...) -- render object @@ -89,15 +92,26 @@ function module.init(shared) end end local tween = value.tvalue; + local from = value.fvalue; -- adding event function local function regFn(newValue,store) + if from then + newValue = from[newValue]; + end if with then newValue = with(newValue,item,store); end - item[index] = newValue; + 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; + end end - value.register(regFn); + value:register(regFn); -- this is using hacky of roblox instance -- this is will keep reference from week table until @@ -208,7 +222,7 @@ function module.init(shared) if child then for _,v in pairs(child) do 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 diff --git a/src/init.lua b/src/init.lua index 68d5481..f05849d 100644 --- a/src/init.lua +++ b/src/init.lua @@ -24,15 +24,17 @@ frame{ ]] local require = require(script.require); -local event = require("event"); ---@module "src.event" -local store = require("store"); ---@module "src.store" +local event = require "event"; ---@module "src.event" +local store = require "store"; ---@module "src.store" --local style = require("style"); -local class = require("class"); ---@module "src.class" -local mount = require("mount"); ---@module "src.mount" +local class = require "class"; ---@module "src.class" +local mount = require "mount"; ---@module "src.mount" +local _,advancedTween = pcall(require,"src.libs.AdvancedTween"); ---@module "src.libs.AdvancedTween" function module.init() local this = {items = {}}; + this.advancedTween = type(advancedTween) == "table" and advancedTween; this.event = event.init(this); this.store = store.init(this); --this.style = style.init(this); diff --git a/src/libs/AdvancedTween/BezierCurves.lua b/src/libs/AdvancedTween/BezierCurves.lua new file mode 100644 index 0000000..e64743e --- /dev/null +++ b/src/libs/AdvancedTween/BezierCurves.lua @@ -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 \ No newline at end of file diff --git a/src/libs/AdvancedTween/EasingFunctions.lua b/src/libs/AdvancedTween/EasingFunctions.lua new file mode 100644 index 0000000..74fd386 --- /dev/null +++ b/src/libs/AdvancedTween/EasingFunctions.lua @@ -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 diff --git a/src/libs/AdvancedTween/Stepped.lua b/src/libs/AdvancedTween/Stepped.lua new file mode 100644 index 0000000..00190af --- /dev/null +++ b/src/libs/AdvancedTween/Stepped.lua @@ -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 diff --git a/src/libs/AdvancedTween/init.lua b/src/libs/AdvancedTween/init.lua new file mode 100644 index 0000000..47cb201 --- /dev/null +++ b/src/libs/AdvancedTween/init.lua @@ -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 diff --git a/src/store.lua b/src/store.lua index 49b81d7..b28cf92 100644 --- a/src/store.lua +++ b/src/store.lua @@ -84,6 +84,25 @@ function module.init(shared) 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 local store = {}; function store:__index(key) @@ -103,23 +122,12 @@ function module.init(shared) if not register then local event = setmetatable({},week); self.__evt[key] = event; - register = { - register = function (efunc) - 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; + register = setmetatable({ + event = event; key = key; store = self; t = "reg"; - }; + },registerMt); self.__reg[key] = register; end diff --git a/testScript.client.lua b/testScript.client.lua index 687781d..8c7d3b2 100644 --- a/testScript.client.lua +++ b/testScript.client.lua @@ -1,67 +1,4 @@ --- 이렇게 모듈을 부를 수 있다, 뒤에 if 가 붇은것은 자동완성이 뜨도록 하기 위해서 사용된다 ----@module "src/init.lua" -local quad = require(game.ReplicatedStorage:WaitForChild "Quad"); -local render = quad.init(); --- init 함수를 이용해 여러 스크립트가 이 모듈을 호출해도 완전히 별계의 --- 환경에서 실행될 수 있도록 만든다, init 를 호출하면 완전히 새로운 store 와 style --- 등을 가진 모듈을 새로 생성한다 +local Quad = require(game.ReplicatedStorage:WaitForChild "Quad"); ---@module "src" +local _ = Quad.init(); local class,mount,store,event,advancedTween = _.class,_.mount,_.store,_.event,_.advancedTween; --- 하위 모듈을 이렇게 부른다 -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; \ No newline at end of file