[*] Add examples.
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
|
Binary file not shown.
After Width: | Height: | Size: 8.8 KiB |
Loading…
Reference in New Issue