Update with some fixxes and improvements
This commit is contained in:
235
install.lua
235
install.lua
@@ -1,100 +1,167 @@
|
|||||||
local basalt = http.get("https://raw.githubusercontent.com/Pyroxenium/Basalt2/master/release/basalt.lua")
|
local basalt = require("src")
|
||||||
|
local configPath = "https://raw.githubusercontent.com/Pyroxenium/Basalt2/refs/heads/main/config.lua"
|
||||||
|
|
||||||
|
local coloring = {foreground=colors.black, background=colors.white}
|
||||||
|
local currentScreen = 1
|
||||||
|
local screens = {}
|
||||||
|
local main = basalt.getMainFrame():setBackground(colors.black)
|
||||||
|
local config
|
||||||
|
|
||||||
local REPO_URL = "https://raw.githubusercontent.com/Pyroxenium/Basalt2/master/src"
|
local function getConfig()
|
||||||
|
if not config then
|
||||||
|
local request = http.get(configPath)
|
||||||
|
if request then
|
||||||
|
local content = request.readAll()
|
||||||
|
config = load(content)()
|
||||||
|
request.close()
|
||||||
|
else
|
||||||
|
error("Failed to fetch config")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return config
|
||||||
|
end
|
||||||
|
|
||||||
-- Basis-Komponenten die immer installiert werden müssen
|
local function getChildrenHeight(container)
|
||||||
local REQUIRED_FILES = {
|
local height = 0
|
||||||
"init.lua",
|
for _, child in ipairs(container:getChildren()) do
|
||||||
"render.lua",
|
local newHeight = child.get("y") + child.get("height")
|
||||||
"elementManager.lua",
|
if newHeight > height then
|
||||||
"propertySystem.lua",
|
height = newHeight
|
||||||
"elements/BaseElement.lua",
|
end
|
||||||
"elements/VisualElement.lua",
|
end
|
||||||
"elements/Container.lua",
|
return height
|
||||||
"elements/BaseFrame.lua"
|
end
|
||||||
}
|
|
||||||
|
|
||||||
-- Optionale Komponenten
|
local function createScreen(index)
|
||||||
local OPTIONAL_ELEMENTS = {
|
local screen = main:addFrame(coloring)
|
||||||
"Button",
|
:onMouseScroll(function(self, direction)
|
||||||
"Input",
|
local height = getChildrenHeight(self)
|
||||||
"Label",
|
local scrollOffset = self:getOffsetY()
|
||||||
"List",
|
local maxScroll = height - self:getHeight()
|
||||||
"Menu",
|
scrollOffset = math.max(0, math.min(maxScroll, scrollOffset + direction))
|
||||||
"Table",
|
self:setOffsetY(scrollOffset)
|
||||||
"Tree",
|
end)
|
||||||
"Dropdown"
|
:setSize("{parent.width - 2}", "{parent.height - 4}")
|
||||||
}
|
if(index==1)then
|
||||||
|
screen:setPosition(2, 2)
|
||||||
|
else
|
||||||
|
screen:setPosition("{parent.width * "..(index-1).." + 2}", 2)
|
||||||
|
end
|
||||||
|
screens[index] = screen
|
||||||
|
return screen
|
||||||
|
end
|
||||||
|
|
||||||
local OPTIONAL_PLUGINS = {
|
local function switchScreen(direction)
|
||||||
"animation",
|
local newScreen = currentScreen + direction
|
||||||
"theme",
|
if screens[newScreen] then
|
||||||
"xml",
|
--main:setOffsetX((newScreen - 1) * main:getWidth())
|
||||||
"state"
|
main:animate():moveOffset((newScreen - 1) * main:getWidth(), 0, 0.5):start()
|
||||||
}
|
currentScreen = newScreen
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
local main = basalt.createFrame()
|
main:addButton()
|
||||||
|
:setBackground("{self.clicked and colors.black or colors.white}")
|
||||||
|
:setForeground("{self.clicked and colors.white or colors.black}")
|
||||||
|
:setSize(8, 1)
|
||||||
|
:setText("Next")
|
||||||
|
:setPosition("{parent.width - 9}", "{parent.height - 1}")
|
||||||
|
:setIgnoreOffset(true)
|
||||||
|
:onMouseClick(function() switchScreen(1) end)
|
||||||
|
|
||||||
|
main:addButton()
|
||||||
|
:setBackground("{self.clicked and colors.black or colors.white}")
|
||||||
|
:setForeground("{self.clicked and colors.white or colors.black}")
|
||||||
|
:setSize(8, 1)
|
||||||
|
:setText("Back")
|
||||||
|
:setPosition(2, "{parent.height - 1}")
|
||||||
|
:setIgnoreOffset(true)
|
||||||
|
:onMouseClick(function() switchScreen(-1) end)
|
||||||
|
|
||||||
|
-- Screen 1: Welcome
|
||||||
|
local welcomeScreen = createScreen(1)
|
||||||
|
welcomeScreen:addLabel(coloring)
|
||||||
|
:setText("Welcome to Basalt!")
|
||||||
|
:setPosition(2, 2)
|
||||||
|
|
||||||
|
welcomeScreen:addLabel(coloring)
|
||||||
|
:setWidth("{parent.width - 2}")
|
||||||
|
:setAutoSize(false)
|
||||||
|
:setText([[Basalt is an open-source project created with passion for the ComputerCraft community. It provides you with all the tools you need to create beautiful and interactive user interfaces.
|
||||||
|
|
||||||
|
The project is actively maintained and continuously improving thanks to our amazing community. Whether you're a beginner or an experienced developer, you'll find Basalt easy to use yet powerful enough for complex applications.
|
||||||
|
|
||||||
|
Have ideas or want to get involved? Join our friendly community on Discord or GitHub - we'd love to hear from you and welcome contributions of any kind!
|
||||||
|
|
||||||
|
Let's start creating something awesome together!]])
|
||||||
|
:setPosition(2, 4)
|
||||||
|
|
||||||
|
-- Screen 2: Installation
|
||||||
|
local installScreen = createScreen(2)
|
||||||
|
installScreen:addLabel(coloring)
|
||||||
|
:setText("Choose Your Installation")
|
||||||
|
:setPosition(2, 2)
|
||||||
|
|
||||||
|
installScreen:addLabel(coloring)
|
||||||
|
:setText("Select Version:")
|
||||||
|
:setPosition(2, 4)
|
||||||
|
|
||||||
|
local versionDropdown = installScreen:addDropdown()
|
||||||
|
:setPosition("{parent.width - self.width - 1}", 4)
|
||||||
|
:setSize(15, 1)
|
||||||
|
:setBackground(colors.black)
|
||||||
|
:setForeground(colors.white)
|
||||||
|
:addItem("Release")
|
||||||
|
:addItem("Dev")
|
||||||
|
:addItem("Custom")
|
||||||
|
|
||||||
|
local versionDesc = installScreen:addLabel("versionDesc")
|
||||||
|
:setWidth("{parent.width - 2}")
|
||||||
|
:setAutoSize(false)
|
||||||
|
:setText("The Release version is the most stable and tested version of Basalt. It is recommended for production use.")
|
||||||
|
:setPosition(2, 7)
|
||||||
|
:setSize("{parent.width - 4}", 3)
|
||||||
:setBackground(colors.lightGray)
|
:setBackground(colors.lightGray)
|
||||||
|
|
||||||
-- Header
|
versionDropdown:onSelect(function(self, index, value)
|
||||||
main:addLabel()
|
if(value == "Release") then
|
||||||
:setText("Basalt2 Installer")
|
versionDesc:setText("The Release version is the most stable and tested version of Basalt. It is recommended for production use.")
|
||||||
:setPosition(2,2)
|
elseif(value == "Custom") then
|
||||||
:setForeground(colors.black)
|
versionDesc:setText("The Custom version allows you to specify which elements or plugins you want to install.")
|
||||||
|
else
|
||||||
|
versionDesc:setText("The Dev version is the latest development version of Basalt. It may contain new features and improvements, but it may also have bugs and issues.")
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
-- Element Selection
|
installScreen:addLabel(coloring)
|
||||||
local elementList = main:addList()
|
:setText("Additional Components:")
|
||||||
:setPosition(2,4)
|
:setPosition(2, "{versionDesc.y + versionDesc.height + 1}")
|
||||||
:setSize(20,8)
|
|
||||||
|
local luaLSCheckbox = installScreen:addCheckbox()
|
||||||
|
:setPosition(2, 12)
|
||||||
|
:setText("[ ] LLS definitions")
|
||||||
|
:setCheckedText("[x] LLS definitions")
|
||||||
:setBackground(colors.white)
|
:setBackground(colors.white)
|
||||||
:setForeground(colors.black)
|
:setForeground(colors.black)
|
||||||
|
|
||||||
for _, element in ipairs(OPTIONAL_ELEMENTS) do
|
-- Screen 3: Elements
|
||||||
elementList:addItem({
|
local elementsScreen = createScreen(3)
|
||||||
text = element,
|
elementsScreen:addLabel(coloring)
|
||||||
selected = true
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Plugin Selection
|
|
||||||
local pluginList = main:addList()
|
|
||||||
:setPosition(24,4)
|
|
||||||
:setSize(20,8)
|
|
||||||
:setBackground(colors.white)
|
|
||||||
:setForeground(colors.black)
|
|
||||||
|
|
||||||
for _, plugin in ipairs(OPTIONAL_PLUGINS) do
|
|
||||||
pluginList:addItem({
|
|
||||||
text = plugin,
|
|
||||||
selected = true
|
|
||||||
})
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Labels
|
|
||||||
main:addLabel()
|
|
||||||
:setText("Elements:")
|
:setText("Elements:")
|
||||||
:setPosition(2,3)
|
:setPosition(2, 2)
|
||||||
:setForeground(colors.black)
|
|
||||||
|
|
||||||
main:addLabel()
|
local elementsList = elementsScreen:addList()
|
||||||
:setText("Plugins:")
|
:setPosition(2, 4)
|
||||||
:setPosition(24,3)
|
:setSize("{parent.width - 2}", "{parent.height - 6}")
|
||||||
:setForeground(colors.black)
|
|
||||||
|
|
||||||
-- Install Button
|
local function addElements()
|
||||||
main:addButton()
|
elementsList:clear()
|
||||||
:setText("Install")
|
for k,v in pairs(getConfig().files)do
|
||||||
:setPosition(2,13)
|
if(k:match("src/elements/"))then
|
||||||
:setSize(42,1)
|
elementsList:addItem(v.name)
|
||||||
:onClick(function()
|
end
|
||||||
-- Installation Logic hier
|
end
|
||||||
local selectedElements = {}
|
end
|
||||||
local selectedPlugins = {}
|
addElements()
|
||||||
|
|
||||||
-- Sammle ausgewählte Items
|
|
||||||
-- Download Files
|
|
||||||
-- Erstelle Ordnerstruktur
|
|
||||||
end)
|
|
||||||
|
|
||||||
basalt.autoUpdate()
|
basalt.run()
|
||||||
@@ -54,6 +54,8 @@ end
|
|||||||
--- @param fg string The foreground color
|
--- @param fg string The foreground color
|
||||||
--- @param bg string The background color
|
--- @param bg string The background color
|
||||||
function BaseFrame:multiBlit(x, y, width, height, text, fg, bg)
|
function BaseFrame:multiBlit(x, y, width, height, text, fg, bg)
|
||||||
|
if(x<1)then width = width + x - 1; x = 1 end
|
||||||
|
if(y<1)then height = height + y - 1; y = 1 end
|
||||||
self._render:multiBlit(x, y, width, height, text, fg, bg)
|
self._render:multiBlit(x, y, width, height, text, fg, bg)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -64,6 +66,7 @@ end
|
|||||||
--- @param text string The text to render
|
--- @param text string The text to render
|
||||||
--- @param fg colors The foreground color
|
--- @param fg colors The foreground color
|
||||||
function BaseFrame:textFg(x, y, text, fg)
|
function BaseFrame:textFg(x, y, text, fg)
|
||||||
|
if x < 1 then text = string.sub(text, 1 - x); x = 1 end
|
||||||
self._render:textFg(x, y, text, fg)
|
self._render:textFg(x, y, text, fg)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -74,6 +77,7 @@ end
|
|||||||
--- @param text string The text to render
|
--- @param text string The text to render
|
||||||
--- @param bg colors The background color
|
--- @param bg colors The background color
|
||||||
function BaseFrame:textBg(x, y, text, bg)
|
function BaseFrame:textBg(x, y, text, bg)
|
||||||
|
if x < 1 then text = string.sub(text, 1 - x); x = 1 end
|
||||||
self._render:textBg(x, y, text, bg)
|
self._render:textBg(x, y, text, bg)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -85,6 +89,11 @@ end
|
|||||||
--- @param fg string The foreground color
|
--- @param fg string The foreground color
|
||||||
--- @param bg string The background color
|
--- @param bg string The background color
|
||||||
function BaseFrame:blit(x, y, text, fg, bg)
|
function BaseFrame:blit(x, y, text, fg, bg)
|
||||||
|
if x < 1 then
|
||||||
|
text = string.sub(text, 1 - x)
|
||||||
|
fg = string.sub(fg, 1 - x)
|
||||||
|
bg = string.sub(bg, 1 - x)
|
||||||
|
x = 1 end
|
||||||
self._render:blit(x, y, text, fg, bg)
|
self._render:blit(x, y, text, fg, bg)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ local elementManager = require("elementManager")
|
|||||||
local VisualElement = elementManager.getElement("VisualElement")
|
local VisualElement = elementManager.getElement("VisualElement")
|
||||||
local getCenteredPosition = require("libraries/utils").getCenteredPosition
|
local getCenteredPosition = require("libraries/utils").getCenteredPosition
|
||||||
|
|
||||||
--- This is the button class. It is a visual element that can be clicked.
|
|
||||||
---@class Button : VisualElement
|
---@class Button : VisualElement
|
||||||
local Button = setmetatable({}, VisualElement)
|
local Button = setmetatable({}, VisualElement)
|
||||||
Button.__index = Button
|
Button.__index = Button
|
||||||
@@ -12,30 +11,21 @@ Button.defineProperty(Button, "text", {default = "Button", type = "string", canT
|
|||||||
|
|
||||||
---@event mouse_click The event that is triggered when the button is clicked
|
---@event mouse_click The event that is triggered when the button is clicked
|
||||||
Button.listenTo(Button, "mouse_click")
|
Button.listenTo(Button, "mouse_click")
|
||||||
Button.listenTo(Button, "mouse_up")
|
|
||||||
|
|
||||||
--- Creates a new Button instance
|
function Button.new(props, basalt)
|
||||||
--- @shortDescription Creates a new Button instance
|
|
||||||
--- @return table self The created instance
|
|
||||||
function Button.new()
|
|
||||||
local self = setmetatable({}, Button):__init()
|
local self = setmetatable({}, Button):__init()
|
||||||
|
self:init(props, basalt)
|
||||||
self.set("width", 10)
|
self.set("width", 10)
|
||||||
self.set("height", 3)
|
self.set("height", 3)
|
||||||
self.set("z", 5)
|
self.set("z", 5)
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Initializes the Button instance
|
|
||||||
--- @shortDescription Initializes the Button instance
|
|
||||||
--- @param props table The properties to initialize the element with
|
|
||||||
--- @param basalt table The basalt instance
|
|
||||||
function Button:init(props, basalt)
|
function Button:init(props, basalt)
|
||||||
VisualElement.init(self, props, basalt)
|
VisualElement.init(self, props, basalt)
|
||||||
self.set("type", "Button")
|
self.set("type", "Button")
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Renders the Button
|
|
||||||
--- @shortDescription Renders the Button
|
|
||||||
function Button:render()
|
function Button:render()
|
||||||
VisualElement.render(self)
|
VisualElement.render(self)
|
||||||
local text = self.get("text")
|
local text = self.get("text")
|
||||||
|
|||||||
@@ -7,10 +7,26 @@ Checkbox.__index = Checkbox
|
|||||||
|
|
||||||
---@property checked boolean Whether checkbox is checked
|
---@property checked boolean Whether checkbox is checked
|
||||||
Checkbox.defineProperty(Checkbox, "checked", {default = false, type = "boolean", canTriggerRender = true})
|
Checkbox.defineProperty(Checkbox, "checked", {default = false, type = "boolean", canTriggerRender = true})
|
||||||
---@property text string Label text
|
---@property text string empty Text to display
|
||||||
Checkbox.defineProperty(Checkbox, "text", {default = "", type = "string", canTriggerRender = true})
|
Checkbox.defineProperty(Checkbox, "text", {default = " ", type = "string", canTriggerRender = true, setter=function(self, value)
|
||||||
---@property symbol string Check symbol
|
local checkedText = self.get("checkedText")
|
||||||
Checkbox.defineProperty(Checkbox, "symbol", {default = "x", type = "string"})
|
local width = math.max(#value, #checkedText)
|
||||||
|
if(self.get("autoSize"))then
|
||||||
|
self.set("width", width)
|
||||||
|
end
|
||||||
|
return value
|
||||||
|
end})
|
||||||
|
---@property checkedText string Text when checked
|
||||||
|
Checkbox.defineProperty(Checkbox, "checkedText", {default = "x", type = "string", canTriggerRender = true, setter=function(self, value)
|
||||||
|
local text = self.get("text")
|
||||||
|
local width = math.max(#value, #text)
|
||||||
|
if(self.get("autoSize"))then
|
||||||
|
self.set("width", width)
|
||||||
|
end
|
||||||
|
return value
|
||||||
|
end})
|
||||||
|
---@property autoSize boolean true Whether to automatically size the checkbox
|
||||||
|
Checkbox.defineProperty(Checkbox, "autoSize", {default = true, type = "boolean"})
|
||||||
|
|
||||||
Checkbox.listenTo(Checkbox, "mouse_click")
|
Checkbox.listenTo(Checkbox, "mouse_click")
|
||||||
|
|
||||||
@@ -19,8 +35,6 @@ Checkbox.listenTo(Checkbox, "mouse_click")
|
|||||||
--- @return Checkbox self The created instance
|
--- @return Checkbox self The created instance
|
||||||
function Checkbox.new()
|
function Checkbox.new()
|
||||||
local self = setmetatable({}, Checkbox):__init()
|
local self = setmetatable({}, Checkbox):__init()
|
||||||
self.set("width", 1)
|
|
||||||
self.set("height", 1)
|
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -53,13 +67,12 @@ end
|
|||||||
function Checkbox:render()
|
function Checkbox:render()
|
||||||
VisualElement.render(self)
|
VisualElement.render(self)
|
||||||
|
|
||||||
local text = self.get("checked") and self.get("symbol") or " "
|
local checked = self.get("checked")
|
||||||
self:textFg(1, 1, "["..text.."]", self.get("foreground"))
|
local defaultText = self.get("text")
|
||||||
|
local checkedText = self.get("checkedText")
|
||||||
|
local text = string.sub(checked and checkedText or defaultText, 1, self.get("width"))
|
||||||
|
|
||||||
local label = self.get("text")
|
self:textFg(1, 1, text, self.get("foreground"))
|
||||||
if #label > 0 then
|
|
||||||
self:textFg(4, 1, label, self.get("foreground"))
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return Checkbox
|
return Checkbox
|
||||||
@@ -47,6 +47,19 @@ Container.defineProperty(Container, "visibleChildren", {default = {}, type = "ta
|
|||||||
---@property visibleChildrenEvents table {} The visible children events of the container
|
---@property visibleChildrenEvents table {} The visible children events of the container
|
||||||
Container.defineProperty(Container, "visibleChildrenEvents", {default = {}, type = "table"})
|
Container.defineProperty(Container, "visibleChildrenEvents", {default = {}, type = "table"})
|
||||||
|
|
||||||
|
---@property offsetX number 0 Horizontal content offset
|
||||||
|
Container.defineProperty(Container, "offsetX", {default = 0, type = "number", canTriggerRender = true, setter=function(self, value)
|
||||||
|
self.set("childrenSorted", false)
|
||||||
|
self.set("childrenEventsSorted", false)
|
||||||
|
return value
|
||||||
|
end})
|
||||||
|
---@property offsetY number 0 Vertical content offset
|
||||||
|
Container.defineProperty(Container, "offsetY", {default = 0, type = "number", canTriggerRender = true, setter=function(self, value)
|
||||||
|
self.set("childrenSorted", false)
|
||||||
|
self.set("childrenEventsSorted", false)
|
||||||
|
return value
|
||||||
|
end})
|
||||||
|
|
||||||
for k, _ in pairs(elementManager:getElementList()) do
|
for k, _ in pairs(elementManager:getElementList()) do
|
||||||
local capitalizedName = k:sub(1,1):upper() .. k:sub(2)
|
local capitalizedName = k:sub(1,1):upper() .. k:sub(2)
|
||||||
if capitalizedName ~= "BaseFrame" then
|
if capitalizedName ~= "BaseFrame" then
|
||||||
@@ -87,14 +100,26 @@ end
|
|||||||
--- @param child table The child to check
|
--- @param child table The child to check
|
||||||
--- @return boolean boolean the child is visible
|
--- @return boolean boolean the child is visible
|
||||||
function Container:isChildVisible(child)
|
function Container:isChildVisible(child)
|
||||||
|
local containerW, containerH = self.get("width"), self.get("height")
|
||||||
|
local offsetX, offsetY = self.get("offsetX"), self.get("offsetY")
|
||||||
|
|
||||||
local childX, childY = child.get("x"), child.get("y")
|
local childX, childY = child.get("x"), child.get("y")
|
||||||
local childW, childH = child.get("width"), child.get("height")
|
local childW, childH = child.get("width"), child.get("height")
|
||||||
local containerW, containerH = self.get("width"), self.get("height")
|
|
||||||
|
|
||||||
return childX <= containerW and
|
local relativeX
|
||||||
childY <= containerH and
|
local relativeY
|
||||||
childX + childW > 0 and
|
if(child.get("ignoreOffset"))then
|
||||||
childY + childH > 0
|
relativeX = childX
|
||||||
|
relativeY = childY
|
||||||
|
else
|
||||||
|
relativeX = childX - offsetX
|
||||||
|
relativeY = childY - offsetY
|
||||||
|
end
|
||||||
|
|
||||||
|
return (relativeX + childW > 0) and
|
||||||
|
(relativeX <= containerW) and
|
||||||
|
(relativeY + childH > 0) and
|
||||||
|
(relativeY <= containerH)
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Adds a child to the container
|
--- Adds a child to the container
|
||||||
@@ -115,7 +140,7 @@ end
|
|||||||
|
|
||||||
local function sortAndFilterChildren(self, children)
|
local function sortAndFilterChildren(self, children)
|
||||||
local visibleChildren = {}
|
local visibleChildren = {}
|
||||||
|
|
||||||
for _, child in ipairs(children) do
|
for _, child in ipairs(children) do
|
||||||
if self:isChildVisible(child) and child.get("visible") then
|
if self:isChildVisible(child) and child.get("visible") then
|
||||||
table.insert(visibleChildren, child)
|
table.insert(visibleChildren, child)
|
||||||
@@ -295,7 +320,8 @@ local function convertMousePosition(self, event, ...)
|
|||||||
local args = {...}
|
local args = {...}
|
||||||
if event:find("mouse_") then
|
if event:find("mouse_") then
|
||||||
local button, absX, absY = ...
|
local button, absX, absY = ...
|
||||||
local relX, relY = self:getRelativePosition(absX, absY)
|
local xOffset, yOffset = self.get("offsetX"), self.get("offsetY")
|
||||||
|
local relX, relY = self:getRelativePosition(absX + xOffset, absY + yOffset)
|
||||||
args = {button, relX, relY}
|
args = {button, relX, relY}
|
||||||
end
|
end
|
||||||
return args
|
return args
|
||||||
@@ -308,7 +334,7 @@ function Container:callChildrenEvents(visibleOnly, event, ...)
|
|||||||
for i = #events, 1, -1 do
|
for i = #events, 1, -1 do
|
||||||
local child = events[i]
|
local child = events[i]
|
||||||
if(child:dispatchEvent(event, ...))then
|
if(child:dispatchEvent(event, ...))then
|
||||||
return true, child
|
return true, child
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -447,7 +473,7 @@ end
|
|||||||
--- @return Container self The container instance
|
--- @return Container self The container instance
|
||||||
function Container:multiBlit(x, y, width, height, text, fg, bg)
|
function Container:multiBlit(x, y, width, height, text, fg, bg)
|
||||||
local w, h = self.get("width"), self.get("height")
|
local w, h = self.get("width"), self.get("height")
|
||||||
|
|
||||||
width = x < 1 and math.min(width + x - 1, w) or math.min(width, math.max(0, w - x + 1))
|
width = x < 1 and math.min(width + x - 1, w) or math.min(width, math.max(0, w - x + 1))
|
||||||
height = y < 1 and math.min(height + y - 1, h) or math.min(height, math.max(0, h - y + 1))
|
height = y < 1 and math.min(height + y - 1, h) or math.min(height, math.max(0, h - y + 1))
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
local elementManager = require("elementManager")
|
local elementManager = require("elementManager")
|
||||||
local VisualElement = elementManager.getElement("VisualElement")
|
local VisualElement = elementManager.getElement("VisualElement")
|
||||||
|
local wrapText = require("libraries/utils").wrapText
|
||||||
|
|
||||||
--- This is the label class. It provides a simple text display element that automatically
|
--- This is the label class. It provides a simple text display element that automatically
|
||||||
--- resizes its width based on the text content.
|
--- resizes its width based on the text content.
|
||||||
@@ -8,9 +9,23 @@ local Label = setmetatable({}, VisualElement)
|
|||||||
Label.__index = Label
|
Label.__index = Label
|
||||||
|
|
||||||
---@property text string Label The text content to display. Can be a string or a function that returns a string
|
---@property text string Label The text content to display. Can be a string or a function that returns a string
|
||||||
Label.defineProperty(Label, "text", {default = "Label", type = "string", setter = function(self, value)
|
Label.defineProperty(Label, "text", {default = "Label", type = "string", canTriggerRender = true, setter = function(self, value)
|
||||||
if(type(value)=="function")then value = value() end
|
if(type(value)=="function")then value = value() end
|
||||||
self.set("width", #value)
|
if(self.get("autoSize"))then
|
||||||
|
self.set("width", #value)
|
||||||
|
else
|
||||||
|
self.set("height", #wrapText(value, self.get("width")))
|
||||||
|
end
|
||||||
|
return value
|
||||||
|
end})
|
||||||
|
|
||||||
|
---@property autoSize boolean true Whether the label should automatically resize its width based on the text content
|
||||||
|
Label.defineProperty(Label, "autoSize", {default = true, type = "boolean", canTriggerRender = true, setter = function(self, value)
|
||||||
|
if(value)then
|
||||||
|
self.set("width", #self.get("text"))
|
||||||
|
else
|
||||||
|
self.set("height", #wrapText(self.get("text"), self.get("width")))
|
||||||
|
end
|
||||||
return value
|
return value
|
||||||
end})
|
end})
|
||||||
|
|
||||||
@@ -37,12 +52,28 @@ function Label:init(props, basalt)
|
|||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
|
--- Gets the wrapped lines of the Label
|
||||||
|
--- @shortDescription Gets the wrapped lines of the Label
|
||||||
|
--- @return table wrappedText The wrapped lines of the Label
|
||||||
|
function Label:getWrappedText()
|
||||||
|
local text = self.get("text")
|
||||||
|
local wrappedText = wrapText(text, self.get("width"))
|
||||||
|
return wrappedText
|
||||||
|
end
|
||||||
|
|
||||||
--- Renders the Label
|
--- Renders the Label
|
||||||
--- @shortDescription Renders the Label by drawing its text content
|
--- @shortDescription Renders the Label by drawing its text content
|
||||||
function Label:render()
|
function Label:render()
|
||||||
VisualElement.render(self)
|
VisualElement.render(self)
|
||||||
local text = self.get("text")
|
local text = self.get("text")
|
||||||
self:textFg(1, 1, text, self.get("foreground"))
|
if(self.get("autoSize"))then
|
||||||
|
self:textFg(1, 1, text, self.get("foreground"))
|
||||||
|
else
|
||||||
|
local wrappedText = wrapText(text, self.get("width"))
|
||||||
|
for i, line in ipairs(wrappedText) do
|
||||||
|
self:textFg(1, i, line, self.get("foreground"))
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return Label
|
return Label
|
||||||
@@ -29,6 +29,7 @@ function List.new()
|
|||||||
local self = setmetatable({}, List):__init()
|
local self = setmetatable({}, List):__init()
|
||||||
self.set("width", 16)
|
self.set("width", 16)
|
||||||
self.set("height", 8)
|
self.set("height", 8)
|
||||||
|
self.set("z", 5)
|
||||||
self.set("background", colors.gray)
|
self.set("background", colors.gray)
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@@ -41,6 +42,7 @@ end
|
|||||||
function List:init(props, basalt)
|
function List:init(props, basalt)
|
||||||
VisualElement.init(self, props, basalt)
|
VisualElement.init(self, props, basalt)
|
||||||
self.set("type", "List")
|
self.set("type", "List")
|
||||||
|
return self
|
||||||
end
|
end
|
||||||
|
|
||||||
--- Adds an item to the list
|
--- Adds an item to the list
|
||||||
|
|||||||
@@ -64,6 +64,9 @@ VisualElement.defineProperty(VisualElement, "visible", {default = true, type = "
|
|||||||
return value
|
return value
|
||||||
end})
|
end})
|
||||||
|
|
||||||
|
---@property ignoreOffset boolean false Whether to ignore the parent's offset
|
||||||
|
VisualElement.defineProperty(VisualElement, "ignoreOffset", {default = false, type = "boolean"})
|
||||||
|
|
||||||
---@combinedProperty position {x y} Combined x, y position
|
---@combinedProperty position {x y} Combined x, y position
|
||||||
VisualElement.combineProperties(VisualElement, "position", "x", "y")
|
VisualElement.combineProperties(VisualElement, "position", "x", "y")
|
||||||
---@combinedProperty size {width height} Combined width, height
|
---@combinedProperty size {width height} Combined width, height
|
||||||
@@ -85,6 +88,7 @@ VisualElement.listenTo(VisualElement, "focus")
|
|||||||
VisualElement.listenTo(VisualElement, "blur")
|
VisualElement.listenTo(VisualElement, "blur")
|
||||||
VisualElement.listenTo(VisualElement, "mouse_enter", "mouse_move")
|
VisualElement.listenTo(VisualElement, "mouse_enter", "mouse_move")
|
||||||
VisualElement.listenTo(VisualElement, "mouse_leave", "mouse_move")
|
VisualElement.listenTo(VisualElement, "mouse_leave", "mouse_move")
|
||||||
|
VisualElement.listenTo(VisualElement, "mouse_scroll")
|
||||||
|
|
||||||
local max, min = math.max, math.min
|
local max, min = math.max, math.min
|
||||||
|
|
||||||
@@ -112,8 +116,9 @@ end
|
|||||||
--- @shortDescription Multi-character drawing with colors
|
--- @shortDescription Multi-character drawing with colors
|
||||||
---@protected
|
---@protected
|
||||||
function VisualElement:multiBlit(x, y, width, height, text, fg, bg)
|
function VisualElement:multiBlit(x, y, width, height, text, fg, bg)
|
||||||
x = x + self.get("x") - 1
|
local xElement, yElement = self:calculatePosition()
|
||||||
y = y + self.get("y") - 1
|
x = x + xElement - 1
|
||||||
|
y = y + yElement - 1
|
||||||
self.parent:multiBlit(x, y, width, height, text, fg, bg)
|
self.parent:multiBlit(x, y, width, height, text, fg, bg)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -124,8 +129,9 @@ end
|
|||||||
--- @param text string The text char to draw
|
--- @param text string The text char to draw
|
||||||
--- @param fg color The foreground color
|
--- @param fg color The foreground color
|
||||||
function VisualElement:textFg(x, y, text, fg)
|
function VisualElement:textFg(x, y, text, fg)
|
||||||
x = x + self.get("x") - 1
|
local xElement, yElement = self:calculatePosition()
|
||||||
y = y + self.get("y") - 1
|
x = x + xElement - 1
|
||||||
|
y = y + yElement - 1
|
||||||
self.parent:textFg(x, y, text, fg)
|
self.parent:textFg(x, y, text, fg)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -136,8 +142,9 @@ end
|
|||||||
--- @param text string The text char to draw
|
--- @param text string The text char to draw
|
||||||
--- @param bg color The background color
|
--- @param bg color The background color
|
||||||
function VisualElement:textBg(x, y, text, bg)
|
function VisualElement:textBg(x, y, text, bg)
|
||||||
x = x + self.get("x") - 1
|
local xElement, yElement = self:calculatePosition()
|
||||||
y = y + self.get("y") - 1
|
x = x + xElement - 1
|
||||||
|
y = y + yElement - 1
|
||||||
self.parent:textBg(x, y, text, bg)
|
self.parent:textBg(x, y, text, bg)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -149,8 +156,9 @@ end
|
|||||||
--- @param fg string The foreground color
|
--- @param fg string The foreground color
|
||||||
--- @param bg string The background color
|
--- @param bg string The background color
|
||||||
function VisualElement:blit(x, y, text, fg, bg)
|
function VisualElement:blit(x, y, text, fg, bg)
|
||||||
x = x + self.get("x") - 1
|
local xElement, yElement = self:calculatePosition()
|
||||||
y = y + self.get("y") - 1
|
x = x + xElement - 1
|
||||||
|
y = y + yElement - 1
|
||||||
self.parent:blit(x, y, text, fg, bg)
|
self.parent:blit(x, y, text, fg, bg)
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -162,6 +170,12 @@ end
|
|||||||
function VisualElement:isInBounds(x, y)
|
function VisualElement:isInBounds(x, y)
|
||||||
local xPos, yPos = self.get("x"), self.get("y")
|
local xPos, yPos = self.get("x"), self.get("y")
|
||||||
local width, height = self.get("width"), self.get("height")
|
local width, height = self.get("width"), self.get("height")
|
||||||
|
if(self.get("ignoreOffset"))then
|
||||||
|
if(self.parent)then
|
||||||
|
x = x - self.parent.get("offsetX")
|
||||||
|
y = y - self.parent.get("offsetY")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
return x >= xPos and x <= xPos + width - 1 and
|
return x >= xPos and x <= xPos + width - 1 and
|
||||||
y >= yPos and y <= yPos + height - 1
|
y >= yPos and y <= yPos + height - 1
|
||||||
@@ -256,6 +270,18 @@ function VisualElement:blur()
|
|||||||
self:setCursor(1,1, false)
|
self:setCursor(1,1, false)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function VisualElement:calculatePosition()
|
||||||
|
local x, y = self.get("x"), self.get("y")
|
||||||
|
if not self.get("ignoreOffset") then
|
||||||
|
if self.parent ~= nil then
|
||||||
|
local xO, yO = self.parent.get("offsetX"), self.parent.get("offsetY")
|
||||||
|
x = x - xO
|
||||||
|
y = y - yO
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return x, y
|
||||||
|
end
|
||||||
|
|
||||||
--- Returns the absolute position of the element or the given coordinates.
|
--- Returns the absolute position of the element or the given coordinates.
|
||||||
--- @shortDescription Returns the absolute position of the element
|
--- @shortDescription Returns the absolute position of the element
|
||||||
---@param x? number x position
|
---@param x? number x position
|
||||||
@@ -295,9 +321,7 @@ function VisualElement:getRelativePosition(x, y)
|
|||||||
parentX, parentY = self.parent:getRelativePosition()
|
parentX, parentY = self.parent:getRelativePosition()
|
||||||
end
|
end
|
||||||
|
|
||||||
local elementX = self.get("x")
|
local elementX, elementY = self.get("x"), self.get("y")
|
||||||
local elementY = self.get("y")
|
|
||||||
|
|
||||||
return x - (elementX - 1) - (parentX - 1),
|
return x - (elementX - 1) - (parentX - 1),
|
||||||
y - (elementY - 1) - (parentY - 1)
|
y - (elementY - 1) - (parentY - 1)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -47,25 +47,61 @@ function utils.uuid()
|
|||||||
math.random(0, 0xffff), math.random(0, 0xffff), math.random(0, 0xffff))
|
math.random(0, 0xffff), math.random(0, 0xffff), math.random(0, 0xffff))
|
||||||
end
|
end
|
||||||
|
|
||||||
function utils.split(str, sep)
|
function utils.split(str, delimiter)
|
||||||
local parts = {}
|
local result = {}
|
||||||
local start = 1
|
for match in (str..delimiter):gmatch("(.-)"..delimiter) do
|
||||||
local len = len(str)
|
table.insert(result, match)
|
||||||
local splitIndex = 1
|
end
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
while true do
|
function utils.removeTags(input)
|
||||||
local index = str:find(sep, start, true)
|
return input:gsub("{[^}]+}", "")
|
||||||
if not index then
|
end
|
||||||
parts[splitIndex] = str:sub(start, len)
|
|
||||||
break
|
function utils.wrapText(str, width)
|
||||||
|
if str == nil then return {} end
|
||||||
|
str = utils.removeTags(str)
|
||||||
|
local lines = {}
|
||||||
|
|
||||||
|
local paragraphs = utils.split(str, "\n\n")
|
||||||
|
|
||||||
|
for i, paragraph in ipairs(paragraphs) do
|
||||||
|
if #paragraph == 0 then
|
||||||
|
table.insert(lines, "")
|
||||||
|
if i < #paragraphs then
|
||||||
|
table.insert(lines, "")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local textLines = utils.split(paragraph, "\n")
|
||||||
|
|
||||||
|
for _, line in ipairs(textLines) do
|
||||||
|
local words = utils.split(line, " ")
|
||||||
|
local currentLine = ""
|
||||||
|
|
||||||
|
for _, word in ipairs(words) do
|
||||||
|
if #currentLine == 0 then
|
||||||
|
currentLine = word
|
||||||
|
elseif #currentLine + #word + 1 <= width then
|
||||||
|
currentLine = currentLine .. " " .. word
|
||||||
|
else
|
||||||
|
table.insert(lines, currentLine)
|
||||||
|
currentLine = word
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if #currentLine > 0 then
|
||||||
|
table.insert(lines, currentLine)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if i < #paragraphs then
|
||||||
|
table.insert(lines, "")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
parts[splitIndex] = str:sub(start, index - 1)
|
|
||||||
start = index + 1
|
|
||||||
splitIndex = splitIndex + 1
|
|
||||||
end
|
end
|
||||||
|
|
||||||
return parts
|
return lines
|
||||||
end
|
end
|
||||||
|
|
||||||
return utils
|
return utils
|
||||||
@@ -48,7 +48,7 @@ function AnimationInstance.new(element, animType, args, duration, easing)
|
|||||||
self.element = element
|
self.element = element
|
||||||
self.type = animType
|
self.type = animType
|
||||||
self.args = args
|
self.args = args
|
||||||
self.duration = duration
|
self.duration = duration or 1
|
||||||
self.startTime = 0
|
self.startTime = 0
|
||||||
self.isPaused = false
|
self.isPaused = false
|
||||||
self.handlers = registeredAnimations[animType]
|
self.handlers = registeredAnimations[animType]
|
||||||
@@ -288,6 +288,26 @@ Animation.registerAnimation("move", {
|
|||||||
end
|
end
|
||||||
})
|
})
|
||||||
|
|
||||||
|
Animation.registerAnimation("moveOffset", {
|
||||||
|
start = function(anim)
|
||||||
|
anim.startX = anim.element.get("offsetX")
|
||||||
|
anim.startY = anim.element.get("offsetY")
|
||||||
|
end,
|
||||||
|
|
||||||
|
update = function(anim, progress)
|
||||||
|
local x = anim.startX + (anim.args[1] - anim.startX) * progress
|
||||||
|
local y = anim.startY + (anim.args[2] - anim.startY) * progress
|
||||||
|
anim.element.set("offsetX", math.floor(x))
|
||||||
|
anim.element.set("offsetY", math.floor(y))
|
||||||
|
return progress >= 1
|
||||||
|
end,
|
||||||
|
|
||||||
|
complete = function(anim)
|
||||||
|
anim.element.set("offsetX", anim.args[1])
|
||||||
|
anim.element.set("offsetY", anim.args[2])
|
||||||
|
end
|
||||||
|
})
|
||||||
|
|
||||||
Animation.registerAnimation("morphText", {
|
Animation.registerAnimation("morphText", {
|
||||||
start = function(anim)
|
start = function(anim)
|
||||||
local startText = anim.element.get(anim.args[1])
|
local startText = anim.element.get(anim.args[1])
|
||||||
@@ -384,12 +404,12 @@ function VisualElement.hooks.dispatchEvent(self, event, ...)
|
|||||||
if animation then
|
if animation then
|
||||||
animation:event(event, ...)
|
animation:event(event, ...)
|
||||||
end
|
end
|
||||||
|
return true
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
---@private
|
---@private
|
||||||
function VisualElement.setup(element)
|
function VisualElement.setup(element)
|
||||||
VisualElementBaseDispatchEvent = element.dispatchEvent
|
|
||||||
element.defineProperty(element, "animation", {default = nil, type = "table"})
|
element.defineProperty(element, "animation", {default = nil, type = "table"})
|
||||||
element.listenTo(element, "timer")
|
element.listenTo(element, "timer")
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -313,6 +313,11 @@ function API.start(name, options)
|
|||||||
profile.name = name
|
profile.name = name
|
||||||
profile.startTime = os.clock() * 1000
|
profile.startTime = os.clock() * 1000
|
||||||
profile.custom = true
|
profile.custom = true
|
||||||
|
profile.calls = 0
|
||||||
|
profile.totalTime = 0
|
||||||
|
profile.minTime = math.huge
|
||||||
|
profile.maxTime = 0
|
||||||
|
profile.lastTime = 0
|
||||||
activeProfiles[name] = profile
|
activeProfiles[name] = profile
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ local function parseExpression(expr, element, propName)
|
|||||||
elseif objName == "parent" then
|
elseif objName == "parent" then
|
||||||
return element.parent.get(propName)
|
return element.parent.get(propName)
|
||||||
else
|
else
|
||||||
local target = element:getBaseFrame():getChild(objName)
|
local target = element.parent:getChild(objName)
|
||||||
if not target then
|
if not target then
|
||||||
errorManager.header = "Reactive evaluation error"
|
errorManager.header = "Reactive evaluation error"
|
||||||
errorManager.error("Could not find element: " .. objName)
|
errorManager.error("Could not find element: " .. objName)
|
||||||
@@ -103,7 +103,7 @@ local function validateReferences(expr, element)
|
|||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
local target = element:getBaseFrame():getChild(ref)
|
local target = element.parent:getChild(ref)
|
||||||
if not target then
|
if not target then
|
||||||
errorManager.header = "Reactive evaluation error"
|
errorManager.header = "Reactive evaluation error"
|
||||||
errorManager.error("Referenced element not found: " .. ref)
|
errorManager.error("Referenced element not found: " .. ref)
|
||||||
|
|||||||
@@ -91,7 +91,6 @@ function Render:multiBlit(x, y, width, height, text, fg, bg)
|
|||||||
if(#text ~= #fg or #text ~= #bg)then
|
if(#text ~= #fg or #text ~= #bg)then
|
||||||
error("Text, fg, and bg must be the same length")
|
error("Text, fg, and bg must be the same length")
|
||||||
end
|
end
|
||||||
|
|
||||||
text = text:rep(width)
|
text = text:rep(width)
|
||||||
fg = fg:rep(width)
|
fg = fg:rep(width)
|
||||||
bg = bg:rep(width)
|
bg = bg:rep(width)
|
||||||
@@ -119,7 +118,6 @@ function Render:textFg(x, y, text, fg)
|
|||||||
if y < 1 or y > self.height then return self end
|
if y < 1 or y > self.height then return self end
|
||||||
fg = colorChars[fg] or "0"
|
fg = colorChars[fg] or "0"
|
||||||
fg = fg:rep(#text)
|
fg = fg:rep(#text)
|
||||||
|
|
||||||
self.buffer.text[y] = sub(self.buffer.text[y]:sub(1,x-1) .. text .. self.buffer.text[y]:sub(x+#text), 1, self.width)
|
self.buffer.text[y] = sub(self.buffer.text[y]:sub(1,x-1) .. text .. self.buffer.text[y]:sub(x+#text), 1, self.width)
|
||||||
self.buffer.fg[y] = sub(self.buffer.fg[y]:sub(1,x-1) .. fg .. self.buffer.fg[y]:sub(x+#fg), 1, self.width)
|
self.buffer.fg[y] = sub(self.buffer.fg[y]:sub(1,x-1) .. fg .. self.buffer.fg[y]:sub(x+#fg), 1, self.width)
|
||||||
self:addDirtyRect(x, y, #text, 1)
|
self:addDirtyRect(x, y, #text, 1)
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
local customElements = {}
|
||||||
|
local customPlugins = {}
|
||||||
|
|
||||||
local function serialize(t, indent)
|
local function serialize(t, indent)
|
||||||
indent = indent or ""
|
indent = indent or ""
|
||||||
local result = "{\n"
|
local result = "{\n"
|
||||||
@@ -22,14 +25,76 @@ local function serialize(t, indent)
|
|||||||
return result .. indent .. "}"
|
return result .. indent .. "}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
local function extractConfigDescription(filePath)
|
||||||
|
local f = io.open(filePath, "r")
|
||||||
|
if not f then return nil end
|
||||||
|
|
||||||
|
local content = f:read("*all")
|
||||||
|
f:close()
|
||||||
|
|
||||||
|
return content:match("%-%-%-@configDescription%s*(.-)%s*[\n\r]") or "No description available"
|
||||||
|
end
|
||||||
|
|
||||||
|
local function categorizeFile(path)
|
||||||
|
if path:match("^src/elements/") then
|
||||||
|
return "elements", "UI Elements"
|
||||||
|
elseif path:match("^src/plugins/") then
|
||||||
|
return "plugins", "Plugins and Extensions"
|
||||||
|
elseif path:match("^src/libraries/") then
|
||||||
|
return "libraries", "Utility Libraries"
|
||||||
|
elseif path:match("^src/[^/]+%.lua$") then
|
||||||
|
return "core", "Core Framework Files"
|
||||||
|
else
|
||||||
|
return "other", "Other Files"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local function sortFiles(files)
|
||||||
|
local categories = {}
|
||||||
|
for path, info in pairs(files) do
|
||||||
|
local category, categoryDesc = categorizeFile(path)
|
||||||
|
if not categories[category] then
|
||||||
|
categories[category] = {
|
||||||
|
description = categoryDesc,
|
||||||
|
files = {}
|
||||||
|
}
|
||||||
|
end
|
||||||
|
table.insert(categories[category].files, {
|
||||||
|
path = path,
|
||||||
|
name = info.name,
|
||||||
|
description = info.description
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, cat in pairs(categories) do
|
||||||
|
table.sort(cat.files, function(a, b)
|
||||||
|
return a.name < b.name
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
|
return categories
|
||||||
|
end
|
||||||
|
|
||||||
local function scanDir(dir)
|
local function scanDir(dir)
|
||||||
local files = {}
|
local files = {}
|
||||||
for file in io.popen('find "'..dir..'" -type f -name "*.lua"'):lines() do
|
for file in io.popen('find "'..dir..'" -maxdepth 1 -type f -name "*.lua"'):lines() do
|
||||||
local name = file:match("([^/]+)%.lua$")
|
local name = file:match("([^/]+)%.lua$")
|
||||||
if name then
|
if name then
|
||||||
files[file] = {
|
files[file] = {
|
||||||
name = name,
|
name = name,
|
||||||
path = file:gsub("^src/", ""),
|
path = file:gsub("^src/", ""),
|
||||||
|
description = extractConfigDescription(file)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
for file in io.popen('find "'..dir..'/elements" "'..dir..'/plugins" "'..dir..'/libraries" -type f -name "*.lua"'):lines() do
|
||||||
|
local name = file:match("([^/]+)%.lua$")
|
||||||
|
if name then
|
||||||
|
files[file] = {
|
||||||
|
name = name,
|
||||||
|
path = file:gsub("^src/", ""),
|
||||||
|
description = extractConfigDescription(file)
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -37,8 +102,14 @@ local function scanDir(dir)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local sourceFiles = scanDir("src")
|
local sourceFiles = scanDir("src")
|
||||||
|
local categories = sortFiles(sourceFiles)
|
||||||
|
|
||||||
local config = {
|
local config = {
|
||||||
files = sourceFiles,
|
categories = categories,
|
||||||
|
metadata = {
|
||||||
|
generated = os.date(),
|
||||||
|
version = "2.0"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
local f = io.open("config.lua", "w")
|
local f = io.open("config.lua", "w")
|
||||||
|
|||||||
Reference in New Issue
Block a user