diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 81b0c56..0000000 --- a/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -dev -build/ -games/* -!games/.gitkeep - diff --git a/lib/chroot.lua b/lib/chroot.lua deleted file mode 100644 index f0abb42..0000000 --- a/lib/chroot.lua +++ /dev/null @@ -1,37 +0,0 @@ -return function(ll) - -ll.mdir = nil -ll.mgme = nil - -local ffi = require 'ffi' -ffi.cdef [[ - int PHYSFS_mount(const char *, const char *, int); - int PHYSFS_unmount(const char *); -]] - -local baseReq = '?.lua;?/init.lua;' -function ll.mount(gme) - local mdir = gme.base .. gme.dir - ll.mgme = gme - - love.filesystem.setRequirePath('' - .. mdir .. '/?.lua;' - .. mdir .. '/?/init.lua;' - .. baseReq - ) - -- FIXME: Bug may appear in Linux. Recompile Love2D or use official PPA. - if ffi.C.PHYSFS_mount(mdir, '/', 0) == 0 - then error('Cannot mount '..mdir) - love.filesystem.setRequirePath(baseReq) - else ll.mdir = mdir - end -end - -function ll.umount() - if ll.mdir ~= nil then - ffi.C.PHYSFS_unmount(ll.mdir) - ll.mdir = nil - end -end - -end diff --git a/lib/fs.lua b/lib/fs.lua deleted file mode 100644 index e6088c3..0000000 --- a/lib/fs.lua +++ /dev/null @@ -1,20 +0,0 @@ -return function(ll) - -function ll.fsIsAbs(f) - f = f:sub(1, 1) - return f == '/' or f == '\\' -end - -function ll.fsIsRel(f) - return not ll.fsIsAbs(f) -end - -function ll.fsFile(f) - return f:match '([^/\\]*)[/\\]*$' -end - -function ll.fsDir(f) - return f:match '^(.*)[/\\]+[^/\\]*[/\\]*$' -end - -end diff --git a/lib/game.lua b/lib/game.lua deleted file mode 100644 index b9d88f7..0000000 --- a/lib/game.lua +++ /dev/null @@ -1,100 +0,0 @@ -return function(ll) - -ll.games = {} - -local function parse(conf) - local r = {} - local k, v - - local buf = '' - local t = 'str' - local esc = false - local prg = true - - local i = 1 - repeat - local ch = conf:sub(i, i) - - if ch == '\\' - then esc = true - - elseif ch == '#' then - repeat i = i + 1 - ch = conf:sub(i, i) - until ch == '' or ch == '\n' or ch == '\r' - - elseif ch == '[' then - buf = buf:match '%s*(.*)%s*' - assert(#buf == 0, 'Unexpected array usage') - t = 'arr' - prg = true - v = {} - - elseif ch == '' - or (ch == '=' and not k) - or (ch == ']' and t == 'arr') - or (ch == ';' and t == 'arr') - or ch == '\n' or ch == '\r' then - buf = buf:match '^%s*(.-)%s*$' - - if ch == '=' then - assert(t == 'str', 'Cannot use other types than string for key') - end - - if t == 'str' - or (t == 'arr' and ch == ']') - then prg = false end - - if not prg or ch == ';' then - if #buf ~= 0 then - if k then - if t == 'str' - then v = buf - elseif t == 'arr' - then table.insert(v, buf) - else error 'wut?' end - else k = buf - end - buf = '' - elseif ch ~= '' - and ch ~= '\r' - and ch ~= '\n' - then error 'empty buffer' - end - end - if k and v and not prg then - r[k] = v - k = nil - v = nil - buf = '' - t = 'str' - end - - elseif esc then - buf = buf .. ch - esc = false - - else buf = buf .. ch - end - i = i + 1 - until i >= #conf + 1 - return r -end - -function ll.gameNew(conf, file, base, dir) - local cfg = parse(conf or '') - local gme = { - name = cfg.name or dir or 'No name', - desc = cfg.desc or 'No description provided.', - base = base, - dir = dir, - main = cfg.main or 'main.lua', - screens = cfg.screens or cfg.pics or nil, - scrcur = 1, - scrprv = 1, - dat = nil, - } - return gme -end - -end diff --git a/lib/keyb.lua b/lib/keyb.lua deleted file mode 100644 index e3c0719..0000000 --- a/lib/keyb.lua +++ /dev/null @@ -1,81 +0,0 @@ -return function(ll) - -local mx, my, mb, mpb -local dir, sc1, sc2, sclm - --- d - direction (h, v, x, y, *) --- c1 - coordinate before card (mouse) (be left or top) --- c2 - coordinate after card (mouse) (be right or bottom) --- clm - other coordinate limit (mouse) (set -1 to disable) -function ll.kbInit(d, c1, c2, clim) - if d == 'h' or d == 'v' or d == '*' - then dir = d - elseif d == 'y' - then dir = 'v' - elseif d == 'x' - then dir = 'h' - else error 'Direction must be *, h (x) or v (y)' - end - - c1, c2 = - tonumber(c1) or 0, - tonumber(c2) or 0 - sc1, sc2, sclm = - math.min(c1, c2), - math.max(c1, c2), - tonumber(clim) or -1 -end - --- returns: <, >, o, m, nil --- ^ and v if dir is * -function ll.kbGet() - assert(dir, 'Call ll.kbInit(dir, coord1, coord2, coordlimit) before') - mx, my = love.mouse.getPosition() - mpb = mb - if love.mouse.isDown(1) then mb = 1 - else mb = 0 - end - - if love.keyboard.isScancodeDown('up', 'w') - then return dir == '*' and '^' or '<' - - elseif love.keyboard.isScancodeDown('left', 'a') - then return '<' - - elseif love.keyboard.isScancodeDown('down', 's') - then return dir == '*' and 'v' or '>' - - elseif love.keyboard.isScancodeDown('right', 'd') - then return '>' - - elseif love.keyboard.isScancodeDown('return', 'space') - then return 'o' - - elseif love.keyboard.isDown 'menu' - then return 'm' - - elseif mb == 0 and mpb == 1 then -- unpressed - if dir == 'h' then - if sclm < 0 or my <= sclm then - if mx <= sc1 - then return '<' - elseif mx >= sc2 - then return '>' - else return 'o' - end - end - else - if sclm < 0 or mx <= sclm then - if my <= sc1 - then return '<' - elseif my >= sc2 - then return '>' - else return 'o' - end - end - end - - end -end - -end diff --git a/lib/load.lua b/lib/load.lua deleted file mode 100644 index 04a40e1..0000000 --- a/lib/load.lua +++ /dev/null @@ -1,51 +0,0 @@ -return function(ll) - -function ll.addGame(file, cont) - local dir = ll.fsDir(file) - file = ll.fsFile(file) - local ext = file:match '%.(%w+)$' - print(file, ext, dir) - return 'NO!', nil -end - -function ll.gameAdd(conf, file, base, dir) - local gme = ll.gameNew(conf, file, base, dir) - gme.dat = {} - - if gme.screens and gme.screens[1] then - gme.dat.scr = {} - for i = 1, #gme.screens do - table.insert(gme.dat.scr, love.graphics.newImage(ll.cfg.root .. gme.dir ..'/'.. gme.screens[i])) - end - end - - table.insert(ll.games, gme) - return gme -end - -local lfs = love.filesystem -local info = lfs.getInfo - -for _, dir in pairs(love.filesystem.getDirectoryItems(ll.cfg.root)) do - local isDir - if info - then isDir = info(ll.cfg.root .. dir).type == 'directory' - else isDir = lfs.isDirectory(ll.cfg.root .. dir) - end - - if isDir then - local file = ll.cfg.root .. dir..'/'.. 'info.ll' - local realDir = love.filesystem.getRealDirectory(file) - or love.filesystem.getRealDirectory(ll.cfg.root .. dir..'/main.lua') - if realDir - then ll.gameAdd( - love.filesystem.read(file), - file, - realDir ..'/'.. ll.cfg.root, - dir - ) - end - end -end - -end diff --git a/lib/main.lua b/lib/main.lua deleted file mode 100644 index dee7506..0000000 --- a/lib/main.lua +++ /dev/null @@ -1,27 +0,0 @@ -local ll = {} - -ll.cfg = { - root = 'games/', -} - -require 'lib.fs' (ll) -require 'lib.game' (ll) -require 'lib.chroot' (ll) -require 'lib.load' (ll) -require 'lib.keyb' (ll) - -function ll.home() - ll.umount() - love.event.push('quit', 'restart') -end - -ll.dt = false -function ll.devtools() - if not ll.dt then - ll.dt = true - __LL = ll - pcall(function() require 'dev.tools' end) - end -end - -return ll diff --git a/ll-min.lua b/ll-min.lua index eafd105..37edda9 100644 --- a/ll-min.lua +++ b/ll-min.lua @@ -1,17 +1,8 @@ --- Minimal Love Loader API --- Version 2.1 --- (c) Er2 2022 --- Zlib License +-- minimal Love Loader API if not llUsed then COLDIV = love.getVersion() == 0 and 1 or 255 -MOBILE = love.system.getOS() == 'Android' - or love.system.getOS() == 'iOS' - -if MOBILE -then love.window.setFullscreen(true) -end function love.resize(x, y) W, H = x, y diff --git a/luapack.lua b/luapack.lua deleted file mode 100644 index ab4dec7..0000000 --- a/luapack.lua +++ /dev/null @@ -1,17 +0,0 @@ -return { - entry = 'main.lua', - output = 'build/main.lua', - plug = { - require 'plug.minify' { - extGlob = { - 'love', - 'llUsed', - 'llHome', - 'resize', - 'COLDIV', - 'MOBILE', - 'W', 'H', - } - }, - } -} diff --git a/main.lua b/main.lua index 5dd9deb..c45271c 100644 --- a/main.lua +++ b/main.lua @@ -1,71 +1,219 @@ -local ll = require 'lib.main' -error = love.errhand or love.errorhandler -function splash() - love.graphics.setColor(255, 255, 255, 100 / COLDIV) - if ll.mgme.screens and ll.mgme.screens[1] then - local img = love.graphics.newImage(ll.mgme.screens[1]) - love.graphics.draw(img, 0, 0, 0, W / img:getWidth(), H / img:getHeight()) - end - love.graphics.setColor(255, 255, 255, 255) - love.graphics.print('Loading '..ll.mgme.name, W / 2, H / 2) +local root = 'games/' + +-- games library and selection +local gms = {} +local sel = 1 +local sgme + +-- some internals +local cx, cy, cw, ch +local f, bf + +local ffi = require 'ffi' +local fd +ffi.cdef [[ + int PHYSFS_mount(const char *, const char *, int); + int PHYSFS_unmount(const char *); +]] + +local function llResz() + cw, ch = W / 1.25, H / 1.25 + cx, cy = (W - cw) / 2, (H - ch) / 2 + + local th = math.min(W, H) / 8 + + f = love.graphics.newFont(th / 3) + bf = love.graphics.newFont(th / 2) end - -ll.skin = require 'skins.psp' (ll) +resize = llResz require 'll-min' llUsed = true -if love.errorhandler -then love.errorhandler = error -else love.errhand = error +local function chroot(dir, main) + fd = love.filesystem.getSource() .. dir + love.filesystem.setRequirePath( + '?.lua;?/init.lua;' + .. dir .. '/?.lua;' + .. dir .. '/?/init.lua;' + ) + -- FIXME: Bug in Linux (Debian) + ffi.C.PHYSFS_mount(fd, '/', 0); + if main then + load(love.filesystem.read(dir ..'/'.. main), main)() + end +end + +local function escChroot() + if fd then + ffi.C.PHYSFS_unmount(fd); + fd = nil + end +end + +local function gmeNew(cont, dir, file) + local gme = { + name = 'No name', + desc = 'No description provided.', + dir = dir, + main = 'main.lua', + pics = nil, + psel = 2, + ppsl = 1, + } + local fi = false + cont = cont or '' + cont = cont:gsub('[^\\]#[^\n]*', '') + for v in cont:gmatch '([^\n]+)' do + local k, v = v:match '^%s*([%w_]+)%s*=%s*(.*)%s*$' + if k == 'name' + or k == 'desc' + or k == 'main' + then gme[k] = v + fi = true + elseif k == 'pic' then + gme.pics = gme.pics or {} + table.insert(gme.pics, v) + fi = true + elseif k == 'pics' then + local t = {} + v = v:sub(2, -2) + for v in v:gmatch '%s*([^;]+%a+)%s*;?' + do table.insert(t, v) end + gme[k] = t + fi = true + elseif k + then error('unknown field "'.. k ..'" in "'.. file ..'"') + end + end + if gme.pics then + for k, v in pairs(gme.pics) do + gme.pics[k] = love.graphics.newImage(root .. dir ..'/'.. v) + end + gme.psel = math.min(2, #gme.pics) + end + if not fi then + gme.name = dir + end + table.insert(gms, gme) +end + +for _, v in pairs(love.filesystem.getDirectoryItems(root)) do + local file = v..'/'.. 'info.ll' + gmeNew(love.filesystem.read(root .. file), v, file) +end + +local pf, mx, mb, mpb + +local pcht = 60 * 5 +local pchat = math.floor(1 / pcht * 2 * 255 + 0.5) +local pchv, pcha = 0, 0 +local function llUpdate() + mx = love.mouse.getX() + mpb = mb + mb = 0 + if love.mouse.isDown(1) then mb = 1 + end + + if mpb == 1 and mb == 0 then + if mx <= cx then + sel = sel - 1 + if sel < 1 then sel = #gms end + elseif mx >= cx + cw then + sel = sel + 1 + if sel > #gms then sel = 1 end + else sgme = gms[sel] + end + end + + pchv = pchv + 1 + if pchv >= pcht then + pchv, pcha = 0, 0 + for _, v in pairs(gms) do + if v.pics then + v.ppsl = v.psel + v.psel = v.psel + 1 + if v.psel > #v.pics + then v.psel = 1 end + end + end + else pcha = math.min(255, pcha + pchat) + end +end + +local function llDraw() + 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) + + local oy, t = 0, '' + local gme = gms[sel] + if gme then + local ph = ch / 1.5 + if gme.pics then + local p, n = gme.pics[gme.ppsl], gme.pics[gme.psel] + love.graphics.draw(p, cx, cy, 0, cw / p:getWidth(), ph / p:getHeight()) + love.graphics.setColor(255, 255, 255, pcha / COLDIV) + love.graphics.draw(n, cx, cy, 0, cw / n:getWidth(), ph / n:getHeight()) + love.graphics.setColor(255, 255, 255, 255) + end + love.graphics.rectangle('line', cx, cy, cw, ph) + love.graphics.rectangle('line', cx, cy, cw, ch) + + oy = cy + ph + love.graphics.setFont(bf) + love.graphics.print(gme.name, cx, oy) + oy = oy + bf:getHeight(gme.name) + love.graphics.setFont(f) + love.graphics.print(gme.desc, cx, oy) + + else oy = H / 2 + 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 is no projects/games to run' + love.graphics.print(t, (W - f:getWidth(t)) / 2, oy) + end +end + +function llHome() + escChroot() + love.event.push('quit', 'restart') end local brk = false -while not brk and not ll.mdir do +while not brk and not sgme do -- event handling love.event.pump() - for n, a,b,c in love.event.poll() do - if n == 'quit' - or (n == 'keypressed' and a == 'escape') - then ll.umount() + for n, a,b,c,d,e,f in love.event.poll() do + if n == 'quit' then + escChroot() love.event.push('quit') brk = true; break end - love.handlers[n](a,b,c) + love.handlers[n](a,b,c,d,e,f) end -- update and drawing - ll.skin.update() + llUpdate() love.graphics.origin() love.graphics.clear(0, 0, 0) - ll.skin.draw() + llDraw() love.graphics.present() love.timer.sleep(0.001) end -if ll.mdir then +if sgme then love.graphics.setNewFont() resize = nil - - love.graphics.clear(0, 0, 0) - splash() - love.graphics.present() - - if ll.skin.lovecb then - for _, v in pairs(ll.skin.lovecb) - do love[v] = nil - end - end - - love.filesystem.setIdentity(ll.mgme.dir) - local f, err = load(love.filesystem.read(ll.mgme.main), ll.mgme.name) - if not f then error(err) - else xpcall(f, function(e) - error(e) - llHome() - end) - end - - love.resize(love.graphics.getDimensions()) + chroot(root .. sgme.dir, sgme.main) end diff --git a/readme.md b/readme.md index f0871b3..46bbbf1 100644 --- a/readme.md +++ b/readme.md @@ -2,99 +2,31 @@ Custom menu for selecting game from multiple for Love2D. -![PSP Style](./scr/psp.png) - -[Other screenshots](./scr) - # How it works? -Just place games into `games` folder! (like `this_folder/games/game/main.lua`) +If simple: just place games in `games` folder with structure like `games/yourgame/main.lua` -Technically, this creates the loop until game wasn't selected or user wants to exit -with custom event handling and redrawing. +If technically: creates local variables functions and variables. +Creates the loop until game wasn't selected with manual event handling and redrawing. -# LibLL +# Things left or API -Love Loader from 2.0 includes backend API to simplify creating custom skins. +We are not keep environment super clear (except local variables ;)) +so there are some variables can be used in game: -It have not so many functions and fields: +`W` and `H` variables: width and height of the screen, controlled by love.resize function. -- `ll.games` - field for games, which have this structure: - ```lua - { - name = 'string', -- Friendly name for game or placeholder - desc = 'string', -- Description for game or placeholder - base = 'string', -- base directory used in game mounting, must end with `/` - dir = 'string', -- directory name, used if no name was defined - main = 'string', -- main file to execute or `main.lua` - screens = {'array of', 'path to screenshots'}, - scrcur = 1, --[[number]] -- current index from screenshots - scrprv = 1, --[[number]] -- previous index from screenshots - dat = nil, --[[any]] -- maybe platform-dependent data to reduce operations - } - ``` +`love.resize` and optional `resize` payload: functions called when screen size when changed and at boot. -- `ll.mdir` - string or nil, contains full mounted directory. +`love.event.quit`: function to quit to menu screen -- `ll.mgme` - game or nil, contains mounted game. +`COLDIV`: color divider (1 or 255) to setColor function -- `ll.gameNew(configuration --[[string]], fileName --[[string, not used]], base --[[string]], directory --[[string]])` +`llUsed`: is Love Loader used - Creates game object (defined above) and returns it. +`llHome`: function to quit to menu screen -- `ll.gameAdd(conf, file, base, dir)` - same as `ll.gameNew` with insertion into `ll.games`. - -- `ll.addGame(fileName, fileContent)` - function for file dropping, reserved for v3.0. - -- `ll.mount(game)` - mounts game. - - Can throw an error. - - Sets `ll.mdir` and `ll.mgme`. - -- `ll.umount()` - unmounts game if can. - - Unsets `ll.mdir` and `ll.mgme`. - -- `ll.home()` - calls `llHome` - -- `ll.dt` - is developer tools enabled? - -- `__LL` - global variable of Love Loader instance when developer tools enabled. - -- `ll.devtools()` - enable developer tools. - -- `ll.fsIsAbs(file)` - is file absolute (/file)? - -- `ll.fsIsRel(file)` - is file relative, inverted result of ll.fsIsAbs (./file). - -- `ll.fsDir(path)` - get directory name (2 from /1/2/3.file). - -- `ll.fsFile(path)` - get file (including dividers after) (2 from /1/2/). - -- `ll.kbInit(direction --[[string: *, h, v, x, y]], c1 --[[number, coordinate before card for mouse (left/top)]], c2 --[[number, coordinate after card for mouse (right/bottom)]], clim --[[other coordinate limit for mouse or -1 to disable]])` - initialize keyboard module for skins. - -- `ll.kbGet() --[[nil, string: <, >, o, m, ^ anv v if direction is *]]` - get key pressed. - -# API - -To reduce things to do for game developers, this loader creates some global variables to use. - -You can also use it without Love Loader (or if your game can distribute without loader) by including `ll-min.lua` file. - -`W` and `H`: width and height of the screen which controls by custom love.resize function. - -`love.resize` and optional `resize` payload: functions called when screen size was changed and on booting. - -`love.event.quit`: function to exit to main screen. - -`llHome`: function called by `love.event.quit` (broken for now). - -`llUsed`: is Love Loader (not minimal API) used. - -`COLDIV`: color divider (1 or 255) to `love.graphics.setColor` function. - -`MOBILE`: is this device runs Android or iOS? +They also can be used without Love Loader if load `ll-min.lua` # Fill game information @@ -108,6 +40,5 @@ name = New awesome game using Love Loader desc = Some descripion about the game. # main = optional main file instead of `main.lua` pic = screen.png -pics = [ screen.png; screen2.png ] # wow arrays +pics = [ screen.png; screen2.png ] # wow array ``` - diff --git a/scr/base.png b/scr/base.png deleted file mode 100644 index 4761cbb..0000000 Binary files a/scr/base.png and /dev/null differ diff --git a/scr/gui.png b/scr/gui.png deleted file mode 100644 index 6afbc21..0000000 Binary files a/scr/gui.png and /dev/null differ diff --git a/scr/psp.png b/scr/psp.png deleted file mode 100644 index be2d517..0000000 Binary files a/scr/psp.png and /dev/null differ diff --git a/skins/base.lua b/skins/base.lua deleted file mode 100644 index ca31268..0000000 --- a/skins/base.lua +++ /dev/null @@ -1,190 +0,0 @@ -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\tInformation about game' - .. '\ninfo\t\tSame as cat' - .. '\nrun\t\tStart game' - .. '\nmount\t\tSame as run' - .. '\nchroot\t\tSame as run' - .. '\nclear\t\tClear screen' - .. '\neval\t\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 diff --git a/skins/gui.lua b/skins/gui.lua deleted file mode 100644 index fdb2708..0000000 --- a/skins/gui.lua +++ /dev/null @@ -1,198 +0,0 @@ -return function(ll) - -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 sel = 1 -local cdir - -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) - - ll.kbInit('h', cx, cx + cw) -end - -local function update() - local sdi = ll.kbGet() - - if cdir ~= sdi then - cdir = sdi - if sdi == '<' - then sel = sel - 1 - elseif sdi == '>' - then sel = sel + 1 - elseif sdi == 'o' and ll.games[sel] - then ll.mount(ll.games[sel]) - - elseif sdi == 'm' - and love.mouse.getX() >= W - 8 - then ll.devtools() - 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 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 diff --git a/skins/psp.lua b/skins/psp.lua deleted file mode 100644 index 2427148..0000000 --- a/skins/psp.lua +++ /dev/null @@ -1,159 +0,0 @@ -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) - -local logger = '' -local chc = '<>><' - -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) - - ll.kbInit('v', H / 2 - ch, H / 2 + ch + cg, cx + cw * 2) -end - -love.window.setMode(800, 600, {resizable = true}) - -local sdir -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 = ll.kbGet() - - if sdi ~= sdir then - if sdi - then rcss = css - css = 1 - psel = sel - logger = logger .. sdi - if logger == chc then - resize() - ll.devtools() - end - end - sdir = sdi - if sdi == '<' - then sel = sel - 1 - elseif sdi == '>' - then sel = sel + 1 - elseif sdi == 'o' 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