Lots of shit

This commit is contained in:
2025-06-02 10:23:40 +03:00
parent f1b31c5c3e
commit 42b7d798e1
68 changed files with 11580 additions and 516 deletions

View File

@@ -0,0 +1,47 @@
local XMLParser = require("xmlParser")
return {
VisualObject = function(base)
local bgSymbol = false
local bgSymbolColor = colors.black
local object = {
setBackground = function(self, bg, symbol, symbolCol)
base.setBackground(self, bg)
bgSymbol = symbol or bgSymbol
bgSymbolColor = symbolCol or bgSymbolColor
return self
end,
setBackgroundSymbol = function(self, symbol, symbolCol)
bgSymbol = symbol
bgSymbolColor = symbolCol or bgSymbolColor
self:updateDraw()
return self
end,
getBackgroundSymbol = function(self)
return bgSymbol
end,
getBackgroundSymbolColor = function(self)
return bgSymbolColor
end,
draw = function(self)
base.draw(self)
self:addDraw("advanced-bg", function()
local w, h = self:getSize()
if(bgSymbol~=false)then
self:addTextBox(1, 1, w, h, bgSymbol:sub(1,1))
if(bgSymbol~=" ")then
self:addForegroundBox(1, 1, w, h, bgSymbolColor)
end
end
end, 2)
end
}
return object
end
}

View File

