Fix indents, method names

This commit is contained in:
Qwreey 2023-02-17 01:26:57 +09:00
parent 83bb7ee817
commit 46da90f5f8
9 changed files with 553 additions and 531 deletions

View file

@ -1,323 +1,343 @@
local module = {};
local pack = table.pack;
local match = string.match;
local insert = table.insert;
local module = {}
local pack = table.pack
local match = string.match
local insert = table.insert
local gsub = string.gsub
---@param shared quad_export
---@return quad_module_class
function module.init(shared)
local warn = shared.warn;
local warn = shared.warn
---@class quad_module_class
local new = {__type = "quad_module_class"};
local InstanceNew = Instance.new;
local event = shared.Event; ---@type quad_module_event
local bind = event.Bind;
local store = shared.Store; ---@type quad_module_store
local initStoreRegisterBinding = store.__initStoreRegisterBinding;
local addObject = store.AddObject;
local storeNew = store.New;
local mount = shared.Mount; ---@type quad_module_mount
local getHolder = mount.GetHolder;
local mountfunc = mount.Mount;
local style = shared.Style; ---@type quad_module_style
local styleList = style.Styles;
local parseStyles = style.ParseStyles;
local advancedTween = shared.Tween; ---@type quad_module_tween
local round = shared.Round; ---@type quad_module_round
local new = {__type = "quad_module_class"}
local InstanceNew = Instance.new
local event = shared.Event ---@type quad_module_event
local bind = event.Bind
local store = shared.Store ---@type quad_module_store
local initStoreRegisterBinding = store.__initStoreRegisterBinding
local addObject = store.AddObject
local storeNew = store.New
local mount = shared.Mount ---@type quad_module_mount
local getHolder = mount.GetHolder
local mountfunc = mount.Mount
local style = shared.Style ---@type quad_module_style
local styleList = style.Styles
local parseStyles = style.ParseStyles
local advancedTween = shared.Tween ---@type quad_module_tween
local round = shared.Round ---@type quad_module_round
local function InstanceNewWithName(classname,parent,name)
local item = InstanceNew(classname,parent);
item.Name = name;
return item;
local item = InstanceNew(classname,parent)
item.Name = name
return item
end
local function GetProperty(item,index,ClassName)
if type(item) == "table" then return item[index]; end
ClassName = ClassName or item.ClassName;
local isImage = (ClassName == "ImageLabel" or ClassName == "ImageButton");
if (index == "RoundSize" or index == "roundSize") and isImage then
if type(item) == "table" then return item[index] end
ClassName = ClassName or item.ClassName
local isImage = (ClassName == "ImageLabel" or ClassName == "ImageButton")
if (index == "RoundSize") and isImage then
if not round then
error("module 'round' needs to be loaded for get image round size but it is not found on 'src.libs'. you should adding that to src.libs directory");
error("module 'round' needs to be loaded for get image round size but it is not found on 'src.libs'. you should adding that to src.libs directory")
end
return round.GetRound(item);
elseif index == "UiRoundSize" or index == "uiRoundSize" or index == "UIRoundSize" then
local target = (ClassName == "UICorner" and item) or item:FindFirstChildOfClass("UICorner");
return (target and target.CornerRadius.Offset) or 0;
elseif index == "PaddingAll" or index == "paddingAll" then
local target = (ClassName == "UIPadding" and item) or item:FindFirstChildOfClass("UIPadding");
return (target and target.PaddingLeft) or UDim.new(0,0);
elseif index == "PaddingAllOffset" or index == "paddingAllOffset" then
local target = (ClassName == "UIPadding" and item) or item:FindFirstChildOfClass("UIPadding");
return (target and target.PaddingLeft.Offset) or 0;
return round.GetRound(item)
elseif index == "Corner" then
local target = (ClassName == "UICorner" and item) or item:FindFirstChildOfClass("UICorner")
return (target and target.CornerRadius.Offset) or 0
elseif index == "PaddingAll" then
local target = (ClassName == "UIPadding" and item) or item:FindFirstChildOfClass("UIPadding")
return (target and target.PaddingLeft) or UDim.new(0,0)
elseif index == "PaddingAllOffset" then
local target = (ClassName == "UIPadding" and item) or item:FindFirstChildOfClass("UIPadding")
return (target and target.PaddingLeft.Offset) or 0
elseif index == "Scale" then
local target = (ClassName == "UIScale" and item) or item:FindFirstChildOfClass("UIScale");
return (target and target.Scale) or 1;
local target = (ClassName == "UIScale" and item) or item:FindFirstChildOfClass("UIScale")
return (target and target.Scale) or 1
end
return item[index];
return item[index]
end
new.GetProperty = GetProperty
local function SetProperty(item,index,value,ClassName)
if type(item) == "table" then item[index] = value; return; end
ClassName = ClassName or item.ClassName;
local isImage = (ClassName == "ImageLabel" or ClassName == "ImageButton");
if (index == "RoundSize" or index == "roundSize") and isImage then
-- if it is not a roblox instance, just call __index
if type(item) == "table" then
item[index] = value
return
end
-- check class name
ClassName = ClassName or item.ClassName
-- check is ImageLabel or ImageButton
local isImage = (ClassName == "ImageLabel" or ClassName == "ImageButton")
-- Round Image
if index == "RoundSize" and isImage then
if not round then
error("[QUAD] module 'round' needs to be loaded for set image round size but it is not found on 'src.libs'. you should adding that to src.libs directory");
error("[QUAD] module 'round' needs to be loaded for set image round size but it is not found on 'src.libs'. you should adding that to src.libs directory")
end
round.SetRound(item,value);
elseif index == "UIRoundSize" or index == "uiRoundSize" or index == "UiRoundSize" then
local uiCorner = (ClassName == "UICorner" and item) or item:FindFirstChildOfClass("UICorner") or InstanceNewWithName("UICorner",item,"_quad_round");
uiCorner.CornerRadius = UDim.new(0,value);
elseif index == "PaddingAll" or index == "paddingAll" then
local target = (ClassName == "UIPadding" and item) or item:FindFirstChildOfClass("UIPadding") or InstanceNewWithName("UIPadding",item,"_quad_padding");
target.PaddingLeft = value;
target.PaddingRight = value;
target.PaddingTop = value;
target.PaddingBottom = value;
elseif index == "PaddingAllOffset" or index == "paddingAllOffset" then
local target = (ClassName == "UIPadding" and item) or item:FindFirstChildOfClass("UIPadding") or InstanceNewWithName("UIPadding",item,"_quad_padding");
local padding = UDim.new(0,value);
target.PaddingLeft = padding;
target.PaddingRight = padding;
target.PaddingTop = padding;
target.PaddingBottom = padding;
round.SetRound(item,value)
-- UIRound
elseif index == "Corner" then
local uiCorner = (ClassName == "UICorner" and item) or item:FindFirstChildOfClass("UICorner") or InstanceNewWithName("UICorner",item,"_quad_round")
uiCorner.CornerRadius = UDim.new(0,value)
-- PaddingAll
elseif index == "PaddingAll" then
local target = (ClassName == "UIPadding" and item) or item:FindFirstChildOfClass("UIPadding") or InstanceNewWithName("UIPadding",item,"_quad_padding")
target.PaddingLeft = value
target.PaddingRight = value
target.PaddingTop = value
target.PaddingBottom = value
-- PaddingAll with Offset
elseif index == "PaddingAllOffset" then
local target = (ClassName == "UIPadding" and item) or item:FindFirstChildOfClass("UIPadding") or InstanceNewWithName("UIPadding",item,"_quad_padding")
local padding = UDim.new(0,value)
target.PaddingLeft = padding
target.PaddingRight = padding
target.PaddingTop = padding
target.PaddingBottom = padding
-- Scale
elseif index == "Scale" then
local target = (ClassName == "UIScale" and item) or item:FindFirstChildOfClass("UIScale") or InstanceNewWithName("UIScale",item,"_quad_scale");
target.Scale = value;
local target = (ClassName == "UIScale" and item) or item:FindFirstChildOfClass("UIScale") or InstanceNewWithName("UIScale",item,"_quad_scale")
target.Scale = value
else
item[index] = value; -- set property
-- other, just set property
item[index] = value
end
end
new.SetProperty = SetProperty
local function RawGetProperty(item,index)
return item[index];
return item[index]
end
local function PcallGetProperty(item,index)
local ok,err = pcall(RawGetProperty,item,index);
if ok then return err; end
return nil;
local ok,err = pcall(RawGetProperty,item,index)
if ok then return err end
return nil
end
local function ProcessQuadProperty(processedProperty,iprop,holder,item,className,index,value)
if processedProperty[index] then return; end
if processedProperty[index] then
return
end
local valueType = typeof(value);
local indexType = typeof(index);
local valueType = typeof(value)
local indexType = typeof(index)
local quadType = valueType == "table" and PcallGetProperty(value,"__type")
if indexType == "string" and quadType == "quad_register" then
-- register (bind to store event)
processedProperty[index] = true; -- ignore next
processedProperty[index] = true -- ignore next
-- store reading
do
local setValue = value:calcWithDefault(item);
local setValue = value:calcWithDefault(item)
if setValue == nil then
warn "[Quad] register return value must not be nil, but got nil. did you inited values before?";
warn "[Quad] register return value must not be nil, but got nil. did you inited values before?"
end
SetProperty(item,index,setValue,className);
SetProperty(item,index,setValue,className)
end
-- adding handle function (bindding)
local function regFn(_,newValue,key)
local setValue,tween = value:calcWithNewValue(item,newValue,key);
local setValue,tween = value:calcWithNewValue(item,newValue,key)
if tween then
if not advancedTween then
return warn "[QUAD] module 'AdvancedTween' needs to be loaded for tween properties but it is not found on 'src.libs'. you should adding that to src.libs directory";
return warn "[QUAD] module 'AdvancedTween' needs to be loaded for tween properties but it is not found on 'src.libs'. you should adding that to src.libs directory"
end
local ended, onStepped;
local ended, onStepped
if tween.Ended then
ended = function (...)
tween.Ended(item,...);
tween.Ended(item,...)
end
end
if tween.OnStepped then
onStepped = function (...)
tween.OnStepped(item,...);
tween.OnStepped(item,...)
end
end
advancedTween.RunTween(item,tween,{[index] = setValue},ended,onStepped,SetProperty,GetProperty);
advancedTween.RunTween(item,tween,{[index] = setValue},ended,onStepped,SetProperty,GetProperty)
else
SetProperty(item,index,setValue,className);
SetProperty(item,index,setValue,className)
end
end
value:register(regFn);
value:register(regFn)
-- this is using hacky of roblox instance
-- this is will keep reference from week table until
-- inscance got GCed
item:GetPropertyChangedSignal("ClassName"):Connect(regFn);
item:GetPropertyChangedSignal("ClassName"):Connect(regFn)
elseif (valueType == "function" or valueType == "table") and indexType == "string" and bind(item,index,value,valueType) then -- connect event
-- event binding
elseif indexType == "string" then
processedProperty[index] = true; -- ignore next
processedProperty[index] = true -- ignore next
-- prop set
SetProperty(item,index,value,className);
SetProperty(item,index,value,className)
elseif indexType == "number" and valueType == "table" and quadType == "quad_style" then -- style
-- style parsing
for _,thisStyle in ipairs(parseStyles(value)) do
if not processedProperty[thisStyle] then
processedProperty[thisStyle] = true;
processedProperty[thisStyle] = true
for styleIndex,styleValue in pairs(thisStyle) do
if type(styleValue) ~= "table" or pcall(styleValue,"__type") ~= "quad_style" then
ProcessQuadProperty(processedProperty,iprop,holder,item,className,styleIndex,styleValue);
ProcessQuadProperty(processedProperty,iprop,holder,item,className,styleIndex,styleValue)
end
end
end
end
elseif indexType == "number" and valueType ~= "boolean" then -- object
-- child object
mountfunc(item,((iprop == 1) and value or value:Clone()),holder);
mountfunc(item,((iprop == 1) and value or value:Clone()),holder)
end
end
-- make object that from instance, class and more
function new.make(ClassName,...) -- render object
function new.Make(ClassName,...) -- render object
-- make object from ClassName
local item;
local classOfClassName = type(ClassName);
local item
local classOfClassName = type(ClassName)
if classOfClassName == "string" then -- if classname is a string value, cdall instance.new for making new roblox instance
item = InstanceNew(ClassName);
item = InstanceNew(ClassName)
elseif classOfClassName == "function" then -- if classname is a function value, call it for making new object (OOP object)
item = ClassName();
item = ClassName()
elseif classOfClassName == "table" then -- if classname is a calss what is included new function, call it for making new object (object)
local func = ClassName.new or ClassName.New or ClassName.__new;
local func = ClassName.new or ClassName.New or ClassName.__new
if ClassName.__noSetup then -- if is support initing props
local childs,props,parsed,binds = {},pack(...),{},{};
local childs,props,parsed,binds = {},pack(...),{},{}
for iprop = props.n,1,-1 do
local prop = props[iprop];
local prop = props[iprop]
if prop then
for i,v in pairs(prop) do
if type(i) == "number" then
childs[i] = ((iprop == 1) and v or v:Clone());
childs[i] = ((iprop == 1) and v or v:Clone())
elseif bind(i) then
binds[i] = v;
binds[i] = v
else
parsed[i] = v;
parsed[i] = v
end
end
end
end
item = func(parsed);
local holder = getHolder(item);
item = func(parsed)
local holder = getHolder(item)
for _,v in ipairs(childs) do
mountfunc(item,v,holder);
mountfunc(item,v,holder)
end
for i,v in pairs(binds) do
bind(item,i,v);
bind(item,i,v)
end
return item;
return item
end
item = func();
item = func()
end
if not item then -- if cannot make new object, ignore this call
local str = tostring(ClassName);
warn(("[Quad] fail to make item '%s', did you forget to checking the class '%s' is exist?"):format(str,str));
local str = tostring(ClassName)
warn(("[Quad] fail to make item '%s', did you forget to checking the class '%s' is exist?"):format(str,str))
end
-- set property and adding child and binding functions
local holder = getHolder(item); -- to __holder or holder or it self (for tabled)
local holder = getHolder(item) -- to __holder or holder or it self (for tabled)
-- for iprop,prop in ipairs({...}) do
local propsListArray = pack(...);
local processedProperty = {};
local propsListArray = pack(...)
local processedProperty = {}
for iprop = 1,propsListArray.n do
local prop = propsListArray[iprop]
if prop then
for index,value in pairs(prop) do
if type(index) ~= "number" then
ProcessQuadProperty(processedProperty,iprop,holder,item,ClassName,index,value);
ProcessQuadProperty(processedProperty,iprop,holder,item,ClassName,index,value)
end
end
for index,value in ipairs(prop) do
ProcessQuadProperty(processedProperty,iprop,holder,item,ClassName,index,value);
ProcessQuadProperty(processedProperty,iprop,holder,item,ClassName,index,value)
end
end
end
return item;
return item
end
local make = new.make;
local make = new.Make
-- import quad object
function new.import(ClassName,defaultProperties) -- make new quad class object
function new.Import(ClassName,defaultProperties) -- make new quad class object
if type(ClassName) == "userdata" and ClassName.ClassName == "ModuleScript" then
ClassName = require(ClassName);
ClassName = require(ClassName)
end
local this = defaultProperties or {};
local this = defaultProperties or {}
setmetatable(this,{
__type = "quad_imported_class",
__call = function (self,prop,...)
local propType = type(prop);
local propType = type(prop)
if propType == "string" then
local lastName = prop;
local lastName = prop
return function (nprop,...)
nprop = nprop or {};
nprop.Name = gsub(gsub(match(lastName,"[^,]+")," +$",""),"^ +","");
nprop = nprop or {}
nprop.Name = gsub(gsub(match(lastName,"[^,]+")," +$",""),"^ +","")
for styleName,styleObj in pairs(styleList) do
if match(prop,styleName) then
insert(nprop,styleObj);
insert(nprop,styleObj)
end
end
local item = make(ClassName,nprop,...,this);
addObject(lastName,item);
return item;
end;
local item = make(ClassName,nprop,...,this)
addObject(lastName,item)
return item
end
elseif propType == "nil" then
return make(ClassName,this);
return make(ClassName,this)
end
return make(ClassName,prop,...,this);
end;
});
return this;
return make(ClassName,prop,...,this)
end
})
return this
end
-- set module calling function
setmetatable(new,{
__call = function (self,...)
return new.import(...);
end;
});
return new.Import(...)
end
})
-- make class
function new.extend()
local this = {__type = "quad_extend"};
function new.Extend()
local this = {__type = "quad_extend"}
--- make new object
function this.new(prop)
function this.New(prop)
-- make metatable
prop = storeNew(prop,nil);
local parent = prop and (prop.Parent or prop.parent);
local self = {__prop = prop; __parent = parent,__propertyChangedSignals = {}};
local init = this.init;
prop = storeNew(prop,nil)
local parent = prop and (prop.Parent or prop.parent)
local self = {
__prop = prop;
__parent = parent;
__propertyChangedSignals = {};
}
local init = this.Init
if init then
init(self,prop);
init(self,prop)
end
setmetatable(self,this);
initStoreRegisterBinding(prop,this);
setmetatable(self,this)
initStoreRegisterBinding(prop,this)
-- render that
local object = self:render(prop);
rawset(self,"__object",object);
rawset(self,"__holder",object);
local object = self:Render(prop)
rawset(self,"__object",object)
rawset(self,"__holder",object)
if parent then
rawset(self,"__parent",parent);
rawset(self,"__parent",parent)
mountfunc(self,parent)
end
-- prevent gc
((type(object) == "table" and object.__object) or object)
:GetPropertyChangedSignal "ClassName":Connect(function()
return self;
end);
return self
end)
--after render
local afterRender = this.afterRender;
local afterRender = this.AfterRender
if afterRender then
afterRender(self,object);
afterRender(self,object)
end
return self;
return self
end
function this:GetPropertyChangedSignal(propertyName)
@ -333,126 +353,123 @@ function module.init(shared)
end
--- re-render object (if some props chaged, call this to render again)
function this:update() -- swap object
local object = rawget(self,"__object"); -- get last instance
local parent = object and object.Parent; -- date parent
function this:Update() -- swap object
local object = rawget(self,"__object") -- get last instance
local parent = object and object.Parent -- date parent
if not object then
parent = rawget(self,"__parent");
parent = rawget(self,"__parent")
end
local lastObject = object;
local lastObject = object
if lastObject then
lastObject.Parent = nil;
lastObject.Parent = nil
end
object = self:render(self.__prop); -- new instance
rawset(self,"__holder",object);
rawset(self,"__object",object);
object.Parent = getHolder(parent); -- update parent
object = self:Render(self.__prop) -- new instance
rawset(self,"__holder",object)
rawset(self,"__object",object)
object.Parent = getHolder(parent) -- update parent
-- restore childs
local child = rawget(self,"__child");
local child = rawget(self,"__child")
if child then
for _,v in pairs(child) do
if v then
v.Parent = object;
v.Parent = object
end
end
end
-- prevnet gc
((type(object) == "table" and object.__object) or object):GetPropertyChangedSignal "ClassName":Connect(function()
return self;
end);
return self
end)
if lastObject then -- remove old instance
self:Destroy(lastObject);
self:Destroy(lastObject)
end
--after render
local afterRender = this.afterRender;
local afterRender = this.AfterRender
if afterRender then
afterRender(self,object);
afterRender(self,object)
end
end
-- define destroy method
function this:Destroy(object)
local unload = rawget(self,"unload");
object = object or rawget(self,"__object");
local unload = this.Unload
object = object or rawget(self,"__object")
if object then
if unload then
unload(self,object);
unload(self,object)
else
local destroy = (object.Destroy or object.destroy);
local destroy = (object.Destroy or object.destroy)
if destroy then
pcall(destroy,object);
pcall(destroy,object)
end
end
end
self = nil;
self = nil
end
--- link to new
function this.__call(self,...)
return (self.new or self.New or self.__new)(...);
end;
return (self.new or self.New or self.__new)(...)
end
-- indexer (getter)
function this:__index(k)
if k == "destroy" then
return self.Destroy;
end
local getter = this.getter[k];
local getter = this.Getter[k]
if getter then
return getter(self,rawget(self,"__object"));
return getter(self,rawget(self,"__object"))
end
-- from this (have more priority)
local fromThis = this[k];
local fromThis = this[k]
if fromThis then
return fromThis;
return fromThis
end
-- from prop, not start with '_' (private value)
if k:sub(1,1) ~= "_" then
return self.__prop[k];
return self.__prop[k]
end
end
--- new indexer (setter)
function this:__newindex(k,v)
-- from setter
local setter = this.setter[k];
local setter = this.Setter[k]
if setter then
return setter(self,v,rawget(self,"__object"));
return setter(self,v,rawget(self,"__object"))
end
-- is private (self value)
if k == "holder" or k:sub(1,1) == "_" then
return rawset(self,k,v);
return rawset(self,k,v)
end
-- prop update
self.__prop[k] = v;
if this.updateTriggers[k] then
self:update();
self.__prop[k] = v
if this.UpdateTriggers[k] then
self:Update()
end
end
this.getter = {};
this.setter = {
this.Getter = {}
this.Setter = {
Parent = function(self,parent,object)
rawset(self,"__parent",parent);
rawset(self,"__parent",parent)
if object then
object.Parent = getHolder(parent);
object.Parent = getHolder(parent)
end
end;
};
this.updateTriggers = {};
this.__noSetup = true;
return this;
end
}
this.UpdateTriggers = {}
this.__noSetup = true
return this
end
return new;
return new
end
return module;
return module

