mirror of
https://github.com/S4mpsa/InfOS.git
synced 2025-08-03 18:06:04 -04:00
commit
a7ef9a0002
@ -5,37 +5,50 @@ local colors = {
|
||||
magenta = 0xFF00FF,
|
||||
yellow = 0xFFFF00,
|
||||
cyan = 0x00FFFF,
|
||||
greenYellow = 0xADFF2F,
|
||||
green = 0x008000,
|
||||
darkOliveGreen = 0x556B2F,
|
||||
indigo = 0x4B0082,
|
||||
purple = 0x800080,
|
||||
deepSkyBlue = 0x00BFFF,
|
||||
dodgerBlue = 0x1E90FF,
|
||||
steelBlue = 0x4682B4,
|
||||
brown = 0xA52A2A,
|
||||
chocolate = 0xD2691E,
|
||||
darkSlateBlue = 0x483D8B,
|
||||
midnightBlue = 0x191970,
|
||||
navy = 0x000080,
|
||||
darkOrange = 0xFFA500,
|
||||
rosyBrown = 0xBC8F8F,
|
||||
goldenRod = 0xDAA520,
|
||||
chocolate = 0xD2691E,
|
||||
brown = 0xA52A2A,
|
||||
maroon = 0x800000,
|
||||
white = 0xFFFFFF,
|
||||
lightGray = 0xD3D3D3,
|
||||
darkGray = 0xA9A9A9,
|
||||
darkSlateGrey = 0x2F4F4F,
|
||||
notBlack = 0x181828,
|
||||
black = 0x000000
|
||||
}
|
||||
|
||||
---[[
|
||||
local newColors = {
|
||||
machineBackground = colors.darkGray,
|
||||
progressBackground = colors.lightGray,
|
||||
labelColor = colors.chocolate,
|
||||
errorColor = colors.red,
|
||||
idleColor = colors.purple,
|
||||
workingColor = colors.steelBlue,
|
||||
positiveEUColor = colors.lime,
|
||||
negativeEUColor = colors.brown,
|
||||
timeColor = colors.purple,
|
||||
textColor = colors.black,
|
||||
hudColor = colors.darkSlateGrey,
|
||||
mainColor = colors.rosyBrown,
|
||||
background = colors.black,
|
||||
machineBackground = colors.notBlack,
|
||||
progressBackground = colors.indigo,
|
||||
barColor = colors.deepSkyBlue,
|
||||
labelColor = colors.goldenRod,
|
||||
idleColor = colors.lime,
|
||||
workingColor = colors.deepSkyBlue,
|
||||
offColor = colors.brown,
|
||||
errorColor = colors.red,
|
||||
positiveEUColor = colors.lime,
|
||||
negativeEUColor = colors.red,
|
||||
timeColor = colors.purple,
|
||||
textColor = colors.steelBlue,
|
||||
hudColor = colors.darkSlateGrey,
|
||||
mainColor = colors.goldenRod,
|
||||
accentA = colors.cyan,
|
||||
accentB = colors.magenta,
|
||||
barColor = colors.blue
|
||||
accentB = colors.blue
|
||||
}
|
||||
|
||||
for name, color in pairs(newColors) do
|
||||
@ -58,13 +71,15 @@ end
|
||||
|
||||
colors.RGB = RGB
|
||||
|
||||
--]]
|
||||
setmetatable(
|
||||
colors,
|
||||
{
|
||||
__index = function(self, color)
|
||||
return self.RGB[color] or 0, 0, 0
|
||||
return self[color] or 0, 0, 0
|
||||
end
|
||||
}
|
||||
)
|
||||
|
||||
--]]
|
||||
return colors
|
||||
|
795
Libraries/graphics/doubleBuffering.lua
Normal file
795
Libraries/graphics/doubleBuffering.lua
Normal file
@ -0,0 +1,795 @@
|
||||
local component = require("component")
|
||||
local unicode = require("unicode")
|
||||
Computer = require("computer")
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
local bufferWidth, bufferHeight
|
||||
local currentFrameBackgrounds,
|
||||
currentFrameForegrounds,
|
||||
currentFrameSymbols,
|
||||
newFrameBackgrounds,
|
||||
newFrameForegrounds,
|
||||
newFrameSymbols
|
||||
local drawLimitX1, drawLimitX2, drawLimitY1, drawLimitY2
|
||||
local GPUProxy,
|
||||
GPUProxyGetResolution,
|
||||
GPUProxySetResolution,
|
||||
GPUProxyBind,
|
||||
GPUProxySetBackground,
|
||||
GPUProxySetForeground,
|
||||
GPUProxySet
|
||||
|
||||
local mathCeil, mathFloor, mathAbs = math.ceil, math.floor, math.abs
|
||||
local tableInsert, tableConcat = table.insert, table.concat
|
||||
local colorBlend
|
||||
if Computer.getArchitecture and Computer.getArchitecture() == "Lua 5.3" then
|
||||
colorBlend = load([[function(color1, color2, transparency)
|
||||
local invertedTransparency = 1 - transparency
|
||||
return ((color2 >> 16) * invertedTransparency + (color1 >> 16) * transparency) // 1 << 16 |
|
||||
((color2 >> 8 & 0xFF) * invertedTransparency + (color1 >> 8 & 0xFF) * transparency) // 1 << 8 |
|
||||
((color2 & 0xFF) * invertedTransparency + (color1 & 0xFF) * transparency) // 1
|
||||
end]])
|
||||
else
|
||||
colorBlend = load([[function(color1, color2, transparency)
|
||||
local invertedTransparency = 1 - transparency
|
||||
|
||||
local r1 = color1 / 65536
|
||||
r1 = r1 - r1 % 1
|
||||
local g1 = (color1 - r1 * 65536) / 256
|
||||
g1 = g1 - g1 % 1
|
||||
|
||||
local r2 = color2 / 65536
|
||||
r2 = r2 - r2 % 1
|
||||
local g2 = (color2 - r2 * 65536) / 256
|
||||
g2 = g2 - g2 % 1
|
||||
|
||||
local r, g, b =
|
||||
r2 * invertedTransparency + r1 * transparency,
|
||||
g2 * invertedTransparency + g1 * transparency,
|
||||
(color2 - r2 * 65536 - g2 * 256) * invertedTransparency + (color1 - r1 * 65536 - g1 * 256) * transparency
|
||||
|
||||
return (r - r % 1) * 65536 + (g - g % 1) * 256 + (b - b % 1)
|
||||
end]])
|
||||
end
|
||||
local unicodeLen, unicodeSub = unicode.len, unicode.sub
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
local function getIndex(x, y)
|
||||
return bufferWidth * (y - 1) + x
|
||||
end
|
||||
|
||||
local function getCurrentFrameTables()
|
||||
return currentFrameBackgrounds, currentFrameForegrounds, currentFrameSymbols
|
||||
end
|
||||
|
||||
local function getNewFrameTables()
|
||||
return newFrameBackgrounds, newFrameForegrounds, newFrameSymbols
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
local function setDrawLimit(x1, y1, x2, y2)
|
||||
drawLimitX1, drawLimitY1, drawLimitX2, drawLimitY2 = x1, y1, x2, y2
|
||||
end
|
||||
|
||||
local function resetDrawLimit()
|
||||
drawLimitX1, drawLimitY1, drawLimitX2, drawLimitY2 = 1, 1, bufferWidth, bufferHeight
|
||||
end
|
||||
|
||||
local function getDrawLimit()
|
||||
return drawLimitX1, drawLimitY1, drawLimitX2, drawLimitY2
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
local function flush(width, height)
|
||||
if not width or not height then
|
||||
width, height = GPUProxyGetResolution()
|
||||
end
|
||||
|
||||
currentFrameBackgrounds,
|
||||
currentFrameForegrounds,
|
||||
currentFrameSymbols,
|
||||
newFrameBackgrounds,
|
||||
newFrameForegrounds,
|
||||
newFrameSymbols = {}, {}, {}, {}, {}, {}
|
||||
bufferWidth = width
|
||||
bufferHeight = height
|
||||
resetDrawLimit()
|
||||
|
||||
for y = 1, bufferHeight do
|
||||
for x = 1, bufferWidth do
|
||||
tableInsert(currentFrameBackgrounds, 0x010101)
|
||||
tableInsert(currentFrameForegrounds, 0xFEFEFE)
|
||||
tableInsert(currentFrameSymbols, " ")
|
||||
|
||||
tableInsert(newFrameBackgrounds, 0x010101)
|
||||
tableInsert(newFrameForegrounds, 0xFEFEFE)
|
||||
tableInsert(newFrameSymbols, " ")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function setResolution(width, height)
|
||||
GPUProxySetResolution(width, height)
|
||||
flush(width, height)
|
||||
end
|
||||
|
||||
local function getResolution()
|
||||
return bufferWidth, bufferHeight
|
||||
end
|
||||
|
||||
local function getWidth()
|
||||
return bufferWidth
|
||||
end
|
||||
|
||||
local function getHeight()
|
||||
return bufferHeight
|
||||
end
|
||||
|
||||
local function bindScreen(...)
|
||||
GPUProxyBind(...)
|
||||
flush(GPUProxyGetResolution())
|
||||
end
|
||||
|
||||
local function getGPUProxy()
|
||||
return GPUProxy
|
||||
end
|
||||
|
||||
local function updateGPUProxyMethods()
|
||||
GPUProxyGet = GPUProxy.get
|
||||
GPUProxyGetResolution = GPUProxy.getResolution
|
||||
GPUProxyGetBackground = GPUProxy.getBackground
|
||||
GPUProxyGetForeground = GPUProxy.getForeground
|
||||
|
||||
GPUProxySet = GPUProxy.set
|
||||
GPUProxySetResolution = GPUProxy.setResolution
|
||||
GPUProxySetBackground = GPUProxy.setBackground
|
||||
GPUProxySetForeground = GPUProxy.setForeground
|
||||
|
||||
GPUProxyBind = GPUProxy.bind
|
||||
GPUProxyFill = GPUProxy.fill
|
||||
end
|
||||
|
||||
local function bindGPU(address)
|
||||
GPUProxy = component.proxy(address)
|
||||
updateGPUProxyMethods()
|
||||
flush(GPUProxyGetResolution())
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
local function rawSet(index, background, foreground, symbol)
|
||||
newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] = background, foreground, symbol
|
||||
end
|
||||
|
||||
local function rawGet(index)
|
||||
return newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index]
|
||||
end
|
||||
|
||||
local function get(x, y)
|
||||
if x >= 1 and y >= 1 and x <= bufferWidth and y <= bufferHeight then
|
||||
local index = bufferWidth * (y - 1) + x
|
||||
return newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index]
|
||||
else
|
||||
return 0x000000, 0x000000, " "
|
||||
end
|
||||
end
|
||||
|
||||
local function set(x, y, background, foreground, symbol)
|
||||
if x >= drawLimitX1 and y >= drawLimitY1 and x <= drawLimitX2 and y <= drawLimitY2 then
|
||||
local index = bufferWidth * (y - 1) + x
|
||||
newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] = background, foreground, symbol
|
||||
end
|
||||
end
|
||||
|
||||
local function drawRectangle(x, y, width, height, background, foreground, symbol, transparency)
|
||||
local index, indexStepOnReachOfSquareWidth = bufferWidth * (y - 1) + x, bufferWidth - width
|
||||
for j = y, y + height - 1 do
|
||||
if j >= drawLimitY1 and j <= drawLimitY2 then
|
||||
for i = x, x + width - 1 do
|
||||
if i >= drawLimitX1 and i <= drawLimitX2 then
|
||||
if transparency then
|
||||
newFrameBackgrounds[index], newFrameForegrounds[index] =
|
||||
colorBlend(newFrameBackgrounds[index], background, transparency),
|
||||
colorBlend(newFrameForegrounds[index], background, transparency)
|
||||
else
|
||||
newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] =
|
||||
background,
|
||||
foreground,
|
||||
symbol
|
||||
end
|
||||
end
|
||||
|
||||
index = index + 1
|
||||
end
|
||||
|
||||
index = index + indexStepOnReachOfSquareWidth
|
||||
else
|
||||
index = index + bufferWidth
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function clear(color, transparency)
|
||||
drawRectangle(1, 1, bufferWidth, bufferHeight, color or 0x0, 0x000000, " ", transparency)
|
||||
end
|
||||
|
||||
local function copy(x, y, width, height)
|
||||
local copyArray, index = {width, height}
|
||||
|
||||
for j = y, y + height - 1 do
|
||||
for i = x, x + width - 1 do
|
||||
if i >= 1 and j >= 1 and i <= bufferWidth and j <= bufferHeight then
|
||||
index = bufferWidth * (j - 1) + i
|
||||
tableInsert(copyArray, newFrameBackgrounds[index])
|
||||
tableInsert(copyArray, newFrameForegrounds[index])
|
||||
tableInsert(copyArray, newFrameSymbols[index])
|
||||
else
|
||||
tableInsert(copyArray, 0x0)
|
||||
tableInsert(copyArray, 0x0)
|
||||
tableInsert(copyArray, " ")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return copyArray
|
||||
end
|
||||
|
||||
local function paste(startX, startY, picture)
|
||||
local imageWidth = picture[1]
|
||||
local bufferIndex, pictureIndex, bufferIndexStepOnReachOfImageWidth =
|
||||
bufferWidth * (startY - 1) + startX,
|
||||
3,
|
||||
bufferWidth - imageWidth
|
||||
|
||||
for y = startY, startY + picture[2] - 1 do
|
||||
if y >= drawLimitY1 and y <= drawLimitY2 then
|
||||
for x = startX, startX + imageWidth - 1 do
|
||||
if x >= drawLimitX1 and x <= drawLimitX2 then
|
||||
newFrameBackgrounds[bufferIndex] = picture[pictureIndex]
|
||||
newFrameForegrounds[bufferIndex] = picture[pictureIndex + 1]
|
||||
newFrameSymbols[bufferIndex] = picture[pictureIndex + 2]
|
||||
end
|
||||
|
||||
bufferIndex, pictureIndex = bufferIndex + 1, pictureIndex + 3
|
||||
end
|
||||
|
||||
bufferIndex = bufferIndex + bufferIndexStepOnReachOfImageWidth
|
||||
else
|
||||
bufferIndex, pictureIndex = bufferIndex + bufferWidth, pictureIndex + imageWidth * 3
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function rasterizeLine(x1, y1, x2, y2, method)
|
||||
local inLoopValueFrom,
|
||||
inLoopValueTo,
|
||||
outLoopValueFrom,
|
||||
outLoopValueTo,
|
||||
isReversed,
|
||||
inLoopValueDelta,
|
||||
outLoopValueDelta = x1, x2, y1, y2, false, mathAbs(x2 - x1), mathAbs(y2 - y1)
|
||||
if inLoopValueDelta < outLoopValueDelta then
|
||||
inLoopValueFrom,
|
||||
inLoopValueTo,
|
||||
outLoopValueFrom,
|
||||
outLoopValueTo,
|
||||
isReversed,
|
||||
inLoopValueDelta,
|
||||
outLoopValueDelta = y1, y2, x1, x2, true, outLoopValueDelta, inLoopValueDelta
|
||||
end
|
||||
|
||||
if outLoopValueFrom > outLoopValueTo then
|
||||
outLoopValueFrom, outLoopValueTo = outLoopValueTo, outLoopValueFrom
|
||||
inLoopValueFrom, inLoopValueTo = inLoopValueTo, inLoopValueFrom
|
||||
end
|
||||
|
||||
local outLoopValue, outLoopValueCounter, outLoopValueTriggerIncrement =
|
||||
outLoopValueFrom,
|
||||
1,
|
||||
inLoopValueDelta / outLoopValueDelta
|
||||
local outLoopValueTrigger = outLoopValueTriggerIncrement
|
||||
for inLoopValue = inLoopValueFrom, inLoopValueTo, inLoopValueFrom < inLoopValueTo and 1 or -1 do
|
||||
if isReversed then
|
||||
method(outLoopValue, inLoopValue)
|
||||
else
|
||||
method(inLoopValue, outLoopValue)
|
||||
end
|
||||
|
||||
outLoopValueCounter = outLoopValueCounter + 1
|
||||
if outLoopValueCounter > outLoopValueTrigger then
|
||||
outLoopValue, outLoopValueTrigger = outLoopValue + 1, outLoopValueTrigger + outLoopValueTriggerIncrement
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function rasterizeEllipse(centerX, centerY, radiusX, radiusY, method)
|
||||
local function rasterizeEllipsePoints(XP, YP)
|
||||
method(centerX + XP, centerY + YP)
|
||||
method(centerX - XP, centerY + YP)
|
||||
method(centerX - XP, centerY - YP)
|
||||
method(centerX + XP, centerY - YP)
|
||||
end
|
||||
|
||||
local x, y, changeX, changeY, ellipseError, twoASquare, twoBSquare =
|
||||
radiusX,
|
||||
0,
|
||||
radiusY * radiusY * (1 - 2 * radiusX),
|
||||
radiusX * radiusX,
|
||||
0,
|
||||
2 * radiusX * radiusX,
|
||||
2 * radiusY * radiusY
|
||||
local stoppingX, stoppingY = twoBSquare * radiusX, 0
|
||||
|
||||
while stoppingX >= stoppingY do
|
||||
rasterizeEllipsePoints(x, y)
|
||||
|
||||
y, stoppingY, ellipseError = y + 1, stoppingY + twoASquare, ellipseError + changeY
|
||||
changeY = changeY + twoASquare
|
||||
|
||||
if (2 * ellipseError + changeX) > 0 then
|
||||
x, stoppingX, ellipseError = x - 1, stoppingX - twoBSquare, ellipseError + changeX
|
||||
changeX = changeX + twoBSquare
|
||||
end
|
||||
end
|
||||
|
||||
x, y, changeX, changeY, ellipseError, stoppingX, stoppingY =
|
||||
0,
|
||||
radiusY,
|
||||
radiusY * radiusY,
|
||||
radiusX * radiusX * (1 - 2 * radiusY),
|
||||
0,
|
||||
0,
|
||||
twoASquare * radiusY
|
||||
|
||||
while stoppingX <= stoppingY do
|
||||
rasterizeEllipsePoints(x, y)
|
||||
|
||||
x, stoppingX, ellipseError = x + 1, stoppingX + twoBSquare, ellipseError + changeX
|
||||
changeX = changeX + twoBSquare
|
||||
|
||||
if (2 * ellipseError + changeY) > 0 then
|
||||
y, stoppingY, ellipseError = y - 1, stoppingY - twoASquare, ellipseError + changeY
|
||||
changeY = changeY + twoASquare
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function drawLine(x1, y1, x2, y2, background, foreground, symbol)
|
||||
rasterizeLine(
|
||||
x1,
|
||||
y1,
|
||||
x2,
|
||||
y2,
|
||||
function(x, y)
|
||||
set(x, y, background, foreground, symbol)
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
local function drawEllipse(centerX, centerY, radiusX, radiusY, background, foreground, symbol)
|
||||
rasterizeEllipse(
|
||||
centerX,
|
||||
centerY,
|
||||
radiusX,
|
||||
radiusY,
|
||||
function(x, y)
|
||||
set(x, y, background, foreground, symbol)
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
local function drawText(x, y, textColor, data, transparency)
|
||||
if y >= drawLimitY1 and y <= drawLimitY2 then
|
||||
local charIndex, bufferIndex = 1, bufferWidth * (y - 1) + x
|
||||
|
||||
for charIndex = 1, unicodeLen(data) do
|
||||
if x >= drawLimitX1 and x <= drawLimitX2 then
|
||||
if transparency then
|
||||
newFrameForegrounds[bufferIndex] =
|
||||
colorBlend(newFrameBackgrounds[bufferIndex], textColor, transparency)
|
||||
else
|
||||
newFrameForegrounds[bufferIndex] = textColor
|
||||
end
|
||||
|
||||
newFrameSymbols[bufferIndex] = unicodeSub(data, charIndex, charIndex)
|
||||
end
|
||||
|
||||
x, bufferIndex = x + 1, bufferIndex + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function drawImage(startX, startY, picture, blendForeground)
|
||||
local bufferIndex, pictureIndex, imageWidth, backgrounds, foregrounds, alphas, symbols =
|
||||
bufferWidth * (startY - 1) + startX,
|
||||
1,
|
||||
picture[1],
|
||||
picture[3],
|
||||
picture[4],
|
||||
picture[5],
|
||||
picture[6]
|
||||
local bufferIndexStepOnReachOfImageWidth = bufferWidth - imageWidth
|
||||
|
||||
for y = startY, startY + picture[2] - 1 do
|
||||
if y >= drawLimitY1 and y <= drawLimitY2 then
|
||||
for x = startX, startX + imageWidth - 1 do
|
||||
if x >= drawLimitX1 and x <= drawLimitX2 then
|
||||
if alphas[pictureIndex] == 0 then
|
||||
newFrameBackgrounds[bufferIndex], newFrameForegrounds[bufferIndex] =
|
||||
backgrounds[pictureIndex],
|
||||
foregrounds[pictureIndex]
|
||||
elseif alphas[pictureIndex] > 0 and alphas[pictureIndex] < 1 then
|
||||
newFrameBackgrounds[bufferIndex] =
|
||||
colorBlend(
|
||||
newFrameBackgrounds[bufferIndex],
|
||||
backgrounds[pictureIndex],
|
||||
alphas[pictureIndex]
|
||||
)
|
||||
|
||||
if blendForeground then
|
||||
newFrameForegrounds[bufferIndex] =
|
||||
colorBlend(
|
||||
newFrameForegrounds[bufferIndex],
|
||||
foregrounds[pictureIndex],
|
||||
alphas[pictureIndex]
|
||||
)
|
||||
else
|
||||
newFrameForegrounds[bufferIndex] = foregrounds[pictureIndex]
|
||||
end
|
||||
elseif alphas[pictureIndex] == 1 and symbols[pictureIndex] ~= " " then
|
||||
newFrameForegrounds[bufferIndex] = foregrounds[pictureIndex]
|
||||
end
|
||||
|
||||
newFrameSymbols[bufferIndex] = symbols[pictureIndex]
|
||||
end
|
||||
|
||||
bufferIndex, pictureIndex = bufferIndex + 1, pictureIndex + 1
|
||||
end
|
||||
|
||||
bufferIndex = bufferIndex + bufferIndexStepOnReachOfImageWidth
|
||||
else
|
||||
bufferIndex, pictureIndex = bufferIndex + bufferWidth, pictureIndex + imageWidth
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function drawFrame(x, y, width, height, color)
|
||||
local stringUp, stringDown, x2 =
|
||||
"╭" .. string.rep("─", width - 2) .. "╮",
|
||||
"╰" .. string.rep("─", width - 2) .. "╯",
|
||||
x + width - 1
|
||||
|
||||
drawText(x, y, color, stringUp)
|
||||
y = y + 1
|
||||
for i = 1, height - 2 do
|
||||
drawText(x, y, color, "│")
|
||||
drawText(x2, y, color, "│")
|
||||
y = y + 1
|
||||
end
|
||||
drawText(x, y, color, stringDown)
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
local function semiPixelRawSet(index, color, yPercentTwoEqualsZero)
|
||||
local upperPixel, lowerPixel, bothPixel = "▀", "▄", "█"
|
||||
local background, foreground, symbol =
|
||||
newFrameBackgrounds[index],
|
||||
newFrameForegrounds[index],
|
||||
newFrameSymbols[index]
|
||||
|
||||
if yPercentTwoEqualsZero then
|
||||
if symbol == upperPixel then
|
||||
if color == foreground then
|
||||
newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] =
|
||||
color,
|
||||
foreground,
|
||||
bothPixel
|
||||
else
|
||||
newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] =
|
||||
color,
|
||||
foreground,
|
||||
symbol
|
||||
end
|
||||
elseif symbol == bothPixel then
|
||||
if color ~= background then
|
||||
newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] =
|
||||
background,
|
||||
color,
|
||||
lowerPixel
|
||||
end
|
||||
else
|
||||
newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] =
|
||||
background,
|
||||
color,
|
||||
lowerPixel
|
||||
end
|
||||
else
|
||||
if symbol == lowerPixel then
|
||||
if color == foreground then
|
||||
newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] =
|
||||
color,
|
||||
foreground,
|
||||
bothPixel
|
||||
else
|
||||
newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] =
|
||||
color,
|
||||
foreground,
|
||||
symbol
|
||||
end
|
||||
elseif symbol == bothPixel then
|
||||
if color ~= background then
|
||||
newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] =
|
||||
background,
|
||||
color,
|
||||
upperPixel
|
||||
end
|
||||
else
|
||||
newFrameBackgrounds[index], newFrameForegrounds[index], newFrameSymbols[index] =
|
||||
background,
|
||||
color,
|
||||
upperPixel
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function semiPixelSet(x, y, color)
|
||||
local yFixed = mathCeil(y / 2)
|
||||
if x >= drawLimitX1 and yFixed >= drawLimitY1 and x <= drawLimitX2 and yFixed <= drawLimitY2 then
|
||||
semiPixelRawSet(bufferWidth * (yFixed - 1) + x, color, y % 2 == 0)
|
||||
end
|
||||
end
|
||||
|
||||
local function drawSemiPixelRectangle(x, y, width, height, color)
|
||||
local index, indexStepForward, indexStepBackward, jPercentTwoEqualsZero, jFixed =
|
||||
bufferWidth * (mathCeil(y / 2) - 1) + x,
|
||||
(bufferWidth - width),
|
||||
width
|
||||
for j = y, y + height - 1 do
|
||||
jPercentTwoEqualsZero = j % 2 == 0
|
||||
|
||||
for i = x, x + width - 1 do
|
||||
jFixed = mathCeil(j / 2)
|
||||
semiPixelRawSet(index, color, jPercentTwoEqualsZero)
|
||||
index = index + 1
|
||||
end
|
||||
|
||||
if jPercentTwoEqualsZero then
|
||||
index = index + indexStepForward
|
||||
else
|
||||
index = index - indexStepBackward
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function drawSemiPixelLine(x1, y1, x2, y2, color)
|
||||
rasterizeLine(
|
||||
x1,
|
||||
y1,
|
||||
x2,
|
||||
y2,
|
||||
function(x, y)
|
||||
semiPixelSet(x, y, color)
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
local function drawSemiPixelEllipse(centerX, centerY, radiusX, radiusY, color)
|
||||
rasterizeEllipse(
|
||||
centerX,
|
||||
centerY,
|
||||
radiusX,
|
||||
radiusY,
|
||||
function(x, y)
|
||||
semiPixelSet(x, y, color)
|
||||
end
|
||||
)
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
local function getPointTimedPosition(firstPoint, secondPoint, time)
|
||||
return {
|
||||
x = firstPoint.x + (secondPoint.x - firstPoint.x) * time,
|
||||
y = firstPoint.y + (secondPoint.y - firstPoint.y) * time
|
||||
}
|
||||
end
|
||||
|
||||
local function getConnectionPoints(points, time)
|
||||
local connectionPoints = {}
|
||||
for point = 1, #points - 1 do
|
||||
tableInsert(connectionPoints, getPointTimedPosition(points[point], points[point + 1], time))
|
||||
end
|
||||
return connectionPoints
|
||||
end
|
||||
|
||||
local function getMainPointPosition(points, time)
|
||||
if #points > 1 then
|
||||
return getMainPointPosition(getConnectionPoints(points, time), time)
|
||||
else
|
||||
return points[1]
|
||||
end
|
||||
end
|
||||
|
||||
local function drawSemiPixelCurve(points, color, precision)
|
||||
local linePoints = {}
|
||||
for time = 0, 1, precision or 0.01 do
|
||||
tableInsert(linePoints, getMainPointPosition(points, time))
|
||||
end
|
||||
|
||||
for point = 1, #linePoints - 1 do
|
||||
drawSemiPixelLine(
|
||||
mathFloor(linePoints[point].x),
|
||||
mathFloor(linePoints[point].y),
|
||||
mathFloor(linePoints[point + 1].x),
|
||||
mathFloor(linePoints[point + 1].y),
|
||||
color
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
local function drawChanges(force)
|
||||
local index, indexStepOnEveryLine, changes =
|
||||
bufferWidth * (drawLimitY1 - 1) + drawLimitX1,
|
||||
(bufferWidth - drawLimitX2 + drawLimitX1 - 1),
|
||||
{}
|
||||
local x, equalChars, equalCharsIndex, charX, charIndex, currentForeground
|
||||
local currentFrameBackground,
|
||||
currentFrameForeground,
|
||||
currentFrameSymbol,
|
||||
changesCurrentFrameBackground,
|
||||
changesCurrentFrameBackgroundCurrentFrameForeground
|
||||
|
||||
local changesCurrentFrameBackgroundCurrentFrameForegroundIndex
|
||||
|
||||
for y = drawLimitY1, drawLimitY2 do
|
||||
x = drawLimitX1
|
||||
while x <= drawLimitX2 do
|
||||
-- Determine if some pixel data was changed (or if <force> argument was passed)
|
||||
if
|
||||
currentFrameBackgrounds[index] ~= newFrameBackgrounds[index] or
|
||||
currentFrameForegrounds[index] ~= newFrameForegrounds[index] or
|
||||
currentFrameSymbols[index] ~= newFrameSymbols[index] or
|
||||
force
|
||||
then
|
||||
-- Make pixel at both frames equal
|
||||
currentFrameBackground, currentFrameForeground, currentFrameSymbol =
|
||||
newFrameBackgrounds[index],
|
||||
newFrameForegrounds[index],
|
||||
newFrameSymbols[index]
|
||||
currentFrameBackgrounds[index] = currentFrameBackground
|
||||
currentFrameForegrounds[index] = currentFrameForeground
|
||||
currentFrameSymbols[index] = currentFrameSymbol
|
||||
|
||||
-- Look for pixels with equal chars from right of current pixel
|
||||
equalChars, equalCharsIndex, charX, charIndex = {currentFrameSymbol}, 2, x + 1, index + 1
|
||||
while charX <= drawLimitX2 do
|
||||
-- Pixels becomes equal only if they have same background and (whitespace char or same foreground)
|
||||
if
|
||||
currentFrameBackground == newFrameBackgrounds[charIndex] and
|
||||
(newFrameSymbols[charIndex] == " " or
|
||||
currentFrameForeground == newFrameForegrounds[charIndex])
|
||||
then
|
||||
-- Make pixel at both frames equal
|
||||
currentFrameBackgrounds[charIndex] = newFrameBackgrounds[charIndex]
|
||||
currentFrameForegrounds[charIndex] = newFrameForegrounds[charIndex]
|
||||
currentFrameSymbols[charIndex] = newFrameSymbols[charIndex]
|
||||
|
||||
equalChars[equalCharsIndex], equalCharsIndex =
|
||||
currentFrameSymbols[charIndex],
|
||||
equalCharsIndex + 1
|
||||
else
|
||||
break
|
||||
end
|
||||
|
||||
charX, charIndex = charX + 1, charIndex + 1
|
||||
end
|
||||
|
||||
-- Group pixels that need to be drawn by background and foreground
|
||||
changes[currentFrameBackground] = changes[currentFrameBackground] or {}
|
||||
changesCurrentFrameBackground = changes[currentFrameBackground]
|
||||
changesCurrentFrameBackground[currentFrameForeground] =
|
||||
changesCurrentFrameBackground[currentFrameForeground] or {index = 1}
|
||||
changesCurrentFrameBackgroundCurrentFrameForeground =
|
||||
changesCurrentFrameBackground[currentFrameForeground]
|
||||
changesCurrentFrameBackgroundCurrentFrameForegroundIndex =
|
||||
changesCurrentFrameBackgroundCurrentFrameForeground.index
|
||||
|
||||
changesCurrentFrameBackgroundCurrentFrameForeground[
|
||||
changesCurrentFrameBackgroundCurrentFrameForegroundIndex
|
||||
],
|
||||
changesCurrentFrameBackgroundCurrentFrameForegroundIndex =
|
||||
x,
|
||||
changesCurrentFrameBackgroundCurrentFrameForegroundIndex + 1
|
||||
changesCurrentFrameBackgroundCurrentFrameForeground[
|
||||
changesCurrentFrameBackgroundCurrentFrameForegroundIndex
|
||||
],
|
||||
changesCurrentFrameBackgroundCurrentFrameForegroundIndex =
|
||||
y,
|
||||
changesCurrentFrameBackgroundCurrentFrameForegroundIndex + 1
|
||||
changesCurrentFrameBackgroundCurrentFrameForeground[
|
||||
changesCurrentFrameBackgroundCurrentFrameForegroundIndex
|
||||
],
|
||||
changesCurrentFrameBackgroundCurrentFrameForegroundIndex =
|
||||
tableConcat(equalChars),
|
||||
changesCurrentFrameBackgroundCurrentFrameForegroundIndex + 1
|
||||
|
||||
x, index, changesCurrentFrameBackgroundCurrentFrameForeground.index =
|
||||
x + equalCharsIndex - 2,
|
||||
index + equalCharsIndex - 2,
|
||||
changesCurrentFrameBackgroundCurrentFrameForegroundIndex
|
||||
end
|
||||
|
||||
x, index = x + 1, index + 1
|
||||
end
|
||||
|
||||
index = index + indexStepOnEveryLine
|
||||
end
|
||||
|
||||
-- Draw grouped pixels on screen
|
||||
for background, foregrounds in pairs(changes) do
|
||||
GPUProxySetBackground(background)
|
||||
|
||||
for foreground, pixels in pairs(foregrounds) do
|
||||
if currentForeground ~= foreground then
|
||||
GPUProxySetForeground(foreground)
|
||||
currentForeground = foreground
|
||||
end
|
||||
|
||||
for i = 1, #pixels, 3 do
|
||||
GPUProxySet(pixels[i], pixels[i + 1], pixels[i + 2])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
changes = nil
|
||||
end
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
bindGPU(component.getPrimary("gpu").address)
|
||||
|
||||
return {
|
||||
-- getCoordinates = getCoordinates,
|
||||
getIndex = getIndex,
|
||||
setDrawLimit = setDrawLimit,
|
||||
resetDrawLimit = resetDrawLimit,
|
||||
getDrawLimit = getDrawLimit,
|
||||
flush = flush,
|
||||
setResolution = setResolution,
|
||||
bindScreen = bindScreen,
|
||||
bindGPU = bindGPU,
|
||||
getGPUProxy = getGPUProxy,
|
||||
getResolution = getResolution,
|
||||
getWidth = getWidth,
|
||||
getHeight = getHeight,
|
||||
getCurrentFrameTables = getCurrentFrameTables,
|
||||
getNewFrameTables = getNewFrameTables,
|
||||
rawSet = rawSet,
|
||||
rawGet = rawGet,
|
||||
get = get,
|
||||
set = set,
|
||||
clear = clear,
|
||||
copy = copy,
|
||||
paste = paste,
|
||||
rasterizeLine = rasterizeLine,
|
||||
rasterizeEllipse = rasterizeEllipse,
|
||||
semiPixelRawSet = semiPixelRawSet,
|
||||
semiPixelSet = semiPixelSet,
|
||||
drawChanges = drawChanges,
|
||||
drawRectangle = drawRectangle,
|
||||
drawLine = drawLine,
|
||||
drawEllipse = drawEllipse,
|
||||
drawText = drawText,
|
||||
drawImage = drawImage,
|
||||
drawFrame = drawFrame,
|
||||
drawSemiPixelRectangle = drawSemiPixelRectangle,
|
||||
drawSemiPixelLine = drawSemiPixelLine,
|
||||
drawSemiPixelEllipse = drawSemiPixelEllipse,
|
||||
drawSemiPixelCurve = drawSemiPixelCurve
|
||||
}
|
@ -4,7 +4,7 @@ Colors = require("colors")
|
||||
|
||||
local widgets = {}
|
||||
|
||||
function widgets.gtMachineInit(GPU, name, address)
|
||||
function widgets.gtMabchineInit(GPU, name, address)
|
||||
local maintenanceIndex = 0
|
||||
local machine = util.machine(address)
|
||||
Graphics.rectangle(GPU, 1, 1, 28, 9, Colors.background)
|
||||
@ -99,7 +99,8 @@ function widgets.gtMachine(GPU, name, address)
|
||||
end
|
||||
_, f, _ = GPU.get(6, 1)
|
||||
if
|
||||
((Graphics.windows[name].data == 0 or string.match(machine.getSensorInformation()[Graphics.windows[name].data], ".*c0.*")) and
|
||||
((Graphics.windows[name].data == 0 or
|
||||
string.match(machine.getSensorInformation()[Graphics.windows[name].data], ".*c0.*")) and
|
||||
machine.isWorkAllowed()) == true
|
||||
then
|
||||
if f ~= Colors.background then
|
||||
|
6
Programs/monitor-system/api/gui/constants.lua
Normal file
6
Programs/monitor-system/api/gui/constants.lua
Normal file
@ -0,0 +1,6 @@
|
||||
local constants = {}
|
||||
|
||||
constants.baseWidth = 40
|
||||
constants.baseHeight = 10
|
||||
|
||||
return constants
|
@ -1,5 +0,0 @@
|
||||
local function render()
|
||||
|
||||
end
|
||||
|
||||
return render
|
11
Programs/monitor-system/api/gui/page/glasses.lua
Normal file
11
Programs/monitor-system/api/gui/page/glasses.lua
Normal file
@ -0,0 +1,11 @@
|
||||
--[[
|
||||
|ove| glasses |
|
||||
|wid| w | w | w |
|
||||
|hel| w | w | w |
|
||||
|sto| w | w | w |
|
||||
|not| power |b|f|
|
||||
--]]
|
||||
|
||||
return {
|
||||
title = "Glasses"
|
||||
}
|
11
Programs/monitor-system/api/gui/page/help.lua
Normal file
11
Programs/monitor-system/api/gui/page/help.lua
Normal file
@ -0,0 +1,11 @@
|
||||
--[[
|
||||
|gla| help |
|
||||
|wid|ev ti|ev ti|
|
||||
|ove|ev ti|ev ti|
|
||||
|sto|ev ti|ev ti|
|
||||
|not| power |b|f|
|
||||
--]]
|
||||
|
||||
return {
|
||||
title = "Help"
|
||||
}
|
211
Programs/monitor-system/api/gui/page/init.lua
Normal file
211
Programs/monitor-system/api/gui/page/init.lua
Normal file
@ -0,0 +1,211 @@
|
||||
-- Import section
|
||||
Computer = require("computer")
|
||||
Unicode = require("unicode")
|
||||
Event = require("event")
|
||||
DoubleBuffer = require("graphics.doubleBuffering")
|
||||
Constants = require("api.gui.constants")
|
||||
Colors = require("graphics.colors")
|
||||
Widget = require("api.gui.widget")
|
||||
--
|
||||
|
||||
-- GPU resolution should be 160 x 50.
|
||||
-- Screen should be 8 x 5 blocks.
|
||||
-- That way, each block should have a resolution of 20 x 10
|
||||
-- Organizing the page:
|
||||
---- Title on top of the page (title)
|
||||
---- Side panel on the left With a width of 40 pixels (panel)
|
||||
---- 2 buttons for page navigation (b, f)
|
||||
------- Each with a width of 20 pixels
|
||||
---- 1 Power widget on the bottom, with a width of 80 pixels (power)
|
||||
---- 9 Regular widgets on the right, in a 3 x 3 grid (w)
|
||||
------ Each one with a width of 40 pixels
|
||||
--[[
|
||||
| p | title |
|
||||
| a | w | w | w |
|
||||
| n | w | w | w |
|
||||
| e | w | w | w |
|
||||
| l | power |b|f|
|
||||
--]]
|
||||
local pages = {
|
||||
glasses = require("api.gui.page.glasses"),
|
||||
widgets = require("api.gui.page.widgets"),
|
||||
help = require("api.gui.page.help"),
|
||||
stock = require("api.gui.page.stock"),
|
||||
notifications = require("api.gui.page.notifications"),
|
||||
overview = require("api.gui.page.overview")
|
||||
}
|
||||
pages[1] = pages.glasses
|
||||
pages[2] = pages.widgets
|
||||
pages[3] = pages.help
|
||||
pages[4] = pages.stock
|
||||
pages[5] = pages.notifications
|
||||
pages[6] = pages.overview
|
||||
|
||||
local page = {}
|
||||
|
||||
local elements = {
|
||||
machineWidgets = {},
|
||||
powerWidgets = {},
|
||||
panelSections = {},
|
||||
navigationButtons = {}
|
||||
}
|
||||
|
||||
Event.listen(
|
||||
"touch",
|
||||
function(_, _, x, y)
|
||||
local xContribution = x / Constants.baseWidth
|
||||
local yContribution = 4 * math.floor(y / Constants.baseHeight)
|
||||
local screenIndex = 1 + (math.floor(2 * (xContribution + yContribution))) / 2
|
||||
|
||||
local selected = elements[screenIndex] or elements[screenIndex - 0.5]
|
||||
selected:onClick()
|
||||
end
|
||||
)
|
||||
|
||||
local function drawTitle(title)
|
||||
local x = Constants.baseWidth
|
||||
local y = 1
|
||||
local width = 3 * Constants.baseWidth
|
||||
local height = math.floor(0.8 * Constants.baseHeight)
|
||||
Widget.drawBaseWidget(x, y, width, height, title)
|
||||
end
|
||||
|
||||
local function drawPanelSection(index, title)
|
||||
local width = math.floor(0.6 * Constants.baseWidth)
|
||||
local height = math.floor(0.6 * Constants.baseHeight)
|
||||
local x = math.floor((Constants.baseWidth - width) / 2)
|
||||
local y = (index - 1) * Constants.baseHeight + math.floor((Constants.baseHeight - height) / 2)
|
||||
Widget.drawBaseWidget(x, y, width, height, title)
|
||||
end
|
||||
|
||||
local function drawNavigationButton(self, index)
|
||||
local width = math.floor(0.3 * Constants.baseWidth)
|
||||
local height = math.floor(0.6 * Constants.baseHeight)
|
||||
local x = math.floor((2.4 + 0.4 * index) * Constants.baseWidth) + math.floor((Constants.baseWidth - width) / 2)
|
||||
local y = 4 * Constants.baseHeight + math.floor((Constants.baseHeight - height) / 2)
|
||||
if self.active then
|
||||
Widget.drawBaseWidget(x, y, width, height, self.title)
|
||||
end
|
||||
end
|
||||
|
||||
local function clickNavigationButton(self)
|
||||
if not self.active then
|
||||
return
|
||||
end
|
||||
if self.title == "◀" then
|
||||
elements.machineWidgets.active.index = elements.machineWidgets.active.index - 1
|
||||
else
|
||||
elements.machineWidgets.active.index = elements.machineWidgets.active.index + 1
|
||||
end
|
||||
for i = 1, 9 do
|
||||
elements.machineWidgets.active[i] = elements.machineWidgets[9 * (elements.machineWidgets.active.index - 1) + i]
|
||||
end
|
||||
|
||||
elements[6] = elements.machineWidgets.active[1]
|
||||
elements[7] = elements.machineWidgets.active[2]
|
||||
elements[8] = elements.machineWidgets.active[3]
|
||||
elements[10] = elements.machineWidgets.active[4]
|
||||
elements[11] = elements.machineWidgets.active[5]
|
||||
elements[12] = elements.machineWidgets.active[6]
|
||||
elements[14] = elements.machineWidgets.active[7]
|
||||
elements[15] = elements.machineWidgets.active[8]
|
||||
elements[16] = elements.machineWidgets.active[9]
|
||||
Widget.clear()
|
||||
end
|
||||
|
||||
function page.create(element)
|
||||
drawTitle(element.title)
|
||||
|
||||
local panelIndex = 1
|
||||
for _, pg in ipairs(pages) do
|
||||
if pg ~= element then
|
||||
elements.panelSections[panelIndex] = {
|
||||
title = pg.title,
|
||||
onClick = function()
|
||||
page.create(pg)
|
||||
end
|
||||
}
|
||||
drawPanelSection(panelIndex, pg.title)
|
||||
panelIndex = panelIndex + 1
|
||||
end
|
||||
end
|
||||
|
||||
elements.machineWidgets.active = {}
|
||||
elements.machineWidgets.active.index = 1
|
||||
for i = 1, 9 do
|
||||
elements.machineWidgets.active[i] = elements.machineWidgets[9 * (elements.machineWidgets.active.index - 1) + i]
|
||||
end
|
||||
elements.navigationButtons[1] = {
|
||||
title = "◀",
|
||||
active = true,
|
||||
update = function(self)
|
||||
self.active = elements.machineWidgets[elements.machineWidgets.active.index * 9 - 10] ~= nil
|
||||
end,
|
||||
onClick = clickNavigationButton,
|
||||
draw = drawNavigationButton
|
||||
}
|
||||
elements.navigationButtons[2] = {
|
||||
title = "▶",
|
||||
active = true,
|
||||
update = function(self)
|
||||
self.active = elements.machineWidgets[elements.machineWidgets.active.index * 9 + 1] ~= nil
|
||||
end,
|
||||
onClick = clickNavigationButton,
|
||||
draw = drawNavigationButton
|
||||
}
|
||||
|
||||
elements[4.5] = {
|
||||
onClick = function()
|
||||
Computer.shutdown(true)
|
||||
end
|
||||
}
|
||||
|
||||
elements[6] = elements.machineWidgets.active[1]
|
||||
elements[7] = elements.machineWidgets.active[2]
|
||||
elements[8] = elements.machineWidgets.active[3]
|
||||
elements[10] = elements.machineWidgets.active[4]
|
||||
elements[11] = elements.machineWidgets.active[5]
|
||||
elements[12] = elements.machineWidgets.active[6]
|
||||
elements[14] = elements.machineWidgets.active[7]
|
||||
elements[15] = elements.machineWidgets.active[8]
|
||||
elements[16] = elements.machineWidgets.active[9]
|
||||
|
||||
elements[18] = elements.powerWidgets[1]
|
||||
elements[19] = elements.powerWidgets[1]
|
||||
|
||||
elements[1] = elements.panelSections[1]
|
||||
elements[5] = elements.panelSections[2]
|
||||
elements[9] = elements.panelSections[3]
|
||||
elements[13] = elements.panelSections[4]
|
||||
elements[17] = elements.panelSections[5]
|
||||
|
||||
elements[20] = elements.navigationButtons[1]
|
||||
elements[20.5] = elements.navigationButtons[2]
|
||||
end
|
||||
|
||||
function page.fake()
|
||||
elements.machineWidgets = Widget.fakeWidgets()
|
||||
elements.powerWidgets = Widget.fakePowerWidget()
|
||||
page.create(pages.overview)
|
||||
end
|
||||
|
||||
function page.update()
|
||||
for _, machineWidget in ipairs(elements.machineWidgets) do
|
||||
machineWidget:update()
|
||||
end
|
||||
for index, activeMachineWidget in ipairs(elements.machineWidgets.active) do
|
||||
activeMachineWidget.draw(activeMachineWidget, index)
|
||||
end
|
||||
for index, powerWidget in ipairs(elements.powerWidgets) do
|
||||
powerWidget:update()
|
||||
powerWidget:draw(index)
|
||||
end
|
||||
for index, navigationButton in ipairs(elements.navigationButtons) do
|
||||
navigationButton:update()
|
||||
navigationButton:draw(index)
|
||||
end
|
||||
|
||||
DoubleBuffer.drawChanges()
|
||||
end
|
||||
|
||||
return page
|
11
Programs/monitor-system/api/gui/page/notifications.lua
Normal file
11
Programs/monitor-system/api/gui/page/notifications.lua
Normal file
@ -0,0 +1,11 @@
|
||||
--[[
|
||||
|gla| notifs. |
|
||||
|wid|ev ti|ev ti|
|
||||
|hel|ev ti|ev ti|
|
||||
|sto|ev ti|ev ti|
|
||||
|ove| power |b|f|
|
||||
--]]
|
||||
|
||||
return {
|
||||
title ="Notifications"
|
||||
}
|
11
Programs/monitor-system/api/gui/page/overview.lua
Normal file
11
Programs/monitor-system/api/gui/page/overview.lua
Normal file
@ -0,0 +1,11 @@
|
||||
--[[
|
||||
|gla| overview |
|
||||
|wid| w | w | w |
|
||||
|hel| w | w | w |
|
||||
|sto| w | w | w |
|
||||
|not| power |b|f|
|
||||
--]]
|
||||
|
||||
return {
|
||||
title = "Overview"
|
||||
}
|
11
Programs/monitor-system/api/gui/page/stock.lua
Normal file
11
Programs/monitor-system/api/gui/page/stock.lua
Normal file
@ -0,0 +1,11 @@
|
||||
--[[
|
||||
|gla| stock |
|
||||
|wid|ev ti|ev ti|
|
||||
|hel|ev ti|ev ti|
|
||||
|ove|ev ti|ev ti|
|
||||
|not| power |b|f|
|
||||
--]]
|
||||
|
||||
return {
|
||||
title = "Stock"
|
||||
}
|
11
Programs/monitor-system/api/gui/page/widgets.lua
Normal file
11
Programs/monitor-system/api/gui/page/widgets.lua
Normal file
@ -0,0 +1,11 @@
|
||||
--[[
|
||||
|gla| widgets |
|
||||
|ove| w | w | w |
|
||||
|hel| w | w | w |
|
||||
|sto| w | w | w |
|
||||
|not| power |b|f|
|
||||
--]]
|
||||
|
||||
return {
|
||||
title = "Widgets"
|
||||
}
|
27
Programs/monitor-system/api/gui/panel.lua
Normal file
27
Programs/monitor-system/api/gui/panel.lua
Normal file
@ -0,0 +1,27 @@
|
||||
-- Import section
|
||||
Page = require("api.gui.page")
|
||||
Graphics = require("graphics.graphics")
|
||||
Colors = require("colors")
|
||||
Component = require("component")
|
||||
GPU = Component.gpu
|
||||
--
|
||||
|
||||
local panel = {
|
||||
currentPage = Page.overview
|
||||
}
|
||||
|
||||
function panel.render()
|
||||
Graphics.rectangle(GPU, 0, 0, 20, 160, Colors.background)
|
||||
for index, page in ipairs(Page) do
|
||||
if page ~= panel.currentPage then
|
||||
Graphics.text(GPU, 0, 10 * (index - 1), Colors.labelColor, panel.title)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function panel.navigate(page)
|
||||
panel.findText(page.title)
|
||||
page.render()
|
||||
end
|
||||
|
||||
return panel
|
239
Programs/monitor-system/api/gui/widget.lua
Normal file
239
Programs/monitor-system/api/gui/widget.lua
Normal file
@ -0,0 +1,239 @@
|
||||
Component = require("component")
|
||||
Unicode = require("unicode")
|
||||
DoubleBuffer = require("graphics.doubleBuffering")
|
||||
Constants = require("api.gui.constants")
|
||||
Colors = require("graphics.colors")
|
||||
|
||||
local widget = {}
|
||||
|
||||
local states = {
|
||||
{name = "ON", color = Colors.workingColor},
|
||||
{name = "IDLE", color = Colors.idleColor},
|
||||
{name = "OFF", color = Colors.offColor},
|
||||
{name = "BROKEN", color = Colors.errorColor}
|
||||
}
|
||||
|
||||
local function drawProgress(x, y, width, height, progress, maxProgress, color)
|
||||
progress = math.floor(progress * (width + height - 2) / (maxProgress ~= 0 and maxProgress or 1))
|
||||
|
||||
local lengths = {
|
||||
first = progress > 5 and 5 or progress,
|
||||
second = progress > height - 2 + 5 and height - 2 or progress - (5),
|
||||
third = progress > width - 7 + height - 2 + 5 and width - 7 or progress - (height - 2 + 5)
|
||||
}
|
||||
DoubleBuffer.drawRectangle(x + 6, y / 2 + 1, 2, 1, Colors.machineBackground, Colors.machineBackground, "█")
|
||||
DoubleBuffer.drawSemiPixelRectangle(x + 6 - lengths.first, y + 1, lengths.first, 1, color)
|
||||
DoubleBuffer.drawSemiPixelRectangle(x + 1, y + 2, 1, lengths.second, color)
|
||||
DoubleBuffer.drawSemiPixelRectangle(x + 1, y + height, lengths.third, 1, color)
|
||||
DoubleBuffer.drawRectangle(
|
||||
x + width - 6,
|
||||
(y + height) / 2,
|
||||
2,
|
||||
1,
|
||||
Colors.machineBackground,
|
||||
Colors.machineBackground,
|
||||
"█"
|
||||
)
|
||||
DoubleBuffer.drawSemiPixelRectangle(x + width - 4, y + height, lengths.first, 1, color)
|
||||
DoubleBuffer.drawSemiPixelRectangle(x + width, y + height - lengths.second, 1, lengths.second, color)
|
||||
DoubleBuffer.drawSemiPixelRectangle(x + 1 + width - lengths.third, y + 1, lengths.third, 1, color)
|
||||
end
|
||||
|
||||
function widget.drawBaseWidget(x, y, width, height, title)
|
||||
DoubleBuffer.drawRectangle(
|
||||
x + 1,
|
||||
y + 1,
|
||||
width - 1,
|
||||
height - 1,
|
||||
Colors.machineBackground,
|
||||
Colors.machineBackground,
|
||||
"█"
|
||||
)
|
||||
DoubleBuffer.drawLine(
|
||||
x + 3,
|
||||
y + math.ceil(0.5 * height),
|
||||
x + width - 3,
|
||||
y + math.ceil(0.5 * height),
|
||||
Colors.machineBackground,
|
||||
Colors.textColor,
|
||||
"─"
|
||||
)
|
||||
DoubleBuffer.drawFrame(x + 1, y + 1, width - 1, height - 1, Colors.labelColor)
|
||||
title = Unicode.len(title) < width - 8 and " " .. title .. " " or " " .. string.gsub(title, "%l*%s", "") .. " "
|
||||
DoubleBuffer.drawText(x + math.floor((width - Unicode.len(title) + 1) / 2), y + 3, Colors.labelColor, title)
|
||||
end
|
||||
|
||||
local function draw(self, index)
|
||||
if self.type == "power" then
|
||||
index = 10
|
||||
end
|
||||
local scale = self.scale or 1
|
||||
local width = Constants.baseWidth * scale
|
||||
local height = Constants.baseHeight
|
||||
local x = Constants.baseWidth + Constants.baseWidth * ((index - 1) % 3)
|
||||
local y = height * math.ceil((index) / 3)
|
||||
|
||||
widget.drawBaseWidget(x, y, width, height, self.name)
|
||||
|
||||
drawProgress(x, 2 * y, width - 1, 2 * (height - 1), 1, 1, Colors.progressBackground)
|
||||
drawProgress(x, 2 * y, width - 1, 2 * (height - 1), self.progress, self.maxProgress, Colors.barColor)
|
||||
DoubleBuffer.drawText(x + 4, y + 7, self.state.color, self.state.name)
|
||||
if self.state == states[4] then
|
||||
drawProgress(x, 2 * y, width - 1, 2 * (height - 1), 1, 1, Colors.errorColor)
|
||||
else
|
||||
local middleInfo = self:getMiddleString()
|
||||
if middleInfo then
|
||||
DoubleBuffer.drawText(x + 3 + 3 + Unicode.len("IDLE"), y + height - 3, Colors.textColor, middleInfo)
|
||||
end
|
||||
DoubleBuffer.drawText(
|
||||
x + width - Unicode.len(self.progress .. "/" .. self.maxProgress .. " s") - 3,
|
||||
y + height - 3,
|
||||
Colors.accentA,
|
||||
self.progress .. "/" .. self.maxProgress .. " s"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
function widget.clear()
|
||||
DoubleBuffer.drawRectangle(
|
||||
Constants.baseWidth,
|
||||
Constants.baseHeight,
|
||||
3 * Constants.baseWidth,
|
||||
4 * Constants.baseHeight,
|
||||
Colors.background,
|
||||
Colors.background,
|
||||
"█"
|
||||
)
|
||||
end
|
||||
|
||||
local fake = {}
|
||||
|
||||
fake.names = {
|
||||
"Cleanroom",
|
||||
"Electric Blast Furnace",
|
||||
"Miner",
|
||||
"Vacuum Freezer",
|
||||
"Multi Smelter",
|
||||
"Sifter",
|
||||
"Large Chemical Reactor",
|
||||
"Distillery",
|
||||
"Oil Cracking Unit",
|
||||
"Implosion Compressor"
|
||||
}
|
||||
|
||||
fake.machineWidget = {}
|
||||
|
||||
function fake.machineWidget:update()
|
||||
local breakWidget = math.random(10000) > 9999
|
||||
if breakWidget and self.state ~= states[3] then
|
||||
self.state = states[4]
|
||||
end
|
||||
if self.state == states[1] then
|
||||
self.progress = self.progress + 1
|
||||
if self.progress >= self.maxProgress then
|
||||
self.progress = 0
|
||||
self.maxProgress = 0
|
||||
self.state = states[2]
|
||||
end
|
||||
elseif self.state == states[2] then
|
||||
if math.random(1000) > 999 then
|
||||
self.state = states[1]
|
||||
self.maxProgress = math.random(500)
|
||||
end
|
||||
elseif self.state == states[3] then
|
||||
self.progress = self.progress + 1
|
||||
if self.progress >= self.maxProgress then
|
||||
self.progress = 0
|
||||
self.maxProgress = 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function fake.machineWidget:onClick()
|
||||
if self.state == states[1] or self.state == states[2] then
|
||||
self.state = states[3]
|
||||
elseif self.state == states[3] then
|
||||
if self.progress < self.maxProgress then
|
||||
self.state = states[1]
|
||||
else
|
||||
self.progress = 0
|
||||
self.maxProgress = 0
|
||||
self.state = states[2]
|
||||
end
|
||||
elseif self.state == states[4] then
|
||||
self.progress = 0
|
||||
self.maxProgress = 0
|
||||
self.state = states[2]
|
||||
end
|
||||
end
|
||||
|
||||
function fake.machineWidget:getMiddleString()
|
||||
end
|
||||
|
||||
function fake.machineWidget.create()
|
||||
local state = states[math.random(4)]
|
||||
return {
|
||||
name = fake.names[math.random(10)] .. " " .. math.floor(math.random(3)),
|
||||
state = state,
|
||||
progress = 0,
|
||||
maxProgress = state ~= states[3] and state ~= states[4] and math.random(500) or 0,
|
||||
type = "machine",
|
||||
update = fake.machineWidget.update,
|
||||
onClick = fake.machineWidget.onClick,
|
||||
getMiddleString = fake.machineWidget.getMiddleString,
|
||||
draw = draw
|
||||
}
|
||||
end
|
||||
|
||||
fake.powerWidget = {}
|
||||
|
||||
function fake.powerWidget:update()
|
||||
self.progress = self.progress + self.dProgress
|
||||
end
|
||||
|
||||
function fake.powerWidget:onClick()
|
||||
self.dProgress = -self.dProgress
|
||||
end
|
||||
|
||||
function fake.powerWidget:getMiddleString()
|
||||
local remaining = self.dProgress > 0 and self.maxProgress - self.progress or -self.progress
|
||||
return (self.dProgress > 0 and "+" or "") ..
|
||||
self.dProgress .. "EU/s. " .. (self.dProgress > 0 and "Full in: " or "Empty in: ") .. remaining / self.dProgress
|
||||
end
|
||||
|
||||
function fake.powerWidget.create()
|
||||
return {
|
||||
name = "Power",
|
||||
state = states[1],
|
||||
progress = math.random(16000000),
|
||||
maxProgress = 16000000,
|
||||
scale = 2,
|
||||
type = "power",
|
||||
dProgress = 1,
|
||||
update = fake.powerWidget.update,
|
||||
onClick = fake.powerWidget.onClick,
|
||||
getMiddleString = fake.powerWidget.getMiddleString,
|
||||
draw = draw
|
||||
}
|
||||
end
|
||||
|
||||
function widget.fakeWidgets()
|
||||
local fakeWidgets = {}
|
||||
|
||||
for _ = 1, math.random(30) do
|
||||
table.insert(fakeWidgets, fake.machineWidget.create())
|
||||
end
|
||||
|
||||
return fakeWidgets
|
||||
end
|
||||
|
||||
function widget.fakePowerWidget()
|
||||
local fakePowerWidgets = {}
|
||||
|
||||
table.insert(fakePowerWidgets, fake.powerWidget.create())
|
||||
fakePowerWidgets[11] = fakePowerWidgets[10]
|
||||
|
||||
return fakePowerWidgets
|
||||
end
|
||||
|
||||
return widget
|
@ -19,6 +19,11 @@ function MultiBlock:getNumberOfProblems()
|
||||
return Parser.parseProblems(sensorInformation[5])
|
||||
end
|
||||
|
||||
function MultiBlock:getProgress()
|
||||
local sensorInformation = self:getSensorInformation()
|
||||
return Parser.parseProgress(sensorInformation[1])
|
||||
end
|
||||
|
||||
function MultiBlock:getEfficiencyPercentage()
|
||||
local sensorInformation = self:getSensorInformation()
|
||||
return Parser.parseEfficiency(sensorInformation[5])
|
||||
|
@ -3,7 +3,7 @@ local getConsumption = require("domain.energy.get-consumption-usecase")
|
||||
local getProduction = require("domain.energy.get-production-usecase")
|
||||
--
|
||||
|
||||
local function exec(energyProducers, energyBuffer)
|
||||
local function exec(energyBuffer)
|
||||
-- local comsumption = getConsumption(energyBuffer)
|
||||
-- local production = getProduction(energyBuffer)
|
||||
local consumption = energyBuffer:getAverageInput()
|
||||
|
@ -1,42 +1,50 @@
|
||||
-- Import section
|
||||
MultiBlock = require("data.datasource.multi-block")
|
||||
SingleBlock = require("data.datasource.single-block")
|
||||
EnergyProvider = require("data.datasource.energy-provider")
|
||||
-- Event = require("event")
|
||||
-- Colors = require("graphics.colors")
|
||||
-- Widget = require("api.gui.widget")
|
||||
Page = require("api.gui.page")
|
||||
-- Graphics = require("graphics.graphics")
|
||||
-- MultiBlock = require("data.datasource.multi-block")
|
||||
-- SingleBlock = require("data.datasource.single-block")
|
||||
-- EnergyProvider = require("data.datasource.energy-provider")
|
||||
|
||||
local cleanroomAddresses = require("config.addresses.cleanroom")
|
||||
local multiBlockAddresses = require("config.addresses.multi-blocks")
|
||||
local energyBufferAddress = require("config.addresses.energy-buffers")
|
||||
-- local cleanroomAddresses = require("config.addresses.cleanroom")
|
||||
-- local multiBlockAddresses = require("config.addresses.multi-blocks")
|
||||
-- local energyBufferAddresses = require("config.addresses.energy-buffers")
|
||||
|
||||
local protectCleanroomRecipes = require("domain.cleanroom.protect-recipes-usecase")
|
||||
local getMultiblockStatuses = require("domain.multiblock.get-multiblock-status-usecase")
|
||||
local getEnergyStatus = require("domain.energy.get-energy-status-usecase")
|
||||
local listMiners = require("domain.miner.list-miners-usecase")
|
||||
local getMinersStatuses = require("domain.miner.get-miner-status-usecase")
|
||||
-- local protectCleanroomRecipes = require("domain.cleanroom.protect-recipes-usecase")
|
||||
-- local getMultiblockStatuses = require("domain.multiblock.get-multiblock-status-usecase")
|
||||
-- local getEnergyStatus = require("domain.energy.get-energy-status-usecase")
|
||||
-- local listMiners = require("domain.miner.list-miners-usecase")
|
||||
-- local getMinersStatuses = require("domain.miner.get-miner-status-usecase")
|
||||
|
||||
-- local GPU = Component.gpu
|
||||
--
|
||||
|
||||
local cleanroom = MultiBlock:new(multiBlockAddresses.cleanroom)
|
||||
cleanroom.name = "cleanroom"
|
||||
--[[
|
||||
local cleanroomMachines = {}
|
||||
for _, address in pairs(cleanroomAddresses) do
|
||||
table.insert(cleanroomMachines, SingleBlock:new(address))
|
||||
for name, address in pairs(cleanroomAddresses) do
|
||||
table.insert(cleanroomMachines, SingleBlock:new(address, name))
|
||||
end
|
||||
|
||||
local EBF11 = MultiBlock:new(multiBlockAddresses.EBF11)
|
||||
EBF11.name = "EBF11"
|
||||
local multiblocks = {}
|
||||
for name, address in pairs(multiBlockAddresses) do
|
||||
table.insert(multiblocks, MultiBlock:new(address, name))
|
||||
end
|
||||
|
||||
local multiblocks = {cleanroom, EBF11}
|
||||
local batteryBuffers = {}
|
||||
for name, address in pairs(energyBufferAddresses) do
|
||||
table.insert(batteryBuffers, EnergyProvider:new(address, name))
|
||||
end
|
||||
|
||||
local energyBuffer = EnergyProvider:new(energyBufferAddress.batteryBuffer1)
|
||||
|
||||
local energyProducers = {}
|
||||
local multiblocksStatuses = {}
|
||||
|
||||
for i = 1, 100 do
|
||||
print(i)
|
||||
|
||||
protectCleanroomRecipes(cleanroom, cleanroomMachines)
|
||||
protectCleanroomRecipes(multiblocks[1], cleanroomMachines)
|
||||
multiblocksStatuses = getMultiblockStatuses(multiblocks)
|
||||
local energyStatus = getEnergyStatus(energyProducers, energyBuffer)
|
||||
-- local energyStatus = getEnergyStatus(batteryBuffers[1])
|
||||
|
||||
local minersList = listMiners()
|
||||
local minersStatuses = getMinersStatuses(minersList)
|
||||
@ -45,9 +53,66 @@ for i = 1, 100 do
|
||||
i = i + 1
|
||||
end
|
||||
|
||||
for multiblock, status in pairs(multiblocksStatuses) do
|
||||
print(multiblock .. ": \
|
||||
problems: " .. status.problems .. "\
|
||||
efficiency: " .. status.efficiencyPercentage)
|
||||
for multiblockName, status in pairs(multiblocksStatuses) do
|
||||
print(
|
||||
multiblockName .. ":",
|
||||
"\n problems: " .. status.problems,
|
||||
"\n efficiency: " .. status.efficiencyPercentage,
|
||||
"\n probably uses: " .. status.probablyUses
|
||||
)
|
||||
end
|
||||
|
||||
require("api.sound.zelda-secret")()
|
||||
--]]
|
||||
|
||||
Page.fake()
|
||||
|
||||
while true do
|
||||
Page.update()
|
||||
os.sleep(0)
|
||||
end
|
||||
|
||||
--[[
|
||||
Page = require("api.gui.page")
|
||||
Notifications = {}
|
||||
local components = {}
|
||||
local function getComponents()
|
||||
local multiBlockAddresses = require("config.addresses.multi-blocks")
|
||||
local energyBufferAddresses = require("config.addresses.energy-buffers")
|
||||
|
||||
local multiblocks = {}
|
||||
for name, address in pairs(multiBlockAddresses) do
|
||||
table.insert(multiblocks, MultiBlock:new(address, name))
|
||||
end
|
||||
|
||||
local batteryBuffers = {}
|
||||
for name, address in pairs(energyBufferAddresses) do
|
||||
table.insert(batteryBuffers, EnergyProvider:new(address, name))
|
||||
end
|
||||
|
||||
return {table.unpack(multiblocks), batteryBuffers}
|
||||
end
|
||||
|
||||
local function setup()
|
||||
components = getComponents()
|
||||
Page.overview.setup()
|
||||
end
|
||||
|
||||
local function loop()
|
||||
while true do
|
||||
for index, component in ipairs(components) do
|
||||
local updated, notification = component:update()
|
||||
if updated then
|
||||
Page:draw(component, index)
|
||||
end
|
||||
if notification then
|
||||
table.insert(Notifications, 1, {notification, os.time()})
|
||||
end
|
||||
end
|
||||
Page:render()
|
||||
end
|
||||
end
|
||||
|
||||
setup()
|
||||
loop()
|
||||
--]]
|
||||
|
@ -9,7 +9,7 @@ shell.execute("wget " .. tarMan .. " -f")
|
||||
shell.setWorkingDirectory("/bin")
|
||||
shell.execute("wget " .. tarBin .. " -f")
|
||||
|
||||
local InfOS = "https://github.com/gordominossi/InfOS/releases/download/v0/InfOS.tar"
|
||||
local InfOS = "https://github.com/gordominossi/InfOS/releases/download/v0.1/InfOS.tar"
|
||||
|
||||
shell.setWorkingDirectory("/home")
|
||||
print("Updating InfOS")
|
||||
|
@ -1,18 +0,0 @@
|
||||
-- wget https://raw.githubusercontent.com/gordominossi/InfOS/master/Programs/update.lua -f
|
||||
|
||||
local shell = require("shell")
|
||||
|
||||
local tarMan = "https://raw.githubusercontent.com/mpmxyz/ocprograms/master/usr/man/tar.man"
|
||||
local tarBin = "https://raw.githubusercontent.com/mpmxyz/ocprograms/master/home/bin/tar.lua"
|
||||
local InfOS = "https://github.com/gordominossi/InfOS/releases/download/v0/InfOS.tar"
|
||||
|
||||
shell.setWorkingDirectory("/usr/man")
|
||||
shell.execute("wget " .. tarMan .. " -f")
|
||||
|
||||
shell.setWorkingDirectory("/bin")
|
||||
shell.execute("wget " .. tarBin .. " -f")
|
||||
|
||||
shell.setWorkingDirectory("/home")
|
||||
print("Updating InfOS")
|
||||
shell.execute("wget " .. InfOS .. " -f")
|
||||
shell.execute("tar -xf InfOS.tar")
|
Loading…
x
Reference in New Issue
Block a user