Skip to content

Instantly share code, notes, and snippets.

@MakerTim
Last active January 30, 2021 11:31
Show Gist options
  • Save MakerTim/bccdcda978dbcf227050c490afbaddcc to your computer and use it in GitHub Desktop.
Save MakerTim/bccdcda978dbcf227050c490afbaddcc to your computer and use it in GitHub Desktop.
ComputerCraft (MinecrafMod) Lua libary for making buttons, labels, images and charts on monitors or terminals
local monitors = { term = term }
local monitorsData = {}
local currentMonitor = "term"
function _findMonitors()
for index, peripheralName in pairs(peripheral.getNames()) do
if string.sub(peripheralName, 1, 7) == "monitor" then
monitors[peripheralName] = peripheral.wrap(peripheralName)
end
end
end
_findMonitors()
function _createPage()
return {
header = nil,
buttons = {},
charts = {},
labels = {},
images = {}
}
end
function setupScreen(peripheralName)
peripheralName = peripheralName or currentMonitor
local monitor = monitors[peripheralName]
monitor.setTextScale(0.5)
monitor.setTextColor(colors.white)
monitor.setBackgroundColor(colors.black)
monitor.clear()
monitorsData[peripheralName] = {
name = peripheralName,
backgroundColor = colors.black,
textColor = colors.white,
page = 1,
pages = {
_createPage()
},
}
return monitorsData[peripheralName]
end
-- Hard reset
function resetScreen(peripheralName)
peripheralName = peripheralName or currentMonitor
return setupScreen(peripheralName)
end
function _checkPeripheralSetupOrThrowsNotSetupError(peripheralName)
if monitorsData[peripheralName] == nil then
error("Peripheral " .. peripheralName .. " has not been trough setup, did you start with setupScreen(peripheralName)?", 1)
end
end
-- buttons
function _drawButton(peripheralName, pageData, buttonName, buttonData)
local backgroundColor
if buttonData["active"] then
backgroundColor = buttonData["activeColor"]
else
backgroundColor = buttonData["color"]
end
monitors[peripheralName].setBackgroundColor(backgroundColor)
local yspot = math.floor((buttonData["ymin"] + buttonData["ymax"]) / 2)
local xspot = math.floor((buttonData["xmax"] - buttonData["xmin"] - string.len(text)) / 2) + 1
for j = buttonData["ymin"], buttonData["ymax"] do
monitors[peripheralName].setCursorPos(buttonData["xmin"], j)
if j == yspot then
for k = 0, buttonData["xmax"] - buttonData["xmin"] - string.len(text) + 1 do
if k == xspot then
monitors[peripheralName].write(text)
else
monitors[peripheralName].write(" ")
end
end
else
for i = buttonData["xmin"], buttonData["xmax"] do
monitors[peripheralName].write(" ")
end
end
end
mon.setBackgroundColor(monitorsData[peripheralName].backgroundColor)
end
function _drawButtons(peripheralName, page)
page = page or monitorsData[peripheralName].page
local pageData = monitorsData[peripheralName].pages[page];
local buttons = pageData.buttons
for buttonName, buttonData in pairs(buttons) do
_drawButton(peripheralName, pageData, buttonName, buttonData)
end
end
-- args func = peripheralName, buttonName, buttonData, x, y
function addButton(peripheralName, page, name, func, x, y, width, height, color, activeColor)
_checkPeripheralSetupOrThrowsNotSetupError(peripheralName)
peripheralName = peripheralName or currentMonitor
page = page or monitorsData[peripheralName].page
color = color or colors.red
activeColor = activeColor or colors.lime
local pageData = monitorsData[peripheralName].pages[page];
pageData.buttons[buttonName] = {
name = buttonName,
func = func,
active = false,
xmin = x,
ymin = y,
xmax = x + width - 1,
ymax = y + height - 1,
color = color,
activeColor = activeColor
}
end
function updateButton(peripheralName, page, buttonName, newColor, newActiveColor, newFunction)
_checkPeripheralSetupOrThrowsNotSetupError(peripheralName)
peripheralName = peripheralName or currentMonitor
page = page or monitorsData[peripheralName].page
local pageData = monitorsData[peripheralName].pages[page];
local buttonData = pageData.buttons[buttonName]
if newColor ~= nil then
chartData["color"] = color
end
if newActiveColor ~= nil then
chartData["activeColor"] = newActiveColor
end
if newFunction ~= nil then
chartData["func"] = newFunction
end
_drawButton(peripheralName, pageData, buttonName, buttonData)
end
function updateButtonState(peripheralName, page, buttonName, forceState)
_checkPeripheralSetupOrThrowsNotSetupError(peripheralName)
peripheralName = peripheralName or currentMonitor
page = page or monitorsData[peripheralName].page
local button = monitorsData[peripheralName].pages[page].buttons[buttonName];
if forceState == nil then
button["active"] = not button["active"]
else
button["active"] = forceState == true
end
_drawButtons(peripheralName)
end
function removeButton(peripheralName, page, buttonName)
_checkPeripheralSetupOrThrowsNotSetupError(peripheralName)
peripheralName = peripheralName or currentMonitor
page = page or monitorsData[peripheralName].page
local pageData = monitorsData[peripheralName].pages[page];
pageData.buttons[buttonName] = nil
end
-- charts
function _drawChart(peripheralName, pageData, chartName, chartData)
local heigth = chartData["ymax"] - chartData["ymin"]
local percentPerStep = math.floor(100 / heigth)
local barHeight = math.floor(chartData["value"] / percentPerStep)
local xspot = math.floor((chartData["xmax"] - chartData["xmin"]) / 2) - 1
local yspot = math.floor((chartData["ymin"] + chartData["ymax"]) / 2)
local text = chartData["value"] .. "%"
if chartData["label"] ~= nil then
local labelX = math.floor((chartData["xmax"] - chartData["xmin"] - string.len(chartData["label"])) / 2)
monitors[peripheralName].setCursorPos(chartData["xmin"] + labelX, chartData["ymax"] + 1)
monitors[peripheralName].write(chartData["label"])
end
local emptyColor = 0
if chartData["color"] == colors.gray then
emptyColor = colors.lightGray
else
emptyColor = colors.gray
end
if chartData["color"] == colors.white then
monitors[peripheralName].setTextColor(colors.black)
end
for j = chartData["ymin"], chartData["ymax"] do
monitors[peripheralName].setCursorPos(chartData["xmin"], j)
if j == yspot then
for k = 0, chartData["xmax"] - chartData["xmin"] - string.len(text) + 1 do
if barHeight + chartData["ymax"] >= chartData["ymax"] + (chartData["ymax"] - j) then
monitors[peripheralName].setBackgroundColor(chartData["color"])
else
monitors[peripheralName].setBackgroundColor(emptyColor)
end
if k == xspot then
monitors[peripheralName].write(text)
else
monitors[peripheralName].write(" ")
end
end
else
for i = chartData["xmin"], chartData["xmax"] do
if barHeight + chartData["ymax"] >= chartData["ymax"] + (chartData["ymax"] - j) then
monitors[peripheralName].setBackgroundColor(chartData["color"])
else
monitors[peripheralName].setBackgroundColor(emptyColor)
end
monitors[peripheralName].write(" ")
end
end
end
monitors[peripheralName].setBackgroundColor(colors.black)
monitors[peripheralName].setTextColor(colors.white)
end
function _drawCharts(peripheralName, page)
page = page or monitorsData[peripheralName].page
local pageData = monitorsData[peripheralName].pages[page];
local charts = pageData.charts
for chartName, chartData in pairs(charts) do
_drawChart(peripheralName, pageData, chartName, chartData)
end
end
function addChart(peripheralName, page, chartName, percentage, x, y, width, height, color, label)
_checkPeripheralSetupOrThrowsNotSetupError(peripheralName)
peripheralName = peripheralName or currentMonitor
page = page or monitorsData[peripheralName].page
local pageData = monitorsData[peripheralName].pages[page];
color = color or colors.white
pageData.charts[chartName] = {
value = percentage,
xmin = x,
ymin = y,
xmax = x + width - 1,
ymax = y + height - 1,
color = color,
label = label
}
end
function updateChart(peripheralName, page, chartName, newValue, newColor)
_checkPeripheralSetupOrThrowsNotSetupError(peripheralName)
peripheralName = peripheralName or currentMonitor
page = page or monitorsData[peripheralName].page
local pageData = monitorsData[peripheralName].pages[page];
local chartData = pageData.charts[chartName]
if newValue ~= nil then
chartData["value"] = newValue
end
if newColor ~= nil then
chartData["color"] = newColor
end
_drawChart(peripheralName, pageData, chartName, chartData)
end
function removeChart(peripheralName, page, chartName)
_checkPeripheralSetupOrThrowsNotSetupError(peripheralName)
peripheralName = peripheralName or currentMonitor
page = page or monitorsData[peripheralName].page
local pageData = monitorsData[peripheralName].pages[page];
pageData.charts[chartName] = nil
end
-- labels
function _drawLabel(peripheralName, pageData, labelName, labelData)
monitors[peripheralName].setCursorPos(labelData["x"], labelData["y"])
monitors[peripheralName].setTextColor(labelData["color"] or monitorsData[peripheralName].textColor)
monitors[peripheralName].setBackgroundColor(labelData["backgroundColor"] or monitorsData[peripheralName].backgroundColor)
monitors[peripheralName].write(labelName)
end
function _drawLables(peripheralName, page)
page = page or monitorsData[peripheralName].page
local pageData = monitorsData[peripheralName].pages[page];
local labels = pageData.labels
for labelName, labelData in pairs(labels) do
_drawLabel(peripheralName, pageData, labelName, labelData)
end
end
function setHeader(peripheralName, page, header, color, backgroundColor)
_checkPeripheralSetupOrThrowsNotSetupError(peripheralName)
peripheralName = peripheralName or currentMonitor
page = page or monitorsData[peripheralName].page
if monitorsData[peripheralName].pages[page].header ~= nil then
removeLabel(peripheralName, page, monitorsData[peripheralName].header)
end
monitorsData[peripheralName].pages[page].header = header
local x = (w - string.len(text)) / 2 + 1
local y = 1
addLabel(peripheralName, page, header, x, y, color, backgroundColor)
end
function addLabel(peripheralName, page, labelName, x, y, color, backgroundColor)
_checkPeripheralSetupOrThrowsNotSetupError(peripheralName)
peripheralName = peripheralName or currentMonitor
page = page or monitorsData[peripheralName].page
local pageData = monitorsData[peripheralName].pages[page];
pageData.labels[labelName] = {
x = x,
y = y,
color = color,
backgroundColor = backgroundColor
}
end
function updateLabelSetTextColor(peripheralName, page, labelName, newTextColor)
_checkPeripheralSetupOrThrowsNotSetupError(peripheralName)
peripheralName = peripheralName or currentMonitor
page = page or monitorsData[peripheralName].page
local pageData = monitorsData[peripheralName].pages[page];
pageData.labels[labelName]["color"] = newTextColor
end
function updateLabelSetBackgroundColor(peripheralName, page, labelName, newBackgroundColor)
_checkPeripheralSetupOrThrowsNotSetupError(peripheralName)
peripheralName = peripheralName or currentMonitor
page = page or monitorsData[peripheralName].page
local pageData = monitorsData[peripheralName].pages[page];
pageData.labels[labelName]["backgroundColor"] = newBackgroundColor
end
function removeLabel(peripheralName, page, labelName)
_checkPeripheralSetupOrThrowsNotSetupError(peripheralName)
peripheralName = peripheralName or currentMonitor
page = page or monitorsData[peripheralName].page
local pageData = monitorsData[peripheralName].pages[page];
pageData.labels[labelName] = nil
end
-- images
function _drawImage(peripheralName, pageData, imageName, imageData)
if imageData["paintutil"] then
paintutils.drawImage(imageData["data"], imageData["x"], imageData["y"])
else
for line, colorData in pairs(imageData["data"]) do
monitors[peripheralName].setCursorPos(imageData["x"] + line - 1, imageData["y"])
local spaces = colorData:gsub("%w", " ")
local colorText = colorData:gsub("%w", "0")
monitors[peripheralName].blit(spaces, colorText, colorData)
end
end
end
function _drawImages(peripheralName, page)
page = page or monitorsData[peripheralName].page
local pageData = monitorsData[peripheralName].pages[page];
local images = pageData.images
for imageName, imageData in pairs(images) do
_drawImage(peripheralName, pageData, imageName, imageData)
end
end
function addImage(peripheralName, page, imageName, imageTable, usePaintUtil)
_checkPeripheralSetupOrThrowsNotSetupError(peripheralName)
peripheralName = peripheralName or currentMonitor
page = page or monitorsData[peripheralName].page
local pageData = monitorsData[peripheralName].pages[page];
pageData.images[imageName] = {
x = x,
y = y,
data = imageTable,
paintutil = usePaintUtil
}
end
function updateImagePos(peripheralName, page, imageName, x, y)
_checkPeripheralSetupOrThrowsNotSetupError(peripheralName)
peripheralName = peripheralName or currentMonitor
page = page or monitorsData[peripheralName].page
monitors[peripheralName].clear()
local pageData = monitorsData[peripheralName].pages[page];
pageData.images[imageName].x = x
pageData.images[imageName].y = y
updateMonitor(peripheralName)
end
function removeImage(peripheralName, page, imageName)
_checkPeripheralSetupOrThrowsNotSetupError(peripheralName)
peripheralName = peripheralName or currentMonitor
page = page or monitorsData[peripheralName].page
local pageData = monitorsData[peripheralName].pages[page];
pageData.images[imageName] = nil
end
-- global update all
function updateMonitor(peripheralName)
peripheralName = peripheralName or currentMonitor
_drawButtons(peripheralName)
_drawCharts(peripheralName)
_drawLabels(peripheralName)
_drawImages(peripheralName)
end
function changeToPage(peripheralName, newPage)
_checkPeripheralSetupOrThrowsNotSetupError(peripheralName)
while newPage > table.getn(monitorsData[peripheralName].pages) do
table.insert(monitorsData[peripheralName].pages, _createPage())
end
monitorsData[peripheralName].page = newPage
updateMonitor(peripheralName)
end
function lowerOnePage(peripheralName)
_checkPeripheralSetupOrThrowsNotSetupError(peripheralName)
local currentPage = monitorsData[peripheralName].page
local newPage = currentPage - 1
if currentPage == 1 then
newPage = table.getn(monitorsData[peripheralName].pages)
end
changeToPage(peripheralName, newPage)
end
function lowerOnePage(peripheralName)
_checkPeripheralSetupOrThrowsNotSetupError(peripheralName)
local currentPage = monitorsData[peripheralName].page
local newPage = currentPage + 1
if currentPage == table.getn(monitorsData[peripheralName].pages) then
newPage = 1
end
changeToPage(peripheralName, newPage)
end
-- check if button is pressed and trigger it
function checkPressedButton(peripheralName, x, y)
if monitorsData[peripheralName] ~= nil then
local page = monitorsData[peripheralName].pages[monitorsData[peripheralName].page]
local buttons = page.buttons
for buttonName, buttonData in pairs(buttons) do
if y >= buttonData.ymin and y <= buttonData.ymax then
if x >= buttonData.xmin and x <= buttonData.xmax then
toggleButtonState(peripheralName, buttonName)
buttonData["func"](monitorsData[peripheralName], buttonData, buttonData.xmin - x, y - buttonData.ymin)
sleep(0.15)
toggleButtonState(peripheralName, buttonName)
return true
end
end
end
end
return false
end
-- method to have in while true do loop
function onClick(listenForEvent)
listenForEvent = listenForEvent or "monitor_touch"
local event, side, x, y = os.pullEvent(listenForEvent)
local foundButton = false
if event == "monitor_touch" then
foundButton = checkPressedButton(side, x, y)
end
return event, side, x, y, foundButton;
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment