--- Options screen example -- -- A fairly complete configuration menu to demonstrate -- several types of widgets coexisting. -- Many widgets' behavior is tuned by their attributes. -- -- Relevant code to build UI inside: makeOptionsMenu(). -- -- Layout: Rows, Columns -- Widget: Button, Checkbox, Choice, Input, Label, Slider, Spacer local yui = require 'lib.yui' local Button = yui.Button local Checkbox = yui.Checkbox local Choice = yui.Choice local Columns = yui.Columns local Input = yui.Input local Label = yui.Label local Rows = yui.Rows local Slider = yui.Slider local Spacer = yui.Spacer local Ui = yui.Ui local GUI_WIDTH = 500 local GUI_HEIGHT = 300 local FONT_SIZE = 32 -- A dummy save file, for demo purposes. local dummySave = {} -- Dummy config load mock. function dummySave.load() local config = {} -- The default configuration local defconfig = { name = "Player 1", graphics = 'medium', lang = 'en', fullscreen = false, musicVolume = 80, sfxVolume = 90 } local saved = dummySave.latest or defconfig print("Loading configuration: {") for k,v in pairs(saved) do config[k] = v print(("\t%s = %s,"):format(k, v)) end print("}") return config end -- Dummy config save mock function dummySave.save(config) dummySave.latest = {} print("Saving configuration: {") for k,v in pairs(config) do dummySave.latest[k] = v print(("\t%s = %s,"):format(k, v)) end print("}") end -- Center rectangle on screen. local function centerRectOnScreen(w, h) local x = math.floor((love.graphics.getWidth() - w) / 2) local y = math.floor((love.graphics.getHeight() - h) / 2) return x, y end -- Actual menu creation. local function makeOptionsMenu() -- Position the UI local x,y = centerRectOnScreen(GUI_WIDTH, GUI_HEIGHT) local vpad = 8 local hpad = 4 local w = (GUI_WIDTH - hpad) / 2 -- cut away padding from widget width local h = (GUI_HEIGHT - vpad) / 9 -- 9 rows (Spacer counts as 2) -- Load configuration "from disk" local config = dummySave.load() -- Make configuration editable via UI return Ui:new { x = x, y = y, Rows { padding = vpad, Columns { padding = hpad, Label { w = w, h = h, text = "Name" }, Input { text = config.name, -- populate initial value onChange = function(_, text) config.name = text -- write changed value back end } }, Columns { padding = hpad, Label { w = w, h = h, text = "Language" }, Choice { -- We don't want languages to be translated. notranslate = true, choices = { { text = "English", value = 'en' }, -- just kidding, only English in demo :) -- { text = "Français", value = 'fr' }, -- { text = "Italiano", value = 'it' }, -- { text = "日本語", value = 'ja' } }, default = config.lang, nowrap = true, onChange = function(_, choice) config.lang = choice.value end } }, Columns { padding = hpad, Label { w = w, h = h, text = "Graphics" }, Choice { choices = { -- Text may be localized, -- so map entries to well known enum values. { text = "Fastest", value = 'low' }, { text = "Normal", value = 'medium' }, { text = "Best", value = 'high' } }, default = config.graphics, nowrap = true, onChange = function(_, choice) config.graphics = choice.value end } }, Columns { padding = hpad, Label { w = w, h = h, text = "Fullscreen" }, Checkbox { checked = config.fullscreen, onChange = function(_, checked) config.fullscreen = checked end } }, Columns { padding = hpad, Label { w = w, h = h, text = "Music" }, Slider { min = 0, max = 100, value = config.musicVolume, onChange = function(_, value) config.musicVolume = value end } }, Columns { padding = hpad, Label { w = w, h = h, text = "Effects" }, Slider { min = 0, max = 100, value = config.sfxVolume, onChange = function(_, value) config.sfxVolume = value end } }, Spacer { h = 2*h }, -- leave 2 rows out. Columns { padding = hpad, Button { w = w, h = h, text = "Back", cancelfocus = true, -- gets focused on ESC. onHit = function() love.event.quit() end }, Button { text = "Apply", onHit = function() -- Save configuration "on disk" dummySave.save(config) end } } } } end function love.load() guiFont = love.graphics.newFont('fonts/PixelDroidMenu.ttf', FONT_SIZE) gui = makeOptionsMenu() end function love.update(dt) -- Let the UI update its status gui:update(dt) end -- Options menu contains a text input field, -- this requires propagating LÖVE input events to UI. function love.keypressed(key, scan, isrepeat) gui:keypressed(key, scan, isrepeat) end function love.keyreleased(key, scan) gui:keyreleased(key, scan) end function love.textinput(text) gui:textinput(text) end function love.textedited(text, start, len) gui:textedited(text, start, len) end function love.draw() love.graphics.setFont(guiFont) -- Draw menu title local title = "Options" local tw = guiFont:getWidth(title) local th = guiFont:getHeight() local tx = (love.graphics.getWidth() - tw) / 2 local ty = th*2 love.graphics.print(title, tx,ty) -- Draw UI gui:draw() end