View file

@ -1,139 +1,101 @@
local module = {};
local unpack = table.unpack;
local wrap = coroutine.wrap;
local module = {}
local unpack = table.unpack
local wrap = coroutine.wrap
---@param shared quad_export
---@return quad_module_event
function module.init(shared)
local warn = shared.warn;
local warn = shared.warn
---@class quad_module_event
local new = {__type = "quad_module_event"};
local new = {__type = "quad_module_event"}
local prefix = "Event::";
local prefix = "Event::"
local special = {
["Property::(.+)"] = function (this,func,property)
this:GetPropertyChangedSignal(property):Connect(function()
func(this,this[property]);
end);
func(this,this[property])
end)
end;
["CreatedSync::"] = function (this,func)
func(this);
func(this)
end;
["CreatedAsync::"] = function (this,func)
wrap(func)(this);
wrap(func)(this)
end;
};
}
local prefixLen = #prefix;
local prefixLen = #prefix
setmetatable(new,{
__call = function(self,eventName)
return prefix .. eventName;
return prefix .. eventName
end;
__index = function(self,key)
if key == "createdSync" then
warn "[Quad] event.createdSync is deprecated. Use event.created instead"
return self.created;
return self.created
end
end;
});
})
-- try binding, if key dose match with anything, ignore call
function new.bind(this,key,func,typefunc)
function new.Bind(this,key,func,typefunc)
if not key then
key = this;
this = nil;
key = this
this = nil
end
-- if is advanced binding (self setted)
typefunc = typefunc or type(func);
local self;
typefunc = typefunc or type(func)
local self
if typefunc == "table" then
local t = func;
self = t.self;
func = t.func;
if not self then self = t[1]; end
if not func then func = t[2]; end
local t = func
self = t.self
func = t.func
if not self then self = t[1] end
if not func then func = t[2] end
end
-- check prefix
if key:sub(1,prefixLen) ~= prefix then
return;
return
end
key = key:sub(prefixLen + 1,-1);
key = key:sub(prefixLen + 1,-1)
-- find special bindings
for specKey,specFunc in pairs(special) do
local find = {key:match(specKey)};
local find = {key:match(specKey)}
if #find ~= 0 then
if func then
specFunc(this,func,unpack(find));
specFunc(this,func,unpack(find))
end
return true;
return true
end
end
-- binding normal events
if this then
local event = this[key];
local event = this[key]
if event then
if func then
event:Connect(function(...)
func(self or this,...);
end);
func(self or this,...)
end)
end
return true;
return true
end
end
end
-- property changed binding
local prefixProperty = prefix .. "Property::";
function new.prop(name)
return prefixProperty .. name;
local prefixProperty = prefix .. "Property::"
function new.Prop(name)
return prefixProperty .. name
end
-- when created binding
new.createdAsync = prefix .. "CreatedAsync::";
new.created = prefix .. "CreatedSync::";
new.CreatedAsync = prefix .. "CreatedAsync::"
new.Created = prefix .. "CreatedSync::"
-- roblox connections disconnecter
local insert = table.insert;
local idSpace = {};
local disconnecterClass = {__type = "quad_disconnecter"};
function disconnecterClass:add(connection)
insert(self,connection);
end
function disconnecterClass:disconnect()
for i,v in pairs(self) do
pcall(v.Disconnect,v);
self[i] = nil;
end
end
function disconnecterClass:destroy()
local id = self.id;
if id then
idSpace[id] = nil;
end
for i,v in pairs(self) do
pcall(v.Disconnect,v);
self[i] = nil;
end
end
disconnecterClass.__index = disconnecterClass;
function new.disconnecter(id)
if id then
local old = idSpace[id];
if old then
return old;
end
end
local this = setmetatable({id = id},disconnecterClass);
if id then
idSpace[id] = this;
end
return this;
end
return new;
return new
end
return module;
return module