@@ -0,0 +1,344 @@
local floor,sin,cos,pi,sqrt,pow = math.floor,math.sin,math.cos,math.pi,math.sqrt,math.pow
-- You can find the easing curves here https://easings.net
local function lerp(s, e, pct)
return s + (e - s) * pct
end
local function linear(t)
return t
end
local function flip(t)
return 1 - t
end
local function easeIn(t)
return t * t * t
end
local function easeOut(t)
return flip(easeIn(flip(t)))
end
local function easeInOut(t)
return lerp(easeIn(t), easeOut(t), t)
end
local function easeOutSine(t)
return sin((t * pi) / 2);
end
local function easeInSine(t)
return flip(cos((t * pi) / 2))
end
local function easeInOutSine(t)
return -(cos(pi * x) - 1) / 2
end
local function easeInBack(t)
local c1 = 1.70158;
local c3 = c1 + 1
return c3*t^3-c1*t^2
end
local function easeInCubic(t)
return t^3
end
local function easeInElastic(t)
local c4 = (2*pi)/3;
return t == 0 and 0 or (t == 1 and 1 or (
-2^(10*t-10)*sin((t*10-10.75)*c4)
))
end
local function easeInExpo(t)
return t == 0 and 0 or 2^(10*t-10)
end
local function easeInExpo(t)
return t == 0 and 0 or 2^(10*t-10)
end
local function easeInOutBack(t)
local c1 = 1.70158;
local c2 = c1 * 1.525;
return t < 0.5 and ((2*t)^2*((c2+1)*2*t-c2))/2 or ((2*t-2)^2*((c2+1)*(t*2-2)+c2)+2)/2
end
local function easeInOutCubic(t)
return t < 0.5 and 4 * t^3 or 1-(-2*t+2)^3 / 2
end
local function easeInOutElastic(t)
local c5 = (2*pi) / 4.5
return t==0 and 0 or (t == 1 and 1 or (t < 0.5 and -(2^(20*t-10) * sin((20*t - 11.125) * c5))/2 or (2^(-20*t+10) * sin((20*t - 11.125) * c5))/2 + 1))
end
local function easeInOutExpo(t)
return t == 0 and 0 or (t == 1 and 1 or (t < 0.5 and 2^(20*t-10)/2 or (2-2^(-20*t+10)) /2))
end
local function easeInOutQuad(t)
return t < 0.5 and 2*t^2 or 1-(-2*t+2)^2/2
end
local function easeInOutQuart(t)
return t < 0.5 and 8*t^4 or 1 - (-2*t+2)^4 / 2
end
local function easeInOutQuint(t)
return t < 0.5 and 16*t^5 or 1-(-2*t+2)^5 / 2
end
local function easeInQuad(t)
return t^2
end
local function easeInQuart(t)
return t^4
end
local function easeInQuint(t)
return t^5
end
local function easeOutBack(t)
local c1 = 1.70158;
local c3 = c1 + 1
return 1+c3*(t-1)^3+c1*(t-1)^2
end
local function easeOutCubic(t)
return 1 - (1-t)^3
end
local function easeOutElastic(t)
local c4 = (2*pi)/3;
return t == 0 and 0 or (t == 1 and 1 or (2^(-10*t)*sin((t*10-0.75)*c4)+1))
end
local function easeOutExpo(t)
return t == 1 and 1 or 1-2^(-10*t)
end
local function easeOutQuad(t)
return 1 - (1 - t) * (1 - t)
end
local function easeOutQuart(t)
return 1 - (1-t)^4
end
local function easeOutQuint(t)
return 1 - (1 - t)^5
end
local function easeInCirc(t)
return 1 - sqrt(1 - pow(t, 2))
end
local function easeOutCirc(t)
return sqrt(1 - pow(t - 1, 2))
end
local function easeInOutCirc(t)
return t < 0.5 and (1 - sqrt(1 - pow(2 * t, 2))) / 2 or (sqrt(1 - pow(-2 * t + 2, 2)) + 1) / 2;
end
local function easeOutBounce(t)
local n1 = 7.5625;
local d1 = 2.75;
if (t < 1 / d1)then
return n1 * t * t
elseif (t < 2 / d1)then
local a = t - 1.5 / d1
return n1 * a * a + 0.75;
elseif (t < 2.5 / d1)then
local a = t - 2.25 / d1
return n1 * a * a + 0.9375;
else
local a = t - 2.625 / d1
return n1 * a * a + 0.984375;
end
end
local function easeInBounce(t)
return 1 - easeOutBounce(1 - t)
end
local function easeInOutBounce(t)
return x < 0.5 and (1 - easeOutBounce(1 - 2 * t)) / 2 or (1 + easeOutBounce(2 * t - 1)) / 2;
end
local lerp = {
linear = linear,
lerp = lerp,
flip=flip,
easeIn=easeIn,
easeInSine = easeInSine,
easeInBack=easeInBack,
easeInCubic=easeInCubic,
easeInElastic=easeInElastic,
easeInExpo=easeInExpo,
easeInQuad=easeInQuad,
easeInQuart=easeInQuart,
easeInQuint=easeInQuint,
easeInCirc=easeInCirc,
easeInBounce=easeInBounce,
easeOut=easeOut,
easeOutSine = easeOutSine,
easeOutBack=easeOutBack,
easeOutCubic=easeOutCubic,
easeOutElastic=easeOutElastic,
easeOutExpo=easeOutExpo,
easeOutQuad=easeOutQuad,
easeOutQuart=easeOutQuart,
easeOutQuint=easeOutQuint,
easeOutCirc=easeOutCirc,
easeOutBounce=easeOutBounce,
easeInOut=easeInOut,
easeInOutSine = easeInOutSine,
easeInOutBack=easeInOutBack,
easeInOutCubic=easeInOutCubic,
easeInOutElastic=easeInOutElastic,
easeInOutExpo=easeInOutExpo,
easeInOutQuad=easeInOutQuad,
easeInOutQuart=easeInOutQuart,
easeInOutQuint=easeInOutQuint,
easeInOutCirc=easeInOutCirc,
easeInOutBounce=easeInOutBounce,
}
local XMLParser = require("xmlParser")
return {
VisualObject = function(base, basalt)
local activeAnimations = {}
local defaultMode = "linear"
local function getAnimation(self, timerId)
for k,v in pairs(activeAnimations)do
if(v.timerId==timerId)then
return v
end
end
end
local function createAnimation(self, v1, v2, duration, timeOffset, mode, typ, f, get, set)
local v1Val, v2Val = get(self)
if(activeAnimations[typ]~=nil)then
os.cancelTimer(activeAnimations[typ].timerId)
end
activeAnimations[typ] = {}
activeAnimations[typ].call = function()
local progress = activeAnimations[typ].progress
local _v1 = math.floor(lerp.lerp(v1Val, v1, lerp[mode](progress / duration))+0.5)
local _v2 = math.floor(lerp.lerp(v2Val, v2, lerp[mode](progress / duration))+0.5)
set(self, _v1, _v2)
end
activeAnimations[typ].finished = function()
set(self, v1, v2)
if(f~=nil)then f(self) end
end
activeAnimations[typ].timerId=os.startTimer(0.05+timeOffset)
activeAnimations[typ].progress=0
activeAnimations[typ].duration=duration
activeAnimations[typ].mode=mode
self:listenEvent("other_event")
end
local function createColorAnimation(self, duration, timeOffset, typ, set, ...)
local newColors = {...}
if(activeAnimations[typ]~=nil)then
os.cancelTimer(activeAnimations[typ].timerId)
end
activeAnimations[typ] = {}
local colorIndex = 1
activeAnimations[typ].call = function()
local color = newColors[colorIndex]
set(self, color)
end
end
local object = {
animatePosition = function(self, x, y, duration, timeOffset, mode, f)
mode = mode or defaultMode
duration = duration or 1
timeOffset = timeOffset or 0
x = math.floor(x+0.5)
y = math.floor(y+0.5)
createAnimation(self, x, y, duration, timeOffset, mode, "position", f, self.getPosition, self.setPosition)
return self
end,
animateSize = function(self, w, h, duration, timeOffset, mode, f)
mode = mode or defaultMode
duration = duration or 1
timeOffset = timeOffset or 0
createAnimation(self, w, h, duration, timeOffset, mode, "size", f, self.getSize, self.setSize)
return self
end,
animateOffset = function(self, x, y, duration, timeOffset, mode, f)
mode = mode or defaultMode
duration = duration or 1
timeOffset = timeOffset or 0
createAnimation(self, x, y, duration, timeOffset, mode, "offset", f, self.getOffset, self.setOffset)
return self
end,
animateBackground = function(self, color, duration, timeOffset, mode, f)
mode = mode or defaultMode
duration = duration or 1
timeOffset = timeOffset or 0
createColorAnimation(self, color, nil, duration, timeOffset, mode, "background", f, self.getBackground, self.setBackground)
return self
end,
doneHandler = function(self, timerId, ...)
for k,v in pairs(activeAnimations)do
if(v.timerId==timerId)then
activeAnimations[k] = nil
self:sendEvent("animation_done", self, "animation_done", k)
end
end
end,
onAnimationDone = function(self, ...)
for _,v in pairs(table.pack(...))do
if(type(v)=="function")then
self:registerEvent("animation_done", v)
end
end
return self
end,
eventHandler = function(self, event, timerId, ...)
base.eventHandler(self, event, timerId, ...)
if(event=="timer")then
local animation = getAnimation(self, timerId)
if(animation~=nil)then
if(animation.progress<animation.duration)then
animation.call()
animation.progress = animation.progress+0.05
animation.timerId=os.startTimer(0.05)
else
animation.finished()
self:doneHandler(timerId)
end
end
end
end
}
return object
end
}

