ui = {} ui.textureTree = nil local layout = require("lua.layout") local utils = require("shared.utils") local fonts = require("shared.fonts") 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") } ui.sidebarScale = 1 ui.sidebarWidth = 13 * 16 function ui.update_scale(p_scale) scale = p_scale end 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 ui.helptext = [[[P] toggle fly {A/D} Move {Shift} Move faster [Space] Jump {A/S/DW} Move (flying) [C] Clear canvas [F] Fill foreground [G] Fill background {Mouse1} Draw {Mouse2} Delete {ctrl} Background draw [PGUP/PGDWN] Zoom canvas {Cursor keys} Move camera ]] local menuVisible = false local textEnabled = false local textEntry = "" function ui.keyreleased(key, _) if key == "escape" then menuVisible = not menuVisible if menuVisible then love.visible = function(visible) if visible then love.update = function(dt) levelloop.networkSync(dt) physics.update(dt) camera.update(dt) love.timer.sleep((1/60) -dt) end else love.update = function(dt) levelloop.networkSync(dt) physics.update(dt) end end end ui.drawMenu(window.x, window.y) else love.visible = function(visible) if visible then love.update = levelloop.normalVisible else love.update = levelloop.reducedVisible end end ui.draw(window.x, window.y) end love.visible(true) return end 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) drawing.input(dt) physics.update(dt) camera.update(dt) end else love.update = function(dt) levelloop.networkSync(dt) 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 levelloop.remoteCall("chatMessage", textEntry) textEntry = "" end ui.draw(window.x, window.y) love.keyboard.setTextInput(false) love.keyreleased = levelloop.keyreleased love.keypressed = levelloop.keypressed love.update = levelloop.normalVisible 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 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", color = { r = .1, g = .1, b = .1, .7 } }, {name = "frame", {name = "label", text = passedEntry } } } return chatEntry end chatentries = {name = "vertical", {name = "spacer", width = 0}} function ui.chatlog() return chatentries end function ui.addChatEntry(user, message) if #chatentries > 10 then table.remove(chatentries, 1) end local chatText if user ~= "" then chatText = user .. ": " .. message else chatText = message end local entry = {name = "rotate", rotation = 0, -- OKAY DIEGO >:( {name = "copySize", {name = "rect", fill = "fill", color = { r = .1, g = .1, b = .1, a = .6 } }, {name = "vertical", {name = "label", text = chatText, font = fonts.smallFont }, {name = "spacer", height = 2 } } } } table.insert(chatentries, entry) ui.draw(window.x, window.y) end 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) if entry.type == "directory" and file ~= ".git" then container[file] = {} container[file] = ui.loadTextures(path, container[file]) elseif entry.type == "file" or entry.type == "symlink" then local status, imageData = pcall(love.image.newImageData, path); if status then local hash = love.data.hash("sha512", imageData:getString()) levelloop.textures[hash] = {data = imageData} container[file] = hash end end end return container end function textureEntry(hash) local texture = levelloop.textures[hash] 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() if drawing and drawing.cursorHash and hash == drawing.cursorHash then return {name = "overlayRect", fill = "line", {name = "drawHash", hash = hash, scale = ui.sidebarScale } } else return {name = "cursorSelect", uiSelect = "GameUI", identifier = hash, kind = "picker", {name = "drawHash", hash = hash, scale = ui.sidebarScale } } end end function textureRun(entryTable, width) local textures = levelloop.textures local entries = {name = "naiveGrid", width = width - 20} local entryTableSorted = {} -- Sort the entries alphapetically (or well, probably more... "byte compared") :) -- This implies that in // the fileName controls where -- the texture lands in the block drawer, smaller lands further left. for iter, entry in pairs(entryTable) do table.insert(entryTableSorted, {name = iter, entry = entry}) end table.sort(entryTableSorted, function(k1, k2) return k1.name < k2.name end) for iter, entry in pairs(entryTableSorted) do if not textures[entry.entry].image then textures[entry.entry].image = love.graphics.newImage(textures[entry.entry].data) end table.insert(entries, textureEntry(entry.entry)) end return entries end function ui.blockDrawer(textureTree, w, h, container) if not textureTree then return {name = "label", text = "Loading textures..."} end local pointSize = 8 if ui.sidebarScale == 2 then pointSize = 16 end if not container then container = {name="vertical", {name = "colorPicker", kind = "colorpicker", granularity = 0.25, pointSize = pointSize}, {name = "spacer", height = 5 * ui.sidebarScale}, {name = "bwColorPicker", kind = "bwColorPicker", pointSize = pointSize}} end local textureTreeSorted = {} 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 container.name = "vertical" table.insert(container, {name = "label", text = pack}) table.insert(container, {name = "color", color = drawing.color or {1, 1, 1}, --[[ HACK! remove the 1, 1, 1. drawing.color should be set! ]]-- textureRun(subTree, w) }) end end return container end function ui.menuDrawer(w, h) return {name = "horizontal", {name = "vertical", {name = "button", identifier = "save", uiSelect = "Menu", buttonColor = "greenTranslucent", text = "Save world" }, {name = "spacer", height = 10, }, {name = "button", identifier = "disconnect", uiSelect = "Menu", buttonColor = "pinkTranslucent", text = "Disconnect" }, {name = "spacer", height = 25, }, {name = "button", identifier = "sideBarScaleTwo", uiSelect = "Menu", buttonColor = "grayTranslucent", text = "Ui scale x2" }, {name = "spacer", height = 4, }, {name = "button", identifier = "sideBarScaleOne", uiSelect = "Menu", buttonColor = "grayTranslucent", text = "Ui scale x1" }, }, {name = "spacer", width = 80, }, {name = "label", text = ui.helptext, font = fonts.normallFont } } end function ui.draw(w, h) window.x, window.y = w, h love.graphics.setCanvas(ui.buffer) layout.uiState.GameUI = {} love.graphics.clear( ) 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) layout.handle(ui.chatlog(), 25, 90) love.graphics.setCanvas() end function ui.drawMenu(w, h) window.x, window.y = w, h layout.uiState.Menu = {} 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 function ui.mousepressed(mousex, mousey) local textures = levelloop.textures if menuVisible then for i, v in ipairs(layout.uiState.Menu) do 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") ui.keyreleased("escape") elseif v.identifier == "disconnect" then levelloop.remoteCall("playerLeave") 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") end end return -- Return after the first hit... end end else for i, v in ipairs(layout.uiState.GameUI) do 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") local scale = ui.sidebarScale / granularity 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) 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) return end return end end end end ui.init = function() love.keyboard.setTextInput( false ) local w,h = love.window.getMode() ui.textureTree = ui.loadTextures("textures/blocks") ui.draw(w, h) ui.resize = function() local w,h = love.window.getMode() ui.buffer = love.graphics.newCanvas(w, h) love.graphics.setCanvas(ui.buffer) love.graphics.clear() ui.draw(w, h) love.graphics.setCanvas() end end local w, h = love.window.getMode() ui.buffer = love.graphics.newCanvas(w, h) ui.space = 300