View file

@ -1,5 +1,5 @@
---@class quad
local module = {};
local module = {}
local IS_TEST = true
local VER = "1.14" .. (IS_TEST and "B" or "")
@ -7,19 +7,19 @@ if IS_TEST then
warn("You are using BETA version of quad now. Many features may change in the future and unstable. AS USING BETA VERSION OF QUAD, YOU SHOULD KNOW IT WILL BUGGY SOMETIME. still on development - you can ignore this message if have no issue. if you have issue on using quad, please report issue on github. VERSION: "..VER)
end
local require = require(script.require);
local style = require "style";
local event = require "event";
local store = require "store";
local class = require "class";
local mount = require "mount";
-- local lang = require "lang";
local require = require(script.require)
local style = require "style"
local event = require "event"
local store = require "store"
local class = require "class"
local mount = require "mount"
-- local lang = require "lang"
-- submodule
local _,advancedTween = pcall(require,"libs.AdvancedTween");
local _,round = pcall(require,"libs.round");
local _,advancedTween = pcall(require,"libs.AdvancedTween")
local _,round = pcall(require,"libs.round")
local idSpace = {};
local idSpace = {}
---@return quad_export this
---@return quad_module_round round
@ -63,7 +63,7 @@ end
function module.Uninit(id)
pcall(cleanup,idSpace[id])
idSpace[id] = nil;
idSpace[id] = nil
end
return module;
return module

