change build system
This commit is contained in:
parent
9ec0bf5377
commit
24a6e0f6b7
6 changed files with 18 additions and 672 deletions
9
build.project.json
Normal file
9
build.project.json
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"name": "Plugin",
|
||||
"tree": {
|
||||
"$properties": {
|
||||
"Name": "quad"
|
||||
},
|
||||
"$path": "src"
|
||||
}
|
||||
}
|
||||
648
build.rbxmx
648
build.rbxmx
|
|
@ -1,648 +0,0 @@
|
|||
<roblox version="4">
|
||||
<Item class="ModuleScript" referent="0">
|
||||
<Properties>
|
||||
<string name="Name">Plugin</string>
|
||||
<string name="Name">quad</string>
|
||||
<string name="Source"><![CDATA[local module = {};
|
||||
|
||||
-- TODO : style should be can edited with anytimes, and the object's styles can be changed (add, remove ...)
|
||||
-- and also, styles can be affect by the objects sorts
|
||||
--[[
|
||||
this feature should be like :
|
||||
|
||||
local style_all = style {
|
||||
BackgroundTransparency = 0.2;
|
||||
}
|
||||
|
||||
frame{
|
||||
Size = UDim2.new(1,0,1,0);
|
||||
textBox "#Input" {
|
||||
[event.property "Text"] = function (this,text)
|
||||
print(this,"의 글자가",text,"로 변경됨");
|
||||
end;
|
||||
};
|
||||
[style.set] = {
|
||||
style_all
|
||||
};
|
||||
};
|
||||
|
||||
]]
|
||||
|
||||
local require = require(script.require);
|
||||
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"
|
||||
|
||||
function module.init()
|
||||
local this = {items = {}};
|
||||
|
||||
this.event = event.init(this);
|
||||
this.store = store.init(this);
|
||||
--this.style = style.init(this);
|
||||
this.class = class.init(this);
|
||||
this.mount = mount.init(this);
|
||||
|
||||
--this.makeClass = makeClass;
|
||||
--this.tween = tween;
|
||||
--this.plugin = plugin;
|
||||
|
||||
return this;
|
||||
end
|
||||
|
||||
return module;
|
||||
]]></string>
|
||||
</Properties>
|
||||
<Item class="ModuleScript" referent="1">
|
||||
<Properties>
|
||||
<string name="Name">class</string>
|
||||
<string name="Source">local module = {};
|
||||
|
||||
-- local exportItemMeta = {
|
||||
-- __index = function (self,key)
|
||||
-- local methods = self.__methods;
|
||||
-- local events = self.__events;
|
||||
-- return (methods and methods[key]) or (events and events[key]) or (self.getters[key](self.__this));
|
||||
-- end;
|
||||
-- __newindex = function (self,key,value)
|
||||
-- self.__setters[key](self.__this,value);
|
||||
-- end;
|
||||
-- };
|
||||
|
||||
function module.init(shared)
|
||||
local new = {};
|
||||
local bind = shared.event.bind;
|
||||
local addObject = shared.store.addObject;
|
||||
local storeNew = shared.store.new;
|
||||
|
||||
function new.getHolder(item)
|
||||
return (type(item) == "table") and (item._holder or item.holder or item.__holder) or item;
|
||||
end
|
||||
local getHolder = new.getHolder;
|
||||
|
||||
-- make object that from instance, class and more
|
||||
function new.make(ClassName,...) -- render object
|
||||
-- make thing
|
||||
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 = Instance.new(ClassName);
|
||||
elseif classOfClassName == "function" then -- if classname is a function value, call it for making new object (OOP object)
|
||||
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;
|
||||
if ClassName.__noSetup then -- if is support initing props
|
||||
local childs,props = {},{...};
|
||||
local parsed;
|
||||
for iprop = #props,1,-1 do
|
||||
local prop = props[iprop];
|
||||
for i,v in ipairs(prop) do
|
||||
childs[i] = ((iprop == 1) and v or v:Clone());
|
||||
prop[i] = nil;
|
||||
end
|
||||
if next(prop) then -- there are (key/value)s
|
||||
if parsed then
|
||||
for i,v in pairs(prop) do
|
||||
parsed[i] = v;
|
||||
end
|
||||
else
|
||||
parsed = prop;
|
||||
end
|
||||
end
|
||||
end
|
||||
item = func(parsed);
|
||||
local holder = getHolder(item);
|
||||
for _,v in ipairs(childs) do
|
||||
v.Parent = holder;
|
||||
end
|
||||
return item;
|
||||
end
|
||||
item = func();
|
||||
end
|
||||
if not item then -- if cannot make new object, ignore this call
|
||||
local str = tostring(ClassName);
|
||||
print(("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)
|
||||
-- for iprop,prop in ipairs({...}) do
|
||||
for iprop = select("#",...),1,-1 do
|
||||
local prop = select(iprop,...);
|
||||
for index,value in pairs(prop) do
|
||||
local valueType = typeof(value);
|
||||
local indexType = typeof(index);
|
||||
|
||||
-- child
|
||||
if indexType == "string" and valueType == "table" and value.t == "reg" then -- register (bind to store event)
|
||||
-- store binding
|
||||
local with = value.wfunc;
|
||||
local set = value.store[value.key];
|
||||
if set then
|
||||
if with then
|
||||
set = with(set);
|
||||
end
|
||||
item[index] = set;
|
||||
else
|
||||
local dset = value.dvalue;
|
||||
if dset then
|
||||
item[index] = dset;
|
||||
end
|
||||
end
|
||||
value.register(function (newValue,store)
|
||||
if with then
|
||||
newValue = with(newValue,item,store);
|
||||
end
|
||||
item[index] = newValue;
|
||||
end);
|
||||
elseif (valueType == "function" or valueType == "table") and bind(item,index,value,valueType) then -- connect event
|
||||
-- event binding
|
||||
elseif indexType == "string" then
|
||||
-- prop set
|
||||
item[index] = value; -- set property
|
||||
elseif indexType == "number" then -- object
|
||||
-- child object
|
||||
((iprop == 1) and value or value:Clone()).Parent = holder;
|
||||
end
|
||||
end
|
||||
end
|
||||
return item;
|
||||
end
|
||||
local make = new.make;
|
||||
|
||||
-- import quad object
|
||||
function new.import(ClassName,defaultProperties) -- make new quad class object
|
||||
local this = defaultProperties or {};
|
||||
setmetatable(this,{
|
||||
__call = function (self,prop)
|
||||
if type(prop) == "string" then
|
||||
local lastName = prop;
|
||||
return function (nprop)
|
||||
nprop.Name = lastName;
|
||||
local item = make(ClassName,nprop);
|
||||
addObject(lastName,item);
|
||||
return item;
|
||||
end;
|
||||
end
|
||||
return make(ClassName,prop,this);
|
||||
end;
|
||||
});
|
||||
return this;
|
||||
end
|
||||
|
||||
-- function new.export(newFn,setters,getters,methods,events) -- make quad importable class
|
||||
-- return function ()
|
||||
-- return setmetatable({
|
||||
-- __this = newFn();
|
||||
-- __setters = setters;
|
||||
-- __getters = getters;
|
||||
-- __methods = methods;
|
||||
-- __events = events;
|
||||
-- },exportItemMeta);
|
||||
-- end;
|
||||
-- end
|
||||
|
||||
-- set module calling function
|
||||
setmetatable(new,{
|
||||
__call = function (self,...)
|
||||
return new.import(...);
|
||||
end;
|
||||
});
|
||||
|
||||
-- make class
|
||||
function new.extend()
|
||||
local this = {};
|
||||
|
||||
--- make new object
|
||||
function this.new(prop)
|
||||
-- make metatable
|
||||
prop = storeNew(prop);
|
||||
local parent = prop and (prop.Parent or prop.parent);
|
||||
local self = {__prop = prop; __parent = parent};
|
||||
local init = this.init;
|
||||
if init then
|
||||
init(self,prop);
|
||||
end
|
||||
setmetatable(self,this);
|
||||
|
||||
-- render that
|
||||
local object = self:render(prop);
|
||||
rawset(self,"__object",object);
|
||||
rawset(self,"__holder",object);
|
||||
if parent then
|
||||
rawset(self,"__parent",parent);
|
||||
object.Parent = getHolder(parent);
|
||||
end
|
||||
return self;
|
||||
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 = rawget(self,"__parent") or (object and object.Parent); -- date parent
|
||||
local lastObject = object;
|
||||
if lastObject then
|
||||
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
|
||||
if lastObject then -- remove old instance
|
||||
self:Destroy(lastObject);
|
||||
end
|
||||
end
|
||||
|
||||
-- define destroy method
|
||||
function this:Destroy(object)
|
||||
local unload = rawget(self,"unload");
|
||||
object = object or rawget(self,"__object");
|
||||
if object then
|
||||
if unload then
|
||||
unload(self,object);
|
||||
else
|
||||
local destroy = (object.Destroy or object.destroy);
|
||||
if destroy then
|
||||
pcall(destroy,object);
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- link to new
|
||||
function this.__call(self,...)
|
||||
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];
|
||||
if getter then
|
||||
return getter(self,rawget(self,"__object"));
|
||||
end
|
||||
|
||||
-- from this (have more priority)
|
||||
local fromThis = this[k];
|
||||
if fromThis then
|
||||
return fromThis;
|
||||
end
|
||||
|
||||
-- from prop, not start with '_' (private value)
|
||||
if k:sub(1,1) ~= "_" then
|
||||
return self.__prop[k];
|
||||
end
|
||||
end
|
||||
|
||||
--- new indexer (setter)
|
||||
function this:__newindex(k,v)
|
||||
-- from setter
|
||||
local setter = this.setter[k];
|
||||
if setter then
|
||||
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);
|
||||
end
|
||||
|
||||
-- prop update
|
||||
self.__prop[k] = v;
|
||||
if this.updateTriggers[k] then
|
||||
self:update();
|
||||
end
|
||||
end
|
||||
|
||||
this.getter = {};
|
||||
this.setter = {
|
||||
Parent = function(self,parent,object)
|
||||
rawset(self,"__parent",parent);
|
||||
if object then
|
||||
object.Parent = getHolder(parent);
|
||||
end
|
||||
end;
|
||||
};
|
||||
this.updateTriggers = {};
|
||||
this.__noSetup = true;
|
||||
return this;
|
||||
end
|
||||
|
||||
return new;
|
||||
end
|
||||
|
||||
return module;</string>
|
||||
</Properties>
|
||||
</Item>
|
||||
<Item class="ModuleScript" referent="2">
|
||||
<Properties>
|
||||
<string name="Name">event</string>
|
||||
<string name="Source">local module = {};
|
||||
|
||||
function module.init(shared)
|
||||
local new = {};
|
||||
local unpack = table.unpack;
|
||||
local wrap = coroutine.wrap;
|
||||
|
||||
local prefix = "Event::";
|
||||
local special = {
|
||||
["Property::(.+)"] = function (this,func,property)
|
||||
this.GetPropertyChangedSignal(property):Connect(function()
|
||||
func(this,this[property]);
|
||||
end);
|
||||
end;
|
||||
["CreatedSync::"] = function (this,func)
|
||||
func(this);
|
||||
end;
|
||||
["Created::"] = function (this,func)
|
||||
wrap(func)(this);
|
||||
end;
|
||||
};
|
||||
|
||||
local prefixLen = #prefix;
|
||||
setmetatable(new,{
|
||||
__call = function(self,eventName)
|
||||
return prefix .. eventName;
|
||||
end;
|
||||
});
|
||||
|
||||
-- try binding, if key dose match with anything, ignore call
|
||||
function new.bind(this,key,func,typefunc)
|
||||
-- if is advanced binding (self setted)
|
||||
typefunc = typefunc or type(func);
|
||||
local self;
|
||||
if typefunc == "table" then
|
||||
self = func.self;
|
||||
func = func.func;
|
||||
end
|
||||
-- check prefix
|
||||
if key:sub(1,prefixLen) ~= prefix then
|
||||
return;
|
||||
elseif not func then
|
||||
return true;
|
||||
end
|
||||
key = key:sub(prefixLen + 1,-1);
|
||||
|
||||
-- find special bindings
|
||||
for specKey,specFunc in pairs(special) do
|
||||
local find = {key:match(specKey)};
|
||||
if #find ~= 0 then
|
||||
specFunc(this,func,unpack(find));
|
||||
return true;
|
||||
end
|
||||
end
|
||||
|
||||
-- binding normal events
|
||||
local event = this[key];
|
||||
if event then
|
||||
event:Connect(function(...)
|
||||
func(self or this,...);
|
||||
end);
|
||||
return true;
|
||||
end
|
||||
end
|
||||
|
||||
-- property changed binding
|
||||
local prefixProperty = prefix .. "Property::";
|
||||
function new.prop(name)
|
||||
return prefixProperty .. name;
|
||||
end
|
||||
|
||||
-- when created binding
|
||||
new.created = prefix .. "Created::";
|
||||
new.createdSync = prefix .. "CreatedSync::";
|
||||
return new;
|
||||
end
|
||||
|
||||
return module;</string>
|
||||
</Properties>
|
||||
</Item>
|
||||
<Item class="ModuleScript" referent="3">
|
||||
<Properties>
|
||||
<string name="Name">mount</string>
|
||||
<string name="Source">local module = {};
|
||||
|
||||
function module.init(shared)
|
||||
local new = {};
|
||||
|
||||
local mount = {};
|
||||
mount.__index = mount;
|
||||
function mount:unmount()
|
||||
local this = self.this;
|
||||
local typeThis = type(this);
|
||||
if typeThis == "userdata" then
|
||||
this:Destroy();
|
||||
elseif typeThis == "table" then
|
||||
pcall(function()
|
||||
this.Parent = nil;
|
||||
end);
|
||||
local destroyThis = this.Destroy;
|
||||
if destroyThis then
|
||||
pcall(destroyThis);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- we should add plugin support
|
||||
function new.mount(to,this)
|
||||
this.Parent = to;
|
||||
return setmetatable({to = to,this = this},mount);
|
||||
end
|
||||
|
||||
setmetatable(new,{
|
||||
__call = function (self,...)
|
||||
return new.mount(...);
|
||||
end;
|
||||
});
|
||||
|
||||
return new;
|
||||
end
|
||||
|
||||
return module;</string>
|
||||
</Properties>
|
||||
</Item>
|
||||
<Item class="ModuleScript" referent="4">
|
||||
<Properties>
|
||||
<string name="Name">require</string>
|
||||
<string name="Source">-- remove the roblox's require system,
|
||||
-- now, we can call modules with string path
|
||||
|
||||
if (not workspace) and (not game) and (not script) then
|
||||
return;
|
||||
end
|
||||
|
||||
return function (query)
|
||||
local typeQuery = type(query);
|
||||
|
||||
if typeQuery == "string" then
|
||||
local object = script.Parent;
|
||||
query = query:gsub("/",".");
|
||||
-- local index = 0;
|
||||
query:gsub("[^%.]+",function (this)
|
||||
-- index = index + 1;
|
||||
-- if index == 1 and this == "src" then
|
||||
-- return;
|
||||
-- end
|
||||
local lastObject = object;
|
||||
object = object[this];
|
||||
if not object then
|
||||
object = lastObject.libs
|
||||
error(("[require] : object %s was not found from this worktree, require failed"):format(query));
|
||||
end
|
||||
end);
|
||||
return require(object);
|
||||
elseif typeQuery == "userdata" then
|
||||
return require(query);
|
||||
end
|
||||
end;</string>
|
||||
</Properties>
|
||||
</Item>
|
||||
<Item class="ModuleScript" referent="5">
|
||||
<Properties>
|
||||
<string name="Name">store</string>
|
||||
<string name="Source"><![CDATA[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 function catch(...)
|
||||
local passed,err = pcall(...);
|
||||
if not passed then
|
||||
wran("[QUAD] Error occured while operating async task\n" .. tostring(err));
|
||||
end
|
||||
end
|
||||
|
||||
function module.init(shared)
|
||||
local new = {};
|
||||
local items = shared.items;
|
||||
|
||||
-- id space (array of object)
|
||||
local objSpace = {};
|
||||
function objSpace:each(func)
|
||||
for i,v in ipairs(self) do
|
||||
wrap(catch)(func,i,v);
|
||||
end
|
||||
end
|
||||
function objSpace:eachSync(func)
|
||||
for i,v in ipairs(self) do
|
||||
local ret = func(i,v);
|
||||
if ret then
|
||||
break;
|
||||
end
|
||||
end
|
||||
end
|
||||
function objSpace:remove(indexOrItem)
|
||||
local thisType = type(indexOrItem);
|
||||
if thisType == "number" then
|
||||
remove(self,indexOrItem);
|
||||
else
|
||||
for i,v in pairs(self) do
|
||||
if v == indexOrItem then
|
||||
remove(self,i);
|
||||
break;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
function objSpace.__new()
|
||||
return setmetatable({},objSpace);
|
||||
end
|
||||
function objSpace:__newIndex(key,value) -- props setter
|
||||
self:each(function (this)
|
||||
this[key] = value;
|
||||
end);
|
||||
end
|
||||
objSpace.__mode = "kv"; -- week link for gc
|
||||
objSpace.__index = objSpace;
|
||||
|
||||
-- get object array with id (objSpace)
|
||||
function new.getObjects(id)
|
||||
return items[id];
|
||||
end
|
||||
|
||||
-- get first object with id (not array)
|
||||
function new.getObject(id)
|
||||
local item = items[id];
|
||||
return item and item[1];
|
||||
end
|
||||
|
||||
--TODO: if item is exist already, ignore this call
|
||||
-- adding object with id
|
||||
function new.addObject(ids,object)
|
||||
for id in ids:gmatch("[^,]+") do -- split by ,
|
||||
-- remove trailing, heading spaces
|
||||
id = id:gsub("^ +",""):gsub(" +$","");
|
||||
local array = items[id];
|
||||
if not array then
|
||||
array = objSpace.__new();
|
||||
items[id] = array;
|
||||
end
|
||||
insert(array, object);
|
||||
end
|
||||
end
|
||||
|
||||
-- bindable store object
|
||||
local store = {};
|
||||
function store:__index(key)
|
||||
return self.__self[key];
|
||||
end
|
||||
function store:__newindex(key,value)
|
||||
self.__self[key] = value;
|
||||
local event = self.__evt[key];
|
||||
if event then
|
||||
for _,v in ipairs(event) do
|
||||
wrap(catch)(v,value,store);
|
||||
end
|
||||
end
|
||||
end
|
||||
function store:__call(key,func)
|
||||
local register = self.__reg[key];
|
||||
if not register then
|
||||
local event = {}
|
||||
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;
|
||||
key = key;
|
||||
store = self;
|
||||
t = "reg";
|
||||
};
|
||||
self.__reg[key] = register;
|
||||
end
|
||||
|
||||
if func then
|
||||
register.register(func);
|
||||
end
|
||||
return register;
|
||||
end
|
||||
function new.new(self)
|
||||
return setmetatable(
|
||||
{__self = self or {},__evt = {},__reg = {}},store
|
||||
);
|
||||
end
|
||||
|
||||
return new;
|
||||
end
|
||||
|
||||
return module;
|
||||
]]></string>
|
||||
</Properties>
|
||||
</Item>
|
||||
</Item>
|
||||
</roblox>
|
||||
2
build.sh
2
build.sh
|
|
@ -1 +1 @@
|
|||
rojo build default.project.json -o build.rbxmx
|
||||
rojo build build.project.json -o build.rbxmx
|
||||
|
|
@ -1,9 +1,12 @@
|
|||
{
|
||||
"name": "Plugin",
|
||||
"tree": {
|
||||
"$properties": {
|
||||
"Name": "quad"
|
||||
},
|
||||
"$path": "src"
|
||||
"$className": "DataModel",
|
||||
"ReplicatedStorage": {
|
||||
"$className": "ReplicatedStorage",
|
||||
"Quad": {
|
||||
"$path": "src"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
{
|
||||
"name": "Plugin",
|
||||
"tree": {
|
||||
"$className": "DataModel",
|
||||
"StarterGui": {
|
||||
"$className": "StarterGui",
|
||||
"testGUI": {
|
||||
"$className": "ScreenGui",
|
||||
"testScript": {
|
||||
"$path": "testScript.client.lua"
|
||||
},
|
||||
"quad": {
|
||||
"$path": "src"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
-- 이렇게 모듈을 부를 수 있다, 뒤에 if 가 붇은것은 자동완성이 뜨도록 하기 위해서 사용된다
|
||||
---@module "src/init.lua"
|
||||
local quad = require(script.Parent.quad);
|
||||
local quad = require(game.ReplicatedStorage:WaitForChild "Quad");
|
||||
local render = quad.init();
|
||||
-- init 함수를 이용해 여러 스크립트가 이 모듈을 호출해도 완전히 별계의
|
||||
-- 환경에서 실행될 수 있도록 만든다, init 를 호출하면 완전히 새로운 store 와 style
|
||||
|
|
|
|||
Loading…
Reference in a new issue