poppy-client/lua/ui.lua

461 lines
12 KiB
Lua
Raw Permalink Normal View History

2020-02-20 16:46:19 +00:00
ui = {}
2022-06-23 17:33:05 +00:00
ui.textureTree = nil
2022-08-04 19:06:21 +00:00
local layout = require("lua.layout")
local utils = require("shared.utils")
2022-10-09 10:52:17 +00:00
local fonts = require("shared.fonts")
2021-02-10 20:52:15 +00:00
2023-01-13 19:57:35 +00:00
ui.speedText = {
love.graphics.newText(fonts.normalFont, "0000"),
love.graphics.newText(fonts.normalFont, "0000"),
love.graphics.newText(fonts.normalFont, "0000"),
love.graphics.newText(fonts.normalFont, "0000")
}
2022-07-03 17:57:11 +00:00
ui.sidebarScale = 1
ui.sidebarWidth = 13 * 16
2021-02-10 20:52:15 +00:00
function ui.update_scale(p_scale)
2022-06-24 17:54:38 +00:00
scale = p_scale
2021-02-10 20:52:15 +00:00
end
2023-01-13 19:57:35 +00:00
function ui.updateSpeed(xspeed, yspeed, xpos, ypos)
ui.speedText = {
love.graphics.newText(fonts.normalFont, "XSpeed: " .. xspeed),
love.graphics.newText(fonts.normalFont, "YSpeed: " .. yspeed),
love.graphics.newText(fonts.normalFont, "X: " .. xpos),
love.graphics.newText(fonts.normalFont, "X: " .. ypos)
}
end
2021-11-11 19:31:19 +00:00
2022-06-23 17:33:05 +00:00
ui.helptext = [[[P] toggle fly
2022-06-27 18:06:43 +00:00
{A/D} Move
{Shift} Move faster
2021-11-15 18:32:46 +00:00
[Space] Jump
2022-06-27 18:06:43 +00:00
{A/S/DW} Move (flying)
2021-11-15 18:32:46 +00:00
[C] Clear canvas
[F] Fill foreground
[G] Fill background
2022-06-27 18:06:43 +00:00
{Mouse1} Draw
{Mouse2} Delete
{ctrl} Background draw
[PGUP/PGDWN] Zoom canvas
{Cursor keys} Move camera
2021-11-15 18:32:46 +00:00
]]
2022-10-10 17:46:27 +00:00
local menuVisible = false
2022-01-08 19:59:13 +00:00
local textEnabled = false
local textEntry = ""
function ui.keyreleased(key, _)
2022-10-10 17:46:27 +00:00
if key == "escape" then
menuVisible = not menuVisible
if menuVisible then
love.visible = function(visible)
if visible then
love.update = function(dt)
levelloop.networkSync(dt)
2022-10-10 17:46:27 +00:00
physics.update(dt)
camera.update(dt)
love.timer.sleep((1/60) -dt)
end
else
love.update = function(dt)
levelloop.networkSync(dt)
2022-10-10 17:46:27 +00:00
physics.update(dt)
end
end
end
ui.drawMenu(window.x, window.y)
else
love.visible = function(visible)
if visible then
love.update = levelloop.normalVisible
2022-10-10 17:46:27 +00:00
else
love.update = levelloop.reducedVisible
2022-10-10 17:46:27 +00:00
end
end
ui.draw(window.x, window.y)
end
love.visible(true)
return
end
2022-01-08 19:59:13 +00:00
if key == "return" and not love.keyboard.isDown("lalt") then
textEnabled = true
love.keyboard.setTextInput(true)
ui.draw(window.x, window.y)
end
if textEnabled then
love.visible = function(visible)
if visible then
love.update = function(dt)
levelloop.networkSync(dt)
2022-01-08 19:59:13 +00:00
drawing.input(dt)
physics.update(dt)
camera.update(dt)
end
else
love.update = function(dt)
levelloop.networkSync(dt)
2022-01-08 19:59:13 +00:00
physics.update(dt)
end
end
end
love.visible(true)
love.keyreleased = function(key, _)
if key == "return" and not love.keyboard.isDown("lalt") then
textEnabled = false
if textEntry ~= "" then
2024-02-25 20:48:04 +00:00
levelloop.remoteCall("chatMessage", textEntry)
2022-01-08 19:59:13 +00:00
textEntry = ""
end
ui.draw(window.x, window.y)
love.keyboard.setTextInput(false)
love.keyreleased = levelloop.keyreleased
love.keypressed = levelloop.keypressed
love.update = levelloop.normalVisible
2022-01-08 19:59:13 +00:00
elseif key == "backspace" then
textEntry = string.sub(textEntry, 0, #textEntry -1)
ui.draw(window.x, window.y)
end
end
love.keypressed = function(key, _) return end
else
love.keyreleased = levelloop.keyreleased
love.keypressed = levelloop.keypressed
2022-01-08 19:59:13 +00:00
end
end
function love.textinput(text)
textEntry = textEntry .. text
ui.draw(window.x, window.y)
end
function ui.chatEntry()
local passedEntry = ""
if textEntry == "" then passedEntry = "Start typing your message." else passedEntry = textEntry end
local chatEntry =
{name = "copySize",
{name = "rect",
fill = "fill",
2022-01-08 20:15:39 +00:00
color = { r = .1, g = .1, b = .1, .7 }
2022-01-08 19:59:13 +00:00
},
2022-08-04 19:06:21 +00:00
{name = "frame",
{name = "label",
text = passedEntry
}
2022-01-08 19:59:13 +00:00
}
}
return chatEntry
end
chatentries = {name = "vertical", {name = "spacer", width = 0}}
function ui.chatlog()
return chatentries
end
2022-01-08 20:45:49 +00:00
function ui.addChatEntry(user, message)
2022-01-08 19:59:13 +00:00
if #chatentries > 10 then
table.remove(chatentries, 1)
end
2022-01-08 20:45:49 +00:00
local chatText
if user ~= "" then
chatText = user .. ": " .. message
else
chatText = message
end
2022-01-08 19:59:13 +00:00
local entry = {name = "rotate",
2022-01-08 20:15:39 +00:00
rotation = 0, -- OKAY DIEGO >:(
2022-08-04 19:06:21 +00:00
{name = "copySize",
{name = "rect",
fill = "fill",
color = { r = .1, g = .1, b = .1, a = .6 }
},
{name = "vertical",
{name = "label",
text = chatText,
2022-10-09 10:52:17 +00:00
font = fonts.smallFont
2022-01-08 19:59:13 +00:00
},
2022-08-04 19:06:21 +00:00
{name = "spacer",
height = 2
2022-01-08 19:59:13 +00:00
}
}
}
2022-08-04 19:06:21 +00:00
}
2022-01-08 19:59:13 +00:00
table.insert(chatentries, entry)
ui.draw(window.x, window.y)
end
2022-01-07 22:22:38 +00:00
function ui.loadTextures(directory, container)
if not container then container = {} end
local entries = love.filesystem.getDirectoryItems(directory)
if #entries == 0 then return container end
for i, file in pairs(entries) do
local path = directory .."/".. file
local entry = love.filesystem.getInfo(path)
2022-07-03 17:57:11 +00:00
if entry.type == "directory" and file ~= ".git" then
2022-01-07 22:22:38 +00:00
container[file] = {}
container[file] = ui.loadTextures(path, container[file])
elseif entry.type == "file" or entry.type == "symlink" then
2022-07-03 18:39:15 +00:00
local status, imageData = pcall(love.image.newImageData, path);
if status then
2022-01-07 22:22:38 +00:00
local hash = love.data.hash("sha512", imageData:getString())
levelloop.textures[hash] = {data = imageData}
2022-01-07 22:22:38 +00:00
container[file] = hash
2021-11-13 19:56:43 +00:00
end
end
2022-01-07 22:22:38 +00:00
end
return container
end
function textureEntry(hash)
local texture = levelloop.textures[hash]
2022-06-23 17:33:05 +00:00
assert(texture, "No texture found for textureentry?")
assert(texture.data, "No imagedata found for textureentry?")
if not texture.image then
texture.image = love.graphics.newImage(texture.data)
end
local width = texture.image:getWidth()
local height = texture.image:getHeight()
2022-06-27 18:06:43 +00:00
if drawing and drawing.cursorHash and hash == drawing.cursorHash then
2022-08-04 19:06:21 +00:00
return {name = "overlayRect",
2022-01-07 22:22:38 +00:00
fill = "line",
{name = "drawHash",
2022-06-23 17:33:05 +00:00
hash = hash,
2022-07-03 17:57:11 +00:00
scale = ui.sidebarScale
2022-01-07 22:22:38 +00:00
}
}
else
return {name = "cursorSelect", uiSelect = "GameUI",
2022-01-07 22:22:38 +00:00
identifier = hash,
kind = "picker",
{name = "drawHash",
2022-06-23 17:33:05 +00:00
hash = hash,
2022-07-03 17:57:11 +00:00
scale = ui.sidebarScale
2022-01-07 22:22:38 +00:00
}
}
end
end
function textureRun(entryTable, width)
local textures = levelloop.textures
2022-07-03 17:57:11 +00:00
local entries = {name = "naiveGrid", width = width - 20}
2022-06-24 19:07:54 +00:00
local entryTableSorted = {}
2022-08-04 19:06:21 +00:00
2022-07-03 17:57:11 +00:00
-- Sort the entries alphapetically (or well, probably more... "byte compared") :)
-- This implies that in <author>/<packname>/<fileName> the fileName controls where
-- the texture lands in the block drawer, smaller lands further left.
2022-01-07 22:22:38 +00:00
for iter, entry in pairs(entryTable) do
2022-06-24 19:07:54 +00:00
table.insert(entryTableSorted, {name = iter, entry = entry})
end
table.sort(entryTableSorted, function(k1, k2) return k1.name < k2.name end)
2022-08-04 19:06:21 +00:00
2022-06-24 19:07:54 +00:00
for iter, entry in pairs(entryTableSorted) do
2022-07-03 17:57:11 +00:00
if not textures[entry.entry].image then
textures[entry.entry].image = love.graphics.newImage(textures[entry.entry].data)
2022-01-07 22:22:38 +00:00
end
2022-07-03 17:57:11 +00:00
table.insert(entries, textureEntry(entry.entry))
2022-01-07 22:22:38 +00:00
end
2022-07-03 17:57:11 +00:00
return entries
2022-01-07 22:22:38 +00:00
end
function ui.blockDrawer(textureTree, w, h, container)
2022-06-23 17:33:05 +00:00
if not textureTree then return {name = "label", text = "Loading textures..."} end
2022-06-27 18:06:43 +00:00
local pointSize = 8
2022-07-03 17:57:11 +00:00
if ui.sidebarScale == 2 then pointSize = 16 end
2022-02-16 18:24:47 +00:00
if not container then container = {name="vertical",
2022-06-27 18:06:43 +00:00
{name = "colorPicker", kind = "colorpicker",
2022-06-27 19:16:53 +00:00
granularity = 0.25, pointSize = pointSize},
2022-07-03 17:57:11 +00:00
{name = "spacer", height = 5 * ui.sidebarScale},
2022-06-27 19:16:53 +00:00
{name = "bwColorPicker", kind = "bwColorPicker",
pointSize = pointSize}}
2022-02-16 18:24:47 +00:00
end
local textureTreeSorted = {}
2022-01-07 22:22:38 +00:00
for author, tree in pairs(textureTree) do
table.insert(textureTreeSorted, {author = author, tree = tree})
end
table.sort(textureTreeSorted, function(k1, k2) return k1.author < k2.author end)
for author, tree in pairs(textureTreeSorted) do
for pack, subTree in pairs(tree.tree) do
2022-01-07 22:22:38 +00:00
container.name = "vertical"
table.insert(container, {name = "label", text = pack})
2022-02-16 18:24:47 +00:00
table.insert(container,
{name = "color",
2022-08-04 19:06:21 +00:00
color = drawing.color or {1, 1, 1},
--[[ HACK! remove the 1, 1, 1.
drawing.color should be set!
]]--
2022-02-16 18:24:47 +00:00
textureRun(subTree, w)
})
2021-11-13 19:56:43 +00:00
end
end
2022-01-07 22:22:38 +00:00
return container
end
2022-10-10 17:46:27 +00:00
function ui.menuDrawer(w, h)
2022-10-10 18:27:31 +00:00
return {name = "horizontal",
2022-10-10 18:15:52 +00:00
{name = "vertical",
{name = "button",
2022-10-10 18:15:52 +00:00
identifier = "save",
uiSelect = "Menu",
buttonColor = "greenTranslucent",
text = "Save world"
2022-10-10 18:15:52 +00:00
},
{name = "spacer",
height = 10,
2022-10-10 18:15:52 +00:00
},
{name = "button",
2022-10-10 18:15:52 +00:00
identifier = "disconnect",
uiSelect = "Menu",
buttonColor = "pinkTranslucent",
text = "Disconnect"
2022-10-10 18:15:52 +00:00
},
{name = "spacer",
height = 25,
2022-10-10 18:15:52 +00:00
},
{name = "button",
2022-10-10 18:15:52 +00:00
identifier = "sideBarScaleTwo",
uiSelect = "Menu",
buttonColor = "grayTranslucent",
text = "Ui scale x2"
},
{name = "spacer",
height = 4,
2022-10-10 18:15:52 +00:00
},
{name = "button",
2022-10-10 18:15:52 +00:00
identifier = "sideBarScaleOne",
uiSelect = "Menu",
buttonColor = "grayTranslucent",
text = "Ui scale x1"
2022-12-04 10:08:48 +00:00
},
2022-10-10 18:27:31 +00:00
},
{name = "spacer",
width = 80,
},
{name = "label",
text = ui.helptext,
font = fonts.normallFont
2022-10-10 17:46:27 +00:00
}
}
end
2022-10-13 10:56:01 +00:00
2020-02-20 16:46:19 +00:00
function ui.draw(w, h)
2020-02-09 18:09:02 +00:00
window.x, window.y = w, h
love.graphics.setCanvas(ui.buffer)
layout.uiState.GameUI = {}
love.graphics.clear( )
2022-10-09 10:52:17 +00:00
local blockDrawer = ui.blockDrawer(ui.textureTree, w, h)
blockMaxX, blockMaxY = layout.handle(blockDrawer, 0, 0, true)
local blockDrawerAdjusted = ui.blockDrawer(ui.textureTree, blockMaxX, blockMaxY)
layout.handle(blockDrawerAdjusted, window.x - blockMaxX, 0)
2022-01-08 19:59:13 +00:00
layout.handle(ui.chatlog(), 25, 90)
2021-02-10 20:52:15 +00:00
love.graphics.setCanvas()
2020-02-09 15:53:45 +00:00
end
2021-11-11 19:31:19 +00:00
2022-10-10 17:46:27 +00:00
function ui.drawMenu(w, h)
window.x, window.y = w, h
layout.uiState.Menu = {}
2022-10-10 17:46:27 +00:00
love.graphics.setCanvas(ui.buffer)
love.graphics.clear()
local menuDrawer = ui.menuDrawer(w, h)
menux, menuy = layout.handle(menuDrawer, 0, 0, true)
layout.handle(menuDrawer, (window.x - menux) /2, (window.y - menuy)/2)
love.graphics.setCanvas()
end
2022-06-24 17:54:38 +00:00
function ui.mousepressed(mousex, mousey)
local textures = levelloop.textures
2022-10-10 17:46:27 +00:00
if menuVisible then
for i, v in ipairs(layout.uiState.Menu) do
2022-10-13 10:56:01 +00:00
if mousex >= v.x and mousex <= v.x2 and --hit testing
mousey >= v.y and mousey <= v.y2 then
if v.kind == "button" then
if v.identifier == "save" then
levelloop.networkSend("saveWorld")
2022-10-13 10:56:01 +00:00
ui.keyreleased("escape")
elseif v.identifier == "disconnect" then
2024-02-25 20:48:04 +00:00
levelloop.remoteCall("playerLeave")
2022-10-13 10:56:01 +00:00
menu.init()
elseif v.identifier == "sideBarScaleTwo" then
ui.sidebarScale = 2
ui.draw(window.x, window.y)
ui.keyreleased("escape")
elseif v.identifier == "sideBarScaleOne" then
ui.sidebarScale = 1
ui.draw(window.x, window.y)
ui.keyreleased("escape")
2022-10-10 17:46:27 +00:00
end
end
2022-10-13 10:56:01 +00:00
return -- Return after the first hit...
2022-10-10 17:46:27 +00:00
end
end
else
for i, v in ipairs(layout.uiState.GameUI) do
2022-10-13 10:56:01 +00:00
if mousex >= v.x and mousex <= v.x2 and
mousey >= v.y and mousey <= v.y2 then
if v.kind == "picker" then
assert(v.identifier, "No identifier in picker!")
drawing.cursorHash = v.identifier
drawing.cursor = textures[v.identifier]
assert(drawing.cursor, "No cursor texture found!")
ui.draw(window.x, window.y)
return
elseif v.kind == "tab" then
selectedTab = v.identifier
ui.draw(window.x, window.y)
return
elseif v.kind == "colorpicker" then
print("Picker hit :D")
2022-12-04 10:08:48 +00:00
local scale = ui.sidebarScale / granularity
2022-10-13 10:56:01 +00:00
local red = math.floor((mousey - v.y) / v.pointSize) / scale
local green = math.floor((mousex - v.x) / v.pointSize / (scale + 1)) / scale
local blue = (math.floor((mousex - v.x) / v.pointSize) % (scale + 1)) / scale
print("I think the color is " .. red .. ":" .. green .. ":" .. blue)
2022-10-13 10:56:01 +00:00
drawing.color = {red, green, blue, 1}
ui.draw(window.x, window.y)
return
elseif v.kind == "bwColorPicker" then
local scale = 1.0 / granularity
local saturation = math.floor((mousex - v.x) / v.pointSize) / scale
drawing.color = {saturation, saturation, saturation, 1}
ui.draw(window.x, window.y)
2022-10-10 17:46:27 +00:00
return
end
2022-10-13 10:56:01 +00:00
return
2021-11-13 19:56:43 +00:00
end
end
end
end
2020-02-20 16:46:19 +00:00
ui.init = function()
2022-06-19 10:41:25 +00:00
love.keyboard.setTextInput( false )
2020-02-20 16:46:19 +00:00
local w,h = love.window.getMode()
2022-06-23 17:33:05 +00:00
ui.textureTree = ui.loadTextures("textures/blocks")
2020-02-20 16:46:19 +00:00
ui.draw(w, h)
2020-08-13 19:13:20 +00:00
ui.resize = function()
2020-02-20 16:46:19 +00:00
local w,h = love.window.getMode()
ui.buffer = love.graphics.newCanvas(w, h)
love.graphics.setCanvas(ui.buffer)
2020-02-20 16:46:19 +00:00
love.graphics.clear()
2022-06-24 17:54:38 +00:00
ui.draw(w, h)
2020-02-20 16:46:19 +00:00
love.graphics.setCanvas()
end
end
2022-06-23 17:33:05 +00:00
local w, h = love.window.getMode()
ui.buffer = love.graphics.newCanvas(w, h)
ui.space = 300