View file

@ -8,28 +8,28 @@ 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
module.Connection = RunService.Heartbeat:Connect(StepFunction)
else
-- RunService:BindToRenderStep("advancedTween",1,StepFunction)
module.Connection = RunService.RenderStepped:Connect(StepFunction)
end
else
-- do something here
end
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
module.Connection = RunService.Heartbeat:Connect(StepFunction)
else
-- 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
if not module.Connection then
error("Function was not binded yet")
end
module.Connection:Disconnect()
module.Connection = nil
end
return module

View file

@ -63,9 +63,9 @@ module.EasingFunction = module.EasingFunctions
------------------------------------
-- 이중 선형, Alpha 를 받아서 값을 구해옴
local function Lerp(start,goal,alpha)
if alpha == 1 then return goal end
if alpha == 0 then return start end
return start + ((goal - start) * alpha)
if alpha == 1 then return goal end
if alpha == 0 then return start end
return start + ((goal - start) * alpha)
end
-- 기본적으로 로블록스가 Lerp 를 지원하는 Class

View file

@ -1,97 +1,102 @@
local module = {};
local insert = table.insert;
local pack = table.pack;
local module = {}
local insert = table.insert
local pack = table.pack
---@param shared quad_export
---@return quad_module_mount
function module.init(shared)
local warn = shared.warn;
local warn = shared.warn
---@class quad_module_mount
local new = {__type = "quad_module_mount"};
local new = {__type = "quad_module_mount"}
local mountClass = {__type = "quad_mount"};
mountClass.__index = mountClass;
function mountClass:unmount()
-- get Holder object
local function getHolder(item)
return (type(item) == "table") and (item._holder or item.holder or item.__holder) or item
end
new.GetHolder = getHolder
-- mount class
local mountClass = {__type = "quad_mount"}
mountClass.__index = mountClass
function mountClass:Unmount()
local this = self.this
local typeThis = type(this);
local typeThis = type(this)
if typeThis == "userdata" then
this:Destroy();
this:Destroy()
elseif typeThis == "table" then
pcall(function()
this.Parent = nil;
end);
local destroyThis = this.Destroy;
this.Parent = nil
end)
local destroyThis = this.Destroy
if destroyThis then
pcall(destroyThis,this);
pcall(destroyThis,this)
end
--if sef.to when
-- todo for remove child on parent
end
end
function new.getHolder(item)
return (type(item) == "table") and (item._holder or item.holder or item.__holder) or item;
end
local getHolder = new.getHolder;
-- we should add plugin support
function new.mount(to,this,holder)
local thisObject = this;
-- mount function
local function mount(to,this,holder)
local thisObject = this
if type(this) == "table" then
thisObject = rawget(this,"__object");
local parent = rawget(this,"__parent");
thisObject = rawget(this,"__object")
local parent = rawget(this,"__parent")
if type(parent) == "table" then
local parentChild = rawget(parent,"__child");
local parentChild = rawget(parent,"__child")
if parentChild then
for i,v in pairs(parentChild) do
if v == this then
parentChild[i] = nil;
parentChild[i] = nil
end
end
end
end
rawset(this,"__parent",to);
rawset(this,"__parent",to)
end
if thisObject then
thisObject.Parent = holder or getHolder(to);
thisObject.Parent = holder or getHolder(to)
else
this.Parent = holder or getHolder(to);
this.Parent = holder or getHolder(to)
end
if type(to) == "table" then
local child = rawget(to,"__child");
local child = rawget(to,"__child")
if not child then
child = {};
rawset(to,"__child",child);
child = {}
rawset(to,"__child",child)
end
insert(child,this);
insert(child,this)
end
return setmetatable({to = to,this = this},mountClass);
return setmetatable({to = to,this = this},mountClass)
end
local mount = new.mount;
new.Mount = mount
local mountsClass = {__type = "quad_mounts"};
mountsClass.__index = mountsClass;
function mountsClass:unmount()
-- mount(s) class
local mountsClass = {__type = "quad_mounts"}
mountsClass.__index = mountsClass
function mountsClass:Unmount()
for _,v in ipairs(self) do
v:unmount();
v:unmount()
end
end
-- handle __call
setmetatable(new,{
__call = function (self,to,...)
if select("#",...) == 1 then
return new.mount(to,...);
return mount(to,...)
end
local mounts = {};
local items = pack(...);
local mounts = {}
local items = pack(...)
for _,item in ipairs(items) do
insert(mounts,mount(to,item));
insert(mounts,mount(to,item))
end
setmetatable(mounts,mountsClass);
return mounts;
end;
});
setmetatable(mounts,mountsClass)
return mounts
end
})
return new;
return new
end
return module;
return module

