clean up and larger importer

This commit is contained in:
bryanthaboi
2026-08-20 08:53:31 -04:00
parent 51c4766ead
commit 2468d5042d
5 changed files with 90 additions and 10 deletions
Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

+52 -2
View File
@@ -233,6 +233,22 @@ function LauncherView.clickAt(imp, x, y)
imp._clickPt = { x = x, y = y }
end
-- Event-driven click: a macOS trackpad tap delivers press+release inside one
-- frame, so update()'s love.mouse.isDown poll never sees it. Mint the click
-- from the press event under the poll's own suppression rules, and mark the
-- press seen so the poll cannot mint a second one when isDown does catch it.
function LauncherView.mousepressed(imp, x, y)
if not imp._flex then return end
local now = love.timer.getTime()
local touching = imp._touchAt ~= nil and next(imp._touchAt) ~= nil
if touching or now < (imp._suppressMouseUntil or 0)
or now < (imp._suppressClickUntil or 0) then
return
end
imp._clickPt = { x = x, y = y }
imp._prevMouseDown = true
end
-- Keyboard focus ring. Returns true when the key was consumed. Arrows arm
-- the ring; Enter only activates a focused control once the user has actually
-- used the arrows this session, so the long-standing "Enter plays the visible
@@ -580,7 +596,7 @@ local function cartridgeButton(imp, x, y, w, h, key, version, gameName, action)
end
local halfW, halfH = w / 2, h / 2
local depth = math.max(8, w * 0.14)
local depth = math.max(6, w * 0.10)
local project = function(px, py, pz)
return cartProject(cx + pressX, cy + pressY, yaw, pitch,
px * pressedScale, py * pressedScale, pz * pressedScale)
@@ -623,6 +639,7 @@ local function cartridgeButton(imp, x, y, w, h, key, version, gameName, action)
cartPolygon({ mainFront[2], mainFront[3], mainBack[3], mainBack[2] }, side, 1)
cartPolygon({ mainFront[3], mainFront[4], mainBack[4], mainBack[3] }, side, 1)
cartPolygon({ mainFront[1], mainFront[2], mainBack[2], mainBack[1] }, side, 1)
cartPolygon({ mainFront[4], mainFront[1], mainBack[1], mainBack[4] }, side, 1)
cartPolygon({ capFront[2], capFront[3], capBack[3], capBack[2] }, side, 1)
cartPolygon({ capFront[1], capFront[2], capBack[2], capBack[1] }, side, 1)
cartPolygon({ capFront[4], capFront[1], capBack[1], capBack[4] }, side, 1)
@@ -632,6 +649,31 @@ local function cartridgeButton(imp, x, y, w, h, key, version, gameName, action)
else
cartPolygon(mainBack, side, 1)
cartPolygon(capBack, side, 1)
-- The tri-wing security screw: a domed brass head with three teardrop
-- recesses pinwheeled at 120 degrees.
local backZ = -(depth + 0.8)
local sd = math.min(w, h) * 0.11
cartPill(project, -sd * 0.62, -sd * 0.62, sd * 1.24, sd * 1.24, backZ,
{ math.floor(shell[1] * 0.4), math.floor(shell[2] * 0.4),
math.floor(shell[3] * 0.4) }, 0.9)
cartPill(project, -sd / 2, -sd / 2, sd, sd, backZ - 0.4,
{ 196, 186, 148 }, 1)
cartPill(project, -sd * 0.32, -sd * 0.32, sd * 0.64, sd * 0.64,
backZ - 0.6, { 220, 212, 178 }, 0.8)
local r = sd / 2
for k = 0, 2 do
local a = -math.pi / 2 + k * (2 * math.pi / 3)
local ux, uy = math.cos(a), math.sin(a)
local vx, vy = -uy, ux
local r0, r1 = r * 0.16, r * 0.82
local w0, w1 = r * 0.13, r * 0.3
cartPolygon({
{ project(ux * r0 + vx * w0, uy * r0 + vy * w0, backZ - 0.8) },
{ project(ux * r0 - vx * w0, uy * r0 - vy * w0, backZ - 0.8) },
{ project(ux * r1 - vx * w1, uy * r1 - vy * w1, backZ - 0.8) },
{ project(ux * r1 + vx * w1, uy * r1 + vy * w1, backZ - 0.8) },
}, { 112, 104, 76 }, 1)
end
end
if frontFacing then
@@ -1119,7 +1161,7 @@ local function buildHeader(imp, m)
end
tx = tx + dropW + tabGap
for _, t in ipairs(tabs) do
local function headerTab(t)
local w = tabH
if tx > tabLeft and tx + w > tabRight then
tx = tabLeft
@@ -1132,6 +1174,11 @@ local function buildHeader(imp, m)
btn(imp, tx, ty, w, tabH, t.key, "", o)
tx = tx + w + tabGap
end
-- The bug-report chip sits LAST, past the sync chip.
local bugTab
for _, t in ipairs(tabs) do
if t.id == "bug" then bugTab = t else headerTab(t) end
end
do
local w = tabH
@@ -1153,6 +1200,7 @@ local function buildHeader(imp, m)
end
tx = tx + w + tabGap
end
if bugTab then headerTab(bugTab) end
-- `ty` has walked down with the wraps, so this stays correct at one row too.
y = ty + tabH + math.floor(8 * m.s)
@@ -2840,6 +2888,8 @@ local function buildConfirmModal(imp, m)
imp:_setAllMods(true, true)
elseif c.kind == "importOversize" then
imp:_importSave(c.version, c.source, true)
elseif c.kind == "largeImport" then
imp:_importRequiredSource(c.modId, c.importId, c.source, true)
else
imp:_toggleMod(c.id, true, c.version)
end
+29 -5
View File
@@ -2060,7 +2060,7 @@ function RomImporter:_importRequiredData(modId, importId, data)
return nil
end
function RomImporter:_importRequiredSource(modId, importId, source)
function RomImporter:_importRequiredSource(modId, importId, source, confirmed)
local manifest = requiredManifest(self, modId)
local spec = manifest and requiredSpec(manifest, importId)
if not spec then
@@ -2068,14 +2068,31 @@ function RomImporter:_importRequiredSource(modId, importId, source)
self.modNotice = nil
return nil
end
local RequiredImports = require("src.mods.RequiredImports")
local info = love.filesystem.getInfo(source, "file")
local size = info and info.size or externalFileSize(source)
local sizeErr = require("src.mods.RequiredImports").sizeError(spec, size, false)
local sizeErr = RequiredImports.sizeError(spec, size, false)
if sizeErr then
requiredImportNotice(self, modId, importId, sizeErr)
self.modNotice = nil
return nil
end
if not confirmed and type(size) == "number"
and size > RequiredImports.LARGE_WARN_BYTES then
self._modConfirm = {
kind = "largeImport",
modId = modId, importId = importId, source = source,
title = Strings("Large import"),
lines = {
Strings("This is a large import (%s).",
RequiredImports.sizeLabel(size)),
Strings("Please ensure you have enough space on your"),
Strings("device before doing this."),
},
yesLabel = Strings("I understand"),
}
return nil
end
local data = love.filesystem.read(source)
if not data then data = readExternalPath(source) end
if not data then
@@ -2118,8 +2135,13 @@ function RomImporter:chooseRequiredImport(modId, importId)
if name:sub(1, 1) ~= "." then
local path = inbox .. "/" .. name
local info = love.filesystem.getInfo(path, "file")
local sizeErr = info and require("src.mods.RequiredImports")
.sizeError(spec, info.size, false)
local RequiredImports = require("src.mods.RequiredImports")
local sizeErr = info
and RequiredImports.sizeError(spec, info.size, false)
if info and not sizeErr
and info.size > RequiredImports.LARGE_WARN_BYTES then
return self:_importRequiredSource(modId, importId, path)
end
local data = not sizeErr and love.filesystem.read(path) or nil
if data and self:_importRequiredData(modId, importId, data) then return end
if sizeErr then lastError = sizeErr
@@ -3098,8 +3120,10 @@ end
-- multi-monitor coords). Same contract as PadCursor.yieldToPointer for
-- the overlay hosts. Touch move/press/release must still reach
-- FlexLove.touch* or scroll containers never drag on phones.
function RomImporter:mousepressed()
function RomImporter:mousepressed(x, y, button)
self._padCursorActive = false
if button ~= 1 or not self._flex then return end
require("src.import.LauncherView").mousepressed(self, x, y)
end
function RomImporter:touchpressed(id, x, y, dx, dy, pressure)
+2 -2
View File
@@ -195,8 +195,8 @@ local function parseImports(value, field, required)
if value == nil then return end
assert(type(value) == "number" and value > 0 and value % 1 == 0,
field .. " " .. label .. " must be a positive integer")
assert(value <= 128 * 1024 * 1024,
field .. " " .. label .. " exceeds the 128 MiB hard limit")
assert(value <= 2 * 1024 * 1024 * 1024,
field .. " " .. label .. " exceeds the 2 GiB hard limit")
end
validateSize(size, "size")
validateSize(maxSize, "max_size")
+7 -1
View File
@@ -23,11 +23,17 @@ local function isRequired(spec)
end
RequiredImports.specs = allSpecs
RequiredImports.MAX_BYTES = 128 * 1024 * 1024
RequiredImports.MAX_BYTES = 2 * 1024 * 1024 * 1024
-- Past this, the launcher interposes a free-space warning before importing.
RequiredImports.LARGE_WARN_BYTES = 128 * 1024 * 1024
local function sizeLabel(bytes)
if bytes >= 1024 * 1024 * 1024 then
return ("%.1f GiB"):format(bytes / (1024 * 1024 * 1024))
end
return ("%.1f MiB"):format(bytes / (1024 * 1024))
end
RequiredImports.sizeLabel = sizeLabel
-- Check size before a caller reads an external or stored file into one large
-- Lua string. N64 sources may carry a 512-byte copier header, while stored