Files
gen1recomp/tools/save-editor/PickerChrome.lua
T
1jamie b796c30278 fix(save-editor): mobile safe areas, move search picker, and release window titles
Inset save-editor chrome and pickers into SafeArea so Save stays tappable on punch-hole phones (#917), replace move cycling with a ranked search modal that reflows on phones/RGxxx, and omit the engine version from window titles on stamped release builds.
2026-08-25 12:43:05 -05:00

84 lines
3.1 KiB
Lua

-- Shared modal-picker frame for Species / Move / Item pickers.
--
-- Desktop keeps a centred card capped at 520x560 logical px. Phones and
-- RGxxx handhelds (RG34XXSP 720x480, RG35XX 640x480, Switch 1280x720, tall
-- portrait Androids) need the card to nearly fill SafeArea.rect() so the
-- search field, list, and pager stay usable instead of collapsing under a
-- fixed 32px margin into a short landscape window (#917 / #715).
local SafeArea = require("src.core.SafeArea")
local PickerChrome = {}
-- Minimum tap target (design rule 6). Scale can sit on the 0.9 floor on a
-- short handheld, so a bare `26 * s` would dip under 26px -- clamp in px.
function PickerChrome.tapMin(Kit)
local s = (Kit and Kit.scale) or 1
return math.max(26, math.floor(30 * s))
end
-- Usable card rect inside the platform safe area.
-- Returns x, y, w, h, pad.
function PickerChrome.card(Kit, windowW, windowH)
local s = (Kit and Kit.scale) or 1
windowW = math.max(1, tonumber(windowW) or 1)
windowH = math.max(1, tonumber(windowH) or 1)
local sox, soy, ssw, ssh = SafeArea.rect()
sox = math.max(0, tonumber(sox) or 0)
soy = math.max(0, tonumber(soy) or 0)
ssw = math.max(1, tonumber(ssw) or windowW)
ssh = math.max(1, tonumber(ssh) or windowH)
-- Shrink the gutter on short / narrow safe areas so the card keeps room
-- for caption + search + at least one list row + pager.
local gutter = math.floor(16 * s)
local minSide = math.min(ssw, ssh)
if minSide < 560 * s then
gutter = math.max(4, math.floor(minSide * 0.03))
end
local maxW = math.floor(520 * s)
local maxH = math.floor(560 * s)
local w = math.min(ssw - 2 * gutter, maxW)
local h = math.min(ssh - 2 * gutter, maxH)
-- Short landscapes (720x480 class): fill the safe height instead of
-- leaving letterbox bands inside an already-short rect.
if ssh <= maxH + 2 * gutter then
h = ssh - 2 * gutter
end
if ssw <= maxW + 2 * gutter then
w = ssw - 2 * gutter
end
w = math.max(1, w)
h = math.max(1, h)
local x = sox + (ssw - w) / 2
local y = soy + (ssh - h) / 2
local pad = math.max(8, math.floor(math.min(18 * s, w * 0.04, h * 0.04)))
return x, y, w, h, pad
end
-- List-body metrics once caption / field / optional extra chrome are placed.
-- `contentTop` is the y just below that chrome; returns listH, rowH, rowGap,
-- pagerH sized so taps stay >= tapMin and listH never goes negative.
function PickerChrome.listMetrics(Kit, cardY, cardH, pad, contentTop)
local s = (Kit and Kit.scale) or 1
local tap = PickerChrome.tapMin(Kit)
local pagerH = math.max(tap, math.floor(30 * s))
local rowH = math.max(tap, math.floor(40 * s))
local rowGap = math.max(4, math.floor(6 * s))
local listBottom = cardY + cardH - pad - pagerH - math.max(6, math.floor(10 * s))
local listH = math.max(0, listBottom - contentTop)
return listH, rowH, rowGap, pagerH
end
function PickerChrome.fieldH(Kit)
return math.max(PickerChrome.tapMin(Kit), math.floor(34 * ((Kit and Kit.scale) or 1)))
end
function PickerChrome.closeSize(Kit)
return math.max(PickerChrome.tapMin(Kit), math.floor(30 * ((Kit and Kit.scale) or 1)))
end
return PickerChrome