View File

@@ -0,0 +1,10 @@
return {
basalt = function()
return {
cool = function()
print("ello")
sleep(2)
end
}
end
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,87 @@
local XMLParser = require("xmlParser")
return {
VisualObject = function(base)
local inline = true
local borderColors = {top = false, bottom = false, left = false, right = false}
local object = {
setBorder = function(self, ...)
local t = {...}
if(t~=nil)then
for k,v in pairs(t)do
if(v=="left")or(#t==1)then
borderColors["left"] = t[1]
end
if(v=="top")or(#t==1)then
borderColors["top"] = t[1]
end
if(v=="right")or(#t==1)then
borderColors["right"] = t[1]
end
if(v=="bottom")or(#t==1)then
borderColors["bottom"] = t[1]
end
end
end
self:updateDraw()
return self
end,
draw = function(self)
base.draw(self)
self:addDraw("border", function()
local x, y = self:getPosition()
local w,h = self:getSize()
local bgCol = self:getBackground()
if(inline)then
if(borderColors["left"]~=false)then
self:addTextBox(1, 1, 1, h, "\149")
if(bgCol~=false)then self:addBackgroundBox(1, 1, 1, h, bgCol) end
self:addForegroundBox(1, 1, 1, h, borderColors["left"])
end
if(borderColors["top"]~=false)then
self:addTextBox(1, 1, w, 1, "\131")
if(bgCol~=false)then self:addBackgroundBox(1, 1, w, 1, bgCol) end
self:addForegroundBox(1, 1, w, 1, borderColors["top"])
end
if(borderColors["left"]~=false)and(borderColors["top"]~=false)then
self:addTextBox(1, 1, 1, 1, "\151")
if(bgCol~=false)then self:addBackgroundBox(1, 1, 1, 1, bgCol) end
self:addForegroundBox(1, 1, 1, 1, borderColors["left"])
end
if(borderColors["right"]~=false)then
self:addTextBox(w, 1, 1, h, "\149")
if(bgCol~=false)then self:addForegroundBox(w, 1, 1, h, bgCol) end
self:addBackgroundBox(w, 1, 1, h, borderColors["right"])
end
if(borderColors["bottom"]~=false)then
self:addTextBox(1, h, w, 1, "\143")
if(bgCol~=false)then self:addForegroundBox(1, h, w, 1, bgCol) end
self:addBackgroundBox(1, h, w, 1, borderColors["bottom"])
end
if(borderColors["top"]~=false)and(borderColors["right"]~=false)then
self:addTextBox(w, 1, 1, 1, "\148")
if(bgCol~=false)then self:addForegroundBox(w, 1, 1, 1, bgCol) end
self:addBackgroundBox(w, 1, 1, 1, borderColors["right"])
end
if(borderColors["right"]~=false)and(borderColors["bottom"]~=false)then
self:addTextBox(w, h, 1, 1, "\133")
if(bgCol~=false)then self:addForegroundBox(w, h, 1, 1, bgCol) end
self:addBackgroundBox(w, h, 1, 1, borderColors["right"])
end
if(borderColors["bottom"]~=false)and(borderColors["left"]~=false)then
self:addTextBox(1, h, 1, 1, "\138")
if(bgCol~=false)then self:addForegroundBox(0, h, 1, 1, bgCol) end
self:addBackgroundBox(1, h, 1, 1, borderColors["left"])
end
end
end)
end
}
return object
end
}

View File

@@ -0,0 +1,97 @@
local utils = require("utils")
local wrapText = utils.wrapText
return {
basalt = function(basalt)
local mainFrame = basalt.getMainFrame()
local debugFrame
local debugList
local debugLabel
local debugExitButton
local function createDebuggingFrame()
local minW = 16
local minH = 6
local maxW = 99
local maxH = 99
local w, h = mainFrame:getSize()
debugFrame = mainFrame:addMovableFrame("basaltDebuggingFrame"):setSize(w-20, h-10):setBackground(colors.gray):setForeground(colors.white):setZIndex(100):hide()
debugFrame:addPane():setSize("parent.w", 1):setPosition(1, 1):setBackground(colors.black):setForeground(colors.white)
debugFrame:setPosition(-w, h/2-debugFrame:getHeight()/2):setBorder(colors.black)
local resizeButton = debugFrame:addButton()
:setPosition("parent.w", "parent.h")
:setSize(1, 1)
:setText("\133")
:setForeground(colors.gray)
:setBackground(colors.black)
:onClick(function() end)
:onDrag(function(self, event, btn, xOffset, yOffset)
local w, h = debugFrame:getSize()
local wOff, hOff = w, h
if(w+xOffset-1>=minW)and(w+xOffset-1<=maxW)then
wOff = w+xOffset-1
end
if(h+yOffset-1>=minH)and(h+yOffset-1<=maxH)then
hOff = h+yOffset-1
end
debugFrame:setSize(wOff, hOff)
end)
debugExitButton = debugFrame:addButton():setText("Close"):setPosition("parent.w - 6", 1):setSize(7, 1):setBackground(colors.red):setForeground(colors.white):onClick(function()
debugFrame:animatePosition(-w, h/2-debugFrame:getHeight()/2, 0.5)
end)
debugList = debugFrame:addList()
:setSize("parent.w - 2", "parent.h - 3")
:setPosition(2, 3)
:setBackground(colors.gray)
:setForeground(colors.white)
:setSelectionColor(colors.gray, colors.white)
if(debugLabel==nil)then
debugLabel = mainFrame:addLabel()
:setPosition(1, "parent.h")
:setBackground(colors.black)
:setForeground(colors.white)
:setZIndex(100)
:onClick(function()
debugFrame:show()
debugFrame:animatePosition(w/2-debugFrame:getWidth()/2, h/2-debugFrame:getHeight()/2, 0.5)
end)
end
end
return {
debug = function(...)
local args = { ... }
if(mainFrame==nil)then
mainFrame = basalt.getMainFrame()
if(mainFrame~=nil)then
createDebuggingFrame()
else
print(...) return
end
end
if (mainFrame:getName() ~= "basaltDebuggingFrame") then
if (mainFrame ~= debugFrame) then
debugLabel:setParent(mainFrame)
end
end
local str = ""
for key, value in pairs(args) do
str = str .. tostring(value) .. (#args ~= key and ", " or "")
end
debugLabel:setText("[Debug] " .. str)
for k,v in pairs(wrapText(str, debugList:getWidth()))do
debugList:addItem(v)
end
if (debugList:getItemCount() > 50) then
debugList:removeItem(1)
end
debugList:setValue(debugList:getItem(debugList:getItemCount()))
if(debugList.getItemCount() > debugList:getHeight())then
debugList:setOffset(debugList:getItemCount() - debugList:getHeight())
end
debugLabel:show()
end
}
end
}

View File

@@ -0,0 +1,124 @@
local utils = require("utils")
local count = utils.tableCount
return {
VisualObject = function(base, basalt)
local dynObjects = {}
local curProperties = {}
local properties = {x="getX", y="getY", w="getWidth", h="getHeight"}
local function stringToNumber(str)
local ok, result = pcall(load("return " .. str, "", nil, {math=math}))
if not(ok)then error(str.." - is not a valid dynamic value string") end
return result
end
local function createDynamicValue(self, key, val)
local objectGroup = {}
local properties = properties
for a,b in pairs(properties)do
for v in val:gmatch("%a+%."..a)do
local name = v:gsub("%."..a, "")
if(name~="self")and(name~="parent")then
table.insert(objectGroup, name)
end
end
end
local parent = self:getParent()
local objects = {}
for k,v in pairs(objectGroup)do
objects[v] = parent:getChild(v)
if(objects[v]==nil)then
error("Dynamic Values - unable to find object: "..v)
end
end
objects["self"] = self
objects["parent"] = parent
dynObjects[key] = function()
local mainVal = val
for a,b in pairs(properties)do
for v in val:gmatch("%w+%."..a) do
local obj = objects[v:gsub("%."..a, "")]
if(obj~=nil)then
mainVal = mainVal:gsub(v, obj[b](obj))
else
error("Dynamic Values - unable to find object: "..v)
end
end
end
curProperties[key] = math.floor(stringToNumber(mainVal)+0.5)
end
dynObjects[key]()
end
local function updatePositions(self)
if(count(dynObjects)>0)then
for k,v in pairs(dynObjects)do
v()
end
local properties = {x="getX", y="getY", w="getWidth", h="getHeight"}
for k,v in pairs(properties)do
if(dynObjects[k]~=nil)then
if(curProperties[k]~=self[v](self))then
if(k=="x")or(k=="y")then
base.setPosition(self, curProperties["x"] or self:getX(), curProperties["y"] or self:getY())
end
if(k=="w")or(k=="h")then
base.setSize(self, curProperties["w"] or self:getWidth(), curProperties["h"] or self:getHeight())
end
end
end
end
end
end
local object = {
updatePositions = updatePositions,
createDynamicValue = createDynamicValue,
setPosition = function(self, xPos, yPos, rel)
curProperties.x = xPos
curProperties.y = yPos
if(type(xPos)=="string")then
createDynamicValue(self, "x", xPos)
else
dynObjects["x"] = nil
end
if(type(yPos)=="string")then
createDynamicValue(self, "y", yPos)
else
dynObjects["y"] = nil
end
base.setPosition(self, curProperties.x, curProperties.y, rel)
return self
end,
setSize = function(self, w, h, rel)
curProperties.w = w
curProperties.h = h
if(type(w)=="string")then
createDynamicValue(self, "w", w)
else
dynObjects["w"] = nil
end
if(type(h)=="string")then
createDynamicValue(self, "h", h)
else
dynObjects["h"] = nil
end
base.setSize(self, curProperties.w, curProperties.h, rel)
return self
end,
customEventHandler = function(self, event, ...)
base.customEventHandler(self, event, ...)
if(event=="basalt_FrameReposition")or(event=="basalt_FrameResize")then
updatePositions(self)
end
end,
}
return object
end
}

View File

@@ -0,0 +1,221 @@
-- Most of this is made by Dev9551, you can find his awesome work here: https://github.com/9551-Dev/apis/blob/main/pixelbox_lite.lua
-- Slighly modified by NyoriE to work with Basalt
--[[
The MIT License (MIT)
Copyright © 2022 Oliver Caha (9551Dev)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ?Software?), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED ?AS IS?, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
]]
local t_sort,t_cat,s_char = table.sort,table.concat,string.char
local function sort(a,b) return a[2] > b[2] end
local distances = {
{5,256,16,8,64,32},
{4,16,16384,256,128},
[4] = {4,64,1024,256,128},
[8] = {4,512,2048,256,1},
[16] = {4,2,16384,256,1},
[32] = {4,8192,4096,256,1},
[64] = {4,4,1024,256,1},
[128] = {6,32768,256,1024,2048,4096,16384},
[256] = {6,1,128,2,512,4,8192},
[512] = {4,8,2048,256,128},
[1024] = {4,4,64,128,32768},
[2048] = {4,512,8,128,32768},
[4096] = {4,8192,32,128,32768},
[8192] = {3,32,4096,256128},
[16384] = {4,2,16,128,32768},
[32768] = {5,128,1024,2048,4096,16384}
}
local to_colors = {}
for i = 0, 15 do
to_colors[("%x"):format(i)] = 2^i
end
local to_blit = {}
for i = 0, 15 do
to_blit[2^i] = ("%x"):format(i)
end
local function pixelbox(colTable, defaultCol)
defaultCol = defaultCol or "f"
local width, height = #colTable[1], #colTable
local cache = {}
local canv = {}
local cached = false
local function generateCanvas()
for y = 1, height * 3 do
for x = 1, width * 2 do
if not canv[y] then canv[y] = {} end
canv[y][x] = defaultCol
end
end
for k, v in ipairs(colTable) do
for x = 1, #v do
local col = v:sub(x, x)
canv[k][x] = to_colors[col]
end
end
end
generateCanvas()
local function setSize(w,h)
width, height = w, h
canv = {}
cached = false
generateCanvas()
end
local function generateChar(a,b,c,d,e,f)
local arr = {a,b,c,d,e,f}
local c_types = {}
local sortable = {}
local ind = 0
for i=1,6 do
local c = arr[i]
if not c_types[c] then
ind = ind + 1
c_types[c] = {0,ind}
end
local t = c_types[c]
local t1 = t[1] + 1
t[1] = t1
sortable[t[2]] = {c,t1}
end
local n = #sortable
while n > 2 do
t_sort(sortable,sort)
local bit6 = distances[sortable[n][1]]
local index,run = 1,false
local nm1 = n - 1
for i=2,bit6[1] do
if run then break end
local tab = bit6[i]
for j=1,nm1 do
if sortable[j][1] == tab then
index = j
run = true
break
end
end
end
local from,to = sortable[n][1],sortable[index][1]
for i=1,6 do
if arr[i] == from then
arr[i] = to
local sindex = sortable[index]
sindex[2] = sindex[2] + 1
end
end
sortable[n] = nil
n = n - 1
end
local n = 128
local a6 = arr[6]
if arr[1] ~= a6 then n = n + 1 end
if arr[2] ~= a6 then n = n + 2 end
if arr[3] ~= a6 then n = n + 4 end
if arr[4] ~= a6 then n = n + 8 end
if arr[5] ~= a6 then n = n + 16 end
if sortable[1][1] == arr[6] then
return s_char(n),sortable[2][1],arr[6]
else
return s_char(n),sortable[1][1],arr[6]
end
end
local function convert()
local w_double = width * 2
local sy = 0
for y = 1, height * 3, 3 do
sy = sy + 1
local layer_1 = canv[y]
local layer_2 = canv[y + 1]
local layer_3 = canv[y + 2]
local char_line, fg_line, bg_line = {}, {}, {}
local n = 0
for x = 1, w_double, 2 do
local xp1 = x + 1
local b11, b21, b12, b22, b13, b23 = layer_1[x], layer_1[xp1], layer_2[x], layer_2[xp1], layer_3[x], layer_3[xp1]
local char, fg, bg = " ", 1, b11
if not (b21 == b11 and b12 == b11 and b22 == b11 and b13 == b11 and b23 == b11) then
char, fg, bg = generateChar(b11, b21, b12, b22, b13, b23)
end
n = n + 1
char_line[n] = char
fg_line[n] = to_blit[fg]
bg_line[n] = to_blit[bg]
end
cache[sy] = {t_cat(char_line), t_cat(fg_line), t_cat(bg_line)}
end
cached = true
end
return {
convert = convert,
generateCanvas = generateCanvas,
setSize = setSize,
getSize = function()
return width, height
end,
set = function(colTab, defCol)
colTable = colTab
defaultCol = defCol or defaultCol
canv = {}
cached = false
generateCanvas()
end,
get = function(y)
if not cached then convert() end
return y~= nil and cache[y] or cache
end
}
end
return {
Image = function(base, basalt)
return {
shrink = function(self)
local bimg = self:getImageFrame(1)
local img = {}
for k,v in pairs(bimg)do
if(type(k)=="number")then
table.insert(img,v[3])
end
end
local shrinkedImg = pixelbox(img, self:getBackground()).get()
self:setImage(shrinkedImg)
return self
end,
getShrinkedImage = function(self)
local bimg = self:getImageFrame(1)
local img = {}
for k,v in pairs(bimg)do
if(type(k)=="number")then
table.insert(img, v[3])
end
end
return pixelbox(img, self:getBackground()).get()
end,
}
end,
}

View File

@@ -0,0 +1,203 @@
local XMLParser = require("xmlParser")
local Reactive = {}
Reactive.currentEffect = nil
Reactive.observable = function(initialValue)
local value = initialValue
local observerEffects = {}
local get = function()
if (Reactive.currentEffect ~= nil) then
table.insert(observerEffects, Reactive.currentEffect)
table.insert(Reactive.currentEffect.dependencies, observerEffects)
end
return value
end
local set = function(newValue)
value = newValue
local observerEffectsCopy = {}
for index, effect in ipairs(observerEffects) do
observerEffectsCopy[index] = effect
end
for _, effect in ipairs(observerEffectsCopy) do
effect.execute()
end
end
return get, set
end
Reactive.untracked = function(getter)
local parentEffect = Reactive.currentEffect
Reactive.currentEffect = nil
local value = getter()
Reactive.currentEffect = parentEffect
return value
end
Reactive.effect = function(effectFn)
local effect = {dependencies = {}}
local execute = function()
Reactive.clearEffectDependencies(effect)
local parentEffect = Reactive.currentEffect
Reactive.currentEffect = effect
effectFn()
Reactive.currentEffect = parentEffect
end
effect.execute = execute
effect.execute()
end
Reactive.derived = function(computeFn)
local getValue, setValue = Reactive.observable();
Reactive.effect(function()
setValue(computeFn())
end)
return getValue;
end
Reactive.clearEffectDependencies = function(effect)
for _, dependency in ipairs(effect.dependencies) do
for index, backlink in ipairs(dependency) do
if (backlink == effect) then
table.remove(dependency, index)
end
end
end
effect.dependencies = {};
end
local Layout = {
fromXML = function(text)
local nodes = XMLParser.parseText(text)
local script = nil
for index, node in ipairs(nodes) do
if (node.tag == "script") then
script = node.value
table.remove(nodes, index)
break
end
end
return {
nodes = nodes,
script = script
}
end
}
local executeScript = function(script, env)
return load(script, nil, "t", env)()
end
local registerFunctionEvent = function(object, event, script, env)
event(object, function(...)
local success, msg = pcall(load(script, nil, "t", env))
if not success then
error("XML Error: "..msg)
end
end)
end
return {
basalt = function(basalt)
local createObjectsFromXMLNode = function(node, env)
local layout = env[node.tag]
if (layout ~= nil) then
local props = {}
for prop, expression in pairs(node.attributes) do
props[prop] = load("return " .. expression, nil, "t", env)
end
return basalt.createObjectsFromLayout(layout, props)
end
local objectName = node.tag:gsub("^%l", string.upper)
local object = basalt:createObject(objectName, node.attributes["id"])
for attribute, expression in pairs(node.attributes) do
if (attribute:sub(1, 2) == "on") then
registerFunctionEvent(object, object[attribute], expression .. "()", env)
else
local update = function()
local value = load("return " .. expression, nil, "t", env)()
object:setProperty(attribute, value)
end
basalt.effect(update)
end
end
for _, child in ipairs(node.children) do
local childObjects = basalt.createObjectsFromXMLNode(child, env)
for _, childObject in ipairs(childObjects) do
object:addChild(childObject)
end
end
return {object}
end
local object = {
observable = Reactive.observable,
untracked = Reactive.untracked,
effect = Reactive.effect,
derived = Reactive.derived,
layout = function(path)
if (not fs.exists(path)) then
error("Can't open file " .. path)
end
local f = fs.open(path, "r")
local text = f.readAll()
f.close()
return Layout.fromXML(text)
end,
createObjectsFromLayout = function(layout, props)
local env = _ENV
env.props = {}
local updateFns = {}
for prop, getFn in pairs(props) do
updateFns[prop] = basalt.derived(function()
return getFn()
end)
end
setmetatable(env.props, {
__index = function(_, k)
return updateFns[k]()
end
})
if (layout.script ~= nil) then
executeScript(layout.script, env)
end
local objects = {}
for _, node in ipairs(layout.nodes) do
local _objects = createObjectsFromXMLNode(node, env)
for _, object in ipairs(_objects) do
table.insert(objects, object)
end
end
return objects
end
}
return object
end,
Container = function(base, basalt)
local object = {
loadLayout = function(self, path, props)
local wrappedProps = {}
if (props == nil) then
props = {}
end
for prop, value in pairs(props) do
wrappedProps[prop] = function()
return value
end
end
local layout = basalt.layout(path)
local objects = basalt.createObjectsFromLayout(layout, wrappedProps)
for _, object in ipairs(objects) do
self:addChild(object)
end
return self
end
}
return object
end
}

View File

@@ -0,0 +1,36 @@
local XMLParser = require("xmlParser")
return {
VisualObject = function(base)
local shadow = false
local object = {
setShadow = function(self, color)
shadow = color
self:updateDraw()
return self
end,
getShadow = function(self)
return shadow
end,
draw = function(self)
base.draw(self)
self:addDraw("shadow", function()
if(shadow~=false)then
local w,h = self:getSize()
if(shadow)then
self:addBackgroundBox(w+1, 2, 1, h, shadow)
self:addBackgroundBox(2, h+1, w, 1, shadow)
self:addForegroundBox(w+1, 2, 1, h, shadow)
self:addForegroundBox(2, h+1, w, 1, shadow)
end
end
end)
end
}
return object
end
}

View File

@@ -0,0 +1,115 @@
local images = require("images")
local utils = require("utils")
local XMLParser = require("xmlParser")
return {
VisualObject = function(base)
local textureId, infinitePlay = 1, true
local bimg, texture, textureTimerId
local textureMode = "default"
local object = {
addTexture = function(self, path, animate)
bimg = images.loadImageAsBimg(path)
texture = bimg[1]
if(animate)then
if(bimg.animated)then
self:listenEvent("other_event")
local t = bimg[textureId].duration or bimg.secondsPerFrame or 0.2
textureTimerId = os.startTimer(t)
end
end
self:setBackground(false)
self:setForeground(false)
self:setDrawState("texture-base", true)
self:updateDraw()
return self
end,
setTextureMode = function(self, mode)
textureMode = mode or textureMode
self:updateDraw()
return self
end,
setInfinitePlay = function(self, state)
infinitePlay = state
return self
end,
eventHandler = function(self, event, timerId, ...)
base.eventHandler(self, event, timerId, ...)
if(event=="timer")then
if(timerId == textureTimerId)then
if(bimg[textureId+1]~=nil)then
textureId = textureId + 1
texture = bimg[textureId]
local t = bimg[textureId].duration or bimg.secondsPerFrame or 0.2
textureTimerId = os.startTimer(t)
self:updateDraw()
else
if(infinitePlay)then
textureId = 1
texture = bimg[1]
local t = bimg[textureId].duration or bimg.secondsPerFrame or 0.2
textureTimerId = os.startTimer(t)
self:updateDraw()
end
end
end
end
end,
draw = function(self)
base.draw(self)
self:addDraw("texture-base", function()
local obj = self:getParent() or self
local x, y = self:getPosition()
local w,h = self:getSize()
local wP,hP = obj:getSize()
local textureWidth = bimg.width or #bimg[textureId][1][1]
local textureHeight = bimg.height or #bimg[textureId]
local startX, startY = 0, 0
if (textureMode == "center") then
startX = x + math.floor((w - textureWidth) / 2 + 0.5) - 1
startY = y + math.floor((h - textureHeight) / 2 + 0.5) - 1
elseif (textureMode == "default") then
startX, startY = x, y
elseif (textureMode == "right") then
startX, startY = x + w - textureWidth, y + h - textureHeight
end
local textureX = x - startX
local textureY = y - startY
if startX < x then
startX = x
textureWidth = textureWidth - textureX
end
if startY < y then
startY = y
textureHeight = textureHeight - textureY
end
if startX + textureWidth > x + w then
textureWidth = (x + w) - startX
end
if startY + textureHeight > y + h then
textureHeight = (y + h) - startY
end
for k = 1, textureHeight do
if(texture[k+textureY]~=nil)then
local t, f, b = table.unpack(texture[k+textureY])
self:addBlit(1, k, t:sub(textureX, textureX + textureWidth), f:sub(textureX, textureX + textureWidth), b:sub(textureX, textureX + textureWidth))
end
end
end, 1)
self:setDrawState("texture-base", false)
end
}
return object
end
}

View File

@@ -0,0 +1,99 @@
local baseTheme = { -- The default main theme for basalt!
BaseFrameBG = colors.lightGray,
BaseFrameText = colors.black,
FrameBG = colors.gray,
FrameText = colors.black,
ButtonBG = colors.gray,
ButtonText = colors.black,
CheckboxBG = colors.lightGray,
CheckboxText = colors.black,
InputBG = colors.black,
InputText = colors.lightGray,
TextfieldBG = colors.black,
TextfieldText = colors.white,
ListBG = colors.gray,
ListText = colors.black,
MenubarBG = colors.gray,
MenubarText = colors.black,
DropdownBG = colors.gray,
DropdownText = colors.black,
RadioBG = colors.gray,
RadioText = colors.black,
SelectionBG = colors.black,
SelectionText = colors.lightGray,
GraphicBG = colors.black,
ImageBG = colors.black,
PaneBG = colors.black,
ProgramBG = colors.black,
ProgressbarBG = colors.gray,
ProgressbarText = colors.black,
ProgressbarActiveBG = colors.black,
ScrollbarBG = colors.lightGray,
ScrollbarText = colors.gray,
ScrollbarSymbolColor = colors.black,
SliderBG = false,
SliderText = colors.gray,
SliderSymbolColor = colors.black,
SwitchBG = colors.lightGray,
SwitchText = colors.gray,
LabelBG = false,
LabelText = colors.black,
GraphBG = colors.gray,
GraphText = colors.black
}
local plugin = {
Container = function(base, name, basalt)
local theme = {}
local object = {
getTheme = function(self, name)
local parent = self:getParent()
return theme[name] or (parent~=nil and parent:getTheme(name) or baseTheme[name])
end,
setTheme = function(self, _theme, col)
if(type(_theme)=="table")then
theme = _theme
elseif(type(_theme)=="string")then
theme[_theme] = col
end
self:updateDraw()
return self
end,
}
return object
end,
basalt = function()
return {
getTheme = function(name)
return baseTheme[name]
end,
setTheme = function(_theme, col)
if(type(_theme)=="table")then
baseTheme = _theme
elseif(type(_theme)=="string")then
baseTheme[_theme] = col
end
end
}
end
}
for k,v in pairs({"BaseFrame", "Frame", "ScrollableFrame", "MovableFrame", "Button", "Checkbox", "Dropdown", "Graph", "Graphic", "Input", "Label", "List", "Menubar", "Pane", "Program", "Progressbar", "Radio", "Scrollbar", "Slider", "Switch", "Textfield"})do
plugin[v] = function(base, name, basalt)
local object = {
init = function(self)
if(base.init(self))then
local parent = self:getParent() or self
self:setBackground(parent:getTheme(v.."BG"))
self:setForeground(parent:getTheme(v.."Text"))
end
end
}
return object
end
end
return plugin