Love Loader v2.0
This commit is contained in:
parent
9513a5c471
commit
f562b23197
16 changed files with 933 additions and 207 deletions
190
skins/base.lua
Normal file
190
skins/base.lua
Normal file
|
@ -0,0 +1,190 @@
|
|||
return function(ll)
|
||||
|
||||
-- Basic cmd-like style UI
|
||||
-- FIXME: Console scrolling
|
||||
|
||||
local cw, ch, ctw, cth
|
||||
local ct = 'Love Loader v2.0\n(c) Er2 2022\tZlib License\n\n'
|
||||
local cce = false
|
||||
local buf = ''
|
||||
|
||||
local mb, mpb, mt = 0, 0, 0
|
||||
|
||||
local function ccp()
|
||||
local argv = {}
|
||||
for v in buf:gmatch '%S+'
|
||||
do table.insert(argv, v)
|
||||
end
|
||||
local cmd = (argv[1] or ''):lower()
|
||||
if cmd == '' then return '' -- nothing
|
||||
elseif cmd == 'help' then return 'Available commands:'
|
||||
.. '\nhelp\t\tThis command'
|
||||
.. '\nls\t\tList of games'
|
||||
.. '\ndir\t\tSame as ls'
|
||||
.. '\ncat\t<path>\tInformation about game'
|
||||
.. '\ninfo\t<path>\tSame as cat'
|
||||
.. '\nrun\t<path>\tStart game'
|
||||
.. '\nmount\t<path>\tSame as run'
|
||||
.. '\nchroot\t<path>\tSame as run'
|
||||
.. '\nclear\t\tClear screen'
|
||||
.. '\neval\t<code>\tExecute code'
|
||||
elseif cmd == 'clear' then
|
||||
ct = ''
|
||||
return ''
|
||||
elseif cmd == 'eval' then
|
||||
local code = buf:match '^%S+%s+(.*)'
|
||||
local f, err = load(code, 'test.lua')
|
||||
if not f then return err
|
||||
else return tostring(f() or 'nil')
|
||||
end
|
||||
elseif cmd == 'ls'
|
||||
or cmd == 'dir' then
|
||||
local r = ''
|
||||
if #ll.games == 0 then
|
||||
return ('%s: No games found. Add some to the library.'):format(argv[1])
|
||||
end
|
||||
for i = 1, #ll.games do
|
||||
local v = ll.games[i]
|
||||
r = r .. ('%s\t(%s)\t - %s\n'):format(v.dir, v.name, v.desc)
|
||||
end
|
||||
return r .. ('\nTotal: %3d games\n'):format(#ll.games)
|
||||
elseif cmd == 'cat'
|
||||
or cmd == 'info' then
|
||||
if not argv[2]
|
||||
then return ('%s: Game directory missing'):format(argv[1])
|
||||
end
|
||||
local r = ''
|
||||
for _, v in pairs(ll.games) do
|
||||
if argv[2] == v.dir
|
||||
or argv[2] == v.base .. v.dir
|
||||
then r = r..
|
||||
( '\nFriendly name:\t%s'
|
||||
..'\nDescription:\t%s'
|
||||
..'\nLocation:\t%s%s'
|
||||
..'\nMain file:\t%s'
|
||||
..'\n\n\t\tScreenshots are not supported yet.'
|
||||
..'\n'):format(v.name, v.desc, v.base, v.dir, v.main)
|
||||
end
|
||||
end
|
||||
if r == '' then r = 'Not found' end
|
||||
return r
|
||||
elseif cmd == 'run'
|
||||
or cmd == 'mount'
|
||||
or cmd == 'chroot' then
|
||||
local gme
|
||||
for _, v in pairs(ll.games) do
|
||||
if argv[2] == v.dir
|
||||
or argv[2] == v.base .. v.dir
|
||||
then if gme then
|
||||
return 'Error: multiple paths found, use full location'
|
||||
end
|
||||
gme = v end
|
||||
end
|
||||
if gme
|
||||
then ll.mount(gme)
|
||||
love.keyboard.setTextInput(false)
|
||||
return ''
|
||||
else return 'Not found'
|
||||
end
|
||||
else return 'Unknown command "'.. cmd .. '"'
|
||||
end
|
||||
end
|
||||
|
||||
local function update()
|
||||
mpb = mb
|
||||
if love.mouse.isDown(1) then mb = 1
|
||||
if mpb ~= 1
|
||||
then mt = os.time()
|
||||
end
|
||||
else mb = 0
|
||||
end
|
||||
|
||||
if mb == 0 and mpb == 1
|
||||
and os.time() - mt <= 1 then
|
||||
if love.system.getOS() == 'Android' then
|
||||
love.keyboard.setTextInput(
|
||||
not love.keyboard.hasTextInput(),
|
||||
0, H, W, ch)
|
||||
end
|
||||
end
|
||||
|
||||
if not cce then
|
||||
cce = true
|
||||
local r = ccp()
|
||||
if #r ~= 0 then ct = ct.. '\n'.. r end
|
||||
ct = ct.. '\n> '
|
||||
buf = ''
|
||||
end
|
||||
end
|
||||
|
||||
local utf8 = require 'utf8'
|
||||
local function draw()
|
||||
love.graphics.setColor(255, 255, 255)
|
||||
|
||||
local x, y = 0, 0
|
||||
for p, cde in utf8.codes(ct) do
|
||||
local chr = utf8.char(cde)
|
||||
if chr == '\n'
|
||||
then x, y = 0, y + 1
|
||||
elseif chr == '\r'
|
||||
then x = 0
|
||||
elseif chr == '\t'
|
||||
then x = x + 8 - (x % 8)
|
||||
elseif chr == '\v'
|
||||
then y = y + 1
|
||||
else love.graphics.print(chr, x * cw, y * ch)
|
||||
if x >= ctw
|
||||
then x, y = x - ctw, y + 1
|
||||
else x = x + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
if os.time() % 2 == 0
|
||||
then love.graphics.rectangle('fill', x * cw, y * ch, cw, ch)
|
||||
end
|
||||
end
|
||||
|
||||
function resize()
|
||||
local f = love.graphics.newFont(math.min(W, H) / 32)
|
||||
love.graphics.setFont(f)
|
||||
cw, ch = f:getWidth 'm', f:getHeight 'A'
|
||||
ctw, cth =
|
||||
math.floor(W / cw) - 1,
|
||||
math.floor(H / ch) - 1
|
||||
|
||||
love.keyboard.setTextInput(true, 0, H, W, ch)
|
||||
end
|
||||
|
||||
function love.textinput(txt)
|
||||
ct = ct.. txt
|
||||
buf = buf.. txt
|
||||
end
|
||||
|
||||
function love.keypressed(k)
|
||||
if k == 'backspace' then
|
||||
local off = utf8.offset(buf, -1)
|
||||
if off then
|
||||
buf = buf:sub(1, off - 1)
|
||||
off = utf8.offset(ct, -1)
|
||||
if off
|
||||
then ct = ct:sub(1, off - 1)
|
||||
end
|
||||
end
|
||||
elseif k == 'return'
|
||||
then cce = false
|
||||
end
|
||||
end
|
||||
|
||||
love.keyboard.setKeyRepeat(true)
|
||||
love.window.setMode(800, 600, {resizable = true})
|
||||
|
||||
return {
|
||||
update = update,
|
||||
draw = draw,
|
||||
lovecb = {
|
||||
'textinput',
|
||||
'keypressed',
|
||||
},
|
||||
}
|
||||
|
||||
end
|
220
skins/gui.lua
Normal file
220
skins/gui.lua
Normal file
|
@ -0,0 +1,220 @@
|
|||
return function(ll)
|
||||
|
||||
-- Classic UI from Love Loader v1
|
||||
|
||||
ll.cfg.pcht = ll.cfg.pcht or 60 * 5
|
||||
|
||||
local pikchv, pikcha = 0, 0
|
||||
local pikchao = math.floor(1 / ll.cfg.pcht * 2 * 255 + 0.5)
|
||||
|
||||
local cx, cy, cw, ch
|
||||
local f, bf
|
||||
|
||||
local mx, mb, mpb = 0, 0, 0
|
||||
local cdir, sel = 0, 1
|
||||
|
||||
function resize()
|
||||
cw = W / 1.25
|
||||
ch = H / 1.25
|
||||
cx = (W - cw) / 2
|
||||
cy = (H - ch) / 2
|
||||
|
||||
local th = math.min(W, H) / 8
|
||||
|
||||
f = love.graphics.newFont(th / 3)
|
||||
bf = love.graphics.newFont(th / 2)
|
||||
end
|
||||
|
||||
local function update()
|
||||
mx = love.mouse.getX()
|
||||
mpb = mb
|
||||
if love.mouse.isDown(1) then mb = 1
|
||||
else mb = 0 end
|
||||
|
||||
local sdi = 0
|
||||
if mpb == 1 and mb == 0 then
|
||||
if mx <= cx
|
||||
then sdi = 1
|
||||
elseif mx >= cx + cw
|
||||
then sdi = 2
|
||||
else sdi = 3
|
||||
end
|
||||
end
|
||||
|
||||
if love.keyboard.isScancodeDown('left', 'a')
|
||||
then sdi = 1
|
||||
elseif love.keyboard.isScancodeDown('right', 'd')
|
||||
then sdi = 2
|
||||
elseif love.keyboard.isScancodeDown('return', 'space')
|
||||
then sdi = 3
|
||||
end
|
||||
|
||||
if cdir ~= sdi then
|
||||
cdir = sdi
|
||||
if sdi == 1
|
||||
then sel = sel - 1
|
||||
elseif sdi == 2
|
||||
then sel = sel + 1
|
||||
elseif sdi == 3 and ll.games[sel]
|
||||
then ll.mount(ll.games[sel])
|
||||
end
|
||||
|
||||
if sel < 1 then sel = #ll.games end
|
||||
if sel > #ll.games then sel = 1 end
|
||||
end
|
||||
|
||||
pikchv = pikchv + 1
|
||||
if pikchv >= ll.cfg.pcht then
|
||||
pikchv = 0
|
||||
pikcha = 0
|
||||
for _, v in pairs(ll.games) do
|
||||
if v.dat.scr then
|
||||
v.scrprv = v.scrcur
|
||||
v.scrcur = v.scrcur + 1
|
||||
if v.scrcur > #v.dat.scr
|
||||
then v.scrcur = 1
|
||||
end
|
||||
end
|
||||
end
|
||||
else pikcha = math.min(255, pikcha + pikchao)
|
||||
end
|
||||
|
||||
if love.keyboard.isDown 'menu'
|
||||
and mx >= W - 8
|
||||
then pcall(select(2, pcall(require, 'dev.devtools')), ll)
|
||||
end
|
||||
end
|
||||
|
||||
local tm = 0
|
||||
local function draw()
|
||||
love.graphics.setColor(0 / COLDIV, 50 / COLDIV, 75 / COLDIV)
|
||||
love.graphics.rectangle('fill', 0, 0, W, H)
|
||||
love.graphics.setColor(255, 255, 255, 100 / COLDIV)
|
||||
love.graphics.setLineWidth(8)
|
||||
love.graphics.setFont(bf)
|
||||
local t = 'Love Loader'
|
||||
local tw, th = bf:getWidth(t), bf:getHeight(t)
|
||||
love.graphics.print(t, W - tw - 8, H - th)
|
||||
|
||||
tm = (tm + 0.02) % 6.28
|
||||
local c, pc, ps = tm, math.cos(tm), math.sin(tm)
|
||||
local oy = H / 2
|
||||
for x = 0, W + 8, 8 do
|
||||
c = c + 0.1
|
||||
local c, s = math.cos(c), math.sin(c)
|
||||
local cy, ncy, sy, nsy =
|
||||
pc * H / 12,
|
||||
c * H / 12,
|
||||
ps * H / 12,
|
||||
s * H / 12
|
||||
|
||||
love.graphics.line(x - 8, sy + oy, x-1, nsy + oy)
|
||||
love.graphics.line(x - 8, sy/2 + oy, x-1, nsy/2 + oy)
|
||||
love.graphics.line(x - 8, cy/1.5 + oy, x-1, ncy/1.5 + oy)
|
||||
love.graphics.line(x - 8, cy*1.5 + oy, x-1, ncy*1.5 + oy)
|
||||
pc, ps = c, s
|
||||
end
|
||||
love.graphics.setColor(255, 255, 255, 255)
|
||||
love.graphics.setLineWidth(1)
|
||||
|
||||
local oy, t = 0, ''
|
||||
local gme = ll.games[sel]
|
||||
if gme then
|
||||
love.graphics.polygon('fill',
|
||||
8, H / 2,
|
||||
32, H / 2 - 32,
|
||||
32, H / 2 + 32)
|
||||
|
||||
love.graphics.polygon('fill',
|
||||
W - 8, H / 2,
|
||||
W - 32, H / 2 - 32,
|
||||
W - 32, H / 2 + 32)
|
||||
|
||||
love.graphics.stencil(function()
|
||||
love.graphics.rectangle('fill', cx, cy, cw, ch, 16)
|
||||
end)
|
||||
love.graphics.setStencilTest('greater', 0)
|
||||
love.graphics.setColor(50 / COLDIV, 50 / COLDIV, 50 / COLDIV, 100 / COLDIV)
|
||||
love.graphics.rectangle('fill', cx, cy, cw, ch)
|
||||
love.graphics.setColor(255, 255, 255, 255)
|
||||
|
||||
if gme.dat.scr then
|
||||
local p, n = gme.dat.scr[gme.scrprv], gme.dat.scr[gme.scrcur]
|
||||
love.graphics.draw(p, cx, cy, 0, cw / p:getWidth(), ch / p:getHeight())
|
||||
love.graphics.setColor(255, 255, 255, pikcha / COLDIV)
|
||||
love.graphics.draw(n, cx, cy, 0, cw / n:getWidth(), ch / n:getHeight())
|
||||
love.graphics.setColor(0, 0, 0, 150 / COLDIV)
|
||||
love.graphics.rectangle('fill', cx, cy, cw, ch)
|
||||
love.graphics.setColor(255, 255, 255, 255)
|
||||
end
|
||||
|
||||
oy = cy + ch / 1.25
|
||||
love.graphics.setFont(bf)
|
||||
love.graphics.print(gme.name, cx + 16, oy)
|
||||
oy = oy + bf:getHeight(gme.name)
|
||||
love.graphics.setFont(f)
|
||||
love.graphics.print(gme.desc, cx + 16, oy)
|
||||
love.graphics.setStencilTest()
|
||||
love.graphics.rectangle('line', cx, cy, cw, ch, 16)
|
||||
|
||||
elseif ll.games[1] then
|
||||
sel = 1
|
||||
love.graphics.setColor(255, 255, 255, 255)
|
||||
love.graphics.print('Sorry :)', W / 2, H / 2)
|
||||
else love.graphics.setColor(255, 255, 255, 255)
|
||||
oy = H / 2.5
|
||||
t = 'No games'
|
||||
love.graphics.setFont(bf)
|
||||
love.graphics.print(t, (W - bf:getWidth(t)) / 2, oy)
|
||||
oy = oy + bf:getHeight(t)
|
||||
love.graphics.setFont(f)
|
||||
t = 'There are no projects/games to run'
|
||||
love.graphics.print(t, (W - f:getWidth(t)) / 2, oy)
|
||||
end
|
||||
end
|
||||
|
||||
function error(msg)
|
||||
msg = tostring(msg)
|
||||
|
||||
love.graphics.reset()
|
||||
love.graphics.origin()
|
||||
local bf = love.graphics.newFont(64)
|
||||
local f = love.graphics.setNewFont(16)
|
||||
local perc = 0
|
||||
|
||||
local q
|
||||
repeat
|
||||
perc = math.min(100, perc + 0.1 * math.random(50))
|
||||
|
||||
love.graphics.clear(17/COLDIV, 113/COLDIV, 172/COLDIV)
|
||||
love.graphics.setColor(255, 255, 255)
|
||||
love.graphics.setFont(bf)
|
||||
love.graphics.print(':(', 64, 16)
|
||||
love.graphics.setFont(f)
|
||||
love.graphics.print(('%d%% complete'):format(perc), 64, 100)
|
||||
love.graphics.printf(msg, 64, 132, W - 64)
|
||||
love.graphics.print('(c) Love Loader and Er2', 8, H - 16 - 8)
|
||||
love.graphics.present()
|
||||
|
||||
love.event.pump()
|
||||
for n, a,b,c in love.event.poll() do
|
||||
if n == 'quit'
|
||||
or n == 'mousereleased'
|
||||
or (n == 'keypressed' and a == 'escape')
|
||||
then q = true end
|
||||
end
|
||||
|
||||
love.timer.sleep(0.5)
|
||||
until q or perc == 100
|
||||
|
||||
-- Unfortunately, we can't restart Love in error handler
|
||||
llHome() -- but can outside of love.errorhandler
|
||||
return function() return 1 end
|
||||
end
|
||||
|
||||
return {
|
||||
update = update,
|
||||
draw = draw,
|
||||
}
|
||||
|
||||
end
|
175
skins/psp.lua
Normal file
175
skins/psp.lua
Normal file
|
@ -0,0 +1,175 @@
|
|||
return function(ll)
|
||||
|
||||
-- New UI from Sony PSP
|
||||
|
||||
local sel = 1
|
||||
local psel
|
||||
|
||||
local cx, cy, cw, ch, cg
|
||||
local css, rcss = 2, 0
|
||||
|
||||
local f, bf
|
||||
|
||||
ll.cfg.pcht = ll.cfg.pcht or 60 * 5
|
||||
|
||||
local pikchv, pikcha = 0, 0
|
||||
local pikchao = math.floor(1 / ll.cfg.pcht * 2 * 255 + 0.5)
|
||||
|
||||
function resize()
|
||||
r = math.min(W, H) / 30
|
||||
|
||||
cg = H / 64
|
||||
cw = W / 5
|
||||
ch = (H - cg) / 6
|
||||
cx = W / 10
|
||||
cy = -H / 2
|
||||
|
||||
f = love.graphics.setNewFont(math.min(W, H) / 30)
|
||||
bf = love.graphics.newFont(math.min(W, H) / 20)
|
||||
end
|
||||
|
||||
love.window.setMode(800, 600, {resizable = true})
|
||||
|
||||
local my, mb, mpb
|
||||
|
||||
local sdir = 0
|
||||
local function update()
|
||||
local ty = H / 2 - (ch + cg) * sel
|
||||
cy = cy + (ty - cy) * 0.1
|
||||
css = css + (2 - css) * 0.2
|
||||
rcss = 2 - css + 1
|
||||
|
||||
local sdi
|
||||
|
||||
my = love.mouse.getY()
|
||||
mpb = mb
|
||||
if love.mouse.isDown(1) then mb = 1
|
||||
else mb = 0
|
||||
end
|
||||
if mb == 0 and mpb == 1 then
|
||||
if my <= H / 2 - ch
|
||||
then sdi = 1
|
||||
elseif my >= H / 2 + ch + cg
|
||||
then sdi = 2
|
||||
else sdi = 3
|
||||
end
|
||||
elseif love.keyboard.isScancodeDown('up', 'w')
|
||||
then sdi = 1
|
||||
elseif love.keyboard.isScancodeDown('down', 's')
|
||||
then sdi = 2
|
||||
elseif love.keyboard.isScancodeDown('return', 'space')
|
||||
then sdi = 3
|
||||
else sdi = 0
|
||||
end
|
||||
|
||||
if sdi ~= sdir then
|
||||
if sdi ~= 0
|
||||
then rcss = css
|
||||
css = 1
|
||||
if sdi == 3
|
||||
then css = 1.5
|
||||
end
|
||||
psel = sel
|
||||
end
|
||||
sdir = sdi
|
||||
if sdi == 1
|
||||
then sel = sel - 1
|
||||
elseif sdi == 2
|
||||
then sel = sel + 1
|
||||
elseif sdi == 3 and ll.games[sel]
|
||||
then ll.mount(ll.games[sel])
|
||||
end
|
||||
|
||||
if sel < 1 then sel = #ll.games end
|
||||
if sel > #ll.games then sel = 1 end
|
||||
end
|
||||
|
||||
pikchv = pikchv + 1
|
||||
if pikchv >= ll.cfg.pcht then
|
||||
pikchv = 0
|
||||
pikcha = 0
|
||||
for _, v in pairs(ll.games) do
|
||||
if v.dat.scr then
|
||||
v.scrprv = v.scrcur
|
||||
v.scrcur = v.scrcur + 1
|
||||
if v.scrcur > #v.dat.scr
|
||||
then v.scrcur = 1
|
||||
end
|
||||
end
|
||||
end
|
||||
else pikcha = math.min(255, pikcha + pikchao)
|
||||
end
|
||||
end
|
||||
|
||||
local function scrCard(gme, x, y, w, h, a)
|
||||
if not gme.dat.scr then return end
|
||||
love.graphics.setColor(255, 255, 255, a / COLDIV)
|
||||
local p, n = gme.dat.scr[gme.scrprv], gme.dat.scr[gme.scrcur]
|
||||
love.graphics.draw(p, x, y, 0, w / p:getWidth(), h / p:getHeight())
|
||||
love.graphics.setColor(255, 255, 255, math.min(a, pikcha) / COLDIV)
|
||||
love.graphics.draw(n, x, y, 0, w / n:getWidth(), h / n:getHeight())
|
||||
love.graphics.setColor(0, 0, 0, 150 / COLDIV)
|
||||
love.graphics.rectangle('fill', x, y, w, h)
|
||||
end
|
||||
|
||||
local function draw()
|
||||
love.graphics.setColor(0 / COLDIV, 50 / COLDIV, 75 / COLDIV)
|
||||
love.graphics.rectangle('fill', 0, 0, W, H)
|
||||
if ll.games[sel] then
|
||||
local cur = ll.games[sel]
|
||||
scrCard(cur, 0, 0, W, H, (css - 1) * 255)
|
||||
love.graphics.setColor(255, 255, 255, 255)
|
||||
love.graphics.setFont(bf)
|
||||
love.graphics.printf(cur.desc, cx + cw * 2, cx, W - (cx + cw * 2))
|
||||
else love.graphics.setColor(255, 255, 255, 255)
|
||||
sel = #ll.games
|
||||
end
|
||||
love.graphics.setFont(f)
|
||||
local oy = 0
|
||||
for k, v in pairs(ll.games) do
|
||||
local x, w, h, g = cx, cw, ch, cg
|
||||
if k == sel then
|
||||
x = cx / css
|
||||
w = cw * css
|
||||
h = ch * css
|
||||
g = cg * 3
|
||||
oy = oy + cg * css
|
||||
elseif k == psel then
|
||||
x = cx / rcss
|
||||
w = cw * rcss
|
||||
h = ch * rcss
|
||||
oy = oy + cg * rcss
|
||||
end
|
||||
|
||||
love.graphics.stencil(function()
|
||||
love.graphics.rectangle('fill', x, cy + oy, w, h, r)
|
||||
end)
|
||||
love.graphics.setStencilTest('greater', 0)
|
||||
|
||||
love.graphics.setColor(50 / COLDIV, 50 / COLDIV, 50 / COLDIV, 100 / COLDIV)
|
||||
love.graphics.rectangle('fill', x, cy + oy, w, h)
|
||||
love.graphics.setColor(255, 255, 255, 255)
|
||||
|
||||
scrCard(v, x, cy + oy, w, h, 255)
|
||||
love.graphics.setColor(255, 255, 255, 255)
|
||||
|
||||
local th = f:getHeight(v.name)
|
||||
love.graphics.print(v.name, x + cg, cy + oy + h - th - cg)
|
||||
|
||||
love.graphics.setStencilTest()
|
||||
love.graphics.rectangle('line', x, cy + oy, w, h, r)
|
||||
oy = oy + h + g
|
||||
end
|
||||
if #ll.games == 0 then
|
||||
love.graphics.print('No games', cx, cy - ch)
|
||||
love.graphics.setFont(bf)
|
||||
love.graphics.print('Add some to the library', cx, cy)
|
||||
end
|
||||
end
|
||||
|
||||
return {
|
||||
update = update,
|
||||
draw = draw,
|
||||
}
|
||||
|
||||
end
|
Loading…
Add table
Add a link
Reference in a new issue