[*] Add examples.

master
Lorenzo Cogotti 2 years ago
parent 53fdcdd843
commit c159cb078c

@ -0,0 +1,124 @@
--- Basic menu example
--
-- Trivial menu made of buttons.
-- Illustrates onHit() and onEnter()/onLeave()
-- events.
--
-- Relevant code to build UI inside: makeMainMenu().
--
-- Layout: Rows
-- Widget: Button
local yui = require 'lib.yui'
local Button = yui.Button
local Rows = yui.Rows
local Ui = yui.Ui
local GUI_WIDTH = 500
local GUI_HEIGHT = 300
local FONT_SIZE = 32
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
-- Creates main menu.
local function makeMainMenu()
-- Position the UI
local x,y = centerRectOnScreen(GUI_WIDTH, GUI_HEIGHT)
local rh = GUI_HEIGHT / 5 -- 5 elements along height
-- Keep track what's being focused...
widgetEnter = function (w)
guiStatus.current = "You're hovering \""..w.text.."\", feel like pressing it?"
end
widgetLeave = function (w)
guiStatus.previous = "So you left \""..w.text.."\"..."
end
return Ui.new {
x = x, y = y, -- Place UI at the calculated spot
-- Place the elements in rows from top to bottom
Rows {
Button {
-- Provide first button's size...
w = GUI_WIDTH, h = rh,
text = "Start game",
onHit = function ()
guiStatus = { current = "Game started!" }
end,
onEnter = widgetEnter,
onLeave = widgetLeave
},
Button {
-- ...subsequent widgets _in the same layout_
-- take last widget's size by default.
text = "Continue",
onHit = function()
guiStatus = { current = "Loading game..." }
end,
onEnter = widgetEnter,
onLeave = widgetLeave
},
Button {
text = "Options",
onHit = function()
guiStatus = { current = "Options pressed." }
end,
onEnter = widgetEnter,
onLeave = widgetLeave
},
Button {
text = "Credits",
onHit = function()
guiStatus = { current = "Showcasing credits 8)" }
end,
onEnter = widgetEnter,
onLeave = widgetLeave
},
Button {
text = "Quit",
onHit = function () love.event.quit() end,
onEnter = widgetEnter,
onLeave = widgetLeave
}
}
}
end
function love.load()
guiStatus = { current = "Menu is open." }
guiFont = love.graphics.newFont('fonts/PixelDroidMenu.ttf', FONT_SIZE)
gui = makeMainMenu()
end
function love.update(dt)
-- Let the UI update its status
gui:update(dt)
end
function love.draw()
love.graphics.setFont(guiFont)
-- Print UI status
local y = 0
if guiStatus.previous ~= nil then
love.graphics.print(guiStatus.previous, 0, y)
y = y + guiFont:getHeight()
end
love.graphics.print(guiStatus.current, 0, y)
-- Draw UI
gui:draw()
end

@ -0,0 +1,51 @@
-- the ubiquitous "Hello, World!" demo.
-- 'Nuff said.
--
-- Layout: Rows
-- Widgets: Label, Button
-- Relevant UI construction code in: love.load()
local yui = require 'lib.yui'
-- Some convenience aliases
local Ui = yui.Ui
local Rows = yui.Rows
local Button, Label = yui.Button, yui.Label
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
function love.load()
local W, H = 400, 80 -- pick arbitrary UI size
local x, y = centerRectOnScreen(W, H)
gui = Ui.new {
x = x, y = y,
Rows {
Label {
w = W, h = H,
text = "Hello, World!"
},
Button {
text = "OBEY",
onHit = function () love.event.quit() end
}
}
}
end
function love.update(dt)
gui:update(dt)
end
function love.draw()
-- Pretty black out there, isn't it?
-- See more complete examples for shinier stuff :)
gui:draw()
end

@ -0,0 +1,79 @@
local BASE = (...)..'.'
local endswith = require('lib.gear.strings').endswith
local yui = require 'lib.yui'
local Button = yui.Button
local Rows = yui.Rows
local Ui = yui.Ui
local Examples = {}
Examples.__index = Examples
local function isexample(file)
return file ~= 'init.lua' and endswith(file, '.lua')
end
local function loadexample(file)
love.event.clear()
for i in ipairs(love.handlers) do
love.handlers[i] = nil
end
-- Restart to next example.
require(BASE..file)
if love.load then love.load() end
end
local W = 400
local RH = 32
local function makeSelectionMenu()
local menu = Rows {}
local files = love.filesystem.getDirectoryItems('examples')
table.sort(files)
for _,file in ipairs(files) do
if isexample(file) then
local name = file:sub(1, -5)
menu[#menu+1] = Button {
w = W, h = RH,
text = name,
notranslate = true,
onHit = function() loadexample(name) end
}
end
end
menu[#menu+1] = Button {
w = W, h = RH,
text = "Quit",
onHit = function() love.event.quit() end
}
local x = math.floor(love.graphics.getWidth() - W) / 2
local y = math.floor(love.graphics.getHeight() - RH * #menu) / 2
return Ui.new {
x = x, y = y,
menu
}
end
function love.load()
gui = makeSelectionMenu()
end
function love.update(dt)
gui:update(dt)
end
function love.draw()
gui:draw()
end
return Examples

@ -0,0 +1,264 @@
--- 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

Binary file not shown.

@ -0,0 +1,8 @@
pixeldroid fonts
Available at: https://github.com/pixeldroid/fonts
.otf, .ttf, and .fnt files can be downloaded from the releases page.
pixeldroid fonts are licensed under the Open Font License (OFL).
Full SIL Open Font License: https://scripts.sil.org/cms/scripts/page.php?site_id=nrsi&id=OFL

@ -0,0 +1 @@
require 'examples'

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Loading…
Cancel
Save