View file

@ -2,30 +2,30 @@
-- now, we can call modules with string path
if (not workspace) and (not game) and (not script) then
return;
return
end
return function (query)
local typeQuery = type(query);
local typeQuery = type(query)
if typeQuery == "string" then
local object = script.Parent;
query = query:gsub("/",".");
-- local index = 0;
local object = script.Parent
query = query:gsub("/",".")
-- local index = 0
query:gsub("[^%.]+",function (this)
-- index = index + 1;
-- index = index + 1
-- if index == 1 and this == "src" then
-- return;
-- return
-- end
local lastObject = object;
object = object[this];
local lastObject = object
object = object[this]
if not object then
object = lastObject.libs
error(("[Quad] (require) object %s was not found from this worktree, require failed"):format(query));
error(("[Quad] (require) object %s was not found from this worktree, require failed"):format(query))
end
end);
return require(object);
end)
return require(object)
elseif typeQuery == "userdata" then
return require(query);
return require(query)
end
end;
end

View file

@ -14,7 +14,7 @@ end
local customSignal = {}
customSignal.__index = customSignal
function customSignal:emit(...)
function customSignal:Fire(...)
local waitting = self.waitting
self.waitting = {}
@ -54,3 +54,41 @@ function this.new(...)
customSignal.new(...)
end
this.customSignal = customSignal
-- roblox connections disconnecter
local insert = table.insert
local idSpace = {}
local disconnecterClass = {__type = "quad_disconnecter"}
function disconnecterClass:Add(connection)
insert(self,connection)
end
function disconnecterClass:Disconnect()
for i,v in pairs(self) do
pcall(v.Disconnect,v)
self[i] = nil
end
end
function disconnecterClass:Destroy()
local id = self.id
if id then
idSpace[id] = nil
end
for i,v in pairs(self) do
pcall(v.Disconnect,v)
self[i] = nil
end
end
function disconnecterClass.New(id)
if id then
local old = idSpace[id];
if old then
return old;
end
end
local this = setmetatable({id = id},disconnecterClass);
if id then
idSpace[id] = this;
end
return this;
end
disconnecterClass.__index = disconnecterClass

