Compare commits
	
		
			No commits in common. "e46bc230a6ecef40329d64bcb32ac1c73557f8f9" and "9513a5c4717a0bc7a5ab24a293791df0136fe31c" have entirely different histories.
		
	
	
		
			e46bc230a6
			...
			9513a5c471
		
	
		
					 17 changed files with 208 additions and 1023 deletions
				
			
		
							
								
								
									
										5
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								.gitignore
									
										
									
									
										vendored
									
									
								
							|  | @ -1,5 +0,0 @@ | ||||||
| dev |  | ||||||
| build/ |  | ||||||
| games/* |  | ||||||
| !games/.gitkeep |  | ||||||
| 
 |  | ||||||
|  | @ -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 |  | ||||||
							
								
								
									
										20
									
								
								lib/fs.lua
									
										
									
									
									
								
							
							
						
						
									
										20
									
								
								lib/fs.lua
									
										
									
									
									
								
							|  | @ -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 |  | ||||||
							
								
								
									
										100
									
								
								lib/game.lua
									
										
									
									
									
								
							
							
						
						
									
										100
									
								
								lib/game.lua
									
										
									
									
									
								
							|  | @ -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 |  | ||||||
							
								
								
									
										81
									
								
								lib/keyb.lua
									
										
									
									
									
								
							
							
						
						
									
										81
									
								
								lib/keyb.lua
									
										
									
									
									
								
							|  | @ -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 |  | ||||||
							
								
								
									
										51
									
								
								lib/load.lua
									
										
									
									
									
								
							
							
						
						
									
										51
									
								
								lib/load.lua
									
										
									
									
									
								
							|  | @ -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 |  | ||||||
							
								
								
									
										27
									
								
								lib/main.lua
									
										
									
									
									
								
							
							
						
						
									
										27
									
								
								lib/main.lua
									
										
									
									
									
								
							|  | @ -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 |  | ||||||
							
								
								
									
										11
									
								
								ll-min.lua
									
										
									
									
									
								
							
							
						
						
									
										11
									
								
								ll-min.lua
									
										
									
									
									
								
							|  | @ -1,17 +1,8 @@ | ||||||
| -- Minimal Love Loader API | -- minimal Love Loader API | ||||||
| -- Version 2.1 |  | ||||||
| -- (c) Er2 2022 <er2@dismail.de> |  | ||||||
| -- Zlib License |  | ||||||
| 
 | 
 | ||||||
| if not llUsed then | if not llUsed then | ||||||
| 
 | 
 | ||||||
| COLDIV = love.getVersion() == 0 and 1 or 255 | 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) | function love.resize(x, y) | ||||||
|   W, H = x, y |   W, H = x, y | ||||||
|  |  | ||||||
							
								
								
									
										17
									
								
								luapack.lua
									
										
									
									
									
								
							
							
						
						
									
										17
									
								
								luapack.lua
									
										
									
									
									
								
							|  | @ -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', |  | ||||||
|       } |  | ||||||
|     }, |  | ||||||
|   } |  | ||||||
| } |  | ||||||
							
								
								
									
										238
									
								
								main.lua
									
										
									
									
									
								
							
							
						
						
									
										238
									
								
								main.lua
									
										
									
									
									
								
							|  | @ -1,71 +1,219 @@ | ||||||
| local ll = require 'lib.main' |  | ||||||
| error = love.errhand or love.errorhandler |  | ||||||
| 
 | 
 | ||||||
| function splash() | local root = 'games/' | ||||||
|   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) |  | ||||||
| end |  | ||||||
| 
 | 
 | ||||||
| ll.skin = require 'skins.psp' (ll) | -- 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 | ||||||
|  | resize = llResz | ||||||
| 
 | 
 | ||||||
| require 'll-min' | require 'll-min' | ||||||
| llUsed = true | llUsed = true | ||||||
| 
 | 
 | ||||||
| if love.errorhandler | local function chroot(dir, main) | ||||||
| then love.errorhandler = error |   fd = love.filesystem.getSource() .. dir | ||||||
| else love.errhand = error |   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 | end | ||||||
| 
 | 
 | ||||||
| local brk = false | local brk = false | ||||||
| while not brk and not ll.mdir do | while not brk and not sgme do | ||||||
|   -- event handling |   -- event handling | ||||||
|   love.event.pump() |   love.event.pump() | ||||||
|   for n, a,b,c in love.event.poll() do |   for n, a,b,c,d,e,f in love.event.poll() do | ||||||
|     if n == 'quit' |     if n == 'quit' then | ||||||
|     or (n == 'keypressed' and a == 'escape') |       escChroot() | ||||||
|     then ll.umount() |  | ||||||
|       love.event.push('quit') |       love.event.push('quit') | ||||||
|       brk = true; break |       brk = true; break | ||||||
|     end |     end | ||||||
|     love.handlers[n](a,b,c) |     love.handlers[n](a,b,c,d,e,f) | ||||||
|   end |   end | ||||||
| 
 | 
 | ||||||
|   -- update and drawing |   -- update and drawing | ||||||
|   ll.skin.update() |   llUpdate() | ||||||
|   love.graphics.origin() |   love.graphics.origin() | ||||||
|   love.graphics.clear(0, 0, 0) |   love.graphics.clear(0, 0, 0) | ||||||
|   ll.skin.draw() |   llDraw() | ||||||
|   love.graphics.present() |   love.graphics.present() | ||||||
|   love.timer.sleep(0.001) |   love.timer.sleep(0.001) | ||||||
| end | end | ||||||
| 
 | 
 | ||||||
| if ll.mdir then | if sgme then | ||||||
|   love.graphics.setNewFont() |   love.graphics.setNewFont() | ||||||
|   resize = nil |   resize = nil | ||||||
| 
 |   chroot(root .. sgme.dir, sgme.main) | ||||||
|   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()) |  | ||||||
| end | end | ||||||
|  |  | ||||||
							
								
								
									
										97
									
								
								readme.md
									
										
									
									
									
								
							
							
						
						
									
										97
									
								
								readme.md
									
										
									
									
									
								
							|  | @ -2,99 +2,31 @@ | ||||||
| 
 | 
 | ||||||
| Custom menu for selecting game from multiple for Love2D. | Custom menu for selecting game from multiple for Love2D. | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
| 
 |  | ||||||
| [Other screenshots](./scr) |  | ||||||
| 
 |  | ||||||
| # How it works? | # 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 | If technically: creates local variables functions and variables. | ||||||
| with custom event handling and redrawing. | 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: | `love.resize` and optional `resize` payload: functions called when screen size when changed and at boot. | ||||||
|   ```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 |  | ||||||
|   } |  | ||||||
|   ``` |  | ||||||
| 
 | 
 | ||||||
| - `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`. | They also can be used without Love Loader if load `ll-min.lua` | ||||||
| 
 |  | ||||||
| - `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? |  | ||||||
| 
 | 
 | ||||||
| # Fill game information | # Fill game information | ||||||
| 
 | 
 | ||||||
|  | @ -108,6 +40,5 @@ name = New awesome game using Love Loader | ||||||
| desc = Some descripion about the game. | desc = Some descripion about the game. | ||||||
| # main = optional main file instead of `main.lua` | # main = optional main file instead of `main.lua` | ||||||
| pic = screen.png | pic = screen.png | ||||||
| pics = [ screen.png; screen2.png ] # wow arrays | pics = [ screen.png; screen2.png ] # wow array | ||||||
| ``` | ``` | ||||||
| 
 |  | ||||||
|  |  | ||||||
							
								
								
									
										
											BIN
										
									
								
								scr/base.png
									
										
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								scr/base.png
									
										
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 11 KiB | 
							
								
								
									
										
											BIN
										
									
								
								scr/gui.png
									
										
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								scr/gui.png
									
										
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 62 KiB | 
							
								
								
									
										
											BIN
										
									
								
								scr/psp.png
									
										
									
									
									
								
							
							
						
						
									
										
											BIN
										
									
								
								scr/psp.png
									
										
									
									
									
								
							
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 25 KiB | 
							
								
								
									
										190
									
								
								skins/base.lua
									
										
									
									
									
								
							
							
						
						
									
										190
									
								
								skins/base.lua
									
										
									
									
									
								
							|  | @ -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<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 |  | ||||||
							
								
								
									
										198
									
								
								skins/gui.lua
									
										
									
									
									
								
							
							
						
						
									
										198
									
								
								skins/gui.lua
									
										
									
									
									
								
							|  | @ -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 |  | ||||||
							
								
								
									
										159
									
								
								skins/psp.lua
									
										
									
									
									
								
							
							
						
						
									
										159
									
								
								skins/psp.lua
									
										
									
									
									
								
							|  | @ -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 = '<>><m><' |  | ||||||
| 
 |  | ||||||
| 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 |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue