From 0c41e2dc9a5ccd2bdfcb74c8d8e3b5954dab83a3 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 26 Feb 2025 13:51:28 +0000 Subject: [PATCH] Update config, LuaLS definitions, bundle and changelog --- config.lua | 530 ++++---- release/basalt.lua | 3050 ++++++++++++++++++++++---------------------- 2 files changed, 1790 insertions(+), 1790 deletions(-) diff --git a/config.lua b/config.lua index b1316ae..bbf0386 100644 --- a/config.lua +++ b/config.lua @@ -1,361 +1,361 @@ return { - ["metadata"] = { - ["version"] = "2.0", - ["generated"] = "Wed Feb 26 09:20:12 2025", - }, ["categories"] = { - ["core"] = { - ["description"] = "Core Files", + ["plugins"] = { + ["description"] = "Plugins", ["files"] = { - ["elementManager"] = { - ["default"] = true, - ["size"] = 6297, + ["reactive"] = { + ["path"] = "plugins/reactive.lua", ["requires"] = { }, + ["size"] = 6962, + ["default"] = true, ["description"] = "", - ["path"] = "elementManager.lua", }, - ["errorManager"] = { - ["default"] = true, - ["size"] = 3789, + ["animation"] = { + ["path"] = "plugins/animation.lua", ["requires"] = { }, + ["size"] = 14116, + ["default"] = true, ["description"] = "", - ["path"] = "errorManager.lua", }, - ["propertySystem"] = { - ["default"] = true, - ["size"] = 15220, + ["theme"] = { + ["path"] = "plugins/theme.lua", ["requires"] = { }, + ["size"] = 5885, + ["default"] = true, ["description"] = "", - ["path"] = "propertySystem.lua", }, - ["init"] = { - ["default"] = true, - ["size"] = 519, + ["state"] = { + ["path"] = "plugins/state.lua", ["requires"] = { }, + ["size"] = 5867, + ["default"] = true, ["description"] = "", - ["path"] = "init.lua", }, - ["main"] = { - ["default"] = true, - ["size"] = 7905, + ["benchmark"] = { + ["path"] = "plugins/benchmark.lua", ["requires"] = { }, + ["size"] = 12515, + ["default"] = true, ["description"] = "", - ["path"] = "main.lua", }, - ["render"] = { - ["default"] = true, - ["size"] = 10935, + ["debug"] = { + ["path"] = "plugins/debug.lua", ["requires"] = { }, + ["size"] = 6175, + ["default"] = true, ["description"] = "", - ["path"] = "render.lua", }, - ["log"] = { - ["default"] = true, - ["size"] = 3142, + ["xml"] = { + ["path"] = "plugins/xml.lua", ["requires"] = { }, + ["size"] = 6389, + ["default"] = true, ["description"] = "", - ["path"] = "log.lua", }, }, }, ["elements"] = { ["description"] = "UI Elements", ["files"] = { - ["BaseFrame"] = { - ["default"] = true, - ["size"] = 5542, - ["requires"] = { - [1] = "Container", - }, - ["description"] = "This is the base frame class. It is the root element of all elements and the only element without a parent.", - ["path"] = "elements/BaseFrame.lua", - }, - ["ProgressBar"] = { - ["default"] = true, - ["size"] = 2273, - ["requires"] = { - [1] = "VisualElement", - }, - ["description"] = "", - ["path"] = "elements/ProgressBar.lua", - }, - ["Slider"] = { - ["default"] = true, - ["size"] = 4678, - ["requires"] = { - [1] = "VisualElement", - }, - ["description"] = "", - ["path"] = "elements/Slider.lua", - }, - ["Label"] = { - ["default"] = true, - ["size"] = 2948, - ["requires"] = { - [1] = "VisualElement", - }, - ["description"] = "A simple text display element that automatically resizes its width based on the text content.", - ["path"] = "elements/Label.lua", - }, - ["Image"] = { - ["default"] = false, - ["size"] = 7894, - ["requires"] = { - [1] = "VisualElement", - }, - ["description"] = "An element that displays an image in bimg format", - ["path"] = "elements/Image.lua", - }, - ["Program"] = { - ["default"] = true, - ["size"] = 6295, - ["requires"] = { - [1] = "VisualElement", - }, - ["description"] = "", - ["path"] = "elements/Program.lua", - }, - ["Menu"] = { - ["default"] = true, - ["size"] = 4658, + ["Dropdown"] = { + ["path"] = "elements/Dropdown.lua", ["requires"] = { [1] = "List", }, - ["description"] = "A horizontal menu bar with selectable items.", - ["path"] = "elements/Menu.lua", + ["size"] = 5896, + ["default"] = false, + ["description"] = "A dropdown menu that shows a list of selectable items", }, - ["Frame"] = { - ["default"] = true, - ["size"] = 4291, + ["BaseFrame"] = { + ["path"] = "elements/BaseFrame.lua", ["requires"] = { [1] = "Container", }, - ["description"] = "A frame element that serves as a grouping container for other elements.", - ["path"] = "elements/Frame.lua", - }, - ["Scrollbar"] = { + ["size"] = 5868, ["default"] = true, - ["size"] = 9166, - ["requires"] = { - [1] = "VisualElement", - }, - ["description"] = "", - ["path"] = "elements/Scrollbar.lua", + ["description"] = "This is the base frame class. It is the root element of all elements and the only element without a parent.", }, ["Input"] = { - ["default"] = true, - ["size"] = 7219, + ["path"] = "elements/Input.lua", ["requires"] = { [1] = "VisualElement", }, - ["description"] = "A text input field with various features", - ["path"] = "elements/Input.lua", - }, - ["Flexbox"] = { + ["size"] = 7219, ["default"] = true, - ["size"] = 11530, + ["description"] = "A text input field with various features", + }, + ["TextBox"] = { + ["path"] = "elements/TextBox.lua", + ["requires"] = { + [1] = "VisualElement", + }, + ["size"] = 10905, + ["default"] = false, + ["description"] = "A multi-line text editor component with cursor support and text manipulation features", + }, + ["Table"] = { + ["path"] = "elements/Table.lua", + ["requires"] = { + [1] = "VisualElement", + }, + ["size"] = 7589, + ["default"] = true, + ["description"] = "", + }, + ["Tree"] = { + ["path"] = "elements/Tree.lua", + ["requires"] = { + [1] = "VisualElement", + }, + ["size"] = 7887, + ["default"] = true, + ["description"] = "", + }, + ["List"] = { + ["path"] = "elements/List.lua", + ["requires"] = { + [1] = "VisualElement", + }, + ["size"] = 8302, + ["default"] = true, + ["description"] = "A scrollable list of selectable items", + }, + ["Scrollbar"] = { + ["path"] = "elements/Scrollbar.lua", + ["requires"] = { + [1] = "VisualElement", + }, + ["size"] = 9166, + ["default"] = true, + ["description"] = "", + }, + ["Image"] = { + ["path"] = "elements/Image.lua", + ["requires"] = { + [1] = "VisualElement", + }, + ["size"] = 7894, + ["default"] = false, + ["description"] = "An element that displays an image in bimg format", + }, + ["Label"] = { + ["path"] = "elements/Label.lua", + ["requires"] = { + [1] = "VisualElement", + }, + ["size"] = 2948, + ["default"] = true, + ["description"] = "A simple text display element that automatically resizes its width based on the text content.", + }, + ["BaseElement"] = { + ["path"] = "elements/BaseElement.lua", + ["requires"] = { + }, + ["size"] = 8911, + ["default"] = true, + ["description"] = "The base class for all UI elements in Basalt.", + }, + ["ProgressBar"] = { + ["path"] = "elements/ProgressBar.lua", + ["requires"] = { + [1] = "VisualElement", + }, + ["size"] = 2273, + ["default"] = true, + ["description"] = "", + }, + ["BigFont"] = { + ["path"] = "elements/BigFont.lua", + ["requires"] = { + [1] = "VisualElement", + }, + ["size"] = 20332, + ["default"] = false, + ["description"] = "", + }, + ["Frame"] = { + ["path"] = "elements/Frame.lua", ["requires"] = { [1] = "Container", }, - ["description"] = "A flexbox container that arranges its children in a flexible layout.", + ["size"] = 4291, + ["default"] = true, + ["description"] = "A frame element that serves as a grouping container for other elements.", + }, + ["Menu"] = { + ["path"] = "elements/Menu.lua", + ["requires"] = { + [1] = "List", + }, + ["size"] = 4658, + ["default"] = true, + ["description"] = "A horizontal menu bar with selectable items.", + }, + ["Slider"] = { + ["path"] = "elements/Slider.lua", + ["requires"] = { + [1] = "VisualElement", + }, + ["size"] = 4678, + ["default"] = true, + ["description"] = "", + }, + ["Flexbox"] = { ["path"] = "elements/Flexbox.lua", + ["requires"] = { + [1] = "Container", + }, + ["size"] = 11530, + ["default"] = true, + ["description"] = "A flexbox container that arranges its children in a flexible layout.", + }, + ["Checkbox"] = { + ["path"] = "elements/Checkbox.lua", + ["requires"] = { + [1] = "VisualElement", + }, + ["size"] = 2872, + ["default"] = true, + ["description"] = "", + }, + ["Program"] = { + ["path"] = "elements/Program.lua", + ["requires"] = { + [1] = "VisualElement", + }, + ["size"] = 6295, + ["default"] = true, + ["description"] = "", + }, + ["Container"] = { + ["path"] = "elements/Container.lua", + ["requires"] = { + [1] = "VisualElement", + }, + ["size"] = 22866, + ["default"] = true, + ["description"] = "The container class. It is a visual element that can contain other elements. It is the base class for all containers", }, ["VisualElement"] = { - ["default"] = true, - ["size"] = 16549, + ["path"] = "elements/VisualElement.lua", ["requires"] = { [1] = "BaseElement", }, + ["size"] = 16878, + ["default"] = true, ["description"] = "The Visual Element class which is the base class for all visual UI elements", - ["path"] = "elements/VisualElement.lua", - }, - ["Tree"] = { - ["default"] = true, - ["size"] = 7887, - ["requires"] = { - [1] = "VisualElement", - }, - ["description"] = "", - ["path"] = "elements/Tree.lua", - }, - ["Table"] = { - ["default"] = true, - ["size"] = 7589, - ["requires"] = { - [1] = "VisualElement", - }, - ["description"] = "", - ["path"] = "elements/Table.lua", }, ["Button"] = { - ["default"] = true, - ["size"] = 1632, - ["requires"] = { - [1] = "VisualElement", - }, - ["description"] = "", ["path"] = "elements/Button.lua", - }, - ["TextBox"] = { - ["default"] = false, - ["size"] = 10905, ["requires"] = { [1] = "VisualElement", }, - ["description"] = "A multi-line text editor component with cursor support and text manipulation features", - ["path"] = "elements/TextBox.lua", - }, - ["Checkbox"] = { + ["size"] = 1632, ["default"] = true, - ["size"] = 2872, - ["requires"] = { - [1] = "VisualElement", - }, ["description"] = "", - ["path"] = "elements/Checkbox.lua", }, - ["BaseElement"] = { + }, + }, + ["core"] = { + ["description"] = "Core Files", + ["files"] = { + ["log"] = { + ["path"] = "log.lua", + ["requires"] = { + }, + ["size"] = 3142, ["default"] = true, - ["size"] = 8911, - ["requires"] = { - }, - ["description"] = "The base class for all UI elements in Basalt.", - ["path"] = "elements/BaseElement.lua", - }, - ["List"] = { - ["default"] = true, - ["size"] = 8302, - ["requires"] = { - [1] = "VisualElement", - }, - ["description"] = "A scrollable list of selectable items", - ["path"] = "elements/List.lua", - }, - ["Container"] = { - ["default"] = true, - ["size"] = 22866, - ["requires"] = { - [1] = "VisualElement", - }, - ["description"] = "The container class. It is a visual element that can contain other elements. It is the base class for all containers", - ["path"] = "elements/Container.lua", - }, - ["BigFont"] = { - ["default"] = false, - ["size"] = 20332, - ["requires"] = { - [1] = "VisualElement", - }, ["description"] = "", - ["path"] = "elements/BigFont.lua", }, - ["Dropdown"] = { - ["default"] = false, - ["size"] = 5896, + ["main"] = { + ["path"] = "main.lua", ["requires"] = { - [1] = "List", }, - ["description"] = "A dropdown menu that shows a list of selectable items", - ["path"] = "elements/Dropdown.lua", + ["size"] = 7905, + ["default"] = true, + ["description"] = "", + }, + ["init"] = { + ["path"] = "init.lua", + ["requires"] = { + }, + ["size"] = 519, + ["default"] = true, + ["description"] = "", + }, + ["errorManager"] = { + ["path"] = "errorManager.lua", + ["requires"] = { + }, + ["size"] = 3789, + ["default"] = true, + ["description"] = "", + }, + ["render"] = { + ["path"] = "render.lua", + ["requires"] = { + }, + ["size"] = 10935, + ["default"] = true, + ["description"] = "", + }, + ["elementManager"] = { + ["path"] = "elementManager.lua", + ["requires"] = { + }, + ["size"] = 6297, + ["default"] = true, + ["description"] = "", + }, + ["propertySystem"] = { + ["path"] = "propertySystem.lua", + ["requires"] = { + }, + ["size"] = 15220, + ["default"] = true, + ["description"] = "", }, }, }, ["libraries"] = { ["description"] = "Libraries", ["files"] = { - ["utils"] = { - ["default"] = true, - ["size"] = 2661, + ["expect"] = { + ["path"] = "libraries/expect.lua", ["requires"] = { }, + ["size"] = 880, + ["default"] = true, ["description"] = "", + }, + ["utils"] = { ["path"] = "libraries/utils.lua", + ["requires"] = { + }, + ["size"] = 2661, + ["default"] = true, + ["description"] = "", }, ["colorHex"] = { - ["default"] = true, - ["size"] = 132, - ["requires"] = { - }, - ["description"] = "", ["path"] = "libraries/colorHex.lua", - }, - ["expect"] = { - ["default"] = true, - ["size"] = 880, ["requires"] = { }, - ["description"] = "", - ["path"] = "libraries/expect.lua", - }, - }, - }, - ["plugins"] = { - ["description"] = "Plugins", - ["files"] = { - ["xml"] = { + ["size"] = 132, ["default"] = true, - ["size"] = 6389, - ["requires"] = { - }, ["description"] = "", - ["path"] = "plugins/xml.lua", - }, - ["reactive"] = { - ["default"] = true, - ["size"] = 6962, - ["requires"] = { - }, - ["description"] = "", - ["path"] = "plugins/reactive.lua", - }, - ["animation"] = { - ["default"] = true, - ["size"] = 14116, - ["requires"] = { - }, - ["description"] = "", - ["path"] = "plugins/animation.lua", - }, - ["state"] = { - ["default"] = true, - ["size"] = 5867, - ["requires"] = { - }, - ["description"] = "", - ["path"] = "plugins/state.lua", - }, - ["debug"] = { - ["default"] = true, - ["size"] = 6175, - ["requires"] = { - }, - ["description"] = "", - ["path"] = "plugins/debug.lua", - }, - ["benchmark"] = { - ["default"] = true, - ["size"] = 12515, - ["requires"] = { - }, - ["description"] = "", - ["path"] = "plugins/benchmark.lua", - }, - ["theme"] = { - ["default"] = true, - ["size"] = 5885, - ["requires"] = { - }, - ["description"] = "", - ["path"] = "plugins/theme.lua", }, }, }, }, + ["metadata"] = { + ["generated"] = "Wed Feb 26 13:51:23 2025", + ["version"] = "2.0", + }, } \ No newline at end of file diff --git a/release/basalt.lua b/release/basalt.lua index 8e6b664..dd84a7b 100644 --- a/release/basalt.lua +++ b/release/basalt.lua @@ -5,93 +5,66 @@ local project = {} local loadedProject = {} local baseRequire = require require = function(path) if(project[path..".lua"])then if(loadedProject[path]==nil)then loadedProject[path] = project[path..".lua"]() end return loadedProject[path] end baseRequire(path) end -minified_pluginDirectory["debug"] = {} -minified_pluginDirectory["theme"] = {} -minified_pluginDirectory["reactive"] = {} -minified_pluginDirectory["xml"] = {} -minified_pluginDirectory["animation"] = {} -minified_pluginDirectory["state"] = {} -minified_pluginDirectory["benchmark"] = {} -minified_elementDirectory["Table"] = {} -minified_elementDirectory["BaseFrame"] = {} -minified_elementDirectory["ProgressBar"] = {} -minified_elementDirectory["Menu"] = {} -minified_elementDirectory["Frame"] = {} -minified_elementDirectory["Button"] = {} -minified_elementDirectory["Program"] = {} -minified_elementDirectory["Label"] = {} +minified_elementDirectory["BigFont"] = {} +minified_elementDirectory["TextBox"] = {} +minified_elementDirectory["Container"] = {} minified_elementDirectory["Image"] = {} minified_elementDirectory["Flexbox"] = {} -minified_elementDirectory["Container"] = {} -minified_elementDirectory["Slider"] = {} -minified_elementDirectory["BaseElement"] = {} -minified_elementDirectory["Checkbox"] = {} -minified_elementDirectory["Input"] = {} -minified_elementDirectory["BigFont"] = {} minified_elementDirectory["VisualElement"] = {} minified_elementDirectory["Scrollbar"] = {} -minified_elementDirectory["List"] = {} minified_elementDirectory["Tree"] = {} -minified_elementDirectory["TextBox"] = {} +minified_elementDirectory["Label"] = {} +minified_elementDirectory["Button"] = {} +minified_elementDirectory["Input"] = {} +minified_elementDirectory["BaseFrame"] = {} +minified_elementDirectory["BaseElement"] = {} +minified_elementDirectory["Frame"] = {} +minified_elementDirectory["Checkbox"] = {} +minified_elementDirectory["Program"] = {} +minified_elementDirectory["Table"] = {} +minified_elementDirectory["Slider"] = {} +minified_elementDirectory["ProgressBar"] = {} +minified_elementDirectory["List"] = {} minified_elementDirectory["Dropdown"] = {} -project["elementManager.lua"] = function(...) local ab=table.pack(...) -local bb=fs.getDir(ab[2]or"basalt")local cb=ab[1]if(bb==nil)then -error("Unable to find directory ".. -ab[2].." please report this bug to our discord.")end -local db=require("log")local _c=package.path;local ac="path;/path/?.lua;/path/?/init.lua;" -local bc=ac:gsub("path",bb)local cc={}cc._elements={}cc._plugins={}cc._APIs={} -local dc=fs.combine(bb,"elements")local _d=fs.combine(bb,"plugins") -db.info("Loading elements from "..dc) -if fs.exists(dc)then -for ad,bd in ipairs(fs.list(dc))do local cd=bd:match("(.+).lua")if cd then db.debug( -"Found element: "..cd) -cc._elements[cd]={class=nil,plugins={},loaded=false}end end end;db.info("Loading plugins from ".._d) -if -fs.exists(_d)then -for ad,bd in ipairs(fs.list(_d))do local cd=bd:match("(.+).lua") -if cd then -db.debug("Found plugin: "..cd)local dd=require(fs.combine("plugins",cd)) -if -type(dd)=="table"then -for __a,a_a in pairs(dd)do if(__a~="API")then -if(cc._plugins[__a]==nil)then cc._plugins[__a]={}end;table.insert(cc._plugins[__a],a_a)else -cc._APIs[cd]=a_a end end end end end end -if(minified)then if(minified_elementDirectory==nil)then -error("Unable to find minified_elementDirectory please report this bug to our discord.")end;for ad,bd in -pairs(minified_elementDirectory)do -cc._elements[ad:gsub(".lua","")]={class=nil,plugins={},loaded=false}end;if -(minified_pluginDirectory==nil)then -error("Unable to find minified_pluginDirectory please report this bug to our discord.")end -for ad,bd in -pairs(minified_pluginDirectory)do local cd=ad:gsub(".lua","") -local dd=require(fs.combine("plugins",cd)) -if type(dd)=="table"then -for __a,a_a in pairs(dd)do -if(__a~="API")then if(cc._plugins[__a]==nil)then -cc._plugins[__a]={}end -table.insert(cc._plugins[__a],a_a)else cc._APIs[cd]=a_a end end end end end -function cc.loadElement(ad) -if not cc._elements[ad].loaded then -package.path=bc.."rom/?"local bd=require(fs.combine("elements",ad)) -package.path=_c;cc._elements[ad]={class=bd,plugins=bd.plugins,loaded=true}db.debug( -"Loaded element: "..ad) -if(cc._plugins[ad]~=nil)then -for cd,dd in -pairs(cc._plugins[ad])do if(dd.setup)then dd.setup(bd)end -if(dd.hooks)then -for __a,a_a in pairs(dd.hooks)do -local b_a=bd[__a]if(type(b_a)~="function")then -error("Element ".. -ad.." does not have a method "..__a)end -if(type(a_a)=="function")then -bd[__a]=function(c_a,...) -local d_a=b_a(c_a,...)local _aa=a_a(c_a,...)return _aa==nil and d_a or _aa end elseif(type(a_a)=="table")then -bd[__a]=function(c_a,...)if a_a.pre then a_a.pre(c_a,...)end -local d_a=b_a(c_a,...)if a_a.post then a_a.post(c_a,...)end;return d_a end end end end;for __a,a_a in pairs(dd)do -if __a~="setup"and __a~="hooks"then bd[__a]=a_a end end end end end end -function cc.getElement(ad)if not cc._elements[ad].loaded then -cc.loadElement(ad)end;return cc._elements[ad].class end;function cc.getElementList()return cc._elements end;function cc.getAPI(ad) -return cc._APIs[ad]end;return cc end +minified_elementDirectory["Menu"] = {} +minified_pluginDirectory["xml"] = {} +minified_pluginDirectory["state"] = {} +minified_pluginDirectory["reactive"] = {} +minified_pluginDirectory["animation"] = {} +minified_pluginDirectory["debug"] = {} +minified_pluginDirectory["benchmark"] = {} +minified_pluginDirectory["theme"] = {} +project["errorManager.lua"] = function(...) local d=require("log") +local _a={tracebackEnabled=true,header="Basalt Error"}local function aa(ba,ca)term.setTextColor(ca)print(ba) +term.setTextColor(colors.white)end +function _a.error(ba) +if _a.errorHandled then error()end;term.setBackgroundColor(colors.black) +term.clear()term.setCursorPos(1,1) +aa(_a.header..":",colors.red)print()local ca=2;local da;while true do local db=debug.getinfo(ca,"Sl") +if not db then break end;da=db;ca=ca+1 end;local _b=da or +debug.getinfo(2,"Sl")local ab=_b.source:sub(2) +local bb=_b.currentline;local cb=ba +if(_a.tracebackEnabled)then local db=debug.traceback() +if db then +for _c in db:gmatch("[^\r\n]+")do +local ac,bc=_c:match("([^:]+):(%d+):") +if ac and bc then term.setTextColor(colors.lightGray) +term.write(ac)term.setTextColor(colors.gray)term.write(":") +term.setTextColor(colors.lightBlue)term.write(bc)term.setTextColor(colors.gray)_c=_c:gsub( +ac..":"..bc,"")end;aa(_c,colors.gray)end;print()end end +if ab and bb then term.setTextColor(colors.red) +term.write("Error in ")term.setTextColor(colors.white)term.write(ab) +term.setTextColor(colors.red)term.write(":") +term.setTextColor(colors.lightBlue)term.write(bb)term.setTextColor(colors.red) +term.write(": ") +if cb then cb=string.gsub(cb,"stack traceback:.*","") +if cb~=""then +aa(cb,colors.red)else aa("Error message not available",colors.gray)end else aa("Error message not available",colors.gray)end;local db=fs.open(ab,"r") +if db then local _c=""local ac=1 +repeat _c=db.readLine()if +ac==tonumber(bb)then aa("\149Line "..bb,colors.cyan) +aa(_c,colors.lightGray)break end;ac=ac+1 until not _c;db.close()end end;term.setBackgroundColor(colors.black) +d.error(ba)_a.errorHandled=true;error()end;return _a end project["propertySystem.lua"] = function(...) local ba=require("libraries/utils").deepCopy local ca=require("libraries/expect")local da=require("errorManager")local _b={}_b.__index=_b _b._properties={}local ab={}_b._setterHooks={}function _b.addSetterHook(cb) @@ -198,963 +171,274 @@ function _b:removeProperty(cb)self._values[cb]=nil;self._properties[cb]=nil;self nil local db=cb:sub(1,1):upper()..cb:sub(2)self["get"..db]=nil;self["set"..db]=nil;return self end function _b:getPropertyConfig(cb)return self._properties[cb]end;return _b end -project["main.lua"] = function(...) local cc=require("elementManager") -local dc=require("errorManager")local _d=require("propertySystem") -local ad=require("libraries/expect")local bd={}bd.traceback=true;bd._events={}bd._schedule={}bd._plugins={} -bd.LOGGER=require("log") -if(minified)then -bd.path=fs.getDir(shell.getRunningProgram())else bd.path=fs.getDir(select(2,...))end;local cd=nil;local dd=false;local __a=type;local a_a={}local b_a=10;local c_a=0;local d_a=false;local function _aa()if(d_a)then return end -c_a=os.startTimer(0.2)d_a=true end;local function aaa(_ba) -for _=1,_ba do local aba=a_a[1]if(aba)then -aba:create()end;table.remove(a_a,1)end end -local function baa(_ba,aba)if(_ba=="timer")then -if(aba==c_a)then -aaa(b_a)d_a=false;c_a=0;if(#a_a>0)then _aa()end;return true end end end -function bd.create(_ba,aba,bba,cba)if(__a(aba)=="string")then aba={name=aba}end;if(aba==nil)then -aba={name=_ba}end;local dba=cc.getElement(_ba) -if(bba)then -local _ca=_d.blueprint(dba,aba,bd,cba)table.insert(a_a,_ca)_aa()return _ca else local _ca=dba.new() -_ca:init(aba,bd)return _ca end end -function bd.createFrame()local _ba=bd.create("BaseFrame")_ba:postInit()if(cd==nil)then -cd=_ba end;return _ba end;function bd.getElementManager()return cc end;function bd.getMainFrame()if(cd==nil)then -cd=bd.createFrame()end;return cd end;function bd.setActiveFrame(_ba) -cd=_ba;cd:updateRender()end -function bd.schedule(_ba) -ad(1,_ba,"function")local aba=coroutine.create(_ba) -local bba,cba=coroutine.resume(aba) -if(bba)then -table.insert(bd._schedule,{coroutine=aba,filter=cba})else dc.header="Basalt Schedule Error"dc.error(cba)end;return aba end -function bd.removeSchedule(_ba) -for aba,bba in ipairs(bd._schedule)do if(bba.coroutine==_ba)then -table.remove(bd._schedule,aba)return true end end;return false end -local function caa(_ba,...)if(_ba=="terminate")then bd.stop()end -if baa(_ba,...)then return end;if(cd)then cd:dispatchEvent(_ba,...)end -for aba,bba in -ipairs(bd._schedule)do -if(_ba==bba.filter)or(bba.filter==nil)then -local cba,dba=coroutine.resume(bba.coroutine,_ba,...) -if(not cba)then dc.header="Basalt Schedule Error"dc.error(dba)end;bba.filter=dba end;if(coroutine.status(bba.coroutine)=="dead")then -bd.removeSchedule(bba.coroutine)end end;if bd._events[_ba]then -for aba,bba in ipairs(bd._events[_ba])do bba(...)end end end;local function daa()if(cd)then cd:render()end end;function bd.update(...)caa(...) -daa()end;function bd.stop()dd=false;term.clear() -term.setCursorPos(1,1)end -function bd.run(_ba)dd=_ba;if(_ba==nil)then dd=true end;local function aba() -daa() -while dd do caa(os.pullEventRaw())if(dd)then daa()end end end -while dd do local bba,cba=pcall(aba)if not(bba)then -dc.header="Basalt Runtime Error"dc.error(cba)end end end;function bd.getAPI(_ba)return cc.getAPI(_ba)end;return bd end -project["init.lua"] = function(...) local da={...}local _b=fs.getDir(da[2])local ab=package.path -local bb="path;/path/?.lua;/path/?/init.lua;"local cb=bb:gsub("path",_b)package.path=cb.."rom/?" -local function db(bc) -local cc=require("errorManager")cc.header="Basalt Loading Error"cc.error(bc)end;local _c,ac=pcall(require,"main")package.path=ab -if not _c then db(ac)else return ac end end -project["libraries/expect.lua"] = function(...) local c=require("errorManager") -local function d(_a,aa,ba)local ca=type(aa) -if ba=="element"then if ca=="table"and -aa.get("type")~=nil then return true end end -if ba=="color"then -if ca=="number"and aa>=1 and aa<=32768 then return true end;if ca=="string"and colors[aa]then return true end end;if ca~=ba then c.header="Basalt Type Error" -c.error(string.format("Bad argument #%d: expected %s, got %s",_a,ba,ca))end;return true end;return d end -project["libraries/colorHex.lua"] = function(...) local b={}for i=0,15 do b[2 ^i]=("%x"):format(i) -b[("%x"):format(i)]=2 ^i end;return b end -project["libraries/utils.lua"] = function(...) local d,_a=math.floor,string.len;local aa={} -function aa.getCenteredPosition(ba,ca,da)local _b=_a(ba)local ab=d( -(ca-_b+1)/2 +0.5)local bb=d(da/2 +0.5)return ab,bb end -function aa.deepCopy(ba)if type(ba)~="table"then return ba end;local ca={}for da,_b in pairs(ba)do -ca[aa.deepCopy(da)]=aa.deepCopy(_b)end;return ca end -function aa.copy(ba)local ca={}for da,_b in pairs(ba)do ca[da]=_b end;return ca end;function aa.reverse(ba)local ca={}for i=#ba,1,-1 do table.insert(ca,ba[i])end -return ca end -function aa.uuid() -return -string.format('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',math.random(0,0xffff),math.random(0,0xffff),math.random(0,0xffff), -math.random(0,0x0fff)+0x4000,math.random(0,0x3fff)+0x8000,math.random(0,0xffff),math.random(0,0xffff),math.random(0,0xffff))end -function aa.split(ba,ca)local da={}for _b in(ba..ca):gmatch("(.-)"..ca)do -table.insert(da,_b)end;return da end;function aa.removeTags(ba)return ba:gsub("{[^}]+}","")end -function aa.wrapText(ba,ca)if -ba==nil then return{}end;ba=aa.removeTags(ba)local da={} -local _b=aa.split(ba,"\n\n") -for ab,bb in ipairs(_b)do -if#bb==0 then table.insert(da,"")if ab<#_b then -table.insert(da,"")end else local cb=aa.split(bb,"\n") -for db,_c in ipairs(cb)do -local ac=aa.split(_c," ")local bc="" -for cc,dc in ipairs(ac)do if#bc==0 then bc=dc elseif#bc+#dc+1 <=ca then bc=bc.." "..dc else -table.insert(da,bc)bc=dc end end;if#bc>0 then table.insert(da,bc)end end;if ab<#_b then table.insert(da,"")end end end;return da end;return aa end -project["plugins/debug.lua"] = function(...) local da=require("log")local _b=require("libraries/colorHex") -local ab=10;local bb=false -local function cb(bc) -local cc={renderCount=0,eventCount={},lastRender=os.epoch("utc"),properties={},children={}} -return -{trackProperty=function(dc,_d)cc.properties[dc]=_d end,trackRender=function() -cc.renderCount=cc.renderCount+1;cc.lastRender=os.epoch("utc")end,trackEvent=function(dc)cc.eventCount[dc]=( -cc.eventCount[dc]or 0)+1 end,dump=function()return -{type=bc.get("type"),id=bc.get("id"),stats=cc}end}end;local db={}function db.debug(bc,cc)bc._debugger=cb(bc) -bc._debugLevel=cc or DEBUG_LEVELS.INFO;return bc end -function db.dumpDebug(bc)if -not bc._debugger then return end;return bc._debugger.dump()end;local _c={} -function _c.showDebugLog(bc) -if not bc._debugFrame then local cc=bc.get("width") -local dc=bc.get("height") -bc._debugFrame=bc:addFrame("basaltDebugLog"):setWidth(cc):setHeight(dc):setZ(999):listenEvent("mouse_scroll",true) -bc.basalt.LOGGER.debug("Created debug log frame "..bc._debugFrame.get("name")) -bc._debugFrame:addButton("basaltDebugLogClose"):setWidth(9):setHeight(1):setX( -cc-8):setY(dc):setText("Close"):onMouseClick(function() -bc:hideDebugLog()end)bc._debugFrame._scrollOffset=0 -bc._debugFrame._processedLogs={} -local function _d(__a,a_a)local b_a={}while#__a>0 do local c_a=__a:sub(1,a_a)table.insert(b_a,c_a)__a=__a:sub( -a_a+1)end;return b_a end -local function ad()local __a={}local a_a=bc._debugFrame.get("width") -for b_a,c_a in -ipairs(da._logs)do local d_a=_d(c_a.message,a_a)for _aa,aaa in ipairs(d_a)do -table.insert(__a,{text=aaa,level=c_a.level})end end;return __a end;local bd=#ad()-bc.get("height")bc._scrollOffset=bd -local cd=bc._debugFrame.render -bc._debugFrame.render=function(__a)cd(__a)__a._processedLogs=ad() -local a_a=__a.get("height")-2;local b_a=#__a._processedLogs;local c_a=math.max(0,b_a-a_a) -__a._scrollOffset=math.min(__a._scrollOffset,c_a) -for i=1,a_a-2 do local d_a=i+__a._scrollOffset -local _aa=__a._processedLogs[d_a] -if _aa then -local aaa= - -_aa.level==da.LEVEL.ERROR and colors.red or _aa.level== -da.LEVEL.WARN and colors.yellow or _aa.level==da.LEVEL.DEBUG and colors.lightGray or colors.white;__a:textFg(2,i,_aa.text,aaa)end end end;local dd=bc._debugFrame.dispatchEvent -bc._debugFrame.dispatchEvent=function(__a,a_a,b_a,...) +project["render.lua"] = function(...) local _a=require("libraries/colorHex")local aa=require("log") +local ba={}ba.__index=ba;local ca=string.sub +function ba.new(da)local _b=setmetatable({},ba) +_b.terminal=da;_b.width,_b.height=da.getSize() +_b.buffer={text={},fg={},bg={},dirtyRects={}} +for y=1,_b.height do _b.buffer.text[y]=string.rep(" ",_b.width) +_b.buffer.fg[y]=string.rep("0",_b.width)_b.buffer.bg[y]=string.rep("f",_b.width)end;return _b end;function ba:addDirtyRect(da,_b,ab,bb) +table.insert(self.buffer.dirtyRects,{x=da,y=_b,width=ab,height=bb})return self end +function ba:blit(da,_b,ab,bb,cb)if +_b<1 or _b>self.height then return self end;if(#ab~=#bb or +#ab~=#cb)then +error("Text, fg, and bg must be the same length")end +self.buffer.text[_b]=ca(self.buffer.text[_b]:sub(1, +da-1)..ab.. +self.buffer.text[_b]:sub(da+#ab),1,self.width) +self.buffer.fg[_b]=ca( +self.buffer.fg[_b]:sub(1,da-1)..bb..self.buffer.fg[_b]:sub(da+#bb),1,self.width) +self.buffer.bg[_b]=ca( +self.buffer.bg[_b]:sub(1,da-1)..cb..self.buffer.bg[_b]:sub(da+#cb),1,self.width)self:addDirtyRect(da,_b,#ab,1)return self end +function ba:multiBlit(da,_b,ab,bb,cb,db,_c)if _b<1 or _b>self.height then return self end;if( +#cb~=#db or#cb~=#_c)then +error("Text, fg, and bg must be the same length")end;cb=cb:rep(ab) +db=db:rep(ab)_c=_c:rep(ab) +for dy=0,bb-1 do local ac=_b+dy +if ac>=1 and ac<=self.height then +self.buffer.text[ac]=ca(self.buffer.text[ac]:sub(1, +da-1)..cb.. +self.buffer.text[ac]:sub(da+#cb),1,self.width) +self.buffer.fg[ac]=ca( +self.buffer.fg[ac]:sub(1,da-1)..db..self.buffer.fg[ac]:sub(da+#db),1,self.width) +self.buffer.bg[ac]=ca( +self.buffer.bg[ac]:sub(1,da-1).._c..self.buffer.bg[ac]:sub(da+#_c),1,self.width)end end;self:addDirtyRect(da,_b,ab,bb)return self end +function ba:textFg(da,_b,ab,bb)if _b<1 or _b>self.height then return self end +bb=_a[bb]or"0"bb=bb:rep(#ab) +self.buffer.text[_b]=ca(self.buffer.text[_b]:sub(1, +da-1)..ab.. +self.buffer.text[_b]:sub(da+#ab),1,self.width) +self.buffer.fg[_b]=ca( +self.buffer.fg[_b]:sub(1,da-1)..bb..self.buffer.fg[_b]:sub(da+#bb),1,self.width)self:addDirtyRect(da,_b,#ab,1)return self end +function ba:textBg(da,_b,ab,bb)if _b<1 or _b>self.height then return self end +bb=_a[bb]or"f" +self.buffer.text[_b]=ca( +self.buffer.text[_b]:sub(1,da-1).. +ab..self.buffer.text[_b]:sub(da+#ab),1,self.width) +self.buffer.bg[_b]=ca( +self.buffer.bg[_b]:sub(1,da-1).. +bb:rep(#ab)..self.buffer.bg[_b]:sub(da+#ab),1,self.width)self:addDirtyRect(da,_b,#ab,1)return self end +function ba:text(da,_b,ab)if _b<1 or _b>self.height then return self end +self.buffer.text[_b]=ca(self.buffer.text[_b]:sub(1, +da-1)..ab.. +self.buffer.text[_b]:sub(da+#ab),1,self.width)self:addDirtyRect(da,_b,#ab,1)return self end +function ba:fg(da,_b,ab)if _b<1 or _b>self.height then return self end +self.buffer.fg[_b]=ca(self.buffer.fg[_b]:sub(1, +da-1)..ab.. +self.buffer.fg[_b]:sub(da+#ab),1,self.width)self:addDirtyRect(da,_b,#ab,1)return self end +function ba:bg(da,_b,ab)if _b<1 or _b>self.height then return self end +self.buffer.bg[_b]=ca(self.buffer.bg[_b]:sub(1, +da-1)..ab.. +self.buffer.bg[_b]:sub(da+#ab),1,self.width)self:addDirtyRect(da,_b,#ab,1)return self end +function ba:clear(da)local _b=_a[da]or"f" +for y=1,self.height do +self.buffer.text[y]=string.rep(" ",self.width)self.buffer.fg[y]=string.rep("0",self.width) +self.buffer.bg[y]=string.rep(_b,self.width)self:addDirtyRect(1,y,self.width,1)end;return self end +function ba:render()local da={} +for _b,ab in ipairs(self.buffer.dirtyRects)do local bb=false;for cb,db in ipairs(da)do if -(a_a=="mouse_scroll")then -__a._scrollOffset=math.max(0,__a._scrollOffset+b_a)__a:updateRender()return true else dd(__a,a_a,b_a,...)end end end;bc._debugFrame.set("visible",true)return bc end -function _c.hideDebugLog(bc)if bc._debugFrame then -bc._debugFrame.set("visible",false)end;return bc end;function _c.toggleDebugLog(bc)if bc._debugFrame and bc._debugFrame:isVisible()then -bc:hideDebugLog()else bc:showDebugLog()end -return bc end -local ac={} -function ac.debugChildren(bc,cc)bc:debug(cc)for dc,_d in pairs(bc.get("children"))do if _d.debug then -_d:debug(cc)end end;return bc end;return{BaseElement=db,Container=ac,BaseFrame=_c} end -project["plugins/theme.lua"] = function(...) -local _b={default={background=colors.lightGray,foreground=colors.black},BaseFrame={background=colors.white,foreground=colors.black,Frame={background=colors.black,names={basaltDebugLogClose={background=colors.blue,foreground=colors.white}}},Button={background="{self.clicked and colors.black or colors.cyan}",foreground="{self.clicked and colors.cyan or colors.black}"},names={basaltDebugLog={background=colors.red,foreground=colors.white},test={background="{self.clicked and colors.black or colors.green}",foreground="{self.clicked and colors.green or colors.black}"}}}}local ab={default=_b}local bb="default" -local cb={hooks={postInit={pre=function(dc)dc:applyTheme()end}}} -function cb.____getElementPath(dc,_d)if _d then table.insert(_d,1,dc._values.type)else -_d={dc._values.type}end;local ad=dc.parent;if ad then return -ad.____getElementPath(ad,_d)else return _d end end -local function db(dc,_d)local ad=dc -for i=1,#_d do local bd=false;local cd=_d[i]for dd,__a in ipairs(cd)do -if ad[__a]then ad=ad[__a]bd=true;break end end;if not bd then return nil end end;return ad end -local function _c(dc,_d)local ad={} -if dc.default then for bd,cd in pairs(dc.default)do -if type(cd)~="table"then ad[bd]=cd end end;if dc.default[_d]then -for bd,cd in -pairs(dc.default[_d])do if type(cd)~="table"then ad[bd]=cd end end end end;return ad end -local function ac(dc,_d,ad,bd,cd) -if -_d.default and _d.default.names and _d.default.names[bd]then for dd,__a in pairs(_d.default.names[bd])do -if type(__a)~="table"then dc[dd]=__a end end end -if - -_d.default and _d.default[ad]and _d.default[ad].names and _d.default[ad].names[bd]then -for dd,__a in pairs(_d.default[ad].names[bd])do if -type(__a)~="table"then dc[dd]=__a end end end;if cd and cd.names and cd.names[bd]then -for dd,__a in pairs(cd.names[bd])do if type(__a)~= -"table"then dc[dd]=__a end end end end -local function bc(dc,_d,ad,bd)local cd={}local dd=db(dc,_d) -if dd then for __a,a_a in pairs(dd)do -if type(a_a)~="table"then cd[__a]=a_a end end end;if next(cd)==nil then cd=_c(dc,ad)end;ac(cd,dc,ad,bd,dd) -return cd end -function cb:applyTheme()local dc=self:getTheme()if(dc~=nil)then -for _d,ad in pairs(dc)do self.set(_d,ad)end end end -function cb:getTheme()local dc=self:____getElementPath() -local _d=self.get("type")local ad=self.get("name")return bc(ab[bb],dc,_d,ad)end;local cc={}function cc.setTheme(dc)ab.default=dc end -function cc.getTheme()return ab.default end -function cc.loadTheme(dc)local _d=fs.open(dc,"r")if _d then local ad=_d.readAll()_d.close() -ab.default=textutils.unserializeJSON(ad)end end;return{BaseElement=cb,API=cc} end -project["plugins/reactive.lua"] = function(...) local ab=require("errorManager") -local bb=require("propertySystem")local cb={colors=true,math=true,clamp=true,round=true} -local db={clamp=function(ad,bd,cd)return -math.min(math.max(ad,bd),cd)end,round=function(ad) -return math.floor(ad+0.5)end} -local function _c(ad,bd,cd)ad=ad:gsub("^{(.+)}$","%1") -ad=ad:gsub("([%w_]+)%$([%w_]+)",function(b_a,c_a) -if b_a=="self"then return -string.format('__getState("%s")',c_a)elseif b_a=="parent"then return -string.format('__getParentState("%s")',c_a)else return -string.format('__getElementState("%s", "%s")',b_a,c_a)end end) -ad=ad:gsub("([%w_]+)%.([%w_]+)",function(b_a,c_a)if cb[b_a]then return b_a.."."..c_a end;return -string.format('__getProperty("%s", "%s")',b_a,c_a)end) -local dd=setmetatable({colors=colors,math=math,tostring=tostring,tonumber=tonumber,__getState=function(b_a)return bd:getState(b_a)end,__getParentState=function(b_a)return -bd.parent:getState(b_a)end,__getElementState=function(b_a,c_a) -local d_a=bd:getBaseFrame():getChild(b_a)if not d_a then ab.header="Reactive evaluation error" -ab.error("Could not find element: "..b_a)return nil end;return -d_a:getState(c_a).value end,__getProperty=function(b_a,c_a) -if -b_a=="self"then return bd.get(c_a)elseif b_a=="parent"then -return bd.parent.get(c_a)else local d_a=bd.parent:getChild(b_a)if not d_a then -ab.header="Reactive evaluation error" -ab.error("Could not find element: "..b_a)return nil end -return d_a.get(c_a)end end},{__index=db})if(bd._properties[cd].type=="string")then -ad="tostring("..ad..")"elseif(bd._properties[cd].type=="number")then -ad="tonumber("..ad..")"end;local __a,a_a=load("return ".. -ad,"reactive","t",dd) -if not __a then -ab.header="Reactive evaluation error"ab.error("Invalid expression: "..a_a)return -function()return nil end end;return __a end -local function ac(ad,bd) -for cd in ad:gmatch("([%w_]+)%.")do -if not cb[cd]then -if cd=="self"then elseif cd=="parent"then -if not bd.parent then -ab.header="Reactive evaluation error"ab.error("No parent element available")return false end else local dd=bd.parent:getChild(cd)if not dd then -ab.header="Reactive evaluation error" -ab.error("Referenced element not found: "..cd)return false end end end end;return true end;local bc=setmetatable({},{__mode="k"}) -local cc=setmetatable({},{__mode="k",__index=function(ad,bd)ad[bd]={} -return ad[bd]end}) -local function dc(ad,bd,cd) -if cc[ad][cd]then for __a,a_a in ipairs(cc[ad][cd])do -a_a.target:removeObserver(a_a.property,a_a.callback)end end;local dd={} -for __a,a_a in bd:gmatch("([%w_]+)%.([%w_]+)")do -if not cb[__a]then local b_a;if __a=="self"then b_a=ad elseif -__a=="parent"then b_a=ad.parent else -b_a=ad:getBaseFrame():getChild(__a)end;if b_a then -local c_a={target=b_a,property=a_a,callback=function() -ad:updateRender()end}b_a:observe(a_a,c_a.callback) -table.insert(dd,c_a)end end end;cc[ad][cd]=dd end -bb.addSetterHook(function(ad,bd,cd,dd) -if type(cd)=="string"and cd:match("^{.+}$")then -local __a=cd:gsub("^{(.+)}$","%1")if not ac(__a,ad)then return dd.default end;dc(ad,__a,bd)if -not bc[ad]then bc[ad]={}end;if not bc[ad][cd]then local a_a=_c(cd,ad,bd) -bc[ad][cd]=a_a end -return -function(a_a)local b_a,c_a=pcall(bc[ad][cd]) -if not b_a then -ab.header="Reactive evaluation error" -if type(c_a)=="string"then -ab.error("Error evaluating expression: "..c_a)else ab.error("Error evaluating expression")end;return dd.default end;return c_a end end end)local _d={} -_d.hooks={destroy=function(ad) -if cc[ad]then -for bd,cd in pairs(cc[ad])do for dd,__a in ipairs(cd)do -__a.target:removeObserver(__a.property,__a.callback)end end;cc[ad]=nil end end}return{BaseElement=_d} end -project["plugins/xml.lua"] = function(...) local da=require("errorManager") -local function _b(bc)local cc={attributes={}} -cc.name=bc:match("<(%w+)") -for dc,_d in bc:gmatch('%s(%w+)="([^"]-)"')do cc.attributes[dc]=_d end;return cc end -local function ab(bc,cc)local dc={}local _d={children={}}local ad=_d;local bd=false;local cd="" -for dd in cc:gmatch("[^\r\n]+")do -dd=dd:match("^%s*(.-)%s*$") -if dd:match("^$")and bd then bd=false -ad.content=cd elseif bd then cd=cd..dd.."\n"elseif dd:match("^<[^/]")then local __a=_b(dd)__a.children={} -__a.content=""table.insert(ad.children,__a)if not dd:match("/>$")then -table.insert(dc,ad)ad=__a end elseif dd:match("^0 then _d(__a,b_a,cd)end end end end;_d(dc,self,cc)return self end;return{BaseElement=_c,Container=ac} end -project["plugins/animation.lua"] = function(...) local aa={} -local ba={linear=function(ab)return ab end,easeInQuad=function(ab)return ab*ab end,easeOutQuad=function(ab)return -1 - (1 -ab)* (1 -ab)end,easeInOutQuad=function(ab)if ab<0.5 then return 2 *ab*ab end;return 1 - ( --2 *ab+2)^2 /2 end}local ca={}ca.__index=ca -function ca.new(ab,bb,cb,db,_c)local ac=setmetatable({},ca)ac.element=ab -ac.type=bb;ac.args=cb;ac.duration=db or 1;ac.startTime=0;ac.isPaused=false -ac.handlers=aa[bb]ac.easing=_c;return ac end;function ca:start()self.startTime=os.epoch("local")/1000;if -self.handlers.start then self.handlers.start(self)end +self:rectOverlaps(ab,db)then self:mergeRects(db,ab)bb=true;break end end;if not bb then +table.insert(da,ab)end end +for _b,ab in ipairs(da)do +for y=ab.y,ab.y+ab.height-1 do +if y>=1 and y<=self.height then +self.terminal.setCursorPos(ab.x,y) +self.terminal.blit(self.buffer.text[y]:sub(ab.x,ab.x+ab.width-1),self.buffer.fg[y]:sub(ab.x, +ab.x+ab.width-1),self.buffer.bg[y]:sub(ab.x, +ab.x+ab.width-1))end end end;self.buffer.dirtyRects={} +if self.blink then +self.terminal.setTextColor(self.cursorColor or +colors.white) +self.terminal.setCursorPos(self.xCursor,self.yCursor)self.terminal.setCursorBlink(true)else +self.terminal.setCursorBlink(false)end;return self end +function ba:rectOverlaps(da,_b)return +not( +da.x+da.width<=_b.x or _b.x+_b.width<=da.x or da.y+da.height<=_b.y or +_b.y+_b.height<=da.y)end +function ba:mergeRects(da,_b)local ab=math.min(da.x,_b.x) +local bb=math.min(da.y,_b.y) +local cb=math.max(da.x+da.width,_b.x+_b.width) +local db=math.max(da.y+da.height,_b.y+_b.height)da.x=ab;da.y=bb;da.width=cb-ab;da.height=db-bb end +function ba:setCursor(da,_b,ab,bb) +if bb~=nil then self.terminal.setTextColor(bb)end;self.terminal.setCursorPos(da,_b) +self.terminal.setCursorBlink(ab)self.xCursor=da;self.yCursor=_b;self.blink=ab;self.cursorColor=bb return self end -function ca:update(ab)local bb=math.min(1, -ab/self.duration) -local cb=ba[self.easing](bb)return self.handlers.update(self,cb)end;function ca:complete()if self.handlers.complete then -self.handlers.complete(self)end end -local da={}da.__index=da -function da.registerAnimation(ab,bb)aa[ab]=bb -da[ab]=function(cb,...)local db={...}local _c="linear" -if( -type(db[#db])=="string")then _c=table.remove(db,#db)end;local ac=table.remove(db,#db) -return cb:addAnimation(ab,db,ac,_c)end end;function da.registerEasing(ab,bb)ba[ab]=bb end -function da.new(ab)local bb={}bb.element=ab -bb.sequences={{}}bb.sequenceCallbacks={}bb.currentSequence=1;bb.timer=nil -setmetatable(bb,da)return bb end -function da:sequence()table.insert(self.sequences,{})self.currentSequence=# -self.sequences;self.sequenceCallbacks[self.currentSequence]={start=nil,update=nil,complete= -nil}return self end -function da:onStart(ab) -if -not self.sequenceCallbacks[self.currentSequence]then self.sequenceCallbacks[self.currentSequence]={}end -self.sequenceCallbacks[self.currentSequence].start=ab;return self end -function da:onUpdate(ab) -if -not self.sequenceCallbacks[self.currentSequence]then self.sequenceCallbacks[self.currentSequence]={}end -self.sequenceCallbacks[self.currentSequence].update=ab;return self end -function da:onComplete(ab) -if -not self.sequenceCallbacks[self.currentSequence]then self.sequenceCallbacks[self.currentSequence]={}end -self.sequenceCallbacks[self.currentSequence].complete=ab;return self end -function da:addAnimation(ab,bb,cb,db)local _c=ca.new(self.element,ab,bb,cb,db) -table.insert(self.sequences[self.currentSequence],_c)return self end -function da:start()self.currentSequence=1 -if -(self.sequenceCallbacks[self.currentSequence])then if(self.sequenceCallbacks[self.currentSequence].start)then -self.sequenceCallbacks[self.currentSequence].start(self.element)end end -if -#self.sequences[self.currentSequence]>0 then self.timer=os.startTimer(0.05)for ab,bb in -ipairs(self.sequences[self.currentSequence])do bb:start()end end;return self end -function da:event(ab,bb) -if ab=="timer"and bb==self.timer then -local cb=os.epoch("local")/1000;local db=true;local _c={} -local ac=self.sequenceCallbacks[self.currentSequence] -for bc,cc in ipairs(self.sequences[self.currentSequence])do -local dc=cb-cc.startTime;local _d=dc/cc.duration;local ad=cc:update(dc)if ac and ac.update then -ac.update(self.element,_d)end;if not ad then table.insert(_c,cc)db=false else -cc:complete()end end -if db then -if ac and ac.complete then ac.complete(self.element)end -if self.currentSequence<#self.sequences then -self.currentSequence=self.currentSequence+1;_c={} -local bc=self.sequenceCallbacks[self.currentSequence]if bc and bc.start then bc.start(self.element)end -for cc,dc in -ipairs(self.sequences[self.currentSequence])do dc:start()table.insert(_c,dc)end end end;if#_c>0 then self.timer=os.startTimer(0.05)end end end -da.registerAnimation("move",{start=function(ab)ab.startX=ab.element.get("x") -ab.startY=ab.element.get("y")end,update=function(ab,bb)local cb=ab.startX+ -(ab.args[1]-ab.startX)*bb;local db=ab.startY+ -(ab.args[2]-ab.startY)*bb -ab.element.set("x",math.floor(cb))ab.element.set("y",math.floor(db))return bb>=1 end,complete=function(ab) -ab.element.set("x",ab.args[1])ab.element.set("y",ab.args[2])end}) -da.registerAnimation("moveOffset",{start=function(ab)ab.startX=ab.element.get("offsetX") -ab.startY=ab.element.get("offsetY")end,update=function(ab,bb)local cb=ab.startX+ (ab.args[1]-ab.startX)* -bb;local db=ab.startY+ (ab.args[2]- -ab.startY)*bb -ab.element.set("offsetX",math.floor(cb))ab.element.set("offsetY",math.floor(db))return -bb>=1 end,complete=function(ab) -ab.element.set("offsetX",ab.args[1])ab.element.set("offsetY",ab.args[2])end}) -da.registerAnimation("morphText",{start=function(ab)local bb=ab.element.get(ab.args[1]) -local cb=ab.args[2]local db=math.max(#bb,#cb) -local _c=string.rep(" ",math.floor(db-#bb)/2)ab.startText=_c..bb.._c -ab.targetText=cb..string.rep(" ",db-#cb)ab.length=db end,update=function(ab,bb) -local cb="" -for i=1,ab.length do local db=ab.startText:sub(i,i) -local _c=ab.targetText:sub(i,i) -if bb<0.5 then -cb=cb.. (math.random()>bb*2 and db or" ")else cb=cb.. -(math.random()> (bb-0.5)*2 and" "or _c)end end;ab.element.set(ab.args[1],cb)return bb>=1 end,complete=function(ab) -ab.element.set(ab.args[1],ab.targetText:gsub("%s+$",""))end}) -da.registerAnimation("typewrite",{start=function(ab)ab.targetText=ab.args[2] -ab.element.set(ab.args[1],"")end,update=function(ab,bb) -local cb=math.floor(#ab.targetText*bb) -ab.element.set(ab.args[1],ab.targetText:sub(1,cb))return bb>=1 end}) -da.registerAnimation("fadeText",{start=function(ab)ab.chars={}for i=1,#ab.args[2]do -ab.chars[i]={char=ab.args[2]:sub(i,i),visible=false}end end,update=function(ab,bb) -local cb=""for db,_c in ipairs(ab.chars)do -if math.random()=1 end}) -da.registerAnimation("scrollText",{start=function(ab)ab.width=ab.element.get("width") -ab.targetText=ab.args[2]ab.element.set(ab.args[1],"")end,update=function(ab,bb)local cb=math.floor( -ab.width* (1 -bb)) -local db=string.rep(" ",cb) -ab.element.set(ab.args[1],db..ab.targetText)return bb>=1 end})local _b={hooks={}}function _b.hooks.dispatchEvent(ab,bb,...) -if bb=="timer"then local cb=ab.get("animation")if -cb then cb:event(bb,...)end;return true end end -function _b.setup(ab) -ab.defineProperty(ab,"animation",{default= -nil,type="table"})ab.defineEvent(ab,"timer")end -function _b:animate()local ab=da.new(self)self.set("animation",ab)return ab end;return{VisualElement=_b} end -project["plugins/state.lua"] = function(...) local d=require("propertySystem") -local _a=require("errorManager")local aa={} -function aa.setup(ba) -ba.defineProperty(ba,"states",{default={},type="table"}) -ba.defineProperty(ba,"computedStates",{default={},type="table"}) -ba.defineProperty(ba,"stateUpdate",{default={key="",value=nil,oldValue=nil},type="table"})end -function aa:initializeState(ba,ca,da,_b,ab)local bb=self.get("states") -if bb[ba]then _a.error("State '".. -ba.."' already exists")return self end -if _b then local cb=ab or -("states/"..self.get("name").."_"..ba..".state") -if fs.exists(cb)then -local db=fs.open(cb,"r") -bb[ba]={value=textutils.unserialize(db.readAll()),persist=true,file=cb}db.close()else -bb[ba]={value=ca,persist=true,file=cb,canTriggerRender=da}end else bb[ba]={value=ca,canTriggerRender=da}end;return self end -function aa:setState(ba,ca)local da=self.get("states") -if not da[ba]then error("State '".. -ba.."' not initialized")end;local _b=da[ba].value;da[ba].value=ca -if da[ba].persist then -local ab=fs.getDir(da[ba].file)if not fs.exists(ab)then fs.makeDir(ab)end -local bb=fs.open(da[ba].file,"w")bb.write(textutils.serialize(ca)) -bb.close()end;if da[ba].canTriggerRender then self:updateRender()end -self.set("stateUpdate",{key=ba,value=ca,oldValue=_b})return self end -function aa:getState(ba)local ca=self.get("states") -if not ca[ba]then _a.error("State '".. -ba.."' not initialized")end;return ca[ba].value end -function aa:computed(ba,ca)local da=self.get("computedStates") -da[ba]=setmetatable({},{__call=function() -return ca(self)end})return self end -function aa:shareState(ba,...)local ca=self:getState(ba) -for da,_b in ipairs({...})do if -_b.get("states")[ba]then -_a.error("Cannot share state '"..ba.."': Target element already has this state")return self end -_b:initializeState(ba,ca) -self:observe("stateUpdate",function(ab,bb) -if bb.key==ba then _b:setState(ba,bb.value)end end)end;return self end -function aa:onStateChange(ba,ca)if not self.get("states")[ba]then -_a.error("Cannot observe state '"..ba.. -"': State not initialized")return self end -self:observe("stateUpdate",function(da,_b)if -_b.key==ba then ca(da,_b.value,_b.oldValue)end end)return self end;return{BaseElement=aa} end -project["plugins/benchmark.lua"] = function(...) local ca=require("log")local da=setmetatable({},{__mode="k"})local function _b()return -{methods={}}end -local function ab(_c,ac)local bc=_c[ac] -if not da[_c]then da[_c]=_b()end -if not da[_c].methods[ac]then -da[_c].methods[ac]={calls=0,totalTime=0,minTime=math.huge,maxTime=0,lastTime=0,startTime=0,path={},methodName=ac,originalMethod=bc}end -_c[ac]=function(cc,...)cc:startProfile(ac)local dc=bc(cc,...) -cc:endProfile(ac)return dc end end;local bb={} -function bb:startProfile(_c)local ac=da[self]if not ac then ac=_b()da[self]=ac end;if not -ac.methods[_c]then -ac.methods[_c]={calls=0,totalTime=0,minTime=math.huge,maxTime=0,lastTime=0,startTime=0,path={},methodName=_c}end -local bc=ac.methods[_c]bc.startTime=os.clock()*1000;bc.path={}local cc=self;while cc do -table.insert(bc.path,1, -cc.get("name")or cc.get("id"))cc=cc.parent end;return self end -function bb:endProfile(_c)local ac=da[self] -if not ac or not ac.methods[_c]then return self end;local bc=ac.methods[_c]local cc=os.clock()*1000 -local dc=cc-bc.startTime;bc.calls=bc.calls+1;bc.totalTime=bc.totalTime+dc -bc.minTime=math.min(bc.minTime,dc)bc.maxTime=math.max(bc.maxTime,dc)bc.lastTime=dc;return self end -function bb:benchmark(_c)if not self[_c]then -ca.error("Method ".._c.." does not exist")return self end;da[self]=_b() -da[self].methodName=_c;da[self].isRunning=true;ab(self,_c)return self end -function bb:logBenchmark(_c)local ac=da[self] -if not ac or not ac.methods[_c]then return self end;local bc=ac.methods[_c] -if bc then local cc= -bc.calls>0 and(bc.totalTime/bc.calls)or 0 -ca.info(string.format( -"Benchmark results for %s.%s: ".. -"Path: %s ".."Calls: %d ".. -"Average time: %.2fms ".."Min time: %.2fms ".."Max time: %.2fms ".. -"Last time: %.2fms ".."Total time: %.2fms",table.concat(bc.path,"."),bc.methodName,table.concat(bc.path,"/"),bc.calls,cc, -bc.minTime~=math.huge and bc.minTime or 0,bc.maxTime,bc.lastTime,bc.totalTime))end;return self end -function bb:stopBenchmark(_c)local ac=da[self] -if not ac or not ac.methods[_c]then return self end;local bc=ac.methods[_c]if bc and bc.originalMethod then -self[_c]=bc.originalMethod end;ac.methods[_c]=nil;if -not next(ac.methods)then da[self]=nil end;return self end -function bb:getBenchmarkStats(_c)local ac=da[self] -if not ac or not ac.methods[_c]then return nil end;local bc=ac.methods[_c]return -{averageTime=bc.totalTime/bc.calls,totalTime=bc.totalTime,calls=bc.calls,minTime=bc.minTime,maxTime=bc.maxTime,lastTime=bc.lastTime}end;local cb={} -function cb:benchmarkContainer(_c)self:benchmark(_c) -for ac,bc in -pairs(self.get("children"))do bc:benchmark(_c)if bc:isType("Container")then -bc:benchmarkContainer(_c)end end;return self end -function cb:logContainerBenchmarks(_c,ac)ac=ac or 0;local bc=string.rep(" ",ac)local cc=0;local dc={} -for ad,bd in -pairs(self.get("children"))do local cd=da[bd] -if cd and cd.methods[_c]then local dd=cd.methods[_c] -cc=cc+dd.totalTime -table.insert(dc,{element=bd,type=bd.get("type"),calls=dd.calls,totalTime=dd.totalTime,avgTime=dd.totalTime/dd.calls})end end;local _d=da[self] -if _d and _d.methods[_c]then local ad=_d.methods[_c] -local bd=ad.totalTime-cc;local cd=bd/ad.calls -ca.info(string.format("%sBenchmark %s (%s): ".."%.2fms/call (Self: %.2fms/call) ".. -"[Total: %dms, Calls: %d]",bc,self.get("type"),_c, -ad.totalTime/ad.calls,cd,ad.totalTime,ad.calls)) -if#dc>0 then -for dd,__a in ipairs(dc)do -if __a.element:isType("Container")then __a.element:logContainerBenchmarks(_c, -ac+1)else -ca.info(string.format("%s> %s: %.2fms/call [Total: %dms, Calls: %d]", -bc.." ",__a.type,__a.avgTime,__a.totalTime,__a.calls))end end end end;return self end -function cb:stopContainerBenchmark(_c) -for ac,bc in pairs(self.get("children"))do if bc:isType("Container")then -bc:stopContainerBenchmark(_c)else bc:stopBenchmark(_c)end end;self:stopBenchmark(_c)return self end;local db={} -function db.start(_c,ac)ac=ac or{}local bc=_b()bc.name=_c -bc.startTime=os.clock()*1000;bc.custom=true;bc.calls=0;bc.totalTime=0;bc.minTime=math.huge;bc.maxTime=0 -bc.lastTime=0;da[_c]=bc end -function db.stop(_c)local ac=da[_c]if not ac or not ac.custom then return end;local bc= -os.clock()*1000;local cc=bc-ac.startTime;ac.calls=ac.calls+1;ac.totalTime= -ac.totalTime+cc;ac.minTime=math.min(ac.minTime,cc) -ac.maxTime=math.max(ac.maxTime,cc)ac.lastTime=cc -ca.info(string.format("Custom Benchmark '%s': ".. -"Calls: %d ".."Average time: %.2fms ".. -"Min time: %.2fms ".. -"Max time: %.2fms ".."Last time: %.2fms ".."Total time: %.2fms",_c,ac.calls, -ac.totalTime/ac.calls,ac.minTime,ac.maxTime,ac.lastTime,ac.totalTime))end -function db.getStats(_c)local ac=da[_c]if not ac then return nil end;return -{averageTime=ac.totalTime/ac.calls,totalTime=ac.totalTime,calls=ac.calls,minTime=ac.minTime,maxTime=ac.maxTime,lastTime=ac.lastTime}end;function db.clear(_c)da[_c]=nil end;function db.clearAll()for _c,ac in pairs(da)do -if ac.custom then da[_c]=nil end end end;return -{BaseElement=bb,Container=cb,API=db} end -project["errorManager.lua"] = function(...) local d=require("log") -local _a={tracebackEnabled=true,header="Basalt Error"}local function aa(ba,ca)term.setTextColor(ca)print(ba) -term.setTextColor(colors.white)end -function _a.error(ba) -if _a.errorHandled then error()end;term.setBackgroundColor(colors.black) -term.clear()term.setCursorPos(1,1) -aa(_a.header..":",colors.red)print()local ca=2;local da;while true do local db=debug.getinfo(ca,"Sl") -if not db then break end;da=db;ca=ca+1 end;local _b=da or -debug.getinfo(2,"Sl")local ab=_b.source:sub(2) -local bb=_b.currentline;local cb=ba -if(_a.tracebackEnabled)then local db=debug.traceback() -if db then -for _c in db:gmatch("[^\r\n]+")do -local ac,bc=_c:match("([^:]+):(%d+):") -if ac and bc then term.setTextColor(colors.lightGray) -term.write(ac)term.setTextColor(colors.gray)term.write(":") -term.setTextColor(colors.lightBlue)term.write(bc)term.setTextColor(colors.gray)_c=_c:gsub( -ac..":"..bc,"")end;aa(_c,colors.gray)end;print()end end -if ab and bb then term.setTextColor(colors.red) -term.write("Error in ")term.setTextColor(colors.white)term.write(ab) -term.setTextColor(colors.red)term.write(":") -term.setTextColor(colors.lightBlue)term.write(bb)term.setTextColor(colors.red) -term.write(": ") -if cb then cb=string.gsub(cb,"stack traceback:.*","") -if cb~=""then -aa(cb,colors.red)else aa("Error message not available",colors.gray)end else aa("Error message not available",colors.gray)end;local db=fs.open(ab,"r") -if db then local _c=""local ac=1 -repeat _c=db.readLine()if -ac==tonumber(bb)then aa("\149Line "..bb,colors.cyan) -aa(_c,colors.lightGray)break end;ac=ac+1 until not _c;db.close()end end;term.setBackgroundColor(colors.black) -d.error(ba)_a.errorHandled=true;error()end;return _a end -project["elements/Table.lua"] = function(...) local d=require("elements/VisualElement") -local _a=require("libraries/colorHex")local aa=setmetatable({},d)aa.__index=aa -aa.defineProperty(aa,"columns",{default={},type="table"}) -aa.defineProperty(aa,"data",{default={},type="table",canTriggerRender=true}) -aa.defineProperty(aa,"selectedRow",{default=nil,type="number",canTriggerRender=true}) -aa.defineProperty(aa,"headerColor",{default=colors.blue,type="number"}) -aa.defineProperty(aa,"selectedColor",{default=colors.lightBlue,type="number"}) -aa.defineProperty(aa,"gridColor",{default=colors.gray,type="number"}) -aa.defineProperty(aa,"sortColumn",{default=nil,type="number"}) -aa.defineProperty(aa,"sortDirection",{default="asc",type="string"}) -aa.defineProperty(aa,"scrollOffset",{default=0,type="number",canTriggerRender=true})aa.defineEvent(aa,"mouse_click") -aa.defineEvent(aa,"mouse_scroll") -function aa.new()local ba=setmetatable({},aa):__init() -ba.set("width",30)ba.set("height",10)ba.set("z",5)return ba end -function aa:init(ba,ca)d.init(self,ba,ca)self.set("type","Table")return self end -function aa:sortData(ba)local ca=self.get("data") -local da=self.get("sortDirection") -table.sort(ca,function(_b,ab) -if da=="asc"then return _b[ba]ab[ba]end end)self.set("data",ca)return self end -function aa:mouse_click(ba,ca,da) -if not d.mouse_click(self,ba,ca,da)then return false end;local _b,ab=self:getRelativePosition(ca,da) -if ab==1 then local bb=1 -for cb,db in -ipairs(self.get("columns"))do -if _b>=bb and _b1 then local bb=ab-2 +self.get("scrollOffset")if bb>=0 and bb<# -self.get("data")then -self.set("selectedRow",bb+1)end end;return true end -function aa:mouse_scroll(ba,ca,da)local _b=self.get("data")local ab=self.get("height") -local bb=ab-2;local cb=math.max(0,#_b-bb+1) -local db=math.min(cb,math.max(0, -self.get("scrollOffset")+ba))self.set("scrollOffset",db)return true end -function aa:render()d.render(self)local ba=self.get("columns") -local ca=self.get("data")local da=self.get("selectedRow") -local _b=self.get("sortColumn")local ab=self.get("scrollOffset")local bb=self.get("height") -local cb=1 -for _c,ac in ipairs(ba)do local bc=ac.name;if _c==_b then -bc=bc.. (self.get("sortDirection")=="asc"and -"\30"or"\31")end -self:textFg(cb,1,bc:sub(1,ac.width),self.get("headerColor"))cb=cb+ac.width end;local db=bb-2 -for y=2,bb do local _c=y-2 +ab;local ac=ca[_c+1] -if ac and(_c+1)<=#ca then cb=1 -local bc= -(_c+1)==da and self.get("selectedColor")or self.get("background") -for cc,dc in ipairs(ba)do local _d=ac[cc]or"" -local ad=_d..string.rep(" ",dc.width-#_d) -self:blit(cb,y,ad,string.rep(_a[self.get("foreground")],dc.width),string.rep(_a[bc],dc.width))cb=cb+dc.width end else -self:blit(1,y,string.rep(" ",self.get("width")),string.rep(_a[self.get("foreground")],self.get("width")),string.rep(_a[self.get("background")],self.get("width")))end end -if#ca>bb-2 then local _c=bb-2 -local ac=math.max(1,math.floor(_c* (bb-2)/#ca))local bc=#ca- (bb-2)+1;local cc=ab/bc -local dc=2 +math.floor(cc* (_c-ac))if ab>=bc then dc=bb-ac end;for y=2,bb do -self:blit(self.get("width"),y,"\127",_a[colors.gray],_a[colors.gray])end;for y=dc,math.min(bb,dc+ac-1)do -self:blit(self.get("width"),y,"\127",_a[colors.white],_a[colors.white])end end end;return aa end -project["elements/BaseFrame.lua"] = function(...) local _a=require("elementManager") -local aa=_a.getElement("Container")local ba=require("render")local ca=setmetatable({},aa)ca.__index=ca -ca.defineProperty(ca,"term",{default= -nil,type="table",setter=function(da,_b) -if _b==nil or _b.setCursorPos==nil then return _b end;da._render=ba.new(_b)da._renderUpdate=true;local ab,bb=_b.getSize() -da.set("width",ab)da.set("height",bb)return _b end}) -function ca.new()local da=setmetatable({},ca):__init() -da.set("term",term.current())da.set("background",colors.lightGray)return da end;function ca:init(da,_b)aa.init(self,da,_b)self.set("type","BaseFrame")return -self end -function ca:multiBlit(da,_b,ab,bb,cb,db,_c)if(da<1)then ab=ab+da-1 -da=1 end;if(_b<1)then bb=bb+_b-1;_b=1 end -self._render:multiBlit(da,_b,ab,bb,cb,db,_c)end;function ca:textFg(da,_b,ab,bb)if da<1 then ab=string.sub(ab,1 -da)da=1 end -self._render:textFg(da,_b,ab,bb)end;function ca:textBg(da,_b,ab,bb)if da<1 then ab=string.sub(ab,1 - -da)da=1 end -self._render:textBg(da,_b,ab,bb)end -function ca:blit(da,_b,ab,bb,cb)if da<1 then ab=string.sub(ab,1 - -da)bb=string.sub(bb,1 -da) -cb=string.sub(cb,1 -da)da=1 end -self._render:blit(da,_b,ab,bb,cb)end;function ca:setCursor(da,_b,ab,bb)local cb=self.get("term") -self._render:setCursor(da,_b,ab,bb)end -function ca:mouse_up(da,_b,ab) -aa.mouse_up(self,da,_b,ab)aa.mouse_release(self,da,_b,ab)end -function ca:term_resize()local da,_b=self.get("term").getSize() -if(da== -self.get("width")and _b==self.get("height"))then return end;self.set("width",da)self.set("height",_b) -self._render:setSize(da,_b)self._renderUpdate=true end -function ca:key(da)self:fireEvent("key",da)aa.key(self,da)end -function ca:key_up(da)self:fireEvent("key_up",da)aa.key_up(self,da)end -function ca:char(da)self:fireEvent("char",da)aa.char(self,da)end;function ca:render() -if(self._renderUpdate)then if self._render~=nil then aa.render(self) -self._render:render()self._renderUpdate=false end end end -return ca end -project["elements/ProgressBar.lua"] = function(...) local c=require("elements/VisualElement") -local d=setmetatable({},c)d.__index=d -d.defineProperty(d,"progress",{default=0,type="number",canTriggerRender=true}) -d.defineProperty(d,"showPercentage",{default=false,type="boolean"}) -d.defineProperty(d,"progressColor",{default=colors.black,type="number"}) -function d.new()local _a=setmetatable({},d):__init() -_a.set("width",10)_a.set("height",1)return _a end -function d:init(_a,aa)c.init(self,_a,aa)self.set("type","ProgressBar")end -function d:render()c.render(self)local _a=self.get("width") -local aa=math.min(100,math.max(0,self.get("progress")))local ba=math.floor((_a*aa)/100)for i=1,self.get("height")do -self:textBg(1,i,string.rep(" ",ba),self.get("progressColor"))end;if self.get("showPercentage")then local ca= -tostring(aa).."%" -local da=math.floor((_a-#ca)/2)+1 -self:textFg(da,1,ca,self.get("foreground"))end end;return d end -project["elements/Menu.lua"] = function(...) local _a=require("elements/VisualElement") -local aa=require("elements/List")local ba=require("libraries/colorHex") -local ca=setmetatable({},aa)ca.__index=ca -ca.defineProperty(ca,"separatorColor",{default=colors.gray,type="number"})function ca.new()local da=setmetatable({},ca):__init() -da.set("width",30)da.set("height",1) -da.set("background",colors.gray)return da end -function ca:init(da,_b) -aa.init(self,da,_b)self.set("type","Menu")return self end -function ca:setItems(da)local _b={}local ab=0 -for bb,cb in ipairs(da)do -if cb.separator then -table.insert(_b,{text=cb.text or"|",selectable=false})ab=ab+1 else local db=" "..cb.text.." "cb.text=db -table.insert(_b,cb)ab=ab+#db end end;self.set("width",ab)return aa.setItems(self,_b)end -function ca:render()_a.render(self)local da=1 -for _b,ab in ipairs(self.get("items"))do if type(ab)== -"string"then ab={text=" "..ab.." "} -self.get("items")[i]=ab end;local bb=ab.selected -local cb=ab.selectable==false and -self.get("separatorColor")or(bb and -(ab.selectedForeground or self.get("selectedForeground"))or -(ab.foreground or self.get("foreground"))) -local db= -bb and(ab.selectedBackground or self.get("selectedBackground"))or(ab.background or self.get("background")) -self:blit(da,1,ab.text,string.rep(ba[cb],#ab.text),string.rep(ba[db],#ab.text))da=da+#ab.text end end -function ca:mouse_click(da,_b,ab) -if not _a.mouse_click(self,da,_b,ab)then return false end -if(self.get("selectable")==false)then return false end -local bb=select(1,self:getRelativePosition(_b,ab))local cb=1 -for db,_c in ipairs(self.get("items"))do -if -bb>=cb and bb=ac.x and bb<=ac.x+bc-1 and cb>=dc and cb<=dc+cc-1 then -self.dragStartX=_b-self.get("x")self.dragStartY=ab-self.get("y")self.dragging=true -return true end end;return ba.mouse_click(self,da,_b,ab)end end -function ca:mouse_drag(da,_b,ab) -if self.get("clicked")and self.dragging then -local bb=_b-self.dragStartX;local cb=ab-self.dragStartY;self.set("x",bb) -self.set("y",cb)return true end -if not self.dragging then return ba.mouse_drag(self,da,_b,ab)end;return false end -function ca:mouse_up(da,_b,ab)self.dragging=false;self.dragStartX=nil;self.dragStartY=nil;return -ba.mouse_up(self,da,_b,ab)end;return ca end -project["elements/Button.lua"] = function(...) local _a=require("elementManager") -local aa=_a.getElement("VisualElement") -local ba=require("libraries/utils").getCenteredPosition;local ca=setmetatable({},aa)ca.__index=ca -ca.defineProperty(ca,"text",{default="Button",type="string",canTriggerRender=true})ca.defineEvent(ca,"mouse_click") -ca.defineEvent(ca,"mouse_up") -function ca.new()local da=setmetatable({},ca):__init() -da.set("width",10)da.set("height",3)da.set("z",5)return da end -function ca:init(da,_b)aa.init(self,da,_b)self.set("type","Button")end -function ca:render()aa.render(self)local da=self.get("text") -da=da:sub(1,self.get("width")) -local _b,ab=ba(da,self.get("width"),self.get("height")) -self:textFg(_b,ab,da,self.get("foreground"))end;return ca end -project["elements/Program.lua"] = function(...) local ba=require("elementManager") -local ca=ba.getElement("VisualElement")local da=require("errorManager")local _b=setmetatable({},ca) -_b.__index=_b -_b.defineProperty(_b,"program",{default=nil,type="table"}) -_b.defineProperty(_b,"path",{default="",type="string"}) -_b.defineProperty(_b,"running",{default=false,type="boolean"})_b.defineEvent(_b,"*")local ab={}ab.__index=ab -local bb=dofile("rom/modules/main/cc/require.lua").make -function ab.new()local cb=setmetatable({},ab)cb.env={}cb.args={}return cb end -function ab:run(cb,db,_c) -self.window=window.create(term.current(),1,1,db,_c,false)local ac=shell.resolveProgram(cb) -if(ac~=nil)then -if(fs.exists(ac))then -local bc=fs.open(ac,"r")local cc=bc.readAll()bc.close() -local dc=setmetatable(self.env,{__index=_ENV})dc.shell=shell;dc.term=self.window -dc.require,dc.package=bb(dc,fs.getDir(ac))dc.term.current=term.current;dc.term.redirect=term.redirect -dc.term.native=term.native -self.coroutine=coroutine.create(function()local cd=load(cc,cb,"bt",dc) -if cd then -local dd=term.current()term.redirect(self.window) -local __a=cd(cb,table.unpack(self.args))term.redirect(dd)return __a end end)local _d=term.current()term.redirect(self.window) -local ad,bd=coroutine.resume(self.coroutine)term.redirect(_d)if not ad then -da.header="Basalt Program Error "..cb;da.error(bd)end else -da.header="Basalt Program Error "..cb;da.error("File not found")end else da.header="Basalt Program Error" -da.error("Program "..cb.." not found")end end -function ab:resize(cb,db)self.window.reposition(1,1,cb,db)end -function ab:resume(cb,...)if self.coroutine==nil or -coroutine.status(self.coroutine)=="dead"then return end -if( -self.filter~=nil)then if(cb~=self.filter)then return end;self.filter=nil end;local db=term.current()term.redirect(self.window) -local _c,ac=coroutine.resume(self.coroutine,cb,...)term.redirect(db)if _c then self.filter=ac else -da.header="Basalt Program Error"da.error(ac)end;return _c,ac end;function ab:stop()end;function _b.new() -local cb=setmetatable({},_b):__init()cb.set("z",5)cb.set("width",30)cb.set("height",12) -return cb end -function _b:init(cb,db) -ca.init(self,cb,db)self.set("type","Program")return self end -function _b:execute(cb)self.set("path",cb)self.set("running",true) -local db=ab.new()self.set("program",db) -db:run(cb,self.get("width"),self.get("height"))self:updateRender()return self end -function _b:dispatchEvent(cb,...)local db=self.get("program") -local _c=ca.dispatchEvent(self,cb,...) -if db then db:resume(cb,...) -if(self.get("focused"))then -local ac=db.window.getCursorBlink()local bc,cc=db.window.getCursorPos() -self:setCursor(bc,cc,ac,db.window.getTextColor())end;self:updateRender()end;return _c end -function _b:focus() -if(ca.focus(self))then local cb=self.get("program")if cb then -local db=cb.window.getCursorBlink()local _c,ac=cb.window.getCursorPos() -self:setCursor(_c,ac,db,cb.window.getTextColor())end end end -function _b:render()ca.render(self)local cb=self.get("program") -if cb then -local db,_c=cb.window.getSize()for y=1,_c do local ac,bc,cc=cb.window.getLine(y)if ac then -self:blit(1,y,ac,bc,cc)end end end end;return _b end -project["elements/Label.lua"] = function(...) local _a=require("elementManager") -local aa=_a.getElement("VisualElement")local ba=require("libraries/utils").wrapText -local ca=setmetatable({},aa)ca.__index=ca -ca.defineProperty(ca,"text",{default="Label",type="string",canTriggerRender=true,setter=function(da,_b) -if(type(_b)=="function")then _b=_b()end -if(da.get("autoSize"))then da.set("width",#_b)else da.set("height",# -ba(_b,da.get("width")))end;return _b end}) -ca.defineProperty(ca,"autoSize",{default=true,type="boolean",canTriggerRender=true,setter=function(da,_b)if(_b)then -da.set("width",#da.get("text"))else -da.set("height",#ba(da.get("text"),da.get("width")))end;return _b end}) -function ca.new()local da=setmetatable({},ca):__init() -da.set("z",3)da.set("foreground",colors.black) -da.set("backgroundEnabled",false)return da end;function ca:init(da,_b)aa.init(self,da,_b)self.set("type","Label") -return self end -function ca:getWrappedText() -local da=self.get("text")local _b=ba(da,self.get("width"))return _b end -function ca:render()aa.render(self)local da=self.get("text") -if -(self.get("autoSize"))then self:textFg(1,1,da,self.get("foreground"))else -local _b=ba(da,self.get("width"))for ab,bb in ipairs(_b)do -self:textFg(1,ab,bb,self.get("foreground"))end end end;return ca end -project["elements/Image.lua"] = function(...) local aa=require("elementManager") -local ba=aa.getElement("VisualElement")local ca=require("libraries/colorHex") -local da=setmetatable({},ba)da.__index=da -da.defineProperty(da,"bimg",{default={{}},type="table",canTriggerRender=true}) -da.defineProperty(da,"currentFrame",{default=1,type="number",canTriggerRender=true}) -da.defineProperty(da,"metadata",{default={},type="table"}) -da.defineProperty(da,"autoResize",{default=true,type="boolean"}) -da.defineProperty(da,"offsetX",{default=0,type="number",canTriggerRender=true}) -da.defineProperty(da,"offsetY",{default=0,type="number",canTriggerRender=true}) -function da.new()local ab=setmetatable({},da):__init() -ab.set("width",12)ab.set("height",6) -ab.set("background",colors.black)ab.set("z",5)return ab end;function da:init(ab,bb)ba.init(self,ab,bb)self.set("type","Image") -return self end -function da:loadBimg(ab) -if type(ab)~="table"then return self end;local bb={}local cb={}for db,_c in pairs(ab)do -if type(db)=="number"then bb[db]=_c else cb[db]=_c end end;self.set("bimg",bb) -self.set("metadata",cb) -if bb[1]and bb[1][1]then -self.set("width",#bb[1][1][2])self.set("height",#bb[1])end;return self end -function da:resizeImage(ab,bb)local cb=self.get("bimg") -for db,_c in ipairs(cb)do local ac={} -for y=1,bb do -local bc=string.rep(" ",ab)local cc=string.rep("f",ab)local dc=string.rep("0",ab) -if _c[y]and -_c[y][1]then local _d=_c[y][1]local ad=_c[y][2]local bd=_c[y][3]bc=(_d.. -string.rep(" ",ab)):sub(1,ab)cc=(ad.. -string.rep("f",ab)):sub(1,ab)dc=(bd.. -string.rep("0",ab)):sub(1,ab)end;ac[y]={bc,cc,dc}end;cb[db]=ac end;self:updateRender()return self end -function da:getImageSize()local ab=self.get("bimg")if not ab[1]or not ab[1][1]then -return 0,0 end;return#ab[1][1][1],#ab[1]end -function da:getPixelData(ab,bb) -local cb=self.get("bimg")[self.get("currentFrame")]if not cb or not cb[bb]then return end;local db=cb[bb][1] -local _c=cb[bb][2]local ac=cb[bb][3] -if not db or not _c or not ac then return end;local bc=tonumber(_c:sub(ab,ab),16) -local cc=tonumber(ac:sub(ab,ab),16)local dc=db:sub(ab,ab)return bc,cc,dc end -local function _b(ab,bb) -local cb=ab.get("bimg")[ab.get("currentFrame")]if not cb then cb={} -ab.get("bimg")[ab.get("currentFrame")]=cb end -if not cb[bb]then cb[bb]={"","",""}end;return cb end -function da:setText(ab,bb,cb) -if type(cb)~="string"or#cb<1 then return self end;local db=_b(self,bb)local _c=db[bb][1] -while#_c#ab then cb=1 end;self.set("currentFrame",cb)return self end -function da:render()ba.render(self) -local ab=self.get("bimg")[self.get("currentFrame")]if not ab then return end;local bb=self.get("offsetX") -local cb=self.get("offsetY")local db=self.get("width")local _c=self.get("height") -for y=1,_c do local ac=y+cb -local bc=ab[ac] -if bc then local cc=bc[1]:sub(1 +bb,db+bb) -local dc=bc[2]:sub(1 +bb,db+bb)local _d=bc[3]:sub(1 +bb,db+bb)if cc and dc and _d then -self:blit(1 +bb,y,cc,dc,_d)end end end end;return da end -project["elements/Flexbox.lua"] = function(...) local da=require("elementManager") -local _b=da.getElement("Container")local ab=setmetatable({},_b)ab.__index=ab -ab.defineProperty(ab,"flexDirection",{default="row",type="string"}) -ab.defineProperty(ab,"flexSpacing",{default=1,type="number"}) -ab.defineProperty(ab,"flexJustifyContent",{default="flex-start",type="string",setter=function(bc,cc)if not cc:match("^flex%-")then -cc="flex-"..cc end;return cc end}) -ab.defineProperty(ab,"flexWrap",{default=false,type="boolean"}) -ab.defineProperty(ab,"flexUpdateLayout",{default=false,type="boolean"}) -local bb={getHeight=function(bc)return 0 end,getWidth=function(bc)return 0 end,getZ=function(bc)return 1 end,getPosition=function(bc)return 0,0 end,getSize=function(bc)return 0,0 end,isType=function(bc)return -false end,getType=function(bc)return"lineBreak"end,getName=function(bc)return"lineBreak"end,setPosition=function(bc) -end,setParent=function(bc)end,setSize=function(bc)end,getFlexGrow=function(bc)return 0 end,getFlexShrink=function(bc)return 0 end,getFlexBasis=function(bc)return 0 end,init=function(bc)end,getVisible=function(bc)return -true end} -local function cb(bc,cc,dc,_d)local ad=bc.get("children")local bd={} -if not(_d)then local cd=1;local dd=1;local __a=1 -for a_a,b_a in pairs(ad)do if -(bd[cd]==nil)then bd[cd]={offset=1}end;local c_a= -cc=="row"and b_a.get("height")or b_a.get("width")if -c_a>dd then dd=c_a end -if(b_a==bb)then __a=__a+dd+dc;dd=1;cd=cd+1 -bd[cd]={offset=__a}else table.insert(bd[cd],b_a)end end elseif(_d)then local cd=1;local dd=1 -local __a=cc=="row"and bc.get("width")or bc.get("height")local a_a=0;local b_a=1 -for c_a,d_a in pairs(ad)do -if(bd[b_a]==nil)then bd[b_a]={offset=1}end -if d_a:getType()=="lineBreak"then dd=dd+cd+dc;a_a=0;cd=1;b_a=b_a+1 -bd[b_a]={offset=dd}else -local _aa=cc=="row"and d_a.get("width")or d_a.get("height") -if(_aa+a_a<=__a)then table.insert(bd[b_a],d_a) -a_a=a_a+_aa+dc else dd=dd+cd+dc -cd=cc=="row"and d_a.get("height")or d_a.get("width")b_a=b_a+1;a_a=_aa+dc;bd[b_a]={offset=dd,d_a}end -local aaa=cc=="row"and d_a.get("height")or d_a.get("width")if aaa>cd then cd=aaa end end end end;return bd end -local function db(bc,cc,dc,_d)local ad=bc.get("width")local bd=dc* (#cc-1)local cd=0;for c_a,d_a in ipairs(cc)do -if d_a~=bb then bd=bd+ -d_a.get("width")cd=cd+d_a.get("flexGrow")end end;local dd=ad-bd;local __a= -cd>0 and(dd/cd)or 0;local a_a=0;local b_a=1 -for c_a,d_a in ipairs(cc)do -if d_a~=bb then -local _aa=d_a.get("width") -if d_a.get("flexGrow")>0 then if c_a==#cc then local aaa=dd-a_a;_aa=_aa+aaa else local aaa=math.floor(__a* -d_a.get("flexGrow"))_aa=_aa+aaa -a_a=a_a+aaa end end;d_a.set("x",b_a)d_a.set("y",cc.offset or 1) -d_a.set("width",_aa)b_a=b_a+_aa+dc end end -if _d=="flex-end"then local c_a=ad- (b_a-dc-1)for d_a,_aa in ipairs(cc)do -_aa.set("x",_aa.get("x")+c_a)end elseif _d=="flex-center"or _d=="center"then local c_a=math.floor(( -ad- (b_a-dc-1))/2)for d_a,_aa in ipairs(cc)do _aa.set("x", -_aa.get("x")+c_a)end end end -local function _c(bc,cc,dc,_d)local ad=bc.get("height")local bd=dc* (#cc-1)local cd=0;for c_a,d_a in ipairs(cc)do -if d_a~=bb then bd=bd+ -d_a.get("height")cd=cd+d_a.get("flexGrow")end end;local dd=ad-bd;local __a= -cd>0 and(dd/cd)or 0;local a_a=0;local b_a=1 -for c_a,d_a in ipairs(cc)do -if d_a~=bb then -local _aa=d_a.get("height") -if d_a.get("flexGrow")>0 then if c_a==#cc then local aaa=dd-a_a;_aa=_aa+aaa else local aaa=math.floor(__a* -d_a.get("flexGrow"))_aa=_aa+aaa -a_a=a_a+aaa end end;d_a.set("x",cc.offset or 1)d_a.set("y",b_a) -d_a.set("height",_aa)b_a=b_a+_aa+dc end end -if _d=="flex-end"then local c_a=ad- (b_a-dc-1)for d_a,_aa in ipairs(cc)do -_aa.set("y",_aa.get("y")+c_a)end elseif _d=="flex-center"or _d=="center"then local c_a=math.floor(( -ad- (b_a-dc-1))/2)for d_a,_aa in ipairs(cc)do _aa.set("y", -_aa.get("y")+c_a)end end end -local function ac(bc,cc,dc,_d,ad)local bd=cb(bc,cc,dc,ad) -if cc=="row"then -for cd,dd in pairs(bd)do db(bc,dd,dc,_d)end else for cd,dd in pairs(bd)do _c(bc,dd,dc,_d)end end;bc.set("flexUpdateLayout",false)end -function ab.new()local bc=setmetatable({},ab):__init() -bc.set("width",12)bc.set("height",6) -bc.set("background",colors.blue)bc.set("z",10) -bc:observe("width",function() -bc.set("flexUpdateLayout",true)end) -bc:observe("height",function()bc.set("flexUpdateLayout",true)end)return bc end;function ab:init(bc,cc)_b.init(self,bc,cc)self.set("type","Flexbox") -return self end -function ab:addChild(bc) -_b.addChild(self,bc) -if(bc~=bb)then -bc:instanceProperty("flexGrow",{default=0,type="number"}) -bc:instanceProperty("flexShrink",{default=0,type="number"}) -bc:instanceProperty("flexBasis",{default=0,type="number"})end;self.set("flexUpdateLayout",true)return self end -function ab:removeChild(bc)_b.removeChild(self,bc) -if(bc~=bb)then bc.setFlexGrow=nil;bc.setFlexShrink= -nil;bc.setFlexBasis=nil;bc.getFlexGrow=nil;bc.getFlexShrink=nil;bc.getFlexBasis= -nil;bc.set("flexGrow",nil) -bc.set("flexShrink",nil)bc.set("flexBasis",nil)end;self.set("flexUpdateLayout",true)return self end;function ab:addLineBreak()self:addChild(bb)return self end -function ab:render() -if -(self.get("flexUpdateLayout"))then -ac(self,self.get("flexDirection"),self.get("flexSpacing"),self.get("flexJustifyContent"),self.get("flexWrap"))end;_b.render(self)end;return ab end +function ba:clearArea(da,_b,ab,bb,cb)local db=_a[cb]or"f" +for dy=0,bb-1 do local _c=_b+dy;if +_c>=1 and _c<=self.height then local ac=string.rep(" ",ab)local bc=string.rep(db,ab) +self:blit(da,_c,ac,"0",db)end end;return self end;function ba:getSize()return self.width,self.height end +function ba:setSize(da,_b) +self.width=da;self.height=_b +for y=1,self.height do +self.buffer.text[y]=string.rep(" ",self.width)self.buffer.fg[y]=string.rep("0",self.width) +self.buffer.bg[y]=string.rep("f",self.width)end;return self end;return ba end +project["log.lua"] = function(...) local aa={}aa._logs={}aa._enabled=false;aa._logToFile=false +aa._logFile="basalt.log"fs.delete(aa._logFile) +aa.LEVEL={DEBUG=1,INFO=2,WARN=3,ERROR=4} +local ba={[aa.LEVEL.DEBUG]="Debug",[aa.LEVEL.INFO]="Info",[aa.LEVEL.WARN]="Warn",[aa.LEVEL.ERROR]="Error"} +local ca={[aa.LEVEL.DEBUG]=colors.lightGray,[aa.LEVEL.INFO]=colors.white,[aa.LEVEL.WARN]=colors.yellow,[aa.LEVEL.ERROR]=colors.red}function aa.setLogToFile(ab)aa._logToFile=ab end +function aa.setEnabled(ab)aa._enabled=ab end;local function da(ab) +if aa._logToFile then local bb=io.open(aa._logFile,"a")if bb then +bb:write(ab.."\n")bb:close()end end end +local function _b(ab,...)if +not aa._enabled then return end;local bb=os.date("%H:%M:%S") +local cb=debug.getinfo(3,"Sl")local db=cb.source:match("@?(.*)")local _c=cb.currentline +local ac=string.format("[%s:%d]",db:match("([^/\\]+)%.lua$"),_c)local bc="["..ba[ab].."]"local cc="" +for _d,ad in ipairs(table.pack(...))do if _d>1 then cc= +cc.." "end;cc=cc..tostring(ad)end;local dc=string.format("%s %s%s %s",bb,ac,bc,cc)da(dc) +table.insert(aa._logs,{time=bb,level=ab,message=cc})end;function aa.debug(...)_b(aa.LEVEL.DEBUG,...)end;function aa.info(...) +_b(aa.LEVEL.INFO,...)end +function aa.warn(...)_b(aa.LEVEL.WARN,...)end;function aa.error(...)_b(aa.LEVEL.ERROR,...)end;return aa end +project["elements/BigFont.lua"] = function(...) local _b=require("libraries/colorHex") +local ab={{"\32\32\32\137\156\148\158\159\148\135\135\144\159\139\32\136\157\32\159\139\32\32\143\32\32\143\32\32\32\32\32\32\32\32\147\148\150\131\148\32\32\32\151\140\148\151\140\147","\32\32\32\149\132\149\136\156\149\144\32\133\139\159\129\143\159\133\143\159\133\138\32\133\138\32\133\32\32\32\32\32\32\150\150\129\137\156\129\32\32\32\133\131\129\133\131\132","\32\32\32\130\131\32\130\131\32\32\129\32\32\32\32\130\131\32\130\131\32\32\32\32\143\143\143\32\32\32\32\32\32\130\129\32\130\135\32\32\32\32\131\32\32\131\32\131","\139\144\32\32\143\148\135\130\144\149\32\149\150\151\149\158\140\129\32\32\32\135\130\144\135\130\144\32\149\32\32\139\32\159\148\32\32\32\32\159\32\144\32\148\32\147\131\132","\159\135\129\131\143\149\143\138\144\138\32\133\130\149\149\137\155\149\159\143\144\147\130\132\32\149\32\147\130\132\131\159\129\139\151\129\148\32\32\139\131\135\133\32\144\130\151\32","\32\32\32\32\32\32\130\135\32\130\32\129\32\129\129\131\131\32\130\131\129\140\141\132\32\129\32\32\129\32\32\32\32\32\32\32\131\131\129\32\32\32\32\32\32\32\32\32","\32\32\32\32\149\32\159\154\133\133\133\144\152\141\132\133\151\129\136\153\32\32\154\32\159\134\129\130\137\144\159\32\144\32\148\32\32\32\32\32\32\32\32\32\32\32\151\129","\32\32\32\32\133\32\32\32\32\145\145\132\141\140\132\151\129\144\150\146\129\32\32\32\138\144\32\32\159\133\136\131\132\131\151\129\32\144\32\131\131\129\32\144\32\151\129\32","\32\32\32\32\129\32\32\32\32\130\130\32\32\129\32\129\32\129\130\129\129\32\32\32\32\130\129\130\129\32\32\32\32\32\32\32\32\133\32\32\32\32\32\129\32\129\32\32","\150\156\148\136\149\32\134\131\148\134\131\148\159\134\149\136\140\129\152\131\32\135\131\149\150\131\148\150\131\148\32\148\32\32\148\32\32\152\129\143\143\144\130\155\32\134\131\148","\157\129\149\32\149\32\152\131\144\144\131\148\141\140\149\144\32\149\151\131\148\32\150\32\150\131\148\130\156\133\32\144\32\32\144\32\130\155\32\143\143\144\32\152\129\32\134\32","\130\131\32\131\131\129\131\131\129\130\131\32\32\32\129\130\131\32\130\131\32\32\129\32\130\131\32\130\129\32\32\129\32\32\133\32\32\32\129\32\32\32\130\32\32\32\129\32","\150\140\150\137\140\148\136\140\132\150\131\132\151\131\148\136\147\129\136\147\129\150\156\145\138\143\149\130\151\32\32\32\149\138\152\129\149\32\32\157\152\149\157\144\149\150\131\148","\149\143\142\149\32\149\149\32\149\149\32\144\149\32\149\149\32\32\149\32\32\149\32\149\149\32\149\32\149\32\144\32\149\149\130\148\149\32\32\149\32\149\149\130\149\149\32\149","\130\131\129\129\32\129\131\131\32\130\131\32\131\131\32\131\131\129\129\32\32\130\131\32\129\32\129\130\131\32\130\131\32\129\32\129\131\131\129\129\32\129\129\32\129\130\131\32","\136\140\132\150\131\148\136\140\132\153\140\129\131\151\129\149\32\149\149\32\149\149\32\149\137\152\129\137\152\129\131\156\133\149\131\32\150\32\32\130\148\32\152\137\144\32\32\32","\149\32\32\149\159\133\149\32\149\144\32\149\32\149\32\149\32\149\150\151\129\138\155\149\150\130\148\32\149\32\152\129\32\149\32\32\32\150\32\32\149\32\32\32\32\32\32\32","\129\32\32\130\129\129\129\32\129\130\131\32\32\129\32\130\131\32\32\129\32\129\32\129\129\32\129\32\129\32\131\131\129\130\131\32\32\32\129\130\131\32\32\32\32\140\140\132","\32\154\32\159\143\32\149\143\32\159\143\32\159\144\149\159\143\32\159\137\145\159\143\144\149\143\32\32\145\32\32\32\145\149\32\144\32\149\32\143\159\32\143\143\32\159\143\32","\32\32\32\152\140\149\151\32\149\149\32\145\149\130\149\157\140\133\32\149\32\154\143\149\151\32\149\32\149\32\144\32\149\149\153\32\32\149\32\149\133\149\149\32\149\149\32\149","\32\32\32\130\131\129\131\131\32\130\131\32\130\131\129\130\131\129\32\129\32\140\140\129\129\32\129\32\129\32\137\140\129\130\32\129\32\130\32\129\32\129\129\32\129\130\131\32","\144\143\32\159\144\144\144\143\32\159\143\144\159\138\32\144\32\144\144\32\144\144\32\144\144\32\144\144\32\144\143\143\144\32\150\129\32\149\32\130\150\32\134\137\134\134\131\148","\136\143\133\154\141\149\151\32\129\137\140\144\32\149\32\149\32\149\154\159\133\149\148\149\157\153\32\154\143\149\159\134\32\130\148\32\32\149\32\32\151\129\32\32\32\32\134\32","\133\32\32\32\32\133\129\32\32\131\131\32\32\130\32\130\131\129\32\129\32\130\131\129\129\32\129\140\140\129\131\131\129\32\130\129\32\129\32\130\129\32\32\32\32\32\129\32","\32\32\32\32\149\32\32\149\32\32\32\32\32\32\32\32\149\32\32\149\32\32\32\32\32\32\32\32\149\32\32\149\32\32\32\32\32\32\32\32\149\32\32\149\32\32\32\32","\32\32\32\32\32\32\32\32\32\32\32\32\32\149\32\32\149\32\32\149\32\32\149\32\32\149\32\32\149\32\32\149\32\32\149\32\32\32\32\32\32\32\32\32\32\32\32\32","\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32","\32\32\32\32\149\32\32\149\32\32\32\32\32\32\32\32\149\32\32\149\32\32\32\32\32\32\32\32\149\32\32\149\32\32\32\32\32\32\32\32\149\32\32\149\32\32\32\32","\32\32\32\32\32\32\32\32\32\32\32\32\32\149\32\32\149\32\32\149\32\32\149\32\32\149\32\32\149\32\32\149\32\32\149\32\32\32\32\32\32\32\32\32\32\32\32\32","\32\149\32\32\149\32\32\149\32\32\149\32\32\149\32\32\149\32\32\149\32\32\149\32\32\149\32\32\149\32\32\149\32\32\149\32\32\149\32\32\149\32\32\149\32\32\149\32","\32\32\32\32\145\32\159\139\32\151\131\132\155\143\132\134\135\145\32\149\32\158\140\129\130\130\32\152\147\155\157\134\32\32\144\144\32\32\32\32\32\32\152\131\155\131\131\129","\32\32\32\32\149\32\149\32\145\148\131\32\149\32\149\140\157\132\32\148\32\137\155\149\32\32\32\149\154\149\137\142\32\153\153\32\131\131\149\131\131\129\149\135\145\32\32\32","\32\32\32\32\129\32\130\135\32\131\131\129\134\131\132\32\129\32\32\129\32\131\131\32\32\32\32\130\131\129\32\32\32\32\129\129\32\32\32\32\32\32\130\131\129\32\32\32","\150\150\32\32\148\32\134\32\32\132\32\32\134\32\32\144\32\144\150\151\149\32\32\32\32\32\32\145\32\32\152\140\144\144\144\32\133\151\129\133\151\129\132\151\129\32\145\32","\130\129\32\131\151\129\141\32\32\142\32\32\32\32\32\149\32\149\130\149\149\32\143\32\32\32\32\142\132\32\154\143\133\157\153\132\151\150\148\151\158\132\151\150\148\144\130\148","\32\32\32\140\140\132\32\32\32\32\32\32\32\32\32\151\131\32\32\129\129\32\32\32\32\134\32\32\32\32\32\32\32\129\129\32\129\32\129\129\130\129\129\32\129\130\131\32","\156\143\32\159\141\129\153\140\132\153\137\32\157\141\32\159\142\32\150\151\129\150\131\132\140\143\144\143\141\145\137\140\148\141\141\144\157\142\32\159\140\32\151\134\32\157\141\32","\157\140\149\157\140\149\157\140\149\157\140\149\157\140\149\157\140\149\151\151\32\154\143\132\157\140\32\157\140\32\157\140\32\157\140\32\32\149\32\32\149\32\32\149\32\32\149\32","\129\32\129\129\32\129\129\32\129\129\32\129\129\32\129\129\32\129\129\131\129\32\134\32\131\131\129\131\131\129\131\131\129\131\131\129\130\131\32\130\131\32\130\131\32\130\131\32","\151\131\148\152\137\145\155\140\144\152\142\145\153\140\132\153\137\32\154\142\144\155\159\132\150\156\148\147\32\144\144\130\145\136\137\32\146\130\144\144\130\145\130\136\32\151\140\132","\151\32\149\151\155\149\149\32\149\149\32\149\149\32\149\149\32\149\149\32\149\152\137\144\157\129\149\149\32\149\149\32\149\149\32\149\149\32\149\130\150\32\32\157\129\149\32\149","\131\131\32\129\32\129\130\131\32\130\131\32\130\131\32\130\131\32\130\131\32\32\32\32\130\131\32\130\131\32\130\131\32\130\131\32\130\131\32\32\129\32\130\131\32\133\131\32","\156\143\32\159\141\129\153\140\132\153\137\32\157\141\32\159\142\32\159\159\144\152\140\144\156\143\32\159\141\129\153\140\132\157\141\32\130\145\32\32\147\32\136\153\32\130\146\32","\152\140\149\152\140\149\152\140\149\152\140\149\152\140\149\152\140\149\149\157\134\154\143\132\157\140\133\157\140\133\157\140\133\157\140\133\32\149\32\32\149\32\32\149\32\32\149\32","\130\131\129\130\131\129\130\131\129\130\131\129\130\131\129\130\131\129\130\130\131\32\134\32\130\131\129\130\131\129\130\131\129\130\131\129\32\129\32\32\129\32\32\129\32\32\129\32","\159\134\144\137\137\32\156\143\32\159\141\129\153\140\132\153\137\32\157\141\32\32\132\32\159\143\32\147\32\144\144\130\145\136\137\32\146\130\144\144\130\145\130\138\32\146\130\144","\149\32\149\149\32\149\149\32\149\149\32\149\149\32\149\149\32\149\149\32\149\131\147\129\138\134\149\149\32\149\149\32\149\149\32\149\149\32\149\154\143\149\32\157\129\154\143\149","\130\131\32\129\32\129\130\131\32\130\131\32\130\131\32\130\131\32\130\131\32\32\32\32\130\131\32\130\131\129\130\131\129\130\131\129\130\131\129\140\140\129\130\131\32\140\140\129"},{"000110000110110000110010101000000010000000100101","000000110110000000000010101000000010000000100101","000000000000000000000000000000000000000000000000","100010110100000010000110110000010100000100000110","000000110000000010110110000110000000000000110000","000000000000000000000000000000000000000000000000","000000110110000010000000100000100000000000000010","000000000110110100010000000010000000000000000100","000000000000000000000000000000000000000000000000","010000000000100110000000000000000000000110010000","000000000000000000000000000010000000010110000000","000000000000000000000000000000000000000000000000","011110110000000100100010110000000100000000000000","000000000000000000000000000000000000000000000000","000000000000000000000000000000000000000000000000","110000110110000000000000000000010100100010000000","000010000000000000110110000000000100010010000000","000000000000000000000000000000000000000000000000","010110010110100110110110010000000100000110110110","000000000000000000000110000000000110000000000000","000000000000000000000000000000000000000000000000","010100010110110000000000000000110000000010000000","110110000000000000110000110110100000000010000000","000000000000000000000000000000000000000000000000","000100011111000100011111000100011111000100011111","000000000000100100100100011011011011111111111111","000000000000000000000000000000000000000000000000","000100011111000100011111000100011111000100011111","000000000000100100100100011011011011111111111111","100100100100100100100100100100100100100100100100","000000110100110110000010000011110000000000011000","000000000100000000000010000011000110000000001000","000000000000000000000000000000000000000000000000","010000100100000000000000000100000000010010110000","000000000000000000000000000000110110110110110000","000000000000000000000000000000000000000000000000","110110110110110110000000110110110110110110110110","000000000000000000000110000000000000000000000000","000000000000000000000000000000000000000000000000","000000000000110110000110010000000000000000010010","000010000000000000000000000000000000000000000000","000000000000000000000000000000000000000000000000","110110110110110110110000110110110110000000000000","000000000000000000000110000000000000000000000000","000000000000000000000000000000000000000000000000","110110110110110110110000110000000000000000010000","000000000000000000000000100000000000000110000110","000000000000000000000000000000000000000000000000"}}local bb={}local cb={} +do local dc=0;local _d=#ab[1]local ad=#ab[1][1] +for i=1,_d,3 do +for j=1,ad,3 do +local bd=string.char(dc)local cd={}cd[1]=ab[1][i]:sub(j,j+2) +cd[2]=ab[1][i+1]:sub(j,j+2)cd[3]=ab[1][i+2]:sub(j,j+2)local dd={}dd[1]=ab[2][i]:sub(j, +j+2)dd[2]=ab[2][i+1]:sub(j,j+2)dd[3]=ab[2][ +i+2]:sub(j,j+2)cb[bd]={cd,dd}dc=dc+1 end end;bb[1]=cb end +local function db(dc,_d)local ad={["0"]="1",["1"]="0"}if dc<=#bb then return true end +for f=#bb+1,dc do local bd={}local cd=bb[ +f-1] +for char=0,255 do local dd=string.char(char)local __a={}local a_a={} +local b_a=cd[dd][1]local c_a=cd[dd][2] +for i=1,#b_a do local d_a,_aa,aaa,baa,caa,daa={},{},{},{},{},{} +for j=1,#b_a[1]do +local _ba=cb[b_a[i]:sub(j,j)][1]table.insert(d_a,_ba[1]) +table.insert(_aa,_ba[2])table.insert(aaa,_ba[3]) +local aba=cb[b_a[i]:sub(j,j)][2] +if c_a[i]:sub(j,j)=="1"then +table.insert(baa,(aba[1]:gsub("[01]",ad))) +table.insert(caa,(aba[2]:gsub("[01]",ad))) +table.insert(daa,(aba[3]:gsub("[01]",ad)))else table.insert(baa,aba[1]) +table.insert(caa,aba[2])table.insert(daa,aba[3])end end;table.insert(__a,table.concat(d_a)) +table.insert(__a,table.concat(_aa))table.insert(__a,table.concat(aaa)) +table.insert(a_a,table.concat(baa))table.insert(a_a,table.concat(caa)) +table.insert(a_a,table.concat(daa))end;bd[dd]={__a,a_a}if _d then _d="Font"..f.."Yeld"..char +os.queueEvent(_d)os.pullEvent(_d)end end;bb[f]=bd end;return true end +local function _c(dc,_d,ad,bd,cd) +if not type(_d)=="string"then error("Not a String",3)end +local dd=type(ad)=="string"and ad:sub(1,1)or _b[ad]or +error("Wrong Front Color",3) +local __a=type(bd)=="string"and bd:sub(1,1)or _b[bd]or +error("Wrong Back Color",3)if(bb[dc]==nil)then db(3,false)end;local a_a=bb[dc]or +error("Wrong font size selected",3)if _d==""then +return{{""},{""},{""}}end;local b_a={} +for daa in _d:gmatch('.')do table.insert(b_a,daa)end;local c_a={}local d_a=#a_a[b_a[1]][1] +for nLine=1,d_a do local daa={}for i=1,#b_a do +daa[i]= +a_a[b_a[i]]and a_a[b_a[i]][1][nLine]or""end;c_a[nLine]=table.concat(daa)end;local _aa={}local aaa={}local baa={["0"]=dd,["1"]=__a}local caa={["0"]=__a,["1"]=dd} +for nLine=1,d_a +do local daa={}local _ba={} +for i=1,#b_a do local aba= +a_a[b_a[i]]and a_a[b_a[i]][2][nLine]or"" +daa[i]=aba:gsub("[01]",cd and +{["0"]=ad:sub(i,i),["1"]=bd:sub(i,i)}or baa) +_ba[i]=aba:gsub("[01]", +cd and{["0"]=bd:sub(i,i),["1"]=ad:sub(i,i)}or caa)end;_aa[nLine]=table.concat(daa) +aaa[nLine]=table.concat(_ba)end;return{c_a,_aa,aaa}end;local ac=require("elementManager") +local bc=ac.getElement("VisualElement")local cc=setmetatable({},bc)cc.__index=cc +cc.defineProperty(cc,"text",{default="BigFont",type="string",canTriggerRender=true,setter=function(dc,_d) +dc.bigfontText=_c(dc.get("fontSize"),_d,dc.get("foreground"),dc.get("background"))return _d end}) +cc.defineProperty(cc,"fontSize",{default=1,type="number",canTriggerRender=true,setter=function(dc,_d) +dc.bigfontText=_c(_d,dc.get("text"),dc.get("foreground"),dc.get("background"))return _d end}) +function cc.new()local dc=setmetatable({},cc):__init() +dc.set("width",16)dc.set("height",3)dc.set("z",5)return dc end +function cc:init(dc,_d)bc.init(self,dc,_d)self.set("type","BigFont")end +function cc:render()bc.render(self) +if(self.bigfontText)then +local dc,_d=self.get("x"),self.get("y") +for i=1,#self.bigfontText[1]do +local ad=self.bigfontText[1][i]:sub(1,self.get("width")) +local bd=self.bigfontText[2][i]:sub(1,self.get("width")) +local cd=self.bigfontText[3][i]:sub(1,self.get("width"))self:blit(dc,_d+i-1,ad,bd,cd)end end end;return cc end +project["elements/TextBox.lua"] = function(...) local ca=require("elements/VisualElement") +local da=require("libraries/colorHex")local _b=setmetatable({},ca)_b.__index=_b +_b.defineProperty(_b,"lines",{default={""},type="table",canTriggerRender=true}) +_b.defineProperty(_b,"cursorX",{default=1,type="number"}) +_b.defineProperty(_b,"cursorY",{default=1,type="number"}) +_b.defineProperty(_b,"scrollX",{default=0,type="number",canTriggerRender=true}) +_b.defineProperty(_b,"scrollY",{default=0,type="number",canTriggerRender=true}) +_b.defineProperty(_b,"editable",{default=true,type="boolean"}) +_b.defineProperty(_b,"syntaxPatterns",{default={},type="table"}) +_b.defineProperty(_b,"cursorColor",{default=nil,type="number"})_b.defineEvent(_b,"mouse_click") +_b.defineEvent(_b,"key")_b.defineEvent(_b,"char") +_b.defineEvent(_b,"mouse_scroll") +function _b.new()local _c=setmetatable({},_b):__init() +_c.set("width",20)_c.set("height",10)return _c end;function _b:init(_c,ac)ca.init(self,_c,ac)self.set("type","TextBox") +return self end;function _b:addSyntaxPattern(_c,ac) +table.insert(self.get("syntaxPatterns"),{pattern=_c,color=ac})return self end +local function ab(_c,ac) +local bc=_c.get("lines")local cc=_c.get("cursorX")local dc=_c.get("cursorY")local _d=bc[dc]bc[dc]=_d:sub(1, +cc-1)..ac.._d:sub(cc) +_c.set("cursorX",cc+1)_c:updateViewport()_c:updateRender()end +local function bb(_c)local ac=_c.get("lines")local bc=_c.get("cursorX") +local cc=_c.get("cursorY")local dc=ac[cc]local _d=dc:sub(bc)ac[cc]=dc:sub(1,bc-1) +table.insert(ac,cc+1,_d)_c.set("cursorX",1)_c.set("cursorY",cc+1) +_c:updateViewport()_c:updateRender()end +local function cb(_c)local ac=_c.get("lines")local bc=_c.get("cursorX") +local cc=_c.get("cursorY")local dc=ac[cc] +if bc>1 then +ac[cc]=dc:sub(1,bc-2)..dc:sub(bc)_c.set("cursorX",bc-1)elseif cc>1 then local _d=ac[cc-1] +_c.set("cursorX",#_d+1)_c.set("cursorY",cc-1)ac[cc-1]=_d..dc +table.remove(ac,cc)end;_c:updateViewport()_c:updateRender()end +function _b:updateViewport()local _c=self.get("cursorX") +local ac=self.get("cursorY")local bc=self.get("scrollX")local cc=self.get("scrollY") +local dc=self.get("width")local _d=self.get("height") +if _c-bc>dc then +self.set("scrollX",_c-dc)elseif _c-bc<1 then self.set("scrollX",_c-1)end;if ac-cc>_d then self.set("scrollY",ac-_d)elseif ac-cc<1 then +self.set("scrollY",ac-1)end;return self end +function _b:char(_c)if +not self.get("editable")or not self.get("focused")then return false end;ab(self,_c)return true end +function _b:key(_c)if +not self.get("editable")or not self.get("focused")then return false end +local ac=self.get("lines")local bc=self.get("cursorX")local cc=self.get("cursorY") +if _c== +keys.enter then bb(self)elseif _c==keys.backspace then cb(self)elseif _c==keys.left then +if bc>1 then self.set("cursorX", +bc-1)elseif cc>1 then self.set("cursorY",cc-1)self.set("cursorX", +#ac[cc-1]+1)end elseif _c==keys.right then +if bc<=#ac[cc]then self.set("cursorX",bc+1)elseif cc<#ac then self.set("cursorY", +cc+1)self.set("cursorX",1)end elseif _c==keys.up and cc>1 then self.set("cursorY",cc-1) +self.set("cursorX",math.min(bc, +#ac[cc-1]+1))elseif _c==keys.down and cc<#ac then self.set("cursorY",cc+1) +self.set("cursorX",math.min(bc, +#ac[cc+1]+1))end;self:updateRender()self:updateViewport()return true end +function _b:mouse_scroll(_c,ac,bc) +if self:isInBounds(ac,bc)then local cc=self.get("scrollY") +local dc=self.get("height")local _d=self.get("lines")local ad=math.max(0,#_d-dc+2)local bd=math.max(0,math.min(ad, +cc+_c)) +self.set("scrollY",bd)self:updateRender()return true end;return false end +function _b:mouse_click(_c,ac,bc) +if ca.mouse_click(self,_c,ac,bc)then +local cc,dc=self:getRelativePosition(ac,bc)local _d=self.get("scrollX")local ad=self.get("scrollY") +local bd=dc+ad;local cd=self.get("lines")if bd<=#cd then self.set("cursorY",bd) +self.set("cursorX",math.min( +cc+_d,#cd[bd]+1))end;self:updateRender()return +true end;return false end +function _b:setText(_c)local ac={} +if _c==""then ac={""}else for bc in(_c.."\n"):gmatch("([^\n]*)\n")do +table.insert(ac,bc)end end;self.set("lines",ac)return self end +function _b:getText()return table.concat(self.get("lines"),"\n")end +local function db(_c,ac)local bc=ac +local cc=string.rep(da[_c.get("foreground")],#bc)local dc=_c.get("syntaxPatterns") +for _d,ad in ipairs(dc)do local bd=1 +while true do +local cd,dd=bc:find(ad.pattern,bd)if not cd then break end +cc=cc:sub(1,cd-1).. +string.rep(da[ad.color],dd-cd+1)..cc:sub(dd+1)bd=dd+1 end end;return bc,cc end +function _b:render()ca.render(self)local _c=self.get("lines") +local ac=self.get("scrollX")local bc=self.get("scrollY")local cc=self.get("width") +local dc=self.get("height")local _d=da[self.get("foreground")] +local ad=da[self.get("background")] +for y=1,dc do local bd=y+bc;local cd=_c[bd]or""local dd=cd:sub(ac+1,ac+cc)if#dd=1 and bd<=cc and cd>=1 and cd<=dc then +self:setCursor(bd,cd,true,self.get("cursorColor")or self.get("foreground"))end end end;return _b end project["elements/Container.lua"] = function(...) local ca=require("elementManager") local da=ca.getElement("VisualElement")local _b=require("libraries/expect") local ab=require("libraries/utils").split;local bb=setmetatable({},da)bb.__index=bb @@ -1319,241 +603,158 @@ for _c,ac in ipairs(self.get("visibleChildren"))do if ac==self then self.basalt.LOGGER.error("CIRCULAR REFERENCE DETECTED!")return end;ac:render()end end function bb:destroy() for _c,ac in ipairs(self._values.children)do ac:destroy()end;da.destroy(self)return self end;return bb end -project["elements/Slider.lua"] = function(...) local c=require("elements/VisualElement") -local d=setmetatable({},c)d.__index=d -d.defineProperty(d,"step",{default=1,type="number",canTriggerRender=true}) -d.defineProperty(d,"max",{default=100,type="number"}) -d.defineProperty(d,"horizontal",{default=true,type="boolean",canTriggerRender=true}) -d.defineProperty(d,"barColor",{default=colors.gray,type="number",canTriggerRender=true}) -d.defineProperty(d,"sliderColor",{default=colors.blue,type="number",canTriggerRender=true})d.defineEvent(d,"mouse_click") -d.defineEvent(d,"mouse_drag")d.defineEvent(d,"mouse_up")function d.new() -local _a=setmetatable({},d):__init()_a.set("width",8)_a.set("height",1) -_a.set("backgroundEnabled",false)return _a end;function d:init(_a,aa) -c.init(self,_a,aa)self.set("type","Slider")end -function d:getValue() -local _a=self.get("step")local aa=self.get("max") -local ba= -self.get("horizontal")and self.get("width")or self.get("height")return math.floor((_a-1)* (aa/ (ba-1)))end -function d:mouse_click(_a,aa,ba) -if _a==1 and self:isInBounds(aa,ba)then -local ca,da=self:getRelativePosition(aa,ba) -local _b=self.get("horizontal")and ca or da;local ab=self.get("horizontal")and self.get("width")or -self.get("height") -self.set("step",math.min(ab,math.max(1,_b)))self:updateRender()return true end end;d.mouse_drag=d.mouse_click -function d:mouse_scroll(_a,aa,ba) -if self:isInBounds(aa,ba)then -local ca=self.get("step")local da=self.get("horizontal")and self.get("width")or -self.get("height") -self.set("step",math.min(da,math.max(1, -ca+_a)))self:updateRender()return true end end -function d:render()c.render(self)local _a=self.get("width") -local aa=self.get("height")local ba=self.get("horizontal")local ca=self.get("step")local da= -ba and"\140"or"│" -local _b=string.rep(da,ba and _a or aa) -if ba then self:textFg(1,1,_b,self.get("barColor")) -self:textBg(ca,1," ",self.get("sliderColor"))else -for y=1,aa do self:textFg(1,y,da,self.get("barColor"))end -self:textFg(1,ca,"\140",self.get("sliderColor"))end end;return d end -project["elements/BaseElement.lua"] = function(...) local d=require("propertySystem") -local _a=require("libraries/utils").uuid;local aa=setmetatable({},d)aa.__index=aa;aa._events={} -aa.defineProperty(aa,"type",{default={"BaseElement"},type="string",setter=function(ba,ca)if -type(ca)=="string"then table.insert(ba._values.type,1,ca)return -ba._values.type end;return ca end,getter=function(ba,ca,da)if -da~=nil and da<1 then return ba._values.type end;return ba._values.type[ -da or 1]end}) -aa.defineProperty(aa,"id",{default="",type="string",readonly=true}) -aa.defineProperty(aa,"name",{default="",type="string"}) -aa.defineProperty(aa,"eventCallbacks",{default={},type="table"}) -function aa.defineEvent(ba,ca,da) -if not rawget(ba,'_eventConfigs')then ba._eventConfigs={}end;ba._eventConfigs[ca]={requires=da and da or ca}end -function aa.registerEventCallback(ba,ca,...) -local da=ca:match("^on")and ca or"on"..ca;local _b={...}local ab=_b[1] -ba[da]=function(bb,...) -for cb,db in ipairs(_b)do if not bb._registeredEvents[db]then -bb:listenEvent(db,true)end end;bb:registerCallback(ab,...)return bb end end -function aa.new()local ba=setmetatable({},aa):__init()return ba end -function aa:init(ba,ca)self._props=ba;self._values.id=_a()self.basalt=ca -self._registeredEvents={}local da=getmetatable(self).__index;local _b={}da=self -while da do -if -type(da)=="table"and da._eventConfigs then for ab,bb in pairs(da._eventConfigs)do -if not _b[ab]then _b[ab]=bb end end end -da=getmetatable(da)and getmetatable(da).__index end -for ab,bb in pairs(_b)do self._registeredEvents[bb.requires]=true end;if self._callbacks then -for ab,bb in pairs(self._callbacks)do self[bb]=function(cb,...) -cb:registerCallback(ab,...)return cb end end end +project["elements/Image.lua"] = function(...) local aa=require("elementManager") +local ba=aa.getElement("VisualElement")local ca=require("libraries/colorHex") +local da=setmetatable({},ba)da.__index=da +da.defineProperty(da,"bimg",{default={{}},type="table",canTriggerRender=true}) +da.defineProperty(da,"currentFrame",{default=1,type="number",canTriggerRender=true}) +da.defineProperty(da,"metadata",{default={},type="table"}) +da.defineProperty(da,"autoResize",{default=true,type="boolean"}) +da.defineProperty(da,"offsetX",{default=0,type="number",canTriggerRender=true}) +da.defineProperty(da,"offsetY",{default=0,type="number",canTriggerRender=true}) +function da.new()local ab=setmetatable({},da):__init() +ab.set("width",12)ab.set("height",6) +ab.set("background",colors.black)ab.set("z",5)return ab end;function da:init(ab,bb)ba.init(self,ab,bb)self.set("type","Image") return self end -function aa:postInit()if(self._props)then -for ba,ca in pairs(self._props)do self.set(ba,ca)end end;self._props=nil;return self end;function aa:isType(ba) -for ca,da in ipairs(self._values.type)do if da==ba then return true end end;return false end -function aa:listenEvent(ba,ca)ca= -ca~=false +function da:loadBimg(ab) +if type(ab)~="table"then return self end;local bb={}local cb={}for db,_c in pairs(ab)do +if type(db)=="number"then bb[db]=_c else cb[db]=_c end end;self.set("bimg",bb) +self.set("metadata",cb) +if bb[1]and bb[1][1]then +self.set("width",#bb[1][1][2])self.set("height",#bb[1])end;return self end +function da:resizeImage(ab,bb)local cb=self.get("bimg") +for db,_c in ipairs(cb)do local ac={} +for y=1,bb do +local bc=string.rep(" ",ab)local cc=string.rep("f",ab)local dc=string.rep("0",ab) +if _c[y]and +_c[y][1]then local _d=_c[y][1]local ad=_c[y][2]local bd=_c[y][3]bc=(_d.. +string.rep(" ",ab)):sub(1,ab)cc=(ad.. +string.rep("f",ab)):sub(1,ab)dc=(bd.. +string.rep("0",ab)):sub(1,ab)end;ac[y]={bc,cc,dc}end;cb[db]=ac end;self:updateRender()return self end +function da:getImageSize()local ab=self.get("bimg")if not ab[1]or not ab[1][1]then +return 0,0 end;return#ab[1][1][1],#ab[1]end +function da:getPixelData(ab,bb) +local cb=self.get("bimg")[self.get("currentFrame")]if not cb or not cb[bb]then return end;local db=cb[bb][1] +local _c=cb[bb][2]local ac=cb[bb][3] +if not db or not _c or not ac then return end;local bc=tonumber(_c:sub(ab,ab),16) +local cc=tonumber(ac:sub(ab,ab),16)local dc=db:sub(ab,ab)return bc,cc,dc end +local function _b(ab,bb) +local cb=ab.get("bimg")[ab.get("currentFrame")]if not cb then cb={} +ab.get("bimg")[ab.get("currentFrame")]=cb end +if not cb[bb]then cb[bb]={"","",""}end;return cb end +function da:setText(ab,bb,cb) +if type(cb)~="string"or#cb<1 then return self end;local db=_b(self,bb)local _c=db[bb][1] +while#_c#ab then cb=1 end;self.set("currentFrame",cb)return self end +function da:render()ba.render(self) +local ab=self.get("bimg")[self.get("currentFrame")]if not ab then return end;local bb=self.get("offsetX") +local cb=self.get("offsetY")local db=self.get("width")local _c=self.get("height") +for y=1,_c do local ac=y+cb +local bc=ab[ac] +if bc then local cc=bc[1]:sub(1 +bb,db+bb) +local dc=bc[2]:sub(1 +bb,db+bb)local _d=bc[3]:sub(1 +bb,db+bb)if cc and dc and _d then +self:blit(1 +bb,y,cc,dc,_d)end end end end;return da end +project["elements/Flexbox.lua"] = function(...) local da=require("elementManager") +local _b=da.getElement("Container")local ab=setmetatable({},_b)ab.__index=ab +ab.defineProperty(ab,"flexDirection",{default="row",type="string"}) +ab.defineProperty(ab,"flexSpacing",{default=1,type="number"}) +ab.defineProperty(ab,"flexJustifyContent",{default="flex-start",type="string",setter=function(bc,cc)if not cc:match("^flex%-")then +cc="flex-"..cc end;return cc end}) +ab.defineProperty(ab,"flexWrap",{default=false,type="boolean"}) +ab.defineProperty(ab,"flexUpdateLayout",{default=false,type="boolean"}) +local bb={getHeight=function(bc)return 0 end,getWidth=function(bc)return 0 end,getZ=function(bc)return 1 end,getPosition=function(bc)return 0,0 end,getSize=function(bc)return 0,0 end,isType=function(bc)return +false end,getType=function(bc)return"lineBreak"end,getName=function(bc)return"lineBreak"end,setPosition=function(bc) +end,setParent=function(bc)end,setSize=function(bc)end,getFlexGrow=function(bc)return 0 end,getFlexShrink=function(bc)return 0 end,getFlexBasis=function(bc)return 0 end,init=function(bc)end,getVisible=function(bc)return +true end} +local function cb(bc,cc,dc,_d)local ad=bc.get("children")local bd={} +if not(_d)then local cd=1;local dd=1;local __a=1 +for a_a,b_a in pairs(ad)do if +(bd[cd]==nil)then bd[cd]={offset=1}end;local c_a= +cc=="row"and b_a.get("height")or b_a.get("width")if +c_a>dd then dd=c_a end +if(b_a==bb)then __a=__a+dd+dc;dd=1;cd=cd+1 +bd[cd]={offset=__a}else table.insert(bd[cd],b_a)end end elseif(_d)then local cd=1;local dd=1 +local __a=cc=="row"and bc.get("width")or bc.get("height")local a_a=0;local b_a=1 +for c_a,d_a in pairs(ad)do +if(bd[b_a]==nil)then bd[b_a]={offset=1}end +if d_a:getType()=="lineBreak"then dd=dd+cd+dc;a_a=0;cd=1;b_a=b_a+1 +bd[b_a]={offset=dd}else +local _aa=cc=="row"and d_a.get("width")or d_a.get("height") +if(_aa+a_a<=__a)then table.insert(bd[b_a],d_a) +a_a=a_a+_aa+dc else dd=dd+cd+dc +cd=cc=="row"and d_a.get("height")or d_a.get("width")b_a=b_a+1;a_a=_aa+dc;bd[b_a]={offset=dd,d_a}end +local aaa=cc=="row"and d_a.get("height")or d_a.get("width")if aaa>cd then cd=aaa end end end end;return bd end +local function db(bc,cc,dc,_d)local ad=bc.get("width")local bd=dc* (#cc-1)local cd=0;for c_a,d_a in ipairs(cc)do +if d_a~=bb then bd=bd+ +d_a.get("width")cd=cd+d_a.get("flexGrow")end end;local dd=ad-bd;local __a= +cd>0 and(dd/cd)or 0;local a_a=0;local b_a=1 +for c_a,d_a in ipairs(cc)do +if d_a~=bb then +local _aa=d_a.get("width") +if d_a.get("flexGrow")>0 then if c_a==#cc then local aaa=dd-a_a;_aa=_aa+aaa else local aaa=math.floor(__a* +d_a.get("flexGrow"))_aa=_aa+aaa +a_a=a_a+aaa end end;d_a.set("x",b_a)d_a.set("y",cc.offset or 1) +d_a.set("width",_aa)b_a=b_a+_aa+dc end end +if _d=="flex-end"then local c_a=ad- (b_a-dc-1)for d_a,_aa in ipairs(cc)do +_aa.set("x",_aa.get("x")+c_a)end elseif _d=="flex-center"or _d=="center"then local c_a=math.floor(( +ad- (b_a-dc-1))/2)for d_a,_aa in ipairs(cc)do _aa.set("x", +_aa.get("x")+c_a)end end end +local function _c(bc,cc,dc,_d)local ad=bc.get("height")local bd=dc* (#cc-1)local cd=0;for c_a,d_a in ipairs(cc)do +if d_a~=bb then bd=bd+ +d_a.get("height")cd=cd+d_a.get("flexGrow")end end;local dd=ad-bd;local __a= +cd>0 and(dd/cd)or 0;local a_a=0;local b_a=1 +for c_a,d_a in ipairs(cc)do +if d_a~=bb then +local _aa=d_a.get("height") +if d_a.get("flexGrow")>0 then if c_a==#cc then local aaa=dd-a_a;_aa=_aa+aaa else local aaa=math.floor(__a* +d_a.get("flexGrow"))_aa=_aa+aaa +a_a=a_a+aaa end end;d_a.set("x",cc.offset or 1)d_a.set("y",b_a) +d_a.set("height",_aa)b_a=b_a+_aa+dc end end +if _d=="flex-end"then local c_a=ad- (b_a-dc-1)for d_a,_aa in ipairs(cc)do +_aa.set("y",_aa.get("y")+c_a)end elseif _d=="flex-center"or _d=="center"then local c_a=math.floor(( +ad- (b_a-dc-1))/2)for d_a,_aa in ipairs(cc)do _aa.set("y", +_aa.get("y")+c_a)end end end +local function ac(bc,cc,dc,_d,ad)local bd=cb(bc,cc,dc,ad) +if cc=="row"then +for cd,dd in pairs(bd)do db(bc,dd,dc,_d)end else for cd,dd in pairs(bd)do _c(bc,dd,dc,_d)end end;bc.set("flexUpdateLayout",false)end +function ab.new()local bc=setmetatable({},ab):__init() +bc.set("width",12)bc.set("height",6) +bc.set("background",colors.blue)bc.set("z",10) +bc:observe("width",function() +bc.set("flexUpdateLayout",true)end) +bc:observe("height",function()bc.set("flexUpdateLayout",true)end)return bc end;function ab:init(bc,cc)_b.init(self,bc,cc)self.set("type","Flexbox") +return self end +function ab:addChild(bc) +_b.addChild(self,bc) +if(bc~=bb)then +bc:instanceProperty("flexGrow",{default=0,type="number"}) +bc:instanceProperty("flexShrink",{default=0,type="number"}) +bc:instanceProperty("flexBasis",{default=0,type="number"})end;self.set("flexUpdateLayout",true)return self end +function ab:removeChild(bc)_b.removeChild(self,bc) +if(bc~=bb)then bc.setFlexGrow=nil;bc.setFlexShrink= +nil;bc.setFlexBasis=nil;bc.getFlexGrow=nil;bc.getFlexShrink=nil;bc.getFlexBasis= +nil;bc.set("flexGrow",nil) +bc.set("flexShrink",nil)bc.set("flexBasis",nil)end;self.set("flexUpdateLayout",true)return self end;function ab:addLineBreak()self:addChild(bb)return self end +function ab:render() if -ca~= (self._registeredEvents[ba]or false)then -if ca then self._registeredEvents[ba]=true;if self.parent then -self.parent:registerChildEvent(self,ba)end else self._registeredEvents[ba]=nil -if -self.parent then self.parent:unregisterChildEvent(self,ba)end end end;return self end -function aa:registerCallback(ba,ca)if not self._registeredEvents[ba]then -self:listenEvent(ba,true)end -if -not self._values.eventCallbacks[ba]then self._values.eventCallbacks[ba]={}end -table.insert(self._values.eventCallbacks[ba],ca)return self end -function aa:fireEvent(ba,...) -if self.get("eventCallbacks")[ba]then for ca,da in -ipairs(self.get("eventCallbacks")[ba])do local _b=da(self,...)return _b end end;return self end;function aa:dispatchEvent(ba,...)if self[ba]then return self[ba](self,...)end;return -self:handleEvent(ba,...)end;function aa:handleEvent(ba,...)return -false end -function aa:onChange(ba,ca)self:observe(ba,ca)return self end;function aa:getBaseFrame() -if self.parent then return self.parent:getBaseFrame()end;return self end -function aa:destroy()if self.parent then -self.parent:removeChild(self)end;for ba in pairs(self._registeredEvents)do -self:listenEvent(ba,false)end;self._values.eventCallbacks={}self._props= -nil;self._values=nil;self.basalt=nil;self.parent=nil -self.__index=nil;setmetatable(self,nil)end -function aa:updateRender()if(self.parent)then self.parent:updateRender()else -self._renderUpdate=true end end;return aa end -project["elements/Checkbox.lua"] = function(...) local c=require("elements/VisualElement") -local d=setmetatable({},c)d.__index=d -d.defineProperty(d,"checked",{default=false,type="boolean",canTriggerRender=true}) -d.defineProperty(d,"text",{default=" ",type="string",canTriggerRender=true,setter=function(_a,aa)local ba=_a.get("checkedText") -local ca=math.max(#aa,#ba)if(_a.get("autoSize"))then _a.set("width",ca)end;return aa end}) -d.defineProperty(d,"checkedText",{default="x",type="string",canTriggerRender=true,setter=function(_a,aa)local ba=_a.get("text") -local ca=math.max(#aa,#ba)if(_a.get("autoSize"))then _a.set("width",ca)end;return aa end}) -d.defineProperty(d,"autoSize",{default=true,type="boolean"})d.defineEvent(d,"mouse_click")function d.new() -local _a=setmetatable({},d):__init()return _a end;function d:init(_a,aa)c.init(self,_a,aa) -self.set("type","Checkbox")end -function d:mouse_click(_a,aa,ba) -if c.mouse_click(self,_a,aa,ba)then -self.set("checked", -not self.get("checked")) -self:fireEvent("change",self.get("checked"))return true end;return false end -function d:render()c.render(self)local _a=self.get("checked") -local aa=self.get("text")local ba=self.get("checkedText") -local ca=string.sub(_a and ba or aa,1,self.get("width"))self:textFg(1,1,ca,self.get("foreground"))end;return d end -project["elements/Input.lua"] = function(...) local d=require("elements/VisualElement") -local _a=require("libraries/colorHex")local aa=setmetatable({},d)aa.__index=aa -aa.defineProperty(aa,"text",{default="",type="string",canTriggerRender=true}) -aa.defineProperty(aa,"cursorPos",{default=1,type="number"}) -aa.defineProperty(aa,"viewOffset",{default=0,type="number",canTriggerRender=true}) -aa.defineProperty(aa,"maxLength",{default=nil,type="number"}) -aa.defineProperty(aa,"placeholder",{default="...",type="string"}) -aa.defineProperty(aa,"placeholderColor",{default=colors.gray,type="number"}) -aa.defineProperty(aa,"focusedColor",{default=colors.blue,type="number"}) -aa.defineProperty(aa,"pattern",{default=nil,type="string"}) -aa.defineProperty(aa,"cursorColor",{default=nil,type="number"})aa.defineEvent(aa,"mouse_click") -aa.defineEvent(aa,"key")aa.defineEvent(aa,"char") -function aa.new() -local ba=setmetatable({},aa):__init()ba.set("width",8)ba.set("z",3)return ba end -function aa:init(ba,ca)d.init(self,ba,ca)self.set("type","Input")return self end -function aa:setCursor(ba,ca,da,_b) -ba=math.min(self.get("width"),math.max(1,ba))return d.setCursor(self,ba,ca,da,_b)end -function aa:char(ba)if not self.get("focused")then return false end -local ca=self.get("text")local da=self.get("cursorPos")local _b=self.get("maxLength") -local ab=self.get("pattern")if _b and#ca>=_b then return end -if ab and not ba:match(ab)then return end -self.set("text",ca:sub(1,da-1)..ba..ca:sub(da))self.set("cursorPos",da+1)self:updateViewport()local bb= -self.get("cursorPos")-self.get("viewOffset") -self:setCursor(bb,1,true, -self.get("cursorColor")or self.get("foreground"))return true end -function aa:key(ba)if not self.get("focused")then return false end -local ca=self.get("cursorPos")local da=self.get("text")local _b=self.get("viewOffset") -local ab=self.get("width") -if ba==keys.left then if ca>1 then self.set("cursorPos",ca-1) -if ca-1 <=_b then self.set("viewOffset",math.max(0, -ca-2))end end elseif ba==keys.right then if ca<=#da then self.set("cursorPos", -ca+1)if ca-_b>=ab then -self.set("viewOffset",ca-ab+1)end end elseif -ba==keys.backspace then if ca>1 then -self.set("text",da:sub(1,ca-2)..da:sub(ca))self.set("cursorPos",ca-1)self:updateRender() -self:updateViewport()end end -local bb=self.get("cursorPos")-self.get("viewOffset") -self:setCursor(bb,1,true,self.get("cursorColor")or self.get("foreground"))return true end -function aa:mouse_click(ba,ca,da) -if d.mouse_click(self,ba,ca,da)then -local _b,ab=self:getRelativePosition(ca,da)local bb=self.get("text")local cb=self.get("viewOffset") -local db=#bb+1;local _c=math.min(db,cb+_b)self.set("cursorPos",_c) -local ac=_c-cb -self:setCursor(ac,1,true,self.get("cursorColor")or self.get("foreground"))return true end;return false end -function aa:updateViewport()local ba=self.get("width") -local ca=self.get("cursorPos")local da=self.get("viewOffset") -local _b=#self.get("text") -if ca-da>=ba then self.set("viewOffset",ca-ba+1)elseif ca<=da then self.set("viewOffset", -ca-1)end -self.set("viewOffset",math.max(0,math.min(self.get("viewOffset"),_b-ba+1)))return self end -function aa:render()local ba=self.get("text")local ca=self.get("viewOffset") -local da=self.get("width")local _b=self.get("placeholder") -local ab=self.get("focusedColor")local bb=self.get("focused") -local cb,db=self.get("width"),self.get("height") -self:multiBlit(1,1,cb,db," ",_a[self.get("foreground")],_a[bb and ab or -self.get("background")])if -#ba==0 and#_b~=0 and self.get("focused")==false then -self:textFg(1,1,_b:sub(1,cb),self.get("placeholderColor"))return end -local _c=ba:sub(ca+1,ca+cb)self:textFg(1,1,_c,self.get("foreground"))end;return aa end -project["elements/BigFont.lua"] = function(...) local _b=require("libraries/colorHex") -local ab={{"\32\32\32\137\156\148\158\159\148\135\135\144\159\139\32\136\157\32\159\139\32\32\143\32\32\143\32\32\32\32\32\32\32\32\147\148\150\131\148\32\32\32\151\140\148\151\140\147","\32\32\32\149\132\149\136\156\149\144\32\133\139\159\129\143\159\133\143\159\133\138\32\133\138\32\133\32\32\32\32\32\32\150\150\129\137\156\129\32\32\32\133\131\129\133\131\132","\32\32\32\130\131\32\130\131\32\32\129\32\32\32\32\130\131\32\130\131\32\32\32\32\143\143\143\32\32\32\32\32\32\130\129\32\130\135\32\32\32\32\131\32\32\131\32\131","\139\144\32\32\143\148\135\130\144\149\32\149\150\151\149\158\140\129\32\32\32\135\130\144\135\130\144\32\149\32\32\139\32\159\148\32\32\32\32\159\32\144\32\148\32\147\131\132","\159\135\129\131\143\149\143\138\144\138\32\133\130\149\149\137\155\149\159\143\144\147\130\132\32\149\32\147\130\132\131\159\129\139\151\129\148\32\32\139\131\135\133\32\144\130\151\32","\32\32\32\32\32\32\130\135\32\130\32\129\32\129\129\131\131\32\130\131\129\140\141\132\32\129\32\32\129\32\32\32\32\32\32\32\131\131\129\32\32\32\32\32\32\32\32\32","\32\32\32\32\149\32\159\154\133\133\133\144\152\141\132\133\151\129\136\153\32\32\154\32\159\134\129\130\137\144\159\32\144\32\148\32\32\32\32\32\32\32\32\32\32\32\151\129","\32\32\32\32\133\32\32\32\32\145\145\132\141\140\132\151\129\144\150\146\129\32\32\32\138\144\32\32\159\133\136\131\132\131\151\129\32\144\32\131\131\129\32\144\32\151\129\32","\32\32\32\32\129\32\32\32\32\130\130\32\32\129\32\129\32\129\130\129\129\32\32\32\32\130\129\130\129\32\32\32\32\32\32\32\32\133\32\32\32\32\32\129\32\129\32\32","\150\156\148\136\149\32\134\131\148\134\131\148\159\134\149\136\140\129\152\131\32\135\131\149\150\131\148\150\131\148\32\148\32\32\148\32\32\152\129\143\143\144\130\155\32\134\131\148","\157\129\149\32\149\32\152\131\144\144\131\148\141\140\149\144\32\149\151\131\148\32\150\32\150\131\148\130\156\133\32\144\32\32\144\32\130\155\32\143\143\144\32\152\129\32\134\32","\130\131\32\131\131\129\131\131\129\130\131\32\32\32\129\130\131\32\130\131\32\32\129\32\130\131\32\130\129\32\32\129\32\32\133\32\32\32\129\32\32\32\130\32\32\32\129\32","\150\140\150\137\140\148\136\140\132\150\131\132\151\131\148\136\147\129\136\147\129\150\156\145\138\143\149\130\151\32\32\32\149\138\152\129\149\32\32\157\152\149\157\144\149\150\131\148","\149\143\142\149\32\149\149\32\149\149\32\144\149\32\149\149\32\32\149\32\32\149\32\149\149\32\149\32\149\32\144\32\149\149\130\148\149\32\32\149\32\149\149\130\149\149\32\149","\130\131\129\129\32\129\131\131\32\130\131\32\131\131\32\131\131\129\129\32\32\130\131\32\129\32\129\130\131\32\130\131\32\129\32\129\131\131\129\129\32\129\129\32\129\130\131\32","\136\140\132\150\131\148\136\140\132\153\140\129\131\151\129\149\32\149\149\32\149\149\32\149\137\152\129\137\152\129\131\156\133\149\131\32\150\32\32\130\148\32\152\137\144\32\32\32","\149\32\32\149\159\133\149\32\149\144\32\149\32\149\32\149\32\149\150\151\129\138\155\149\150\130\148\32\149\32\152\129\32\149\32\32\32\150\32\32\149\32\32\32\32\32\32\32","\129\32\32\130\129\129\129\32\129\130\131\32\32\129\32\130\131\32\32\129\32\129\32\129\129\32\129\32\129\32\131\131\129\130\131\32\32\32\129\130\131\32\32\32\32\140\140\132","\32\154\32\159\143\32\149\143\32\159\143\32\159\144\149\159\143\32\159\137\145\159\143\144\149\143\32\32\145\32\32\32\145\149\32\144\32\149\32\143\159\32\143\143\32\159\143\32","\32\32\32\152\140\149\151\32\149\149\32\145\149\130\149\157\140\133\32\149\32\154\143\149\151\32\149\32\149\32\144\32\149\149\153\32\32\149\32\149\133\149\149\32\149\149\32\149","\32\32\32\130\131\129\131\131\32\130\131\32\130\131\129\130\131\129\32\129\32\140\140\129\129\32\129\32\129\32\137\140\129\130\32\129\32\130\32\129\32\129\129\32\129\130\131\32","\144\143\32\159\144\144\144\143\32\159\143\144\159\138\32\144\32\144\144\32\144\144\32\144\144\32\144\144\32\144\143\143\144\32\150\129\32\149\32\130\150\32\134\137\134\134\131\148","\136\143\133\154\141\149\151\32\129\137\140\144\32\149\32\149\32\149\154\159\133\149\148\149\157\153\32\154\143\149\159\134\32\130\148\32\32\149\32\32\151\129\32\32\32\32\134\32","\133\32\32\32\32\133\129\32\32\131\131\32\32\130\32\130\131\129\32\129\32\130\131\129\129\32\129\140\140\129\131\131\129\32\130\129\32\129\32\130\129\32\32\32\32\32\129\32","\32\32\32\32\149\32\32\149\32\32\32\32\32\32\32\32\149\32\32\149\32\32\32\32\32\32\32\32\149\32\32\149\32\32\32\32\32\32\32\32\149\32\32\149\32\32\32\32","\32\32\32\32\32\32\32\32\32\32\32\32\32\149\32\32\149\32\32\149\32\32\149\32\32\149\32\32\149\32\32\149\32\32\149\32\32\32\32\32\32\32\32\32\32\32\32\32","\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32\32","\32\32\32\32\149\32\32\149\32\32\32\32\32\32\32\32\149\32\32\149\32\32\32\32\32\32\32\32\149\32\32\149\32\32\32\32\32\32\32\32\149\32\32\149\32\32\32\32","\32\32\32\32\32\32\32\32\32\32\32\32\32\149\32\32\149\32\32\149\32\32\149\32\32\149\32\32\149\32\32\149\32\32\149\32\32\32\32\32\32\32\32\32\32\32\32\32","\32\149\32\32\149\32\32\149\32\32\149\32\32\149\32\32\149\32\32\149\32\32\149\32\32\149\32\32\149\32\32\149\32\32\149\32\32\149\32\32\149\32\32\149\32\32\149\32","\32\32\32\32\145\32\159\139\32\151\131\132\155\143\132\134\135\145\32\149\32\158\140\129\130\130\32\152\147\155\157\134\32\32\144\144\32\32\32\32\32\32\152\131\155\131\131\129","\32\32\32\32\149\32\149\32\145\148\131\32\149\32\149\140\157\132\32\148\32\137\155\149\32\32\32\149\154\149\137\142\32\153\153\32\131\131\149\131\131\129\149\135\145\32\32\32","\32\32\32\32\129\32\130\135\32\131\131\129\134\131\132\32\129\32\32\129\32\131\131\32\32\32\32\130\131\129\32\32\32\32\129\129\32\32\32\32\32\32\130\131\129\32\32\32","\150\150\32\32\148\32\134\32\32\132\32\32\134\32\32\144\32\144\150\151\149\32\32\32\32\32\32\145\32\32\152\140\144\144\144\32\133\151\129\133\151\129\132\151\129\32\145\32","\130\129\32\131\151\129\141\32\32\142\32\32\32\32\32\149\32\149\130\149\149\32\143\32\32\32\32\142\132\32\154\143\133\157\153\132\151\150\148\151\158\132\151\150\148\144\130\148","\32\32\32\140\140\132\32\32\32\32\32\32\32\32\32\151\131\32\32\129\129\32\32\32\32\134\32\32\32\32\32\32\32\129\129\32\129\32\129\129\130\129\129\32\129\130\131\32","\156\143\32\159\141\129\153\140\132\153\137\32\157\141\32\159\142\32\150\151\129\150\131\132\140\143\144\143\141\145\137\140\148\141\141\144\157\142\32\159\140\32\151\134\32\157\141\32","\157\140\149\157\140\149\157\140\149\157\140\149\157\140\149\157\140\149\151\151\32\154\143\132\157\140\32\157\140\32\157\140\32\157\140\32\32\149\32\32\149\32\32\149\32\32\149\32","\129\32\129\129\32\129\129\32\129\129\32\129\129\32\129\129\32\129\129\131\129\32\134\32\131\131\129\131\131\129\131\131\129\131\131\129\130\131\32\130\131\32\130\131\32\130\131\32","\151\131\148\152\137\145\155\140\144\152\142\145\153\140\132\153\137\32\154\142\144\155\159\132\150\156\148\147\32\144\144\130\145\136\137\32\146\130\144\144\130\145\130\136\32\151\140\132","\151\32\149\151\155\149\149\32\149\149\32\149\149\32\149\149\32\149\149\32\149\152\137\144\157\129\149\149\32\149\149\32\149\149\32\149\149\32\149\130\150\32\32\157\129\149\32\149","\131\131\32\129\32\129\130\131\32\130\131\32\130\131\32\130\131\32\130\131\32\32\32\32\130\131\32\130\131\32\130\131\32\130\131\32\130\131\32\32\129\32\130\131\32\133\131\32","\156\143\32\159\141\129\153\140\132\153\137\32\157\141\32\159\142\32\159\159\144\152\140\144\156\143\32\159\141\129\153\140\132\157\141\32\130\145\32\32\147\32\136\153\32\130\146\32","\152\140\149\152\140\149\152\140\149\152\140\149\152\140\149\152\140\149\149\157\134\154\143\132\157\140\133\157\140\133\157\140\133\157\140\133\32\149\32\32\149\32\32\149\32\32\149\32","\130\131\129\130\131\129\130\131\129\130\131\129\130\131\129\130\131\129\130\130\131\32\134\32\130\131\129\130\131\129\130\131\129\130\131\129\32\129\32\32\129\32\32\129\32\32\129\32","\159\134\144\137\137\32\156\143\32\159\141\129\153\140\132\153\137\32\157\141\32\32\132\32\159\143\32\147\32\144\144\130\145\136\137\32\146\130\144\144\130\145\130\138\32\146\130\144","\149\32\149\149\32\149\149\32\149\149\32\149\149\32\149\149\32\149\149\32\149\131\147\129\138\134\149\149\32\149\149\32\149\149\32\149\149\32\149\154\143\149\32\157\129\154\143\149","\130\131\32\129\32\129\130\131\32\130\131\32\130\131\32\130\131\32\130\131\32\32\32\32\130\131\32\130\131\129\130\131\129\130\131\129\130\131\129\140\140\129\130\131\32\140\140\129"},{"000110000110110000110010101000000010000000100101","000000110110000000000010101000000010000000100101","000000000000000000000000000000000000000000000000","100010110100000010000110110000010100000100000110","000000110000000010110110000110000000000000110000","000000000000000000000000000000000000000000000000","000000110110000010000000100000100000000000000010","000000000110110100010000000010000000000000000100","000000000000000000000000000000000000000000000000","010000000000100110000000000000000000000110010000","000000000000000000000000000010000000010110000000","000000000000000000000000000000000000000000000000","011110110000000100100010110000000100000000000000","000000000000000000000000000000000000000000000000","000000000000000000000000000000000000000000000000","110000110110000000000000000000010100100010000000","000010000000000000110110000000000100010010000000","000000000000000000000000000000000000000000000000","010110010110100110110110010000000100000110110110","000000000000000000000110000000000110000000000000","000000000000000000000000000000000000000000000000","010100010110110000000000000000110000000010000000","110110000000000000110000110110100000000010000000","000000000000000000000000000000000000000000000000","000100011111000100011111000100011111000100011111","000000000000100100100100011011011011111111111111","000000000000000000000000000000000000000000000000","000100011111000100011111000100011111000100011111","000000000000100100100100011011011011111111111111","100100100100100100100100100100100100100100100100","000000110100110110000010000011110000000000011000","000000000100000000000010000011000110000000001000","000000000000000000000000000000000000000000000000","010000100100000000000000000100000000010010110000","000000000000000000000000000000110110110110110000","000000000000000000000000000000000000000000000000","110110110110110110000000110110110110110110110110","000000000000000000000110000000000000000000000000","000000000000000000000000000000000000000000000000","000000000000110110000110010000000000000000010010","000010000000000000000000000000000000000000000000","000000000000000000000000000000000000000000000000","110110110110110110110000110110110110000000000000","000000000000000000000110000000000000000000000000","000000000000000000000000000000000000000000000000","110110110110110110110000110000000000000000010000","000000000000000000000000100000000000000110000110","000000000000000000000000000000000000000000000000"}}local bb={}local cb={} -do local dc=0;local _d=#ab[1]local ad=#ab[1][1] -for i=1,_d,3 do -for j=1,ad,3 do -local bd=string.char(dc)local cd={}cd[1]=ab[1][i]:sub(j,j+2) -cd[2]=ab[1][i+1]:sub(j,j+2)cd[3]=ab[1][i+2]:sub(j,j+2)local dd={}dd[1]=ab[2][i]:sub(j, -j+2)dd[2]=ab[2][i+1]:sub(j,j+2)dd[3]=ab[2][ -i+2]:sub(j,j+2)cb[bd]={cd,dd}dc=dc+1 end end;bb[1]=cb end -local function db(dc,_d)local ad={["0"]="1",["1"]="0"}if dc<=#bb then return true end -for f=#bb+1,dc do local bd={}local cd=bb[ -f-1] -for char=0,255 do local dd=string.char(char)local __a={}local a_a={} -local b_a=cd[dd][1]local c_a=cd[dd][2] -for i=1,#b_a do local d_a,_aa,aaa,baa,caa,daa={},{},{},{},{},{} -for j=1,#b_a[1]do -local _ba=cb[b_a[i]:sub(j,j)][1]table.insert(d_a,_ba[1]) -table.insert(_aa,_ba[2])table.insert(aaa,_ba[3]) -local aba=cb[b_a[i]:sub(j,j)][2] -if c_a[i]:sub(j,j)=="1"then -table.insert(baa,(aba[1]:gsub("[01]",ad))) -table.insert(caa,(aba[2]:gsub("[01]",ad))) -table.insert(daa,(aba[3]:gsub("[01]",ad)))else table.insert(baa,aba[1]) -table.insert(caa,aba[2])table.insert(daa,aba[3])end end;table.insert(__a,table.concat(d_a)) -table.insert(__a,table.concat(_aa))table.insert(__a,table.concat(aaa)) -table.insert(a_a,table.concat(baa))table.insert(a_a,table.concat(caa)) -table.insert(a_a,table.concat(daa))end;bd[dd]={__a,a_a}if _d then _d="Font"..f.."Yeld"..char -os.queueEvent(_d)os.pullEvent(_d)end end;bb[f]=bd end;return true end -local function _c(dc,_d,ad,bd,cd) -if not type(_d)=="string"then error("Not a String",3)end -local dd=type(ad)=="string"and ad:sub(1,1)or _b[ad]or -error("Wrong Front Color",3) -local __a=type(bd)=="string"and bd:sub(1,1)or _b[bd]or -error("Wrong Back Color",3)if(bb[dc]==nil)then db(3,false)end;local a_a=bb[dc]or -error("Wrong font size selected",3)if _d==""then -return{{""},{""},{""}}end;local b_a={} -for daa in _d:gmatch('.')do table.insert(b_a,daa)end;local c_a={}local d_a=#a_a[b_a[1]][1] -for nLine=1,d_a do local daa={}for i=1,#b_a do -daa[i]= -a_a[b_a[i]]and a_a[b_a[i]][1][nLine]or""end;c_a[nLine]=table.concat(daa)end;local _aa={}local aaa={}local baa={["0"]=dd,["1"]=__a}local caa={["0"]=__a,["1"]=dd} -for nLine=1,d_a -do local daa={}local _ba={} -for i=1,#b_a do local aba= -a_a[b_a[i]]and a_a[b_a[i]][2][nLine]or"" -daa[i]=aba:gsub("[01]",cd and -{["0"]=ad:sub(i,i),["1"]=bd:sub(i,i)}or baa) -_ba[i]=aba:gsub("[01]", -cd and{["0"]=bd:sub(i,i),["1"]=ad:sub(i,i)}or caa)end;_aa[nLine]=table.concat(daa) -aaa[nLine]=table.concat(_ba)end;return{c_a,_aa,aaa}end;local ac=require("elementManager") -local bc=ac.getElement("VisualElement")local cc=setmetatable({},bc)cc.__index=cc -cc.defineProperty(cc,"text",{default="BigFont",type="string",canTriggerRender=true,setter=function(dc,_d) -dc.bigfontText=_c(dc.get("fontSize"),_d,dc.get("foreground"),dc.get("background"))return _d end}) -cc.defineProperty(cc,"fontSize",{default=1,type="number",canTriggerRender=true,setter=function(dc,_d) -dc.bigfontText=_c(_d,dc.get("text"),dc.get("foreground"),dc.get("background"))return _d end}) -function cc.new()local dc=setmetatable({},cc):__init() -dc.set("width",16)dc.set("height",3)dc.set("z",5)return dc end -function cc:init(dc,_d)bc.init(self,dc,_d)self.set("type","BigFont")end -function cc:render()bc.render(self) -if(self.bigfontText)then -local dc,_d=self.get("x"),self.get("y") -for i=1,#self.bigfontText[1]do -local ad=self.bigfontText[1][i]:sub(1,self.get("width")) -local bd=self.bigfontText[2][i]:sub(1,self.get("width")) -local cd=self.bigfontText[3][i]:sub(1,self.get("width"))self:blit(dc,_d+i-1,ad,bd,cd)end end end;return cc end +(self.get("flexUpdateLayout"))then +ac(self,self.get("flexDirection"),self.get("flexSpacing"),self.get("flexJustifyContent"),self.get("flexWrap"))end;_b.render(self)end;return ab end project["elements/VisualElement.lua"] = function(...) local ba=require("elementManager") local ca=ba.getElement("BaseElement")local da=require("libraries/colorHex") local _b=setmetatable({},ca)_b.__index=_b @@ -1714,60 +915,6 @@ self:blit(1,i,bc,ba[self.get("foreground")],ba[self.get("background")])else self:blit(i,1,bc,ba[self.get("foreground")],ba[self.get("background")])end end for i=dc,dc+cb-1 do if cc then self:blit(1,i,db,ba[_c],ba[ac])else self:blit(i,1,db,ba[_c],ba[ac])end end end;return ca end -project["elements/List.lua"] = function(...) local c=require("elements/VisualElement") -local d=setmetatable({},c)d.__index=d -d.defineProperty(d,"items",{default={},type="table",canTriggerRender=true}) -d.defineProperty(d,"selectable",{default=true,type="boolean"}) -d.defineProperty(d,"multiSelection",{default=false,type="boolean"}) -d.defineProperty(d,"offset",{default=0,type="number",canTriggerRender=true}) -d.defineProperty(d,"selectedBackground",{default=colors.blue,type="number"}) -d.defineProperty(d,"selectedForeground",{default=colors.white,type="number"})d.defineEvent(d,"mouse_click") -d.defineEvent(d,"mouse_scroll") -function d.new()local _a=setmetatable({},d):__init() -_a.set("width",16)_a.set("height",8)_a.set("z",5) -_a.set("background",colors.gray)return _a end -function d:init(_a,aa)c.init(self,_a,aa)self.set("type","List")return self end;function d:addItem(_a)local aa=self.get("items")table.insert(aa,_a) -self:updateRender()return self end -function d:removeItem(_a) -local aa=self.get("items")table.remove(aa,_a)self:updateRender()return self end -function d:clear()self.set("items",{})self:updateRender()return self end -function d:getSelectedItems()local _a={}for aa,ba in ipairs(self.get("items"))do -if -type(ba)=="table"and ba.selected then local ca=ba;ca.index=aa;table.insert(_a,ca)end end;return _a end -function d:mouse_click(_a,aa,ba) -if -_a==1 and self:isInBounds(aa,ba)and self.get("selectable")then local ca,da=self:getRelativePosition(aa,ba) -local _b=da+self.get("offset")local ab=self.get("items") -if _b<=#ab then local bb=ab[_b]if type(bb)=="string"then -bb={text=bb}ab[_b]=bb end;if -not self.get("multiSelection")then -for cb,db in ipairs(ab)do if type(db)=="table"then db.selected=false end end end -bb.selected=not bb.selected;if bb.callback then bb.callback(self)end -self:fireEvent("select",_b,bb)self:updateRender()return true end end;return false end -function d:mouse_scroll(_a,aa,ba) -if self:isInBounds(aa,ba)then local ca=self.get("offset") -local da=math.max(0,# -self.get("items")-self.get("height"))ca=math.min(da,math.max(0,ca+_a)) -self.set("offset",ca)return true end;return false end -function d:onSelect(_a)self:registerCallback("select",_a)return self end -function d:scrollToBottom() -local _a=math.max(0,#self.get("items")-self.get("height"))self.set("offset",_a)return self end;function d:scrollToTop()self.set("offset",0)return self end -function d:render() -c.render(self)local _a=self.get("items")local aa=self.get("height") -local ba=self.get("offset")local ca=self.get("width") -for i=1,aa do local da=i+ba;local _b=_a[da] -if _b then if -type(_b)=="string"then _b={text=_b}_a[da]=_b end -if _b.separator then -local ab=(_b.text or"-"):sub(1,1)local bb=string.rep(ab,ca) -local cb=_b.foreground or self.get("foreground")local db=_b.background or self.get("background") -self:textBg(1,i,string.rep(" ",ca),db)self:textFg(1,i,bb:sub(1,ca),cb)else local ab=_b.text -local bb=_b.selected -local cb= -bb and(_b.selectedBackground or self.get("selectedBackground"))or(_b.background or self.get("background")) -local db= -bb and(_b.selectedForeground or self.get("selectedForeground"))or(_b.foreground or self.get("foreground"))self:textBg(1,i,string.rep(" ",ca),cb) -self:textFg(1,i,ab:sub(1,ca),db)end end end end;return d end project["elements/Tree.lua"] = function(...) local _a=require("elements/VisualElement")local aa=string.sub local ba=setmetatable({},_a)ba.__index=ba ba.defineProperty(ba,"nodes",{default={},type="table",canTriggerRender=true,setter=function(da,_b)if#_b>0 then @@ -1822,92 +969,451 @@ local ad=cc..dc.." ".. (ac.text or"Node")local bd=aa(ad,db+1,db+self.get("width" self:textFg(1,y, bd..string.rep(" ",self.get("width")-#bd),self.get("foreground"))else self:textFg(1,y,string.rep(" ",self.get("width")),self.get("foreground"),self.get("background"))end end end;return ba end -project["elements/TextBox.lua"] = function(...) local ca=require("elements/VisualElement") -local da=require("libraries/colorHex")local _b=setmetatable({},ca)_b.__index=_b -_b.defineProperty(_b,"lines",{default={""},type="table",canTriggerRender=true}) -_b.defineProperty(_b,"cursorX",{default=1,type="number"}) -_b.defineProperty(_b,"cursorY",{default=1,type="number"}) -_b.defineProperty(_b,"scrollX",{default=0,type="number",canTriggerRender=true}) -_b.defineProperty(_b,"scrollY",{default=0,type="number",canTriggerRender=true}) -_b.defineProperty(_b,"editable",{default=true,type="boolean"}) -_b.defineProperty(_b,"syntaxPatterns",{default={},type="table"}) -_b.defineProperty(_b,"cursorColor",{default=nil,type="number"})_b.defineEvent(_b,"mouse_click") -_b.defineEvent(_b,"key")_b.defineEvent(_b,"char") -_b.defineEvent(_b,"mouse_scroll") -function _b.new()local _c=setmetatable({},_b):__init() -_c.set("width",20)_c.set("height",10)return _c end;function _b:init(_c,ac)ca.init(self,_c,ac)self.set("type","TextBox") -return self end;function _b:addSyntaxPattern(_c,ac) -table.insert(self.get("syntaxPatterns"),{pattern=_c,color=ac})return self end -local function ab(_c,ac) -local bc=_c.get("lines")local cc=_c.get("cursorX")local dc=_c.get("cursorY")local _d=bc[dc]bc[dc]=_d:sub(1, -cc-1)..ac.._d:sub(cc) -_c.set("cursorX",cc+1)_c:updateViewport()_c:updateRender()end -local function bb(_c)local ac=_c.get("lines")local bc=_c.get("cursorX") -local cc=_c.get("cursorY")local dc=ac[cc]local _d=dc:sub(bc)ac[cc]=dc:sub(1,bc-1) -table.insert(ac,cc+1,_d)_c.set("cursorX",1)_c.set("cursorY",cc+1) -_c:updateViewport()_c:updateRender()end -local function cb(_c)local ac=_c.get("lines")local bc=_c.get("cursorX") -local cc=_c.get("cursorY")local dc=ac[cc] -if bc>1 then -ac[cc]=dc:sub(1,bc-2)..dc:sub(bc)_c.set("cursorX",bc-1)elseif cc>1 then local _d=ac[cc-1] -_c.set("cursorX",#_d+1)_c.set("cursorY",cc-1)ac[cc-1]=_d..dc -table.remove(ac,cc)end;_c:updateViewport()_c:updateRender()end -function _b:updateViewport()local _c=self.get("cursorX") -local ac=self.get("cursorY")local bc=self.get("scrollX")local cc=self.get("scrollY") -local dc=self.get("width")local _d=self.get("height") -if _c-bc>dc then -self.set("scrollX",_c-dc)elseif _c-bc<1 then self.set("scrollX",_c-1)end;if ac-cc>_d then self.set("scrollY",ac-_d)elseif ac-cc<1 then -self.set("scrollY",ac-1)end;return self end -function _b:char(_c)if -not self.get("editable")or not self.get("focused")then return false end;ab(self,_c)return true end -function _b:key(_c)if -not self.get("editable")or not self.get("focused")then return false end -local ac=self.get("lines")local bc=self.get("cursorX")local cc=self.get("cursorY") -if _c== -keys.enter then bb(self)elseif _c==keys.backspace then cb(self)elseif _c==keys.left then -if bc>1 then self.set("cursorX", -bc-1)elseif cc>1 then self.set("cursorY",cc-1)self.set("cursorX", -#ac[cc-1]+1)end elseif _c==keys.right then -if bc<=#ac[cc]then self.set("cursorX",bc+1)elseif cc<#ac then self.set("cursorY", -cc+1)self.set("cursorX",1)end elseif _c==keys.up and cc>1 then self.set("cursorY",cc-1) -self.set("cursorX",math.min(bc, -#ac[cc-1]+1))elseif _c==keys.down and cc<#ac then self.set("cursorY",cc+1) -self.set("cursorX",math.min(bc, -#ac[cc+1]+1))end;self:updateRender()self:updateViewport()return true end -function _b:mouse_scroll(_c,ac,bc) -if self:isInBounds(ac,bc)then local cc=self.get("scrollY") -local dc=self.get("height")local _d=self.get("lines")local ad=math.max(0,#_d-dc+2)local bd=math.max(0,math.min(ad, -cc+_c)) -self.set("scrollY",bd)self:updateRender()return true end;return false end -function _b:mouse_click(_c,ac,bc) -if ca.mouse_click(self,_c,ac,bc)then -local cc,dc=self:getRelativePosition(ac,bc)local _d=self.get("scrollX")local ad=self.get("scrollY") -local bd=dc+ad;local cd=self.get("lines")if bd<=#cd then self.set("cursorY",bd) -self.set("cursorX",math.min( -cc+_d,#cd[bd]+1))end;self:updateRender()return -true end;return false end -function _b:setText(_c)local ac={} -if _c==""then ac={""}else for bc in(_c.."\n"):gmatch("([^\n]*)\n")do -table.insert(ac,bc)end end;self.set("lines",ac)return self end -function _b:getText()return table.concat(self.get("lines"),"\n")end -local function db(_c,ac)local bc=ac -local cc=string.rep(da[_c.get("foreground")],#bc)local dc=_c.get("syntaxPatterns") -for _d,ad in ipairs(dc)do local bd=1 -while true do -local cd,dd=bc:find(ad.pattern,bd)if not cd then break end -cc=cc:sub(1,cd-1).. -string.rep(da[ad.color],dd-cd+1)..cc:sub(dd+1)bd=dd+1 end end;return bc,cc end -function _b:render()ca.render(self)local _c=self.get("lines") -local ac=self.get("scrollX")local bc=self.get("scrollY")local cc=self.get("width") -local dc=self.get("height")local _d=da[self.get("foreground")] -local ad=da[self.get("background")] -for y=1,dc do local bd=y+bc;local cd=_c[bd]or""local dd=cd:sub(ac+1,ac+cc)if#dd=1 and bd<=cc and cd>=1 and cd<=dc then -self:setCursor(bd,cd,true,self.get("cursorColor")or self.get("foreground"))end end end;return _b end +project["elements/Label.lua"] = function(...) local _a=require("elementManager") +local aa=_a.getElement("VisualElement")local ba=require("libraries/utils").wrapText +local ca=setmetatable({},aa)ca.__index=ca +ca.defineProperty(ca,"text",{default="Label",type="string",canTriggerRender=true,setter=function(da,_b) +if(type(_b)=="function")then _b=_b()end +if(da.get("autoSize"))then da.set("width",#_b)else da.set("height",# +ba(_b,da.get("width")))end;return _b end}) +ca.defineProperty(ca,"autoSize",{default=true,type="boolean",canTriggerRender=true,setter=function(da,_b)if(_b)then +da.set("width",#da.get("text"))else +da.set("height",#ba(da.get("text"),da.get("width")))end;return _b end}) +function ca.new()local da=setmetatable({},ca):__init() +da.set("z",3)da.set("foreground",colors.black) +da.set("backgroundEnabled",false)return da end;function ca:init(da,_b)aa.init(self,da,_b)self.set("type","Label") +return self end +function ca:getWrappedText() +local da=self.get("text")local _b=ba(da,self.get("width"))return _b end +function ca:render()aa.render(self)local da=self.get("text") +if +(self.get("autoSize"))then self:textFg(1,1,da,self.get("foreground"))else +local _b=ba(da,self.get("width"))for ab,bb in ipairs(_b)do +self:textFg(1,ab,bb,self.get("foreground"))end end end;return ca end +project["elements/Button.lua"] = function(...) local _a=require("elementManager") +local aa=_a.getElement("VisualElement") +local ba=require("libraries/utils").getCenteredPosition;local ca=setmetatable({},aa)ca.__index=ca +ca.defineProperty(ca,"text",{default="Button",type="string",canTriggerRender=true})ca.defineEvent(ca,"mouse_click") +ca.defineEvent(ca,"mouse_up") +function ca.new()local da=setmetatable({},ca):__init() +da.set("width",10)da.set("height",3)da.set("z",5)return da end +function ca:init(da,_b)aa.init(self,da,_b)self.set("type","Button")end +function ca:render()aa.render(self)local da=self.get("text") +da=da:sub(1,self.get("width")) +local _b,ab=ba(da,self.get("width"),self.get("height")) +self:textFg(_b,ab,da,self.get("foreground"))end;return ca end +project["elements/Input.lua"] = function(...) local d=require("elements/VisualElement") +local _a=require("libraries/colorHex")local aa=setmetatable({},d)aa.__index=aa +aa.defineProperty(aa,"text",{default="",type="string",canTriggerRender=true}) +aa.defineProperty(aa,"cursorPos",{default=1,type="number"}) +aa.defineProperty(aa,"viewOffset",{default=0,type="number",canTriggerRender=true}) +aa.defineProperty(aa,"maxLength",{default=nil,type="number"}) +aa.defineProperty(aa,"placeholder",{default="...",type="string"}) +aa.defineProperty(aa,"placeholderColor",{default=colors.gray,type="number"}) +aa.defineProperty(aa,"focusedColor",{default=colors.blue,type="number"}) +aa.defineProperty(aa,"pattern",{default=nil,type="string"}) +aa.defineProperty(aa,"cursorColor",{default=nil,type="number"})aa.defineEvent(aa,"mouse_click") +aa.defineEvent(aa,"key")aa.defineEvent(aa,"char") +function aa.new() +local ba=setmetatable({},aa):__init()ba.set("width",8)ba.set("z",3)return ba end +function aa:init(ba,ca)d.init(self,ba,ca)self.set("type","Input")return self end +function aa:setCursor(ba,ca,da,_b) +ba=math.min(self.get("width"),math.max(1,ba))return d.setCursor(self,ba,ca,da,_b)end +function aa:char(ba)if not self.get("focused")then return false end +local ca=self.get("text")local da=self.get("cursorPos")local _b=self.get("maxLength") +local ab=self.get("pattern")if _b and#ca>=_b then return end +if ab and not ba:match(ab)then return end +self.set("text",ca:sub(1,da-1)..ba..ca:sub(da))self.set("cursorPos",da+1)self:updateViewport()local bb= +self.get("cursorPos")-self.get("viewOffset") +self:setCursor(bb,1,true, +self.get("cursorColor")or self.get("foreground"))return true end +function aa:key(ba)if not self.get("focused")then return false end +local ca=self.get("cursorPos")local da=self.get("text")local _b=self.get("viewOffset") +local ab=self.get("width") +if ba==keys.left then if ca>1 then self.set("cursorPos",ca-1) +if ca-1 <=_b then self.set("viewOffset",math.max(0, +ca-2))end end elseif ba==keys.right then if ca<=#da then self.set("cursorPos", +ca+1)if ca-_b>=ab then +self.set("viewOffset",ca-ab+1)end end elseif +ba==keys.backspace then if ca>1 then +self.set("text",da:sub(1,ca-2)..da:sub(ca))self.set("cursorPos",ca-1)self:updateRender() +self:updateViewport()end end +local bb=self.get("cursorPos")-self.get("viewOffset") +self:setCursor(bb,1,true,self.get("cursorColor")or self.get("foreground"))return true end +function aa:mouse_click(ba,ca,da) +if d.mouse_click(self,ba,ca,da)then +local _b,ab=self:getRelativePosition(ca,da)local bb=self.get("text")local cb=self.get("viewOffset") +local db=#bb+1;local _c=math.min(db,cb+_b)self.set("cursorPos",_c) +local ac=_c-cb +self:setCursor(ac,1,true,self.get("cursorColor")or self.get("foreground"))return true end;return false end +function aa:updateViewport()local ba=self.get("width") +local ca=self.get("cursorPos")local da=self.get("viewOffset") +local _b=#self.get("text") +if ca-da>=ba then self.set("viewOffset",ca-ba+1)elseif ca<=da then self.set("viewOffset", +ca-1)end +self.set("viewOffset",math.max(0,math.min(self.get("viewOffset"),_b-ba+1)))return self end +function aa:render()local ba=self.get("text")local ca=self.get("viewOffset") +local da=self.get("width")local _b=self.get("placeholder") +local ab=self.get("focusedColor")local bb=self.get("focused") +local cb,db=self.get("width"),self.get("height") +self:multiBlit(1,1,cb,db," ",_a[self.get("foreground")],_a[bb and ab or +self.get("background")])if +#ba==0 and#_b~=0 and self.get("focused")==false then +self:textFg(1,1,_b:sub(1,cb),self.get("placeholderColor"))return end +local _c=ba:sub(ca+1,ca+cb)self:textFg(1,1,_c,self.get("foreground"))end;return aa end +project["elements/BaseFrame.lua"] = function(...) local _a=require("elementManager") +local aa=_a.getElement("Container")local ba=require("render")local ca=setmetatable({},aa)ca.__index=ca +ca.defineProperty(ca,"term",{default= +nil,type="table",setter=function(da,_b) +if _b==nil or _b.setCursorPos==nil then return _b end;da._render=ba.new(_b)da._renderUpdate=true;local ab,bb=_b.getSize() +da.set("width",ab)da.set("height",bb)return _b end}) +function ca.new()local da=setmetatable({},ca):__init() +da.set("term",term.current())da.set("background",colors.lightGray)return da end;function ca:init(da,_b)aa.init(self,da,_b)self.set("type","BaseFrame")return +self end +function ca:multiBlit(da,_b,ab,bb,cb,db,_c)if(da<1)then ab=ab+da-1 +da=1 end;if(_b<1)then bb=bb+_b-1;_b=1 end +self._render:multiBlit(da,_b,ab,bb,cb,db,_c)end;function ca:textFg(da,_b,ab,bb)if da<1 then ab=string.sub(ab,1 -da)da=1 end +self._render:textFg(da,_b,ab,bb)end;function ca:textBg(da,_b,ab,bb)if da<1 then ab=string.sub(ab,1 - +da)da=1 end +self._render:textBg(da,_b,ab,bb)end +function ca:blit(da,_b,ab,bb,cb)if da<1 then ab=string.sub(ab,1 - +da)bb=string.sub(bb,1 -da) +cb=string.sub(cb,1 -da)da=1 end +self._render:blit(da,_b,ab,bb,cb)end;function ca:setCursor(da,_b,ab,bb)local cb=self.get("term") +self._render:setCursor(da,_b,ab,bb)end +function ca:mouse_up(da,_b,ab) +aa.mouse_up(self,da,_b,ab)aa.mouse_release(self,da,_b,ab)end +function ca:term_resize()local da,_b=self.get("term").getSize() +if(da== +self.get("width")and _b==self.get("height"))then return end;self.set("width",da)self.set("height",_b) +self._render:setSize(da,_b)self._renderUpdate=true end +function ca:key(da)self:fireEvent("key",da)aa.key(self,da)end +function ca:key_up(da)self:fireEvent("key_up",da)aa.key_up(self,da)end +function ca:char(da)self:fireEvent("char",da)aa.char(self,da)end;function ca:render() +if(self._renderUpdate)then if self._render~=nil then aa.render(self) +self._render:render()self._renderUpdate=false end end end +return ca end +project["elements/BaseElement.lua"] = function(...) local d=require("propertySystem") +local _a=require("libraries/utils").uuid;local aa=setmetatable({},d)aa.__index=aa;aa._events={} +aa.defineProperty(aa,"type",{default={"BaseElement"},type="string",setter=function(ba,ca)if +type(ca)=="string"then table.insert(ba._values.type,1,ca)return +ba._values.type end;return ca end,getter=function(ba,ca,da)if +da~=nil and da<1 then return ba._values.type end;return ba._values.type[ +da or 1]end}) +aa.defineProperty(aa,"id",{default="",type="string",readonly=true}) +aa.defineProperty(aa,"name",{default="",type="string"}) +aa.defineProperty(aa,"eventCallbacks",{default={},type="table"}) +function aa.defineEvent(ba,ca,da) +if not rawget(ba,'_eventConfigs')then ba._eventConfigs={}end;ba._eventConfigs[ca]={requires=da and da or ca}end +function aa.registerEventCallback(ba,ca,...) +local da=ca:match("^on")and ca or"on"..ca;local _b={...}local ab=_b[1] +ba[da]=function(bb,...) +for cb,db in ipairs(_b)do if not bb._registeredEvents[db]then +bb:listenEvent(db,true)end end;bb:registerCallback(ab,...)return bb end end +function aa.new()local ba=setmetatable({},aa):__init()return ba end +function aa:init(ba,ca)self._props=ba;self._values.id=_a()self.basalt=ca +self._registeredEvents={}local da=getmetatable(self).__index;local _b={}da=self +while da do +if +type(da)=="table"and da._eventConfigs then for ab,bb in pairs(da._eventConfigs)do +if not _b[ab]then _b[ab]=bb end end end +da=getmetatable(da)and getmetatable(da).__index end +for ab,bb in pairs(_b)do self._registeredEvents[bb.requires]=true end;if self._callbacks then +for ab,bb in pairs(self._callbacks)do self[bb]=function(cb,...) +cb:registerCallback(ab,...)return cb end end end +return self end +function aa:postInit()if(self._props)then +for ba,ca in pairs(self._props)do self.set(ba,ca)end end;self._props=nil;return self end;function aa:isType(ba) +for ca,da in ipairs(self._values.type)do if da==ba then return true end end;return false end +function aa:listenEvent(ba,ca)ca= +ca~=false +if +ca~= (self._registeredEvents[ba]or false)then +if ca then self._registeredEvents[ba]=true;if self.parent then +self.parent:registerChildEvent(self,ba)end else self._registeredEvents[ba]=nil +if +self.parent then self.parent:unregisterChildEvent(self,ba)end end end;return self end +function aa:registerCallback(ba,ca)if not self._registeredEvents[ba]then +self:listenEvent(ba,true)end +if +not self._values.eventCallbacks[ba]then self._values.eventCallbacks[ba]={}end +table.insert(self._values.eventCallbacks[ba],ca)return self end +function aa:fireEvent(ba,...) +if self.get("eventCallbacks")[ba]then for ca,da in +ipairs(self.get("eventCallbacks")[ba])do local _b=da(self,...)return _b end end;return self end;function aa:dispatchEvent(ba,...)if self[ba]then return self[ba](self,...)end;return +self:handleEvent(ba,...)end;function aa:handleEvent(ba,...)return +false end +function aa:onChange(ba,ca)self:observe(ba,ca)return self end;function aa:getBaseFrame() +if self.parent then return self.parent:getBaseFrame()end;return self end +function aa:destroy()if self.parent then +self.parent:removeChild(self)end;for ba in pairs(self._registeredEvents)do +self:listenEvent(ba,false)end;self._values.eventCallbacks={}self._props= +nil;self._values=nil;self.basalt=nil;self.parent=nil +self.__index=nil;setmetatable(self,nil)end +function aa:updateRender()if(self.parent)then self.parent:updateRender()else +self._renderUpdate=true end end;return aa end +project["elements/Frame.lua"] = function(...) local _a=require("elementManager") +local aa=_a.getElement("VisualElement")local ba=_a.getElement("Container")local ca=setmetatable({},ba) +ca.__index=ca +ca.defineProperty(ca,"draggable",{default=false,type="boolean",setter=function(da,_b) +if _b then da:listenEvent("mouse_click",true) +da:listenEvent("mouse_up",true)da:listenEvent("mouse_drag",true)end end}) +ca.defineProperty(ca,"draggingMap",{default={{x=1,y=1,width="width",height=1}},type="table"}) +function ca.new()local da=setmetatable({},ca):__init() +da.set("width",12)da.set("height",6) +da.set("background",colors.gray)da.set("z",10)return da end;function ca:init(da,_b)ba.init(self,da,_b)self.set("type","Frame") +return self end +function ca:mouse_click(da,_b,ab) +if +(aa.mouse_click(self,da,_b,ab))then local bb,cb=self:getRelativePosition(_b,ab) +local db=self.get("draggingMap") +for _c,ac in ipairs(db)do local bc=ac.width or 1;local cc=ac.height or 1;if +type(bc)=="string"and bc=="width"then bc=self.get("width")elseif +type(bc)=="function"then bc=bc(self)end +if type(cc)== +"string"and cc=="height"then cc=self.get("height")elseif +type(cc)=="function"then cc=cc(self)end;local dc=ac.y or 1 +if +bb>=ac.x and bb<=ac.x+bc-1 and cb>=dc and cb<=dc+cc-1 then +self.dragStartX=_b-self.get("x")self.dragStartY=ab-self.get("y")self.dragging=true +return true end end;return ba.mouse_click(self,da,_b,ab)end end +function ca:mouse_drag(da,_b,ab) +if self.get("clicked")and self.dragging then +local bb=_b-self.dragStartX;local cb=ab-self.dragStartY;self.set("x",bb) +self.set("y",cb)return true end +if not self.dragging then return ba.mouse_drag(self,da,_b,ab)end;return false end +function ca:mouse_up(da,_b,ab)self.dragging=false;self.dragStartX=nil;self.dragStartY=nil;return +ba.mouse_up(self,da,_b,ab)end;return ca end +project["elements/Checkbox.lua"] = function(...) local c=require("elements/VisualElement") +local d=setmetatable({},c)d.__index=d +d.defineProperty(d,"checked",{default=false,type="boolean",canTriggerRender=true}) +d.defineProperty(d,"text",{default=" ",type="string",canTriggerRender=true,setter=function(_a,aa)local ba=_a.get("checkedText") +local ca=math.max(#aa,#ba)if(_a.get("autoSize"))then _a.set("width",ca)end;return aa end}) +d.defineProperty(d,"checkedText",{default="x",type="string",canTriggerRender=true,setter=function(_a,aa)local ba=_a.get("text") +local ca=math.max(#aa,#ba)if(_a.get("autoSize"))then _a.set("width",ca)end;return aa end}) +d.defineProperty(d,"autoSize",{default=true,type="boolean"})d.defineEvent(d,"mouse_click")function d.new() +local _a=setmetatable({},d):__init()return _a end;function d:init(_a,aa)c.init(self,_a,aa) +self.set("type","Checkbox")end +function d:mouse_click(_a,aa,ba) +if c.mouse_click(self,_a,aa,ba)then +self.set("checked", +not self.get("checked")) +self:fireEvent("change",self.get("checked"))return true end;return false end +function d:render()c.render(self)local _a=self.get("checked") +local aa=self.get("text")local ba=self.get("checkedText") +local ca=string.sub(_a and ba or aa,1,self.get("width"))self:textFg(1,1,ca,self.get("foreground"))end;return d end +project["elements/Program.lua"] = function(...) local ba=require("elementManager") +local ca=ba.getElement("VisualElement")local da=require("errorManager")local _b=setmetatable({},ca) +_b.__index=_b +_b.defineProperty(_b,"program",{default=nil,type="table"}) +_b.defineProperty(_b,"path",{default="",type="string"}) +_b.defineProperty(_b,"running",{default=false,type="boolean"})_b.defineEvent(_b,"*")local ab={}ab.__index=ab +local bb=dofile("rom/modules/main/cc/require.lua").make +function ab.new()local cb=setmetatable({},ab)cb.env={}cb.args={}return cb end +function ab:run(cb,db,_c) +self.window=window.create(term.current(),1,1,db,_c,false)local ac=shell.resolveProgram(cb) +if(ac~=nil)then +if(fs.exists(ac))then +local bc=fs.open(ac,"r")local cc=bc.readAll()bc.close() +local dc=setmetatable(self.env,{__index=_ENV})dc.shell=shell;dc.term=self.window +dc.require,dc.package=bb(dc,fs.getDir(ac))dc.term.current=term.current;dc.term.redirect=term.redirect +dc.term.native=term.native +self.coroutine=coroutine.create(function()local cd=load(cc,cb,"bt",dc) +if cd then +local dd=term.current()term.redirect(self.window) +local __a=cd(cb,table.unpack(self.args))term.redirect(dd)return __a end end)local _d=term.current()term.redirect(self.window) +local ad,bd=coroutine.resume(self.coroutine)term.redirect(_d)if not ad then +da.header="Basalt Program Error "..cb;da.error(bd)end else +da.header="Basalt Program Error "..cb;da.error("File not found")end else da.header="Basalt Program Error" +da.error("Program "..cb.." not found")end end +function ab:resize(cb,db)self.window.reposition(1,1,cb,db)end +function ab:resume(cb,...)if self.coroutine==nil or +coroutine.status(self.coroutine)=="dead"then return end +if( +self.filter~=nil)then if(cb~=self.filter)then return end;self.filter=nil end;local db=term.current()term.redirect(self.window) +local _c,ac=coroutine.resume(self.coroutine,cb,...)term.redirect(db)if _c then self.filter=ac else +da.header="Basalt Program Error"da.error(ac)end;return _c,ac end;function ab:stop()end;function _b.new() +local cb=setmetatable({},_b):__init()cb.set("z",5)cb.set("width",30)cb.set("height",12) +return cb end +function _b:init(cb,db) +ca.init(self,cb,db)self.set("type","Program")return self end +function _b:execute(cb)self.set("path",cb)self.set("running",true) +local db=ab.new()self.set("program",db) +db:run(cb,self.get("width"),self.get("height"))self:updateRender()return self end +function _b:dispatchEvent(cb,...)local db=self.get("program") +local _c=ca.dispatchEvent(self,cb,...) +if db then db:resume(cb,...) +if(self.get("focused"))then +local ac=db.window.getCursorBlink()local bc,cc=db.window.getCursorPos() +self:setCursor(bc,cc,ac,db.window.getTextColor())end;self:updateRender()end;return _c end +function _b:focus() +if(ca.focus(self))then local cb=self.get("program")if cb then +local db=cb.window.getCursorBlink()local _c,ac=cb.window.getCursorPos() +self:setCursor(_c,ac,db,cb.window.getTextColor())end end end +function _b:render()ca.render(self)local cb=self.get("program") +if cb then +local db,_c=cb.window.getSize()for y=1,_c do local ac,bc,cc=cb.window.getLine(y)if ac then +self:blit(1,y,ac,bc,cc)end end end end;return _b end +project["elements/Table.lua"] = function(...) local d=require("elements/VisualElement") +local _a=require("libraries/colorHex")local aa=setmetatable({},d)aa.__index=aa +aa.defineProperty(aa,"columns",{default={},type="table"}) +aa.defineProperty(aa,"data",{default={},type="table",canTriggerRender=true}) +aa.defineProperty(aa,"selectedRow",{default=nil,type="number",canTriggerRender=true}) +aa.defineProperty(aa,"headerColor",{default=colors.blue,type="number"}) +aa.defineProperty(aa,"selectedColor",{default=colors.lightBlue,type="number"}) +aa.defineProperty(aa,"gridColor",{default=colors.gray,type="number"}) +aa.defineProperty(aa,"sortColumn",{default=nil,type="number"}) +aa.defineProperty(aa,"sortDirection",{default="asc",type="string"}) +aa.defineProperty(aa,"scrollOffset",{default=0,type="number",canTriggerRender=true})aa.defineEvent(aa,"mouse_click") +aa.defineEvent(aa,"mouse_scroll") +function aa.new()local ba=setmetatable({},aa):__init() +ba.set("width",30)ba.set("height",10)ba.set("z",5)return ba end +function aa:init(ba,ca)d.init(self,ba,ca)self.set("type","Table")return self end +function aa:sortData(ba)local ca=self.get("data") +local da=self.get("sortDirection") +table.sort(ca,function(_b,ab) +if da=="asc"then return _b[ba]ab[ba]end end)self.set("data",ca)return self end +function aa:mouse_click(ba,ca,da) +if not d.mouse_click(self,ba,ca,da)then return false end;local _b,ab=self:getRelativePosition(ca,da) +if ab==1 then local bb=1 +for cb,db in +ipairs(self.get("columns"))do +if _b>=bb and _b1 then local bb=ab-2 +self.get("scrollOffset")if bb>=0 and bb<# +self.get("data")then +self.set("selectedRow",bb+1)end end;return true end +function aa:mouse_scroll(ba,ca,da)local _b=self.get("data")local ab=self.get("height") +local bb=ab-2;local cb=math.max(0,#_b-bb+1) +local db=math.min(cb,math.max(0, +self.get("scrollOffset")+ba))self.set("scrollOffset",db)return true end +function aa:render()d.render(self)local ba=self.get("columns") +local ca=self.get("data")local da=self.get("selectedRow") +local _b=self.get("sortColumn")local ab=self.get("scrollOffset")local bb=self.get("height") +local cb=1 +for _c,ac in ipairs(ba)do local bc=ac.name;if _c==_b then +bc=bc.. (self.get("sortDirection")=="asc"and +"\30"or"\31")end +self:textFg(cb,1,bc:sub(1,ac.width),self.get("headerColor"))cb=cb+ac.width end;local db=bb-2 +for y=2,bb do local _c=y-2 +ab;local ac=ca[_c+1] +if ac and(_c+1)<=#ca then cb=1 +local bc= +(_c+1)==da and self.get("selectedColor")or self.get("background") +for cc,dc in ipairs(ba)do local _d=ac[cc]or"" +local ad=_d..string.rep(" ",dc.width-#_d) +self:blit(cb,y,ad,string.rep(_a[self.get("foreground")],dc.width),string.rep(_a[bc],dc.width))cb=cb+dc.width end else +self:blit(1,y,string.rep(" ",self.get("width")),string.rep(_a[self.get("foreground")],self.get("width")),string.rep(_a[self.get("background")],self.get("width")))end end +if#ca>bb-2 then local _c=bb-2 +local ac=math.max(1,math.floor(_c* (bb-2)/#ca))local bc=#ca- (bb-2)+1;local cc=ab/bc +local dc=2 +math.floor(cc* (_c-ac))if ab>=bc then dc=bb-ac end;for y=2,bb do +self:blit(self.get("width"),y,"\127",_a[colors.gray],_a[colors.gray])end;for y=dc,math.min(bb,dc+ac-1)do +self:blit(self.get("width"),y,"\127",_a[colors.white],_a[colors.white])end end end;return aa end +project["elements/Slider.lua"] = function(...) local c=require("elements/VisualElement") +local d=setmetatable({},c)d.__index=d +d.defineProperty(d,"step",{default=1,type="number",canTriggerRender=true}) +d.defineProperty(d,"max",{default=100,type="number"}) +d.defineProperty(d,"horizontal",{default=true,type="boolean",canTriggerRender=true}) +d.defineProperty(d,"barColor",{default=colors.gray,type="number",canTriggerRender=true}) +d.defineProperty(d,"sliderColor",{default=colors.blue,type="number",canTriggerRender=true})d.defineEvent(d,"mouse_click") +d.defineEvent(d,"mouse_drag")d.defineEvent(d,"mouse_up")function d.new() +local _a=setmetatable({},d):__init()_a.set("width",8)_a.set("height",1) +_a.set("backgroundEnabled",false)return _a end;function d:init(_a,aa) +c.init(self,_a,aa)self.set("type","Slider")end +function d:getValue() +local _a=self.get("step")local aa=self.get("max") +local ba= +self.get("horizontal")and self.get("width")or self.get("height")return math.floor((_a-1)* (aa/ (ba-1)))end +function d:mouse_click(_a,aa,ba) +if _a==1 and self:isInBounds(aa,ba)then +local ca,da=self:getRelativePosition(aa,ba) +local _b=self.get("horizontal")and ca or da;local ab=self.get("horizontal")and self.get("width")or +self.get("height") +self.set("step",math.min(ab,math.max(1,_b)))self:updateRender()return true end end;d.mouse_drag=d.mouse_click +function d:mouse_scroll(_a,aa,ba) +if self:isInBounds(aa,ba)then +local ca=self.get("step")local da=self.get("horizontal")and self.get("width")or +self.get("height") +self.set("step",math.min(da,math.max(1, +ca+_a)))self:updateRender()return true end end +function d:render()c.render(self)local _a=self.get("width") +local aa=self.get("height")local ba=self.get("horizontal")local ca=self.get("step")local da= +ba and"\140"or"│" +local _b=string.rep(da,ba and _a or aa) +if ba then self:textFg(1,1,_b,self.get("barColor")) +self:textBg(ca,1," ",self.get("sliderColor"))else +for y=1,aa do self:textFg(1,y,da,self.get("barColor"))end +self:textFg(1,ca,"\140",self.get("sliderColor"))end end;return d end +project["elements/ProgressBar.lua"] = function(...) local c=require("elements/VisualElement") +local d=setmetatable({},c)d.__index=d +d.defineProperty(d,"progress",{default=0,type="number",canTriggerRender=true}) +d.defineProperty(d,"showPercentage",{default=false,type="boolean"}) +d.defineProperty(d,"progressColor",{default=colors.black,type="number"}) +function d.new()local _a=setmetatable({},d):__init() +_a.set("width",10)_a.set("height",1)return _a end +function d:init(_a,aa)c.init(self,_a,aa)self.set("type","ProgressBar")end +function d:render()c.render(self)local _a=self.get("width") +local aa=math.min(100,math.max(0,self.get("progress")))local ba=math.floor((_a*aa)/100)for i=1,self.get("height")do +self:textBg(1,i,string.rep(" ",ba),self.get("progressColor"))end;if self.get("showPercentage")then local ca= +tostring(aa).."%" +local da=math.floor((_a-#ca)/2)+1 +self:textFg(da,1,ca,self.get("foreground"))end end;return d end +project["elements/List.lua"] = function(...) local c=require("elements/VisualElement") +local d=setmetatable({},c)d.__index=d +d.defineProperty(d,"items",{default={},type="table",canTriggerRender=true}) +d.defineProperty(d,"selectable",{default=true,type="boolean"}) +d.defineProperty(d,"multiSelection",{default=false,type="boolean"}) +d.defineProperty(d,"offset",{default=0,type="number",canTriggerRender=true}) +d.defineProperty(d,"selectedBackground",{default=colors.blue,type="number"}) +d.defineProperty(d,"selectedForeground",{default=colors.white,type="number"})d.defineEvent(d,"mouse_click") +d.defineEvent(d,"mouse_scroll") +function d.new()local _a=setmetatable({},d):__init() +_a.set("width",16)_a.set("height",8)_a.set("z",5) +_a.set("background",colors.gray)return _a end +function d:init(_a,aa)c.init(self,_a,aa)self.set("type","List")return self end;function d:addItem(_a)local aa=self.get("items")table.insert(aa,_a) +self:updateRender()return self end +function d:removeItem(_a) +local aa=self.get("items")table.remove(aa,_a)self:updateRender()return self end +function d:clear()self.set("items",{})self:updateRender()return self end +function d:getSelectedItems()local _a={}for aa,ba in ipairs(self.get("items"))do +if +type(ba)=="table"and ba.selected then local ca=ba;ca.index=aa;table.insert(_a,ca)end end;return _a end +function d:mouse_click(_a,aa,ba) +if +_a==1 and self:isInBounds(aa,ba)and self.get("selectable")then local ca,da=self:getRelativePosition(aa,ba) +local _b=da+self.get("offset")local ab=self.get("items") +if _b<=#ab then local bb=ab[_b]if type(bb)=="string"then +bb={text=bb}ab[_b]=bb end;if +not self.get("multiSelection")then +for cb,db in ipairs(ab)do if type(db)=="table"then db.selected=false end end end +bb.selected=not bb.selected;if bb.callback then bb.callback(self)end +self:fireEvent("select",_b,bb)self:updateRender()return true end end;return false end +function d:mouse_scroll(_a,aa,ba) +if self:isInBounds(aa,ba)then local ca=self.get("offset") +local da=math.max(0,# +self.get("items")-self.get("height"))ca=math.min(da,math.max(0,ca+_a)) +self.set("offset",ca)return true end;return false end +function d:onSelect(_a)self:registerCallback("select",_a)return self end +function d:scrollToBottom() +local _a=math.max(0,#self.get("items")-self.get("height"))self.set("offset",_a)return self end;function d:scrollToTop()self.set("offset",0)return self end +function d:render() +c.render(self)local _a=self.get("items")local aa=self.get("height") +local ba=self.get("offset")local ca=self.get("width") +for i=1,aa do local da=i+ba;local _b=_a[da] +if _b then if +type(_b)=="string"then _b={text=_b}_a[da]=_b end +if _b.separator then +local ab=(_b.text or"-"):sub(1,1)local bb=string.rep(ab,ca) +local cb=_b.foreground or self.get("foreground")local db=_b.background or self.get("background") +self:textBg(1,i,string.rep(" ",ca),db)self:textFg(1,i,bb:sub(1,ca),cb)else local ab=_b.text +local bb=_b.selected +local cb= +bb and(_b.selectedBackground or self.get("selectedBackground"))or(_b.background or self.get("background")) +local db= +bb and(_b.selectedForeground or self.get("selectedForeground"))or(_b.foreground or self.get("foreground"))self:textBg(1,i,string.rep(" ",ca),cb) +self:textFg(1,i,ab:sub(1,ca),db)end end end end;return d end project["elements/Dropdown.lua"] = function(...) local _a=require("elements/VisualElement") local aa=require("elements/List")local ba=require("libraries/colorHex") local ca=setmetatable({},aa)ca.__index=ca @@ -1958,122 +1464,616 @@ local cc=bc and local dc= bc and(_c.selectedForeground or self.get("selectedForeground"))or(_c.foreground or self.get("foreground"))self:textBg(1,i+1,string.rep(" ",cb),cc)self:textFg(1, i+1,ac,dc)end end end end end;return ca end -project["render.lua"] = function(...) local _a=require("libraries/colorHex")local aa=require("log") -local ba={}ba.__index=ba;local ca=string.sub -function ba.new(da)local _b=setmetatable({},ba) -_b.terminal=da;_b.width,_b.height=da.getSize() -_b.buffer={text={},fg={},bg={},dirtyRects={}} -for y=1,_b.height do _b.buffer.text[y]=string.rep(" ",_b.width) -_b.buffer.fg[y]=string.rep("0",_b.width)_b.buffer.bg[y]=string.rep("f",_b.width)end;return _b end;function ba:addDirtyRect(da,_b,ab,bb) -table.insert(self.buffer.dirtyRects,{x=da,y=_b,width=ab,height=bb})return self end -function ba:blit(da,_b,ab,bb,cb)if -_b<1 or _b>self.height then return self end;if(#ab~=#bb or -#ab~=#cb)then -error("Text, fg, and bg must be the same length")end -self.buffer.text[_b]=ca(self.buffer.text[_b]:sub(1, -da-1)..ab.. -self.buffer.text[_b]:sub(da+#ab),1,self.width) -self.buffer.fg[_b]=ca( -self.buffer.fg[_b]:sub(1,da-1)..bb..self.buffer.fg[_b]:sub(da+#bb),1,self.width) -self.buffer.bg[_b]=ca( -self.buffer.bg[_b]:sub(1,da-1)..cb..self.buffer.bg[_b]:sub(da+#cb),1,self.width)self:addDirtyRect(da,_b,#ab,1)return self end -function ba:multiBlit(da,_b,ab,bb,cb,db,_c)if _b<1 or _b>self.height then return self end;if( -#cb~=#db or#cb~=#_c)then -error("Text, fg, and bg must be the same length")end;cb=cb:rep(ab) -db=db:rep(ab)_c=_c:rep(ab) -for dy=0,bb-1 do local ac=_b+dy -if ac>=1 and ac<=self.height then -self.buffer.text[ac]=ca(self.buffer.text[ac]:sub(1, -da-1)..cb.. -self.buffer.text[ac]:sub(da+#cb),1,self.width) -self.buffer.fg[ac]=ca( -self.buffer.fg[ac]:sub(1,da-1)..db..self.buffer.fg[ac]:sub(da+#db),1,self.width) -self.buffer.bg[ac]=ca( -self.buffer.bg[ac]:sub(1,da-1).._c..self.buffer.bg[ac]:sub(da+#_c),1,self.width)end end;self:addDirtyRect(da,_b,ab,bb)return self end -function ba:textFg(da,_b,ab,bb)if _b<1 or _b>self.height then return self end -bb=_a[bb]or"0"bb=bb:rep(#ab) -self.buffer.text[_b]=ca(self.buffer.text[_b]:sub(1, -da-1)..ab.. -self.buffer.text[_b]:sub(da+#ab),1,self.width) -self.buffer.fg[_b]=ca( -self.buffer.fg[_b]:sub(1,da-1)..bb..self.buffer.fg[_b]:sub(da+#bb),1,self.width)self:addDirtyRect(da,_b,#ab,1)return self end -function ba:textBg(da,_b,ab,bb)if _b<1 or _b>self.height then return self end -bb=_a[bb]or"f" -self.buffer.text[_b]=ca( -self.buffer.text[_b]:sub(1,da-1).. -ab..self.buffer.text[_b]:sub(da+#ab),1,self.width) -self.buffer.bg[_b]=ca( -self.buffer.bg[_b]:sub(1,da-1).. -bb:rep(#ab)..self.buffer.bg[_b]:sub(da+#ab),1,self.width)self:addDirtyRect(da,_b,#ab,1)return self end -function ba:text(da,_b,ab)if _b<1 or _b>self.height then return self end -self.buffer.text[_b]=ca(self.buffer.text[_b]:sub(1, -da-1)..ab.. -self.buffer.text[_b]:sub(da+#ab),1,self.width)self:addDirtyRect(da,_b,#ab,1)return self end -function ba:fg(da,_b,ab)if _b<1 or _b>self.height then return self end -self.buffer.fg[_b]=ca(self.buffer.fg[_b]:sub(1, -da-1)..ab.. -self.buffer.fg[_b]:sub(da+#ab),1,self.width)self:addDirtyRect(da,_b,#ab,1)return self end -function ba:bg(da,_b,ab)if _b<1 or _b>self.height then return self end -self.buffer.bg[_b]=ca(self.buffer.bg[_b]:sub(1, -da-1)..ab.. -self.buffer.bg[_b]:sub(da+#ab),1,self.width)self:addDirtyRect(da,_b,#ab,1)return self end -function ba:clear(da)local _b=_a[da]or"f" -for y=1,self.height do -self.buffer.text[y]=string.rep(" ",self.width)self.buffer.fg[y]=string.rep("0",self.width) -self.buffer.bg[y]=string.rep(_b,self.width)self:addDirtyRect(1,y,self.width,1)end;return self end -function ba:render()local da={} -for _b,ab in ipairs(self.buffer.dirtyRects)do local bb=false;for cb,db in ipairs(da)do +project["elements/Menu.lua"] = function(...) local _a=require("elements/VisualElement") +local aa=require("elements/List")local ba=require("libraries/colorHex") +local ca=setmetatable({},aa)ca.__index=ca +ca.defineProperty(ca,"separatorColor",{default=colors.gray,type="number"})function ca.new()local da=setmetatable({},ca):__init() +da.set("width",30)da.set("height",1) +da.set("background",colors.gray)return da end +function ca:init(da,_b) +aa.init(self,da,_b)self.set("type","Menu")return self end +function ca:setItems(da)local _b={}local ab=0 +for bb,cb in ipairs(da)do +if cb.separator then +table.insert(_b,{text=cb.text or"|",selectable=false})ab=ab+1 else local db=" "..cb.text.." "cb.text=db +table.insert(_b,cb)ab=ab+#db end end;self.set("width",ab)return aa.setItems(self,_b)end +function ca:render()_a.render(self)local da=1 +for _b,ab in ipairs(self.get("items"))do if type(ab)== +"string"then ab={text=" "..ab.." "} +self.get("items")[i]=ab end;local bb=ab.selected +local cb=ab.selectable==false and +self.get("separatorColor")or(bb and +(ab.selectedForeground or self.get("selectedForeground"))or +(ab.foreground or self.get("foreground"))) +local db= +bb and(ab.selectedBackground or self.get("selectedBackground"))or(ab.background or self.get("background")) +self:blit(da,1,ab.text,string.rep(ba[cb],#ab.text),string.rep(ba[db],#ab.text))da=da+#ab.text end end +function ca:mouse_click(da,_b,ab) +if not _a.mouse_click(self,da,_b,ab)then return false end +if(self.get("selectable")==false)then return false end +local bb=select(1,self:getRelativePosition(_b,ab))local cb=1 +for db,_c in ipairs(self.get("items"))do if -self:rectOverlaps(ab,db)then self:mergeRects(db,ab)bb=true;break end end;if not bb then -table.insert(da,ab)end end -for _b,ab in ipairs(da)do -for y=ab.y,ab.y+ab.height-1 do -if y>=1 and y<=self.height then -self.terminal.setCursorPos(ab.x,y) -self.terminal.blit(self.buffer.text[y]:sub(ab.x,ab.x+ab.width-1),self.buffer.fg[y]:sub(ab.x, -ab.x+ab.width-1),self.buffer.bg[y]:sub(ab.x, -ab.x+ab.width-1))end end end;self.buffer.dirtyRects={} -if self.blink then -self.terminal.setTextColor(self.cursorColor or -colors.white) -self.terminal.setCursorPos(self.xCursor,self.yCursor)self.terminal.setCursorBlink(true)else -self.terminal.setCursorBlink(false)end;return self end -function ba:rectOverlaps(da,_b)return -not( -da.x+da.width<=_b.x or _b.x+_b.width<=da.x or da.y+da.height<=_b.y or -_b.y+_b.height<=da.y)end -function ba:mergeRects(da,_b)local ab=math.min(da.x,_b.x) -local bb=math.min(da.y,_b.y) -local cb=math.max(da.x+da.width,_b.x+_b.width) -local db=math.max(da.y+da.height,_b.y+_b.height)da.x=ab;da.y=bb;da.width=cb-ab;da.height=db-bb end -function ba:setCursor(da,_b,ab,bb) -if bb~=nil then self.terminal.setTextColor(bb)end;self.terminal.setCursorPos(da,_b) -self.terminal.setCursorBlink(ab)self.xCursor=da;self.yCursor=_b;self.blink=ab;self.cursorColor=bb +bb>=cb and bb0)then _aa()end;return true end end end +function bd.create(_ba,aba,bba,cba)if(__a(aba)=="string")then aba={name=aba}end;if(aba==nil)then +aba={name=_ba}end;local dba=cc.getElement(_ba) +if(bba)then +local _ca=_d.blueprint(dba,aba,bd,cba)table.insert(a_a,_ca)_aa()return _ca else local _ca=dba.new() +_ca:init(aba,bd)return _ca end end +function bd.createFrame()local _ba=bd.create("BaseFrame")_ba:postInit()if(cd==nil)then +cd=_ba end;return _ba end;function bd.getElementManager()return cc end;function bd.getMainFrame()if(cd==nil)then +cd=bd.createFrame()end;return cd end;function bd.setActiveFrame(_ba) +cd=_ba;cd:updateRender()end +function bd.schedule(_ba) +ad(1,_ba,"function")local aba=coroutine.create(_ba) +local bba,cba=coroutine.resume(aba) +if(bba)then +table.insert(bd._schedule,{coroutine=aba,filter=cba})else dc.header="Basalt Schedule Error"dc.error(cba)end;return aba end +function bd.removeSchedule(_ba) +for aba,bba in ipairs(bd._schedule)do if(bba.coroutine==_ba)then +table.remove(bd._schedule,aba)return true end end;return false end +local function caa(_ba,...)if(_ba=="terminate")then bd.stop()end +if baa(_ba,...)then return end;if(cd)then cd:dispatchEvent(_ba,...)end +for aba,bba in +ipairs(bd._schedule)do +if(_ba==bba.filter)or(bba.filter==nil)then +local cba,dba=coroutine.resume(bba.coroutine,_ba,...) +if(not cba)then dc.header="Basalt Schedule Error"dc.error(dba)end;bba.filter=dba end;if(coroutine.status(bba.coroutine)=="dead")then +bd.removeSchedule(bba.coroutine)end end;if bd._events[_ba]then +for aba,bba in ipairs(bd._events[_ba])do bba(...)end end end;local function daa()if(cd)then cd:render()end end;function bd.update(...)caa(...) +daa()end;function bd.stop()dd=false;term.clear() +term.setCursorPos(1,1)end +function bd.run(_ba)dd=_ba;if(_ba==nil)then dd=true end;local function aba() +daa() +while dd do caa(os.pullEventRaw())if(dd)then daa()end end end +while dd do local bba,cba=pcall(aba)if not(bba)then +dc.header="Basalt Runtime Error"dc.error(cba)end end end;function bd.getAPI(_ba)return cc.getAPI(_ba)end;return bd end +project["libraries/colorHex.lua"] = function(...) local b={}for i=0,15 do b[2 ^i]=("%x"):format(i) +b[("%x"):format(i)]=2 ^i end;return b end +project["libraries/utils.lua"] = function(...) local d,_a=math.floor,string.len;local aa={} +function aa.getCenteredPosition(ba,ca,da)local _b=_a(ba)local ab=d( +(ca-_b+1)/2 +0.5)local bb=d(da/2 +0.5)return ab,bb end +function aa.deepCopy(ba)if type(ba)~="table"then return ba end;local ca={}for da,_b in pairs(ba)do +ca[aa.deepCopy(da)]=aa.deepCopy(_b)end;return ca end +function aa.copy(ba)local ca={}for da,_b in pairs(ba)do ca[da]=_b end;return ca end;function aa.reverse(ba)local ca={}for i=#ba,1,-1 do table.insert(ca,ba[i])end +return ca end +function aa.uuid() +return +string.format('%04x%04x-%04x-%04x-%04x-%04x%04x%04x',math.random(0,0xffff),math.random(0,0xffff),math.random(0,0xffff), +math.random(0,0x0fff)+0x4000,math.random(0,0x3fff)+0x8000,math.random(0,0xffff),math.random(0,0xffff),math.random(0,0xffff))end +function aa.split(ba,ca)local da={}for _b in(ba..ca):gmatch("(.-)"..ca)do +table.insert(da,_b)end;return da end;function aa.removeTags(ba)return ba:gsub("{[^}]+}","")end +function aa.wrapText(ba,ca)if +ba==nil then return{}end;ba=aa.removeTags(ba)local da={} +local _b=aa.split(ba,"\n\n") +for ab,bb in ipairs(_b)do +if#bb==0 then table.insert(da,"")if ab<#_b then +table.insert(da,"")end else local cb=aa.split(bb,"\n") +for db,_c in ipairs(cb)do +local ac=aa.split(_c," ")local bc="" +for cc,dc in ipairs(ac)do if#bc==0 then bc=dc elseif#bc+#dc+1 <=ca then bc=bc.." "..dc else +table.insert(da,bc)bc=dc end end;if#bc>0 then table.insert(da,bc)end end;if ab<#_b then table.insert(da,"")end end end;return da end;return aa end +project["libraries/expect.lua"] = function(...) local c=require("errorManager") +local function d(_a,aa,ba)local ca=type(aa) +if ba=="element"then if ca=="table"and +aa.get("type")~=nil then return true end end +if ba=="color"then +if ca=="number"and aa>=1 and aa<=32768 then return true end;if ca=="string"and colors[aa]then return true end end;if ca~=ba then c.header="Basalt Type Error" +c.error(string.format("Bad argument #%d: expected %s, got %s",_a,ba,ca))end;return true end;return d end +project["plugins/xml.lua"] = function(...) local da=require("errorManager") +local function _b(bc)local cc={attributes={}} +cc.name=bc:match("<(%w+)") +for dc,_d in bc:gmatch('%s(%w+)="([^"]-)"')do cc.attributes[dc]=_d end;return cc end +local function ab(bc,cc)local dc={}local _d={children={}}local ad=_d;local bd=false;local cd="" +for dd in cc:gmatch("[^\r\n]+")do +dd=dd:match("^%s*(.-)%s*$") +if dd:match("^$")and bd then bd=false +ad.content=cd elseif bd then cd=cd..dd.."\n"elseif dd:match("^<[^/]")then local __a=_b(dd)__a.children={} +__a.content=""table.insert(ad.children,__a)if not dd:match("/>$")then +table.insert(dc,ad)ad=__a end elseif dd:match("^0 then _d(__a,b_a,cd)end end end end;_d(dc,self,cc)return self end;return{BaseElement=_c,Container=ac} end +project["plugins/state.lua"] = function(...) local d=require("propertySystem") +local _a=require("errorManager")local aa={} +function aa.setup(ba) +ba.defineProperty(ba,"states",{default={},type="table"}) +ba.defineProperty(ba,"computedStates",{default={},type="table"}) +ba.defineProperty(ba,"stateUpdate",{default={key="",value=nil,oldValue=nil},type="table"})end +function aa:initializeState(ba,ca,da,_b,ab)local bb=self.get("states") +if bb[ba]then _a.error("State '".. +ba.."' already exists")return self end +if _b then local cb=ab or +("states/"..self.get("name").."_"..ba..".state") +if fs.exists(cb)then +local db=fs.open(cb,"r") +bb[ba]={value=textutils.unserialize(db.readAll()),persist=true,file=cb}db.close()else +bb[ba]={value=ca,persist=true,file=cb,canTriggerRender=da}end else bb[ba]={value=ca,canTriggerRender=da}end;return self end +function aa:setState(ba,ca)local da=self.get("states") +if not da[ba]then error("State '".. +ba.."' not initialized")end;local _b=da[ba].value;da[ba].value=ca +if da[ba].persist then +local ab=fs.getDir(da[ba].file)if not fs.exists(ab)then fs.makeDir(ab)end +local bb=fs.open(da[ba].file,"w")bb.write(textutils.serialize(ca)) +bb.close()end;if da[ba].canTriggerRender then self:updateRender()end +self.set("stateUpdate",{key=ba,value=ca,oldValue=_b})return self end +function aa:getState(ba)local ca=self.get("states") +if not ca[ba]then _a.error("State '".. +ba.."' not initialized")end;return ca[ba].value end +function aa:computed(ba,ca)local da=self.get("computedStates") +da[ba]=setmetatable({},{__call=function() +return ca(self)end})return self end +function aa:shareState(ba,...)local ca=self:getState(ba) +for da,_b in ipairs({...})do if +_b.get("states")[ba]then +_a.error("Cannot share state '"..ba.."': Target element already has this state")return self end +_b:initializeState(ba,ca) +self:observe("stateUpdate",function(ab,bb) +if bb.key==ba then _b:setState(ba,bb.value)end end)end;return self end +function aa:onStateChange(ba,ca)if not self.get("states")[ba]then +_a.error("Cannot observe state '"..ba.. +"': State not initialized")return self end +self:observe("stateUpdate",function(da,_b)if +_b.key==ba then ca(da,_b.value,_b.oldValue)end end)return self end;return{BaseElement=aa} end +project["plugins/reactive.lua"] = function(...) local ab=require("errorManager") +local bb=require("propertySystem")local cb={colors=true,math=true,clamp=true,round=true} +local db={clamp=function(ad,bd,cd)return +math.min(math.max(ad,bd),cd)end,round=function(ad) +return math.floor(ad+0.5)end} +local function _c(ad,bd,cd)ad=ad:gsub("^{(.+)}$","%1") +ad=ad:gsub("([%w_]+)%$([%w_]+)",function(b_a,c_a) +if b_a=="self"then return +string.format('__getState("%s")',c_a)elseif b_a=="parent"then return +string.format('__getParentState("%s")',c_a)else return +string.format('__getElementState("%s", "%s")',b_a,c_a)end end) +ad=ad:gsub("([%w_]+)%.([%w_]+)",function(b_a,c_a)if cb[b_a]then return b_a.."."..c_a end;return +string.format('__getProperty("%s", "%s")',b_a,c_a)end) +local dd=setmetatable({colors=colors,math=math,tostring=tostring,tonumber=tonumber,__getState=function(b_a)return bd:getState(b_a)end,__getParentState=function(b_a)return +bd.parent:getState(b_a)end,__getElementState=function(b_a,c_a) +local d_a=bd:getBaseFrame():getChild(b_a)if not d_a then ab.header="Reactive evaluation error" +ab.error("Could not find element: "..b_a)return nil end;return +d_a:getState(c_a).value end,__getProperty=function(b_a,c_a) +if +b_a=="self"then return bd.get(c_a)elseif b_a=="parent"then +return bd.parent.get(c_a)else local d_a=bd.parent:getChild(b_a)if not d_a then +ab.header="Reactive evaluation error" +ab.error("Could not find element: "..b_a)return nil end +return d_a.get(c_a)end end},{__index=db})if(bd._properties[cd].type=="string")then +ad="tostring("..ad..")"elseif(bd._properties[cd].type=="number")then +ad="tonumber("..ad..")"end;local __a,a_a=load("return ".. +ad,"reactive","t",dd) +if not __a then +ab.header="Reactive evaluation error"ab.error("Invalid expression: "..a_a)return +function()return nil end end;return __a end +local function ac(ad,bd) +for cd in ad:gmatch("([%w_]+)%.")do +if not cb[cd]then +if cd=="self"then elseif cd=="parent"then +if not bd.parent then +ab.header="Reactive evaluation error"ab.error("No parent element available")return false end else local dd=bd.parent:getChild(cd)if not dd then +ab.header="Reactive evaluation error" +ab.error("Referenced element not found: "..cd)return false end end end end;return true end;local bc=setmetatable({},{__mode="k"}) +local cc=setmetatable({},{__mode="k",__index=function(ad,bd)ad[bd]={} +return ad[bd]end}) +local function dc(ad,bd,cd) +if cc[ad][cd]then for __a,a_a in ipairs(cc[ad][cd])do +a_a.target:removeObserver(a_a.property,a_a.callback)end end;local dd={} +for __a,a_a in bd:gmatch("([%w_]+)%.([%w_]+)")do +if not cb[__a]then local b_a;if __a=="self"then b_a=ad elseif +__a=="parent"then b_a=ad.parent else +b_a=ad:getBaseFrame():getChild(__a)end;if b_a then +local c_a={target=b_a,property=a_a,callback=function() +ad:updateRender()end}b_a:observe(a_a,c_a.callback) +table.insert(dd,c_a)end end end;cc[ad][cd]=dd end +bb.addSetterHook(function(ad,bd,cd,dd) +if type(cd)=="string"and cd:match("^{.+}$")then +local __a=cd:gsub("^{(.+)}$","%1")if not ac(__a,ad)then return dd.default end;dc(ad,__a,bd)if +not bc[ad]then bc[ad]={}end;if not bc[ad][cd]then local a_a=_c(cd,ad,bd) +bc[ad][cd]=a_a end +return +function(a_a)local b_a,c_a=pcall(bc[ad][cd]) +if not b_a then +ab.header="Reactive evaluation error" +if type(c_a)=="string"then +ab.error("Error evaluating expression: "..c_a)else ab.error("Error evaluating expression")end;return dd.default end;return c_a end end end)local _d={} +_d.hooks={destroy=function(ad) +if cc[ad]then +for bd,cd in pairs(cc[ad])do for dd,__a in ipairs(cd)do +__a.target:removeObserver(__a.property,__a.callback)end end;cc[ad]=nil end end}return{BaseElement=_d} end +project["plugins/animation.lua"] = function(...) local aa={} +local ba={linear=function(ab)return ab end,easeInQuad=function(ab)return ab*ab end,easeOutQuad=function(ab)return +1 - (1 -ab)* (1 -ab)end,easeInOutQuad=function(ab)if ab<0.5 then return 2 *ab*ab end;return 1 - ( +-2 *ab+2)^2 /2 end}local ca={}ca.__index=ca +function ca.new(ab,bb,cb,db,_c)local ac=setmetatable({},ca)ac.element=ab +ac.type=bb;ac.args=cb;ac.duration=db or 1;ac.startTime=0;ac.isPaused=false +ac.handlers=aa[bb]ac.easing=_c;return ac end;function ca:start()self.startTime=os.epoch("local")/1000;if +self.handlers.start then self.handlers.start(self)end return self end -function ba:clearArea(da,_b,ab,bb,cb)local db=_a[cb]or"f" -for dy=0,bb-1 do local _c=_b+dy;if -_c>=1 and _c<=self.height then local ac=string.rep(" ",ab)local bc=string.rep(db,ab) -self:blit(da,_c,ac,"0",db)end end;return self end;function ba:getSize()return self.width,self.height end -function ba:setSize(da,_b) -self.width=da;self.height=_b -for y=1,self.height do -self.buffer.text[y]=string.rep(" ",self.width)self.buffer.fg[y]=string.rep("0",self.width) -self.buffer.bg[y]=string.rep("f",self.width)end;return self end;return ba end -project["log.lua"] = function(...) local aa={}aa._logs={}aa._enabled=false;aa._logToFile=false -aa._logFile="basalt.log"fs.delete(aa._logFile) -aa.LEVEL={DEBUG=1,INFO=2,WARN=3,ERROR=4} -local ba={[aa.LEVEL.DEBUG]="Debug",[aa.LEVEL.INFO]="Info",[aa.LEVEL.WARN]="Warn",[aa.LEVEL.ERROR]="Error"} -local ca={[aa.LEVEL.DEBUG]=colors.lightGray,[aa.LEVEL.INFO]=colors.white,[aa.LEVEL.WARN]=colors.yellow,[aa.LEVEL.ERROR]=colors.red}function aa.setLogToFile(ab)aa._logToFile=ab end -function aa.setEnabled(ab)aa._enabled=ab end;local function da(ab) -if aa._logToFile then local bb=io.open(aa._logFile,"a")if bb then -bb:write(ab.."\n")bb:close()end end end -local function _b(ab,...)if -not aa._enabled then return end;local bb=os.date("%H:%M:%S") -local cb=debug.getinfo(3,"Sl")local db=cb.source:match("@?(.*)")local _c=cb.currentline -local ac=string.format("[%s:%d]",db:match("([^/\\]+)%.lua$"),_c)local bc="["..ba[ab].."]"local cc="" -for _d,ad in ipairs(table.pack(...))do if _d>1 then cc= -cc.." "end;cc=cc..tostring(ad)end;local dc=string.format("%s %s%s %s",bb,ac,bc,cc)da(dc) -table.insert(aa._logs,{time=bb,level=ab,message=cc})end;function aa.debug(...)_b(aa.LEVEL.DEBUG,...)end;function aa.info(...) -_b(aa.LEVEL.INFO,...)end -function aa.warn(...)_b(aa.LEVEL.WARN,...)end;function aa.error(...)_b(aa.LEVEL.ERROR,...)end;return aa end +function ca:update(ab)local bb=math.min(1, +ab/self.duration) +local cb=ba[self.easing](bb)return self.handlers.update(self,cb)end;function ca:complete()if self.handlers.complete then +self.handlers.complete(self)end end +local da={}da.__index=da +function da.registerAnimation(ab,bb)aa[ab]=bb +da[ab]=function(cb,...)local db={...}local _c="linear" +if( +type(db[#db])=="string")then _c=table.remove(db,#db)end;local ac=table.remove(db,#db) +return cb:addAnimation(ab,db,ac,_c)end end;function da.registerEasing(ab,bb)ba[ab]=bb end +function da.new(ab)local bb={}bb.element=ab +bb.sequences={{}}bb.sequenceCallbacks={}bb.currentSequence=1;bb.timer=nil +setmetatable(bb,da)return bb end +function da:sequence()table.insert(self.sequences,{})self.currentSequence=# +self.sequences;self.sequenceCallbacks[self.currentSequence]={start=nil,update=nil,complete= +nil}return self end +function da:onStart(ab) +if +not self.sequenceCallbacks[self.currentSequence]then self.sequenceCallbacks[self.currentSequence]={}end +self.sequenceCallbacks[self.currentSequence].start=ab;return self end +function da:onUpdate(ab) +if +not self.sequenceCallbacks[self.currentSequence]then self.sequenceCallbacks[self.currentSequence]={}end +self.sequenceCallbacks[self.currentSequence].update=ab;return self end +function da:onComplete(ab) +if +not self.sequenceCallbacks[self.currentSequence]then self.sequenceCallbacks[self.currentSequence]={}end +self.sequenceCallbacks[self.currentSequence].complete=ab;return self end +function da:addAnimation(ab,bb,cb,db)local _c=ca.new(self.element,ab,bb,cb,db) +table.insert(self.sequences[self.currentSequence],_c)return self end +function da:start()self.currentSequence=1 +if +(self.sequenceCallbacks[self.currentSequence])then if(self.sequenceCallbacks[self.currentSequence].start)then +self.sequenceCallbacks[self.currentSequence].start(self.element)end end +if +#self.sequences[self.currentSequence]>0 then self.timer=os.startTimer(0.05)for ab,bb in +ipairs(self.sequences[self.currentSequence])do bb:start()end end;return self end +function da:event(ab,bb) +if ab=="timer"and bb==self.timer then +local cb=os.epoch("local")/1000;local db=true;local _c={} +local ac=self.sequenceCallbacks[self.currentSequence] +for bc,cc in ipairs(self.sequences[self.currentSequence])do +local dc=cb-cc.startTime;local _d=dc/cc.duration;local ad=cc:update(dc)if ac and ac.update then +ac.update(self.element,_d)end;if not ad then table.insert(_c,cc)db=false else +cc:complete()end end +if db then +if ac and ac.complete then ac.complete(self.element)end +if self.currentSequence<#self.sequences then +self.currentSequence=self.currentSequence+1;_c={} +local bc=self.sequenceCallbacks[self.currentSequence]if bc and bc.start then bc.start(self.element)end +for cc,dc in +ipairs(self.sequences[self.currentSequence])do dc:start()table.insert(_c,dc)end end end;if#_c>0 then self.timer=os.startTimer(0.05)end end end +da.registerAnimation("move",{start=function(ab)ab.startX=ab.element.get("x") +ab.startY=ab.element.get("y")end,update=function(ab,bb)local cb=ab.startX+ +(ab.args[1]-ab.startX)*bb;local db=ab.startY+ +(ab.args[2]-ab.startY)*bb +ab.element.set("x",math.floor(cb))ab.element.set("y",math.floor(db))return bb>=1 end,complete=function(ab) +ab.element.set("x",ab.args[1])ab.element.set("y",ab.args[2])end}) +da.registerAnimation("moveOffset",{start=function(ab)ab.startX=ab.element.get("offsetX") +ab.startY=ab.element.get("offsetY")end,update=function(ab,bb)local cb=ab.startX+ (ab.args[1]-ab.startX)* +bb;local db=ab.startY+ (ab.args[2]- +ab.startY)*bb +ab.element.set("offsetX",math.floor(cb))ab.element.set("offsetY",math.floor(db))return +bb>=1 end,complete=function(ab) +ab.element.set("offsetX",ab.args[1])ab.element.set("offsetY",ab.args[2])end}) +da.registerAnimation("morphText",{start=function(ab)local bb=ab.element.get(ab.args[1]) +local cb=ab.args[2]local db=math.max(#bb,#cb) +local _c=string.rep(" ",math.floor(db-#bb)/2)ab.startText=_c..bb.._c +ab.targetText=cb..string.rep(" ",db-#cb)ab.length=db end,update=function(ab,bb) +local cb="" +for i=1,ab.length do local db=ab.startText:sub(i,i) +local _c=ab.targetText:sub(i,i) +if bb<0.5 then +cb=cb.. (math.random()>bb*2 and db or" ")else cb=cb.. +(math.random()> (bb-0.5)*2 and" "or _c)end end;ab.element.set(ab.args[1],cb)return bb>=1 end,complete=function(ab) +ab.element.set(ab.args[1],ab.targetText:gsub("%s+$",""))end}) +da.registerAnimation("typewrite",{start=function(ab)ab.targetText=ab.args[2] +ab.element.set(ab.args[1],"")end,update=function(ab,bb) +local cb=math.floor(#ab.targetText*bb) +ab.element.set(ab.args[1],ab.targetText:sub(1,cb))return bb>=1 end}) +da.registerAnimation("fadeText",{start=function(ab)ab.chars={}for i=1,#ab.args[2]do +ab.chars[i]={char=ab.args[2]:sub(i,i),visible=false}end end,update=function(ab,bb) +local cb=""for db,_c in ipairs(ab.chars)do +if math.random()=1 end}) +da.registerAnimation("scrollText",{start=function(ab)ab.width=ab.element.get("width") +ab.targetText=ab.args[2]ab.element.set(ab.args[1],"")end,update=function(ab,bb)local cb=math.floor( +ab.width* (1 -bb)) +local db=string.rep(" ",cb) +ab.element.set(ab.args[1],db..ab.targetText)return bb>=1 end})local _b={hooks={}}function _b.hooks.dispatchEvent(ab,bb,...) +if bb=="timer"then local cb=ab.get("animation")if +cb then cb:event(bb,...)end;return true end end +function _b.setup(ab) +ab.defineProperty(ab,"animation",{default= +nil,type="table"})ab.defineEvent(ab,"timer")end +function _b:animate()local ab=da.new(self)self.set("animation",ab)return ab end;return{VisualElement=_b} end +project["plugins/debug.lua"] = function(...) local da=require("log")local _b=require("libraries/colorHex") +local ab=10;local bb=false +local function cb(bc) +local cc={renderCount=0,eventCount={},lastRender=os.epoch("utc"),properties={},children={}} +return +{trackProperty=function(dc,_d)cc.properties[dc]=_d end,trackRender=function() +cc.renderCount=cc.renderCount+1;cc.lastRender=os.epoch("utc")end,trackEvent=function(dc)cc.eventCount[dc]=( +cc.eventCount[dc]or 0)+1 end,dump=function()return +{type=bc.get("type"),id=bc.get("id"),stats=cc}end}end;local db={}function db.debug(bc,cc)bc._debugger=cb(bc) +bc._debugLevel=cc or DEBUG_LEVELS.INFO;return bc end +function db.dumpDebug(bc)if +not bc._debugger then return end;return bc._debugger.dump()end;local _c={} +function _c.showDebugLog(bc) +if not bc._debugFrame then local cc=bc.get("width") +local dc=bc.get("height") +bc._debugFrame=bc:addFrame("basaltDebugLog"):setWidth(cc):setHeight(dc):setZ(999):listenEvent("mouse_scroll",true) +bc.basalt.LOGGER.debug("Created debug log frame "..bc._debugFrame.get("name")) +bc._debugFrame:addButton("basaltDebugLogClose"):setWidth(9):setHeight(1):setX( +cc-8):setY(dc):setText("Close"):onMouseClick(function() +bc:hideDebugLog()end)bc._debugFrame._scrollOffset=0 +bc._debugFrame._processedLogs={} +local function _d(__a,a_a)local b_a={}while#__a>0 do local c_a=__a:sub(1,a_a)table.insert(b_a,c_a)__a=__a:sub( +a_a+1)end;return b_a end +local function ad()local __a={}local a_a=bc._debugFrame.get("width") +for b_a,c_a in +ipairs(da._logs)do local d_a=_d(c_a.message,a_a)for _aa,aaa in ipairs(d_a)do +table.insert(__a,{text=aaa,level=c_a.level})end end;return __a end;local bd=#ad()-bc.get("height")bc._scrollOffset=bd +local cd=bc._debugFrame.render +bc._debugFrame.render=function(__a)cd(__a)__a._processedLogs=ad() +local a_a=__a.get("height")-2;local b_a=#__a._processedLogs;local c_a=math.max(0,b_a-a_a) +__a._scrollOffset=math.min(__a._scrollOffset,c_a) +for i=1,a_a-2 do local d_a=i+__a._scrollOffset +local _aa=__a._processedLogs[d_a] +if _aa then +local aaa= + +_aa.level==da.LEVEL.ERROR and colors.red or _aa.level== +da.LEVEL.WARN and colors.yellow or _aa.level==da.LEVEL.DEBUG and colors.lightGray or colors.white;__a:textFg(2,i,_aa.text,aaa)end end end;local dd=bc._debugFrame.dispatchEvent +bc._debugFrame.dispatchEvent=function(__a,a_a,b_a,...) +if +(a_a=="mouse_scroll")then +__a._scrollOffset=math.max(0,__a._scrollOffset+b_a)__a:updateRender()return true else dd(__a,a_a,b_a,...)end end end;bc._debugFrame.set("visible",true)return bc end +function _c.hideDebugLog(bc)if bc._debugFrame then +bc._debugFrame.set("visible",false)end;return bc end;function _c.toggleDebugLog(bc)if bc._debugFrame and bc._debugFrame:isVisible()then +bc:hideDebugLog()else bc:showDebugLog()end +return bc end +local ac={} +function ac.debugChildren(bc,cc)bc:debug(cc)for dc,_d in pairs(bc.get("children"))do if _d.debug then +_d:debug(cc)end end;return bc end;return{BaseElement=db,Container=ac,BaseFrame=_c} end +project["plugins/benchmark.lua"] = function(...) local ca=require("log")local da=setmetatable({},{__mode="k"})local function _b()return +{methods={}}end +local function ab(_c,ac)local bc=_c[ac] +if not da[_c]then da[_c]=_b()end +if not da[_c].methods[ac]then +da[_c].methods[ac]={calls=0,totalTime=0,minTime=math.huge,maxTime=0,lastTime=0,startTime=0,path={},methodName=ac,originalMethod=bc}end +_c[ac]=function(cc,...)cc:startProfile(ac)local dc=bc(cc,...) +cc:endProfile(ac)return dc end end;local bb={} +function bb:startProfile(_c)local ac=da[self]if not ac then ac=_b()da[self]=ac end;if not +ac.methods[_c]then +ac.methods[_c]={calls=0,totalTime=0,minTime=math.huge,maxTime=0,lastTime=0,startTime=0,path={},methodName=_c}end +local bc=ac.methods[_c]bc.startTime=os.clock()*1000;bc.path={}local cc=self;while cc do +table.insert(bc.path,1, +cc.get("name")or cc.get("id"))cc=cc.parent end;return self end +function bb:endProfile(_c)local ac=da[self] +if not ac or not ac.methods[_c]then return self end;local bc=ac.methods[_c]local cc=os.clock()*1000 +local dc=cc-bc.startTime;bc.calls=bc.calls+1;bc.totalTime=bc.totalTime+dc +bc.minTime=math.min(bc.minTime,dc)bc.maxTime=math.max(bc.maxTime,dc)bc.lastTime=dc;return self end +function bb:benchmark(_c)if not self[_c]then +ca.error("Method ".._c.." does not exist")return self end;da[self]=_b() +da[self].methodName=_c;da[self].isRunning=true;ab(self,_c)return self end +function bb:logBenchmark(_c)local ac=da[self] +if not ac or not ac.methods[_c]then return self end;local bc=ac.methods[_c] +if bc then local cc= +bc.calls>0 and(bc.totalTime/bc.calls)or 0 +ca.info(string.format( +"Benchmark results for %s.%s: ".. +"Path: %s ".."Calls: %d ".. +"Average time: %.2fms ".."Min time: %.2fms ".."Max time: %.2fms ".. +"Last time: %.2fms ".."Total time: %.2fms",table.concat(bc.path,"."),bc.methodName,table.concat(bc.path,"/"),bc.calls,cc, +bc.minTime~=math.huge and bc.minTime or 0,bc.maxTime,bc.lastTime,bc.totalTime))end;return self end +function bb:stopBenchmark(_c)local ac=da[self] +if not ac or not ac.methods[_c]then return self end;local bc=ac.methods[_c]if bc and bc.originalMethod then +self[_c]=bc.originalMethod end;ac.methods[_c]=nil;if +not next(ac.methods)then da[self]=nil end;return self end +function bb:getBenchmarkStats(_c)local ac=da[self] +if not ac or not ac.methods[_c]then return nil end;local bc=ac.methods[_c]return +{averageTime=bc.totalTime/bc.calls,totalTime=bc.totalTime,calls=bc.calls,minTime=bc.minTime,maxTime=bc.maxTime,lastTime=bc.lastTime}end;local cb={} +function cb:benchmarkContainer(_c)self:benchmark(_c) +for ac,bc in +pairs(self.get("children"))do bc:benchmark(_c)if bc:isType("Container")then +bc:benchmarkContainer(_c)end end;return self end +function cb:logContainerBenchmarks(_c,ac)ac=ac or 0;local bc=string.rep(" ",ac)local cc=0;local dc={} +for ad,bd in +pairs(self.get("children"))do local cd=da[bd] +if cd and cd.methods[_c]then local dd=cd.methods[_c] +cc=cc+dd.totalTime +table.insert(dc,{element=bd,type=bd.get("type"),calls=dd.calls,totalTime=dd.totalTime,avgTime=dd.totalTime/dd.calls})end end;local _d=da[self] +if _d and _d.methods[_c]then local ad=_d.methods[_c] +local bd=ad.totalTime-cc;local cd=bd/ad.calls +ca.info(string.format("%sBenchmark %s (%s): ".."%.2fms/call (Self: %.2fms/call) ".. +"[Total: %dms, Calls: %d]",bc,self.get("type"),_c, +ad.totalTime/ad.calls,cd,ad.totalTime,ad.calls)) +if#dc>0 then +for dd,__a in ipairs(dc)do +if __a.element:isType("Container")then __a.element:logContainerBenchmarks(_c, +ac+1)else +ca.info(string.format("%s> %s: %.2fms/call [Total: %dms, Calls: %d]", +bc.." ",__a.type,__a.avgTime,__a.totalTime,__a.calls))end end end end;return self end +function cb:stopContainerBenchmark(_c) +for ac,bc in pairs(self.get("children"))do if bc:isType("Container")then +bc:stopContainerBenchmark(_c)else bc:stopBenchmark(_c)end end;self:stopBenchmark(_c)return self end;local db={} +function db.start(_c,ac)ac=ac or{}local bc=_b()bc.name=_c +bc.startTime=os.clock()*1000;bc.custom=true;bc.calls=0;bc.totalTime=0;bc.minTime=math.huge;bc.maxTime=0 +bc.lastTime=0;da[_c]=bc end +function db.stop(_c)local ac=da[_c]if not ac or not ac.custom then return end;local bc= +os.clock()*1000;local cc=bc-ac.startTime;ac.calls=ac.calls+1;ac.totalTime= +ac.totalTime+cc;ac.minTime=math.min(ac.minTime,cc) +ac.maxTime=math.max(ac.maxTime,cc)ac.lastTime=cc +ca.info(string.format("Custom Benchmark '%s': ".. +"Calls: %d ".."Average time: %.2fms ".. +"Min time: %.2fms ".. +"Max time: %.2fms ".."Last time: %.2fms ".."Total time: %.2fms",_c,ac.calls, +ac.totalTime/ac.calls,ac.minTime,ac.maxTime,ac.lastTime,ac.totalTime))end +function db.getStats(_c)local ac=da[_c]if not ac then return nil end;return +{averageTime=ac.totalTime/ac.calls,totalTime=ac.totalTime,calls=ac.calls,minTime=ac.minTime,maxTime=ac.maxTime,lastTime=ac.lastTime}end;function db.clear(_c)da[_c]=nil end;function db.clearAll()for _c,ac in pairs(da)do +if ac.custom then da[_c]=nil end end end;return +{BaseElement=bb,Container=cb,API=db} end +project["plugins/theme.lua"] = function(...) +local _b={default={background=colors.lightGray,foreground=colors.black},BaseFrame={background=colors.white,foreground=colors.black,Frame={background=colors.black,names={basaltDebugLogClose={background=colors.blue,foreground=colors.white}}},Button={background="{self.clicked and colors.black or colors.cyan}",foreground="{self.clicked and colors.cyan or colors.black}"},names={basaltDebugLog={background=colors.red,foreground=colors.white},test={background="{self.clicked and colors.black or colors.green}",foreground="{self.clicked and colors.green or colors.black}"}}}}local ab={default=_b}local bb="default" +local cb={hooks={postInit={pre=function(dc)dc:applyTheme()end}}} +function cb.____getElementPath(dc,_d)if _d then table.insert(_d,1,dc._values.type)else +_d={dc._values.type}end;local ad=dc.parent;if ad then return +ad.____getElementPath(ad,_d)else return _d end end +local function db(dc,_d)local ad=dc +for i=1,#_d do local bd=false;local cd=_d[i]for dd,__a in ipairs(cd)do +if ad[__a]then ad=ad[__a]bd=true;break end end;if not bd then return nil end end;return ad end +local function _c(dc,_d)local ad={} +if dc.default then for bd,cd in pairs(dc.default)do +if type(cd)~="table"then ad[bd]=cd end end;if dc.default[_d]then +for bd,cd in +pairs(dc.default[_d])do if type(cd)~="table"then ad[bd]=cd end end end end;return ad end +local function ac(dc,_d,ad,bd,cd) +if +_d.default and _d.default.names and _d.default.names[bd]then for dd,__a in pairs(_d.default.names[bd])do +if type(__a)~="table"then dc[dd]=__a end end end +if + +_d.default and _d.default[ad]and _d.default[ad].names and _d.default[ad].names[bd]then +for dd,__a in pairs(_d.default[ad].names[bd])do if +type(__a)~="table"then dc[dd]=__a end end end;if cd and cd.names and cd.names[bd]then +for dd,__a in pairs(cd.names[bd])do if type(__a)~= +"table"then dc[dd]=__a end end end end +local function bc(dc,_d,ad,bd)local cd={}local dd=db(dc,_d) +if dd then for __a,a_a in pairs(dd)do +if type(a_a)~="table"then cd[__a]=a_a end end end;if next(cd)==nil then cd=_c(dc,ad)end;ac(cd,dc,ad,bd,dd) +return cd end +function cb:applyTheme()local dc=self:getTheme()if(dc~=nil)then +for _d,ad in pairs(dc)do self.set(_d,ad)end end end +function cb:getTheme()local dc=self:____getElementPath() +local _d=self.get("type")local ad=self.get("name")return bc(ab[bb],dc,_d,ad)end;local cc={}function cc.setTheme(dc)ab.default=dc end +function cc.getTheme()return ab.default end +function cc.loadTheme(dc)local _d=fs.open(dc,"r")if _d then local ad=_d.readAll()_d.close() +ab.default=textutils.unserializeJSON(ad)end end;return{BaseElement=cb,API=cc} end +project["elementManager.lua"] = function(...) local ab=table.pack(...) +local bb=fs.getDir(ab[2]or"basalt")local cb=ab[1]if(bb==nil)then +error("Unable to find directory ".. +ab[2].." please report this bug to our discord.")end +local db=require("log")local _c=package.path;local ac="path;/path/?.lua;/path/?/init.lua;" +local bc=ac:gsub("path",bb)local cc={}cc._elements={}cc._plugins={}cc._APIs={} +local dc=fs.combine(bb,"elements")local _d=fs.combine(bb,"plugins") +db.info("Loading elements from "..dc) +if fs.exists(dc)then +for ad,bd in ipairs(fs.list(dc))do local cd=bd:match("(.+).lua")if cd then db.debug( +"Found element: "..cd) +cc._elements[cd]={class=nil,plugins={},loaded=false}end end end;db.info("Loading plugins from ".._d) +if +fs.exists(_d)then +for ad,bd in ipairs(fs.list(_d))do local cd=bd:match("(.+).lua") +if cd then +db.debug("Found plugin: "..cd)local dd=require(fs.combine("plugins",cd)) +if +type(dd)=="table"then +for __a,a_a in pairs(dd)do if(__a~="API")then +if(cc._plugins[__a]==nil)then cc._plugins[__a]={}end;table.insert(cc._plugins[__a],a_a)else +cc._APIs[cd]=a_a end end end end end end +if(minified)then if(minified_elementDirectory==nil)then +error("Unable to find minified_elementDirectory please report this bug to our discord.")end;for ad,bd in +pairs(minified_elementDirectory)do +cc._elements[ad:gsub(".lua","")]={class=nil,plugins={},loaded=false}end;if +(minified_pluginDirectory==nil)then +error("Unable to find minified_pluginDirectory please report this bug to our discord.")end +for ad,bd in +pairs(minified_pluginDirectory)do local cd=ad:gsub(".lua","") +local dd=require(fs.combine("plugins",cd)) +if type(dd)=="table"then +for __a,a_a in pairs(dd)do +if(__a~="API")then if(cc._plugins[__a]==nil)then +cc._plugins[__a]={}end +table.insert(cc._plugins[__a],a_a)else cc._APIs[cd]=a_a end end end end end +function cc.loadElement(ad) +if not cc._elements[ad].loaded then +package.path=bc.."rom/?"local bd=require(fs.combine("elements",ad)) +package.path=_c;cc._elements[ad]={class=bd,plugins=bd.plugins,loaded=true}db.debug( +"Loaded element: "..ad) +if(cc._plugins[ad]~=nil)then +for cd,dd in +pairs(cc._plugins[ad])do if(dd.setup)then dd.setup(bd)end +if(dd.hooks)then +for __a,a_a in pairs(dd.hooks)do +local b_a=bd[__a]if(type(b_a)~="function")then +error("Element ".. +ad.." does not have a method "..__a)end +if(type(a_a)=="function")then +bd[__a]=function(c_a,...) +local d_a=b_a(c_a,...)local _aa=a_a(c_a,...)return _aa==nil and d_a or _aa end elseif(type(a_a)=="table")then +bd[__a]=function(c_a,...)if a_a.pre then a_a.pre(c_a,...)end +local d_a=b_a(c_a,...)if a_a.post then a_a.post(c_a,...)end;return d_a end end end end;for __a,a_a in pairs(dd)do +if __a~="setup"and __a~="hooks"then bd[__a]=a_a end end end end end end +function cc.getElement(ad)if not cc._elements[ad].loaded then +cc.loadElement(ad)end;return cc._elements[ad].class end;function cc.getElementList()return cc._elements end;function cc.getAPI(ad) +return cc._APIs[ad]end;return cc end +project["init.lua"] = function(...) local da={...}local _b=fs.getDir(da[2])local ab=package.path +local bb="path;/path/?.lua;/path/?/init.lua;"local cb=bb:gsub("path",_b)package.path=cb.."rom/?" +local function db(bc) +local cc=require("errorManager")cc.header="Basalt Loading Error"cc.error(bc)end;local _c,ac=pcall(require,"main")package.path=ab +if not _c then db(ac)else return ac end end return project["main.lua"]() \ No newline at end of file