View file

@ -1,97 +1,97 @@
local module = {};
local module = {}
--[[
this feature allows get object without making some created callback and local var
but, it can't allows mulit id and object
this feature should be upgraded
]]
local wrap = coroutine.wrap;
local insert = table.insert;
local remove = table.remove;
local gmatch = string.gmatch;
local gsub = string.gsub;
local match = string.match;
local wrap = coroutine.wrap
local insert = table.insert
local remove = table.remove
local gmatch = string.gmatch
local gsub = string.gsub
local match = string.match
local function catch(...)
local passed,err = pcall(...);
local passed,err = pcall(...)
if not passed then
warn ("[QUAD] Error occured while operating async task\n" .. tostring(err));
warn ("[QUAD] Error occured while operating async task\n" .. tostring(err))
end
end
local week = {__mode = "v"};
local week = {__mode = "v"}
---@param shared quad_export
---@return quad_module_store
function module.init(shared)
local warn = shared.warn;
local warn = shared.warn
---@class quad_module_store
local new = {__type = "quad_module_store"};
local items = {};
local new = {__type = "quad_module_store"}
local items = {}
new.items = items
-- id space (array of object)
local objectListClass = {__type = "quad_objectlist"};
local objectListClass = {__type = "quad_objectlist"}
function objectListClass:each(func)
local index = 1;
local index = 1
for i,v in pairs(self) do
wrap(catch)(func,index,v);
index = index + 1;
wrap(catch)(func,index,v)
index = index + 1
end
end
function objectListClass:eachSync(func)
local index = 1;
local index = 1
for _,v in pairs(self) do
local ret = func(index,v);
index = index + 1;
local ret = func(index,v)
index = index + 1
if ret then
break;
break
end
end
end
function objectListClass:remove(indexOrItem)
local thisType = type(indexOrItem);
local thisType = type(indexOrItem)
if thisType == "number" then
return remove(self,indexOrItem),indexOrItem;
return remove(self,indexOrItem),indexOrItem
else
for i,v in pairs(self) do
if v == indexOrItem then
return remove(self,i),i;
return remove(self,i),i
end
end
end
end
function objectListClass:isEmpty()
if next(self) then return true; end
return false;
if next(self) then return true end
return false
end
function objectListClass.__new()
return setmetatable({},objectListClass);
return setmetatable({},objectListClass)
end
function objectListClass:__newIndex(key,value) -- props setter
self:each(function (this)
this[key] = value;
end);
this[key] = value
end)
end
objectListClass.__mode = "kv"; -- week link for gc
objectListClass.__index = objectListClass;
objectListClass.__mode = "kv" -- week link for gc
objectListClass.__index = objectListClass
-- get object array with id (objSpace)
function new.getObjects(ids)
if match(ids,",") then
local list = items[ids];
if list then return list; end
list = objectListClass.__new();
items[ids] = list;
return list;
local list = items[ids]
if list then return list end
list = objectListClass.__new()
items[ids] = list
return list
else
local list = objectListClass.__new();
local list = objectListClass.__new()
for id in gmatch(ids,"[^,]+") do -- split by ,
id = gsub(gsub(id,"^ +","")," +$","");
local idItem = items[id];
id = gsub(gsub(id,"^ +","")," +$","")
local idItem = items[id]
if idItem then
for _,item in pairs(idItem) do
insert(list,item);
insert(list,item)
end
end
end
@ -100,227 +100,227 @@ function module.init(shared)
end
-- get first object with id (not array)
function new.getObject(id)
local item = items[id];
return item and item[next(item)];
local item = items[id]
return item and item[next(item)]
end
--TODO: if item is exist already, ignore this call
-- adding object with id
function new.addObject(ids,object)
for id in gmatch(ids,"[^,]+") do -- split by ,
-- remove trailing, heading spaces
id = gsub(gsub(id,"^ +","")," +$","");
local array = items[id];
id = gsub(gsub(id,"^ +","")," +$","")
local array = items[id]
if not array then
array = objectListClass.__new();
items[id] = array;
array = objectListClass.__new()
items[id] = array
end
insert(array, object);
insert(array, object)
end
end
local registerClass = {
__type = "quad_register";
register = function (s,efunc)
local self = s.store;
local events = self.__evt;
local self = s.store
local events = self.__evt
for key in s.key:gmatch("[^,]+") do
key = key:gsub("^ +",""):gsub(" +$","");
local event = events[key];
key = key:gsub("^ +",""):gsub(" +$","")
local event = events[key]
if not event then
event = setmetatable({},week);
events[key] = event;
event = setmetatable({},week)
events[key] = event
end
insert(event,efunc);
insert(event,efunc)
end
end;
with = function (s,wfunc)
-- s.wfunc = wfunc;
-- return s;
return setmetatable({wfunc = wfunc},{__index = s});
-- s.wfunc = wfunc
-- return s
return setmetatable({wfunc = wfunc},{__index = s})
end;
default = function (s,dvalue)
-- s.dvalue = dvalue;
-- return s;
return setmetatable({dvalue = dvalue},{__index = s});
-- s.dvalue = dvalue
-- return s
return setmetatable({dvalue = dvalue},{__index = s})
end;
tween = function (s,tvalue)
-- s.tvalue = tvalue;
-- return s;
return setmetatable({tvalue = tvalue},{__index = s});
-- s.tvalue = tvalue
-- return s
return setmetatable({tvalue = tvalue},{__index = s})
end;
---@deprecated
from = function (s,fvalue)
warn "[QUAD] register:from() is deprecated. Use register:add(t:table|function) instead";
-- s.fvalue = fvalue;
-- return s;
return setmetatable({fvalue = fvalue},{__index = s});
warn "[QUAD] register:from() is deprecated. Use register:add(t:table|function) instead"
-- s.fvalue = fvalue
-- return s
return setmetatable({fvalue = fvalue},{__index = s})
end;
add = function (s,avalue)
-- s.avalue = avalue;
-- return s;
return setmetatable({avalue = avalue},{__index = s});
-- s.avalue = avalue
-- return s
return setmetatable({avalue = avalue},{__index = s})
end;
-- return init data
calcWithDefault = function (s,withItem)
local with = s.wfunc;
local tstore = s.store;
local rawKey = s.key;
local tween = s.tvalue or tstore.__tweens[rawKey];
local from = s.fvalue;
local add = s.avalue;
local set = tstore[rawKey];
local with = s.wfunc
local tstore = s.store
local rawKey = s.key
local tween = s.tvalue or tstore.__tweens[rawKey]
local from = s.fvalue
local add = s.avalue
local set = tstore[rawKey]
if set ~= nil or (rawKey:match(",") and with) then
if add then
set = set + add;
set = set + add
end
if from then
set = from[set];
set = from[set]
end
if with then
set = with(tstore,set,rawKey,withItem);
set = with(tstore,set,rawKey,withItem)
end
return set,tween;
return set,tween
else
local dset = s.dvalue;
local dset = s.dvalue
if dset ~= nil then
return dset,tween;
return dset,tween
end
warn "[Quad] no default value found.";
warn "[Quad] no default value found."
end
end;
calcWithNewValue = function(s,withItem,newValue,key)
local with = s.wfunc;
local tstore = s.store;
local rawKey = s.key;
local tween = s.tvalue or tstore.__tweens[rawKey];
local from = s.fvalue;
local add = s.avalue;
local with = s.wfunc
local tstore = s.store
local rawKey = s.key
local tween = s.tvalue or tstore.__tweens[rawKey]
local from = s.fvalue
local add = s.avalue
if add then
newValue = newValue + add;
newValue = newValue + add
end
if from then
newValue = from[newValue];
newValue = from[newValue]
end
if with then
newValue = with(tstore,newValue,key,withItem);
newValue = with(tstore,newValue,key,withItem)
end
return newValue,tween;
return newValue,tween
end
};
registerClass.__index = registerClass;
}
registerClass.__index = registerClass
-- bindable store object
local store = {__type = "quad_store"};
local storeIdSpace = {};
local store = {__type = "quad_store"}
local storeIdSpace = {}
function store:__index(key)
local this = self.__self[key];
local this = self.__self[key]
if this ~= nil then
return this;
return this
end
return store[key];
return store[key]
end
function store:__newindex(key,value)
-- if got register, just copy data to self and connect
if type(value) == "table" and value.__type == "quad_register" then
-- warn "[Quad] adding register value on store is only allowed when init store. set value request was ignored";
-- warn "[Quad] adding register value on store is only allowed when init store. set value request was ignored"
local selfValues = self.__self;
local selfTweens = self.__tweens;
local selfValues = self.__self
local selfTweens = self.__tweens
-- fetch data from origin
do
local tstore = value.store;
local tstore = value.store
for tkey in value.key:gmatch("^[,]") do
if not selfValues[tkey] then
selfValues[tkey] = tstore[tkey];
selfValues[tkey] = tstore[tkey]
end
end
end
-- calc value
do
local setValue,tween = value:calcWithDefault(self);
selfValues[key] = setValue;
selfTweens[key] = tween;
local setValue,tween = value:calcWithDefault(self)
selfValues[key] = setValue
selfTweens[key] = tween
end
-- make event connection
value:register(function (_,newValue,eventKey)
-- !HOLD IT SELF TO PREVENT THIS REGISTER BEGIN REMOVED FROM MEMORY
local setValue = value:calcWithNewValue(self,newValue,eventKey);
self[key] = setValue;
end);
local setValue = value:calcWithNewValue(self,newValue,eventKey)
self[key] = setValue
end)
return;
return
end
self.__self[key] = value;
local event = self.__evt[key];
self.__self[key] = value
local event = self.__evt[key]
if event then
for _,v in pairs(event) do -- NO ipairs here
wrap(catch)(v,store,value,key);
wrap(catch)(v,store,value,key)
end
end
end
-- init bindings
function new.__initStoreRegisterBinding(self,withItem)
local selfTweens = self.__tweens;
local selfValues = self.__self;
local selfKeep = self.__keep;
local selfTweens = self.__tweens
local selfValues = self.__self
local selfKeep = self.__keep
for key,item in pairs(selfValues) do
if type(item) == "table" and item.__type == "quad_register" then
-- fetch data from origin
do
local tstore = item.store;
local tstore = item.store
for tkey in item.key:gmatch("^[,]") do
if not selfValues[tkey] then
selfValues[tkey] = tstore[tkey];
selfValues[tkey] = tstore[tkey]
end
end
end
-- calc value
do
local setValue,tween = item:calcWithDefault(withItem);
selfValues[key] = setValue;
selfTweens[key] = tween;
local setValue,tween = item:calcWithDefault(withItem)
selfValues[key] = setValue
selfTweens[key] = tween
end
-- make event connection
local function regFn(_,newValue,eventKey)
-- !HOLD IT SELF TO PREVENT THIS REGISTER BEGIN REMOVED FROM MEMORY
local setValue = item:calcWithNewValue(withItem,newValue,eventKey);
self[key] = setValue;
local setValue = item:calcWithNewValue(withItem,newValue,eventKey)
self[key] = setValue
end
item:register(regFn);
insert(selfKeep,item);
insert(selfKeep,regFn);
item:register(regFn)
insert(selfKeep,item)
insert(selfKeep,regFn)
end
end
end
-- create register
function store:__call(key,func)
local last = self.__self[key];
local last = self.__self[key]
if last and type(last) == "table" and getmetatable(last) == registerClass then
return last;
return last
end
local register = self.__reg[key];
local register = self.__reg[key]
if not register then
register = setmetatable({
key = key;
store = self;
},registerClass);
self.__reg[key] = register;
},registerClass)
self.__reg[key] = register
end
if func then
register.register(func);
register.register(func)
end
return register;
return register
end
function store:default(key,value)
if self[key] == nil then
self[key] = value;
return;
self[key] = value
return
end
end
function new.new(self,id)
@ -332,18 +332,18 @@ function module.init(shared)
__tweens = {}, -- tweens (if inited with register, save tween and use as default tween data)
__keep = {} -- store data which should not be destoryed
},store
);
)
if id then -- save in id space
storeIdSpace[id] = this;
storeIdSpace[id] = this
end
return this;
return this
end
local storeNew = new.new;
local storeNew = new.new
function new.getStore(id)
return storeIdSpace[id] or storeNew({},id);
return storeIdSpace[id] or storeNew({},id)
end
return new;
return new
end
return module;
return module