2023-07-28 13:46:06 +00:00
|
|
|
--[[
|
|
|
|
Simple Graphics: An unopinionated graphics API to make hand-made GUIs easy.
|
|
|
|
Author: Andrew Lalis <andrewlalisofficial@gmail.com>
|
|
|
|
]]--
|
|
|
|
|
|
|
|
local lib = {}
|
|
|
|
|
2023-08-29 12:50:39 +00:00
|
|
|
local function tableCount(t)
|
|
|
|
local c = 0
|
|
|
|
for i, item in pairs(t) do c = c + 1 end
|
|
|
|
return c
|
|
|
|
end
|
|
|
|
|
2023-07-28 13:46:06 +00:00
|
|
|
-- Clears a screen or terminal. If c is not nil then the background color will
|
|
|
|
-- be set prior to clearing.
|
|
|
|
function lib.clear(m, c)
|
|
|
|
if c ~= nil then m.setBackgroundColor(c) end
|
|
|
|
m.clear()
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Fills a rectangle from the given X and Y coordinates, with a width and
|
|
|
|
-- height given by w and h respectively. If c is not nil, then the background
|
|
|
|
-- color is set to c.
|
|
|
|
function lib.fillRect(m, x, y, w, h, c)
|
|
|
|
if c ~= nil then m.setBackgroundColor(c) end
|
|
|
|
for i = 1, w do
|
|
|
|
for j = 1, h do
|
|
|
|
m.setCursorPos(x+i-1, y+j-1)
|
|
|
|
m.write(" ")
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2023-07-28 14:07:14 +00:00
|
|
|
-- Draws the outline of a rectangle from the given x and y coordinates with a
|
|
|
|
-- width and height given by w and h respectively. If c is not nil, then the
|
|
|
|
-- color of the border is set to c.
|
|
|
|
function lib.drawRect(m, x, y, w, h, c)
|
|
|
|
if c ~= nil then m.setBackgroundColor(c) end
|
|
|
|
lib.drawXLine(x, x+w-1, y, c)
|
|
|
|
lib.drawXLine(x, x+w-1, y+h-1, c)
|
|
|
|
lib.drawYLine(y+1, y+h-2, x, c)
|
|
|
|
lib.drawYLine(y+1, y+h-2, x+w-1, c)
|
|
|
|
end
|
|
|
|
|
2023-07-28 13:46:06 +00:00
|
|
|
-- Draws a horizontal line from x1 to x2 on the given y level.
|
|
|
|
function lib.drawXLine(m, x1, x2, y, bg, fg, char)
|
|
|
|
char = char or " "
|
|
|
|
if bg ~= nil then m.setBackgroundColor(bg) end
|
|
|
|
if fg ~= nil then m.setTextColor(fg) end
|
|
|
|
for x = x1, x2 do
|
|
|
|
m.setCursorPos(x, y)
|
|
|
|
m.write(char)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Draws a vertical line from y1 to y2, on the given x level.
|
|
|
|
function lib.drawYLine(m, y1, y2, x, bg, fg, char)
|
|
|
|
char = char or " "
|
|
|
|
if bg ~= nil then m.setBackgroundColor(bg) end
|
|
|
|
if fg ~= nil then m.setTextColor(fg) end
|
|
|
|
for y = y1, y2 do
|
|
|
|
m.setCursorPos(x, y)
|
|
|
|
m.write(char)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Draws text starting at the given x y position.
|
|
|
|
function lib.drawText(m, x, y, text, fg, bg)
|
|
|
|
if fg ~= nil then m.setTextColor(fg) end
|
|
|
|
if bg ~= nil then m.setBackgroundColor(bg) end
|
|
|
|
m.setCursorPos(x, y)
|
|
|
|
m.write(text)
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Draws text such that the center of the text is aligned with the given
|
|
|
|
-- x and y coordinates.
|
|
|
|
function lib.drawTextCenter(m, x, y, text, fg, bg)
|
|
|
|
lib.drawText(m, x-(#text/2)+1, y, text, fg, bg)
|
|
|
|
end
|
|
|
|
|
2023-07-28 14:07:14 +00:00
|
|
|
-- Draws a button as a plain rectangle with the given background color, and
|
|
|
|
-- centered text drawn with the foreground color. Returns a table containing
|
|
|
|
-- x1, y1, x2, y2 coordinates for handling the button's event later.
|
|
|
|
function lib.drawButton(m, x, y, w, h, text, fg, bg)
|
|
|
|
local x1 = x
|
|
|
|
local y1 = y
|
|
|
|
local x2 = x+w-1
|
|
|
|
local y2 = y+h-1
|
2023-07-28 14:57:34 +00:00
|
|
|
local midX = x+math.floor(w/2)
|
|
|
|
local midY = y+math.floor(h/2)
|
2023-07-28 14:07:14 +00:00
|
|
|
lib.fillRect(m, x, y, w, h, bg)
|
2023-07-28 14:18:50 +00:00
|
|
|
lib.drawTextCenter(m, midX, midY, text, fg)
|
2023-07-28 14:07:14 +00:00
|
|
|
return {x1=x1,y1=y1,x2=x2,y2=y2}
|
|
|
|
end
|
|
|
|
|
2023-07-28 14:57:34 +00:00
|
|
|
-- Determines if a button is pressed, given the event x and y coordinates and
|
|
|
|
-- the button's coordinates.
|
|
|
|
function lib.isButtonPressed(x, y, buttonCoords)
|
|
|
|
return x >= buttonCoords.x1 and x <= buttonCoords.x2 and
|
|
|
|
y >= buttonCoords.y1 and y <= buttonCoords.y2
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Creates a new button registry table, which is used for registering button
|
|
|
|
-- positions and callbacks for event handling.
|
|
|
|
function lib.createButtonRegistry()
|
|
|
|
return {}
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Adds a new button to a registry, so that `handleButtonPress` can invoke the
|
|
|
|
-- callback if the button is pressed.
|
|
|
|
function lib.registerButton(registry, buttonPos, callback)
|
|
|
|
table.insert(registry, {pos=coords,callback=callback})
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Handles a recent interaction on the screen that's interpreted as a button
|
|
|
|
-- press, by looking for registered buttons whose areas include the given X Y
|
|
|
|
-- coordinates.
|
|
|
|
function lib.handleButtonPress(registry, x, y)
|
|
|
|
for _, button in pairs(registry) do
|
|
|
|
if lib.isButtonPressed(x, y, button.pos) then
|
|
|
|
button.callback()
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2023-08-29 12:50:39 +00:00
|
|
|
-- Creates a "console" to which text can be appended, and it'll be displayed in
|
|
|
|
-- a scrolling style, updated whenever new text is added.
|
|
|
|
function lib.createConsole(width, height, fg, bg, dir)
|
|
|
|
return {
|
|
|
|
width = width,
|
|
|
|
height = height,
|
|
|
|
dir = dir or "UP",
|
|
|
|
fg = fg or colors.white,
|
|
|
|
bg = bg or colors.black,
|
|
|
|
lines = {}
|
|
|
|
}
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Appends some text to a console.
|
|
|
|
function lib.appendToConsole(console, text)
|
|
|
|
local lines = require "cc.strings".wrap(text, console.width)
|
|
|
|
if console.dir == "DOWN" then
|
|
|
|
for i = #lines, 1, -1 do
|
|
|
|
table.insert(console.lines, 1, lines[i])
|
|
|
|
end
|
|
|
|
elseif console.dir == "UP" then
|
|
|
|
for i = 1, #lines do
|
|
|
|
table.insert(console.lines, 1, lines[i])
|
|
|
|
end
|
|
|
|
else
|
|
|
|
error("Invalid console direction. Should be \"DOWN\" or \"UP\".")
|
|
|
|
end
|
|
|
|
while #console.lines > console.height do
|
|
|
|
table.remove(console.lines)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
-- Draws a console at a given x, y position.
|
|
|
|
function lib.drawConsole(m, console, x, y)
|
|
|
|
m.setTextColor(console.fg)
|
|
|
|
m.setBackgroundColor(console.bg)
|
|
|
|
lib.fillRect(m, x, y, console.width, console.height)
|
|
|
|
for i = 1, #console.lines do
|
|
|
|
local lineY
|
|
|
|
if console.dir == "DOWN" then
|
|
|
|
lineY = y + i - 1
|
|
|
|
elseif console.dir == "UP" then
|
|
|
|
lineY = y + console.height - i
|
|
|
|
else
|
|
|
|
error("Invalid console direction. Should be \"DOWN\" or \"UP\".")
|
|
|
|
end
|
|
|
|
m.setCursorPos(x, lineY)
|
|
|
|
m.write(console.lines[i])
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
function lib.appendAndDrawConsole(m, console, text, x, y)
|
|
|
|
lib.appendToConsole(console, text)
|
|
|
|
lib.drawConsole(m, console, x, y)
|
|
|
|
end
|
|
|
|
|
2023-07-28 13:46:06 +00:00
|
|
|
return lib
|