mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-21 05:00:43 +02:00
clean up and larger importer
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 2.7 KiB |
@@ -233,6 +233,22 @@ function LauncherView.clickAt(imp, x, y)
|
|||||||
imp._clickPt = { x = x, y = y }
|
imp._clickPt = { x = x, y = y }
|
||||||
end
|
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
|
-- 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
|
-- 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
|
-- 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
|
end
|
||||||
|
|
||||||
local halfW, halfH = w / 2, h / 2
|
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)
|
local project = function(px, py, pz)
|
||||||
return cartProject(cx + pressX, cy + pressY, yaw, pitch,
|
return cartProject(cx + pressX, cy + pressY, yaw, pitch,
|
||||||
px * pressedScale, py * pressedScale, pz * pressedScale)
|
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[2], mainFront[3], mainBack[3], mainBack[2] }, side, 1)
|
||||||
cartPolygon({ mainFront[3], mainFront[4], mainBack[4], mainBack[3] }, 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[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[2], capFront[3], capBack[3], capBack[2] }, side, 1)
|
||||||
cartPolygon({ capFront[1], capFront[2], capBack[2], capBack[1] }, side, 1)
|
cartPolygon({ capFront[1], capFront[2], capBack[2], capBack[1] }, side, 1)
|
||||||
cartPolygon({ capFront[4], capFront[1], capBack[1], capBack[4] }, 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
|
else
|
||||||
cartPolygon(mainBack, side, 1)
|
cartPolygon(mainBack, side, 1)
|
||||||
cartPolygon(capBack, 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
|
end
|
||||||
|
|
||||||
if frontFacing then
|
if frontFacing then
|
||||||
@@ -1119,7 +1161,7 @@ local function buildHeader(imp, m)
|
|||||||
end
|
end
|
||||||
tx = tx + dropW + tabGap
|
tx = tx + dropW + tabGap
|
||||||
|
|
||||||
for _, t in ipairs(tabs) do
|
local function headerTab(t)
|
||||||
local w = tabH
|
local w = tabH
|
||||||
if tx > tabLeft and tx + w > tabRight then
|
if tx > tabLeft and tx + w > tabRight then
|
||||||
tx = tabLeft
|
tx = tabLeft
|
||||||
@@ -1132,6 +1174,11 @@ local function buildHeader(imp, m)
|
|||||||
btn(imp, tx, ty, w, tabH, t.key, "", o)
|
btn(imp, tx, ty, w, tabH, t.key, "", o)
|
||||||
tx = tx + w + tabGap
|
tx = tx + w + tabGap
|
||||||
end
|
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
|
do
|
||||||
local w = tabH
|
local w = tabH
|
||||||
@@ -1153,6 +1200,7 @@ local function buildHeader(imp, m)
|
|||||||
end
|
end
|
||||||
tx = tx + w + tabGap
|
tx = tx + w + tabGap
|
||||||
end
|
end
|
||||||
|
if bugTab then headerTab(bugTab) end
|
||||||
|
|
||||||
-- `ty` has walked down with the wraps, so this stays correct at one row too.
|
-- `ty` has walked down with the wraps, so this stays correct at one row too.
|
||||||
y = ty + tabH + math.floor(8 * m.s)
|
y = ty + tabH + math.floor(8 * m.s)
|
||||||
@@ -2840,6 +2888,8 @@ local function buildConfirmModal(imp, m)
|
|||||||
imp:_setAllMods(true, true)
|
imp:_setAllMods(true, true)
|
||||||
elseif c.kind == "importOversize" then
|
elseif c.kind == "importOversize" then
|
||||||
imp:_importSave(c.version, c.source, true)
|
imp:_importSave(c.version, c.source, true)
|
||||||
|
elseif c.kind == "largeImport" then
|
||||||
|
imp:_importRequiredSource(c.modId, c.importId, c.source, true)
|
||||||
else
|
else
|
||||||
imp:_toggleMod(c.id, true, c.version)
|
imp:_toggleMod(c.id, true, c.version)
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -2060,7 +2060,7 @@ function RomImporter:_importRequiredData(modId, importId, data)
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
function RomImporter:_importRequiredSource(modId, importId, source)
|
function RomImporter:_importRequiredSource(modId, importId, source, confirmed)
|
||||||
local manifest = requiredManifest(self, modId)
|
local manifest = requiredManifest(self, modId)
|
||||||
local spec = manifest and requiredSpec(manifest, importId)
|
local spec = manifest and requiredSpec(manifest, importId)
|
||||||
if not spec then
|
if not spec then
|
||||||
@@ -2068,14 +2068,31 @@ function RomImporter:_importRequiredSource(modId, importId, source)
|
|||||||
self.modNotice = nil
|
self.modNotice = nil
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
local RequiredImports = require("src.mods.RequiredImports")
|
||||||
local info = love.filesystem.getInfo(source, "file")
|
local info = love.filesystem.getInfo(source, "file")
|
||||||
local size = info and info.size or externalFileSize(source)
|
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
|
if sizeErr then
|
||||||
requiredImportNotice(self, modId, importId, sizeErr)
|
requiredImportNotice(self, modId, importId, sizeErr)
|
||||||
self.modNotice = nil
|
self.modNotice = nil
|
||||||
return nil
|
return nil
|
||||||
end
|
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)
|
local data = love.filesystem.read(source)
|
||||||
if not data then data = readExternalPath(source) end
|
if not data then data = readExternalPath(source) end
|
||||||
if not data then
|
if not data then
|
||||||
@@ -2118,8 +2135,13 @@ function RomImporter:chooseRequiredImport(modId, importId)
|
|||||||
if name:sub(1, 1) ~= "." then
|
if name:sub(1, 1) ~= "." then
|
||||||
local path = inbox .. "/" .. name
|
local path = inbox .. "/" .. name
|
||||||
local info = love.filesystem.getInfo(path, "file")
|
local info = love.filesystem.getInfo(path, "file")
|
||||||
local sizeErr = info and require("src.mods.RequiredImports")
|
local RequiredImports = require("src.mods.RequiredImports")
|
||||||
.sizeError(spec, info.size, false)
|
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
|
local data = not sizeErr and love.filesystem.read(path) or nil
|
||||||
if data and self:_importRequiredData(modId, importId, data) then return end
|
if data and self:_importRequiredData(modId, importId, data) then return end
|
||||||
if sizeErr then lastError = sizeErr
|
if sizeErr then lastError = sizeErr
|
||||||
@@ -3098,8 +3120,10 @@ end
|
|||||||
-- multi-monitor coords). Same contract as PadCursor.yieldToPointer for
|
-- multi-monitor coords). Same contract as PadCursor.yieldToPointer for
|
||||||
-- the overlay hosts. Touch move/press/release must still reach
|
-- the overlay hosts. Touch move/press/release must still reach
|
||||||
-- FlexLove.touch* or scroll containers never drag on phones.
|
-- FlexLove.touch* or scroll containers never drag on phones.
|
||||||
function RomImporter:mousepressed()
|
function RomImporter:mousepressed(x, y, button)
|
||||||
self._padCursorActive = false
|
self._padCursorActive = false
|
||||||
|
if button ~= 1 or not self._flex then return end
|
||||||
|
require("src.import.LauncherView").mousepressed(self, x, y)
|
||||||
end
|
end
|
||||||
|
|
||||||
function RomImporter:touchpressed(id, x, y, dx, dy, pressure)
|
function RomImporter:touchpressed(id, x, y, dx, dy, pressure)
|
||||||
|
|||||||
@@ -195,8 +195,8 @@ local function parseImports(value, field, required)
|
|||||||
if value == nil then return end
|
if value == nil then return end
|
||||||
assert(type(value) == "number" and value > 0 and value % 1 == 0,
|
assert(type(value) == "number" and value > 0 and value % 1 == 0,
|
||||||
field .. " " .. label .. " must be a positive integer")
|
field .. " " .. label .. " must be a positive integer")
|
||||||
assert(value <= 128 * 1024 * 1024,
|
assert(value <= 2 * 1024 * 1024 * 1024,
|
||||||
field .. " " .. label .. " exceeds the 128 MiB hard limit")
|
field .. " " .. label .. " exceeds the 2 GiB hard limit")
|
||||||
end
|
end
|
||||||
validateSize(size, "size")
|
validateSize(size, "size")
|
||||||
validateSize(maxSize, "max_size")
|
validateSize(maxSize, "max_size")
|
||||||
|
|||||||
@@ -23,11 +23,17 @@ local function isRequired(spec)
|
|||||||
end
|
end
|
||||||
|
|
||||||
RequiredImports.specs = allSpecs
|
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)
|
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))
|
return ("%.1f MiB"):format(bytes / (1024 * 1024))
|
||||||
end
|
end
|
||||||
|
RequiredImports.sizeLabel = sizeLabel
|
||||||
|
|
||||||
-- Check size before a caller reads an external or stored file into one large
|
-- 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
|
-- Lua string. N64 sources may carry a 512-byte copier header, while stored
|
||||||
|
|||||||
Reference in New Issue
Block a user