mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-22 13:36:14 +02:00
Merge pull request #1659 from bryanthaboi/dev
skins again skins again skins again skins again skins again skins again skins again skins again skins again skins again skins again skins again skins again skins again skins again skins again
This commit is contained in:
+13
-6
@@ -294,7 +294,6 @@ function TouchSkin.parse(text)
|
|||||||
page.viewport = { x = num(vp[1], 0), y = num(vp[2], 0),
|
page.viewport = { x = num(vp[1], 0), y = num(vp[2], 0),
|
||||||
w = num(vp[3], 1), h = num(vp[4], 1) }
|
w = num(vp[3], 1), h = num(vp[4], 1) }
|
||||||
page.viewportFill = toBool(kv[p .. "_viewport_fill"])
|
page.viewportFill = toBool(kv[p .. "_viewport_fill"])
|
||||||
page.viewportExpand = toBool(kv[p .. "_viewport_expand"])
|
|
||||||
end
|
end
|
||||||
|
|
||||||
page.pixelCoords = not page.normalized
|
page.pixelCoords = not page.normalized
|
||||||
@@ -447,7 +446,6 @@ function TouchSkin.parseNative(text)
|
|||||||
page.viewport = { x = num(raw.viewport.x, 0), y = num(raw.viewport.y, 0),
|
page.viewport = { x = num(raw.viewport.x, 0), y = num(raw.viewport.y, 0),
|
||||||
w = num(raw.viewport.w, 1), h = num(raw.viewport.h, 1) }
|
w = num(raw.viewport.w, 1), h = num(raw.viewport.h, 1) }
|
||||||
page.viewportFill = raw.viewport.fill == true
|
page.viewportFill = raw.viewport.fill == true
|
||||||
page.viewportExpand = raw.viewport.expand == true
|
|
||||||
end
|
end
|
||||||
for _, c in ipairs(raw.controls or {}) do
|
for _, c in ipairs(raw.controls or {}) do
|
||||||
local buttons, hotkeys, keys, decorative = parseBinds(c.bind or "nul")
|
local buttons, hotkeys, keys, decorative = parseBinds(c.bind or "nul")
|
||||||
@@ -526,7 +524,6 @@ function TouchSkin.toNative(skin)
|
|||||||
x = page.viewport.x, y = page.viewport.y,
|
x = page.viewport.x, y = page.viewport.y,
|
||||||
w = page.viewport.w, h = page.viewport.h,
|
w = page.viewport.w, h = page.viewport.h,
|
||||||
fill = page.viewportFill or nil,
|
fill = page.viewportFill or nil,
|
||||||
expand = page.viewportExpand or nil,
|
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
for _, ctl in ipairs(page.controls or {}) do
|
for _, ctl in ipairs(page.controls or {}) do
|
||||||
@@ -922,7 +919,6 @@ function TouchSkin.toRetroArchConfig(skin)
|
|||||||
if page.viewport then
|
if page.viewport then
|
||||||
out[#out + 1] = p .. "_viewport = " .. fmtRect(page.viewport)
|
out[#out + 1] = p .. "_viewport = " .. fmtRect(page.viewport)
|
||||||
if page.viewportFill then out[#out + 1] = p .. "_viewport_fill = true" end
|
if page.viewportFill then out[#out + 1] = p .. "_viewport_fill = true" end
|
||||||
if page.viewportExpand then out[#out + 1] = p .. "_viewport_expand = true" end
|
|
||||||
end
|
end
|
||||||
local controls = {}
|
local controls = {}
|
||||||
for _, ctl in ipairs(page.controls or {}) do
|
for _, ctl in ipairs(page.controls or {}) do
|
||||||
@@ -1434,6 +1430,16 @@ local function remainderBox(ox, oy, w, h, bx, by, bw, bh)
|
|||||||
return best[1], best[2], best[3], best[4]
|
return best[1], best[2], best[3], best[4]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- The deck box pinned to the lower edge (see pageBox) leaves room above it
|
||||||
|
-- that belongs to the game, so a screen rect flush with the top of the deck
|
||||||
|
-- grows into it instead of showing a black band.
|
||||||
|
local function deckHeadroom(y, vh, by, bh, oy, h)
|
||||||
|
if by <= oy + 0.5 then return y, vh end
|
||||||
|
if by + bh < oy + h - 0.5 then return y, vh end
|
||||||
|
if y - by > math.max(2, bh * 0.01) then return y, vh end
|
||||||
|
return oy, vh + (y - oy)
|
||||||
|
end
|
||||||
|
|
||||||
function TouchSkin.pageViewport(page, w, h, ox, oy)
|
function TouchSkin.pageViewport(page, w, h, ox, oy)
|
||||||
if not page then return nil end
|
if not page then return nil end
|
||||||
ox, oy = ox or 0, oy or 0
|
ox, oy = ox or 0, oy or 0
|
||||||
@@ -1443,12 +1449,13 @@ function TouchSkin.pageViewport(page, w, h, ox, oy)
|
|||||||
local x, y = bx + v.x * bw, by + v.y * bh
|
local x, y = bx + v.x * bw, by + v.y * bh
|
||||||
local vw, vh = v.w * bw, v.h * bh
|
local vw, vh = v.w * bw, v.h * bh
|
||||||
if vw <= 0 or vh <= 0 then return nil end
|
if vw <= 0 or vh <= 0 then return nil end
|
||||||
return x, y, vw, vh, page.viewportFill == true, page.viewportExpand == true
|
y, vh = deckHeadroom(y, vh, by, bh, oy, h)
|
||||||
|
return x, y, vw, vh, page.viewportFill == true
|
||||||
end
|
end
|
||||||
if page.screenFit == "remainder" then
|
if page.screenFit == "remainder" then
|
||||||
local x, y, vw, vh = remainderBox(ox, oy, w, h, bx, by, bw, bh)
|
local x, y, vw, vh = remainderBox(ox, oy, w, h, bx, by, bw, bh)
|
||||||
if not x then return nil end
|
if not x then return nil end
|
||||||
return x, y, vw, vh, false, false
|
return x, y, vw, vh, false
|
||||||
end
|
end
|
||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1067,9 +1067,22 @@ local GAME_TABS = {
|
|||||||
local HEADER_TABS = {
|
local HEADER_TABS = {
|
||||||
{ id = "mods", key = "tab-mods" },
|
{ id = "mods", key = "tab-mods" },
|
||||||
{ id = "find", key = "tab-find" },
|
{ id = "find", key = "tab-find" },
|
||||||
{ id = "skins", key = "tab-skins", glyph = true },
|
{ id = "skins", key = "tab-skins", glyph = true, beta = true },
|
||||||
{ id = "bug", key = "tab-bug" },
|
{ id = "bug", key = "tab-bug" },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local BETA_TAG_OPTS = { fill = true, bold = true, ink = PAL.inverse }
|
||||||
|
|
||||||
|
local function drawBetaTag(x, y, w, h)
|
||||||
|
Kit.tag(x, y, w, h, "BETA", PAL.yellow, BETA_TAG_OPTS)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function overlayBeta(tx, ty, w, tabH, m)
|
||||||
|
local bh = math.floor(11 * m.s)
|
||||||
|
local bw = math.min(w, Kit.textWidth("micro", "BETA") + math.floor(10 * m.s))
|
||||||
|
drawBetaTag(tx + (w - bw) / 2, ty + tabH - bh - math.floor(2 * m.s), bw, bh)
|
||||||
|
end
|
||||||
|
|
||||||
for _, t in ipairs(HEADER_TABS) do
|
for _, t in ipairs(HEADER_TABS) do
|
||||||
t.opts = { face = "tab", font = "tab", color = t.color, letter = t.letter }
|
t.opts = { face = "tab", font = "tab", color = t.color, letter = t.letter }
|
||||||
if t.glyph then
|
if t.glyph then
|
||||||
@@ -1273,6 +1286,7 @@ local function buildHeader(imp, m)
|
|||||||
o.image = t.icon
|
o.image = t.icon
|
||||||
o.action = chrome.tab[t.id]
|
o.action = chrome.tab[t.id]
|
||||||
btn(imp, tx, ty, w, tabH, t.key, "", o)
|
btn(imp, tx, ty, w, tabH, t.key, "", o)
|
||||||
|
if t.beta then overlayBeta(tx, ty, w, tabH, m) end
|
||||||
tx = tx + w + tabGap
|
tx = tx + w + tabGap
|
||||||
end
|
end
|
||||||
-- The bug-report chip sits LAST, past the sync chip.
|
-- The bug-report chip sits LAST, past the sync chip.
|
||||||
@@ -1290,10 +1304,7 @@ local function buildHeader(imp, m)
|
|||||||
local o = chrome.sync
|
local o = chrome.sync
|
||||||
o.active = imp._syncModal ~= nil
|
o.active = imp._syncModal ~= nil
|
||||||
btn(imp, tx, ty, w, tabH, "tab-sync", "", o)
|
btn(imp, tx, ty, w, tabH, "tab-sync", "", o)
|
||||||
local bh = math.floor(11 * m.s)
|
overlayBeta(tx, ty, w, tabH, m)
|
||||||
local bw = math.min(w, Kit.textWidth("micro", "BETA") + math.floor(10 * m.s))
|
|
||||||
Kit.tag(tx + (w - bw) / 2, ty + tabH - bh - math.floor(2 * m.s), bw, bh,
|
|
||||||
"BETA", o.active and PAL.inverse or PAL.yellow)
|
|
||||||
local eng = imp._sync
|
local eng = imp._sync
|
||||||
if eng and eng.busy and eng:busy() then
|
if eng and eng.busy and eng:busy() then
|
||||||
Kit.spinner(tx + w - math.floor(8 * m.s), ty + math.floor(8 * m.s),
|
Kit.spinner(tx + w - math.floor(8 * m.s), ty + math.floor(8 * m.s),
|
||||||
@@ -4490,8 +4501,8 @@ local function syncTitle(imp, m, px, py, pw, pad)
|
|||||||
Kit.text("button", label, px + pad, py, PAL.heading)
|
Kit.text("button", label, px + pad, py, PAL.heading)
|
||||||
local bh = math.floor(15 * m.s)
|
local bh = math.floor(15 * m.s)
|
||||||
local bw = Kit.textWidth("micro", "BETA") + math.floor(14 * m.s)
|
local bw = Kit.textWidth("micro", "BETA") + math.floor(14 * m.s)
|
||||||
Kit.tag(px + pad + Kit.textWidth("button", label) + math.floor(8 * m.s),
|
drawBetaTag(px + pad + Kit.textWidth("button", label) + math.floor(8 * m.s),
|
||||||
py + (Kit.textHeight("button") - bh) / 2, bw, bh, "BETA", PAL.yellow)
|
py + (Kit.textHeight("button") - bh) / 2, bw, bh)
|
||||||
return py + Kit.textHeight("button") + math.floor(12 * m.s)
|
return py + Kit.textHeight("button") + math.floor(12 * m.s)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ local TouchSkin = require("src.core.TouchSkin")
|
|||||||
|
|
||||||
local Playfield = {}
|
local Playfield = {}
|
||||||
|
|
||||||
Playfield.WIDTH, Playfield.HEIGHT = 160, 144
|
|
||||||
|
|
||||||
Playfield.entered = false
|
Playfield.entered = false
|
||||||
Playfield.box = nil
|
Playfield.box = nil
|
||||||
|
|
||||||
@@ -35,14 +33,9 @@ function Playfield.cutout(sw, sh)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function Playfield.rect(sw, sh)
|
function Playfield.rect(sw, sh)
|
||||||
local x, y, w, h, _, expand = Playfield.cutout(sw, sh)
|
local x, y, w, h = Playfield.cutout(sw, sh)
|
||||||
if not x then return 0, 0, sw or 0, sh or 0, false end
|
if not x then return 0, 0, sw or 0, sh or 0, false end
|
||||||
if expand then return x, y, w, h, true end
|
return x, y, w, h, true
|
||||||
local s = math.max(1, math.floor(math.min(w / Playfield.WIDTH,
|
|
||||||
h / Playfield.HEIGHT)))
|
|
||||||
local pw = math.min(w, Playfield.WIDTH * s)
|
|
||||||
local ph = math.min(h, Playfield.HEIGHT * s)
|
|
||||||
return x + math.floor((w - pw) / 2), y + math.floor((h - ph) / 2), pw, ph, true
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function Playfield.enter(x, y, w, h)
|
function Playfield.enter(x, y, w, h)
|
||||||
|
|||||||
@@ -87,12 +87,12 @@ local function displayMetrics()
|
|||||||
if dpiX < 1e-6 then dpiX = 1 end
|
if dpiX < 1e-6 then dpiX = 1 end
|
||||||
if dpiY < 1e-6 then dpiY = 1 end
|
if dpiY < 1e-6 then dpiY = 1 end
|
||||||
local vx, vy = 0, 0
|
local vx, vy = 0, 0
|
||||||
local cut, grow = false, false
|
local cut = false
|
||||||
local sx, sy, sw, sh, _, expand = Playfield.cutout(pw, ph)
|
local sx, sy, sw, sh = Playfield.cutout(pw, ph)
|
||||||
if sx then
|
if sx then
|
||||||
vx, vy, pw, ph, cut, grow = sx, sy, sw, sh, true, expand
|
vx, vy, pw, ph, cut = sx, sy, sw, sh, true
|
||||||
end
|
end
|
||||||
return ww, wh, pw, ph, dpiX, dpiY, vx, vy, cut, grow
|
return ww, wh, pw, ph, dpiX, dpiY, vx, vy, cut
|
||||||
end
|
end
|
||||||
|
|
||||||
local function positionLift(ph, contentPx, dpiY, cut)
|
local function positionLift(ph, contentPx, dpiY, cut)
|
||||||
@@ -275,7 +275,7 @@ end
|
|||||||
-- corners; flat mode returns exactly today's size (growth factor is 1 when
|
-- corners; flat mode returns exactly today's size (growth factor is 1 when
|
||||||
-- tilt is inactive).
|
-- tilt is inactive).
|
||||||
function Renderer:worldViewSize()
|
function Renderer:worldViewSize()
|
||||||
local _, _, pw, ph, _, dpiY, _, _, cut, grow = displayMetrics()
|
local _, _, pw, ph, _, dpiY, _, _, cut = displayMetrics()
|
||||||
-- FAITHFUL RATIO on mobile. The world pass deliberately expands to cover the
|
-- FAITHFUL RATIO on mobile. The world pass deliberately expands to cover the
|
||||||
-- WHOLE display, so letterbox voids become more map instead of black bars.
|
-- WHOLE display, so letterbox voids become more map instead of black bars.
|
||||||
-- That is why the lock appeared to do nothing in the overworld: it shrank
|
-- That is why the lock appeared to do nothing in the overworld: it shrank
|
||||||
@@ -287,7 +287,6 @@ function Renderer:worldViewSize()
|
|||||||
-- this is the same sum with the viewport standing in for the window, so
|
-- this is the same sum with the viewport standing in for the window, so
|
||||||
-- both platforms show the same map area at the same zoom.
|
-- both platforms show the same map area at the same zoom.
|
||||||
local cap = FaithfulRes.scaleCap()
|
local cap = FaithfulRes.scaleCap()
|
||||||
if not cap and cut and not grow then cap = self:fitScale() end
|
|
||||||
if cap then
|
if cap then
|
||||||
local uiw, uih = self:uiSize()
|
local uiw, uih = self:uiSize()
|
||||||
pw = cut and math.min(pw, uiw * cap) or uiw * cap
|
pw = cut and math.min(pw, uiw * cap) or uiw * cap
|
||||||
|
|||||||
@@ -456,9 +456,10 @@ function Studio.setCanvas(index, fromSync)
|
|||||||
page.viewportFill = false
|
page.viewportFill = false
|
||||||
markDirty()
|
markDirty()
|
||||||
end
|
end
|
||||||
-- A cfg-authored aspect_ratio is the overlay's design aspect; keep it so
|
-- A cfg-authored aspect_ratio is the overlay's design aspect, and bezel art
|
||||||
-- the preview letterboxes like RetroArch instead of stretching (#1503).
|
-- is its own design canvas (TouchSkin.applyImageAspect); keep either so the
|
||||||
if page and not page.aspectFromCfg then
|
-- preview lays the page out exactly the way the game does (#1503).
|
||||||
|
if page and not (page.aspectFromCfg or page.aspectFromImage) then
|
||||||
page.aspect = canvas.w / canvas.h
|
page.aspect = canvas.w / canvas.h
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
+16
-5
@@ -749,12 +749,23 @@ function Kit.chip(x, y, w, h, label, on, color, id)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- A status label with no interaction: outlined text, the "INSTALLED"/"UPDATE"
|
-- A status label with no interaction: outlined text, the "INSTALLED"/"UPDATE"
|
||||||
-- markers on mod rows.
|
-- markers on mod rows. Pass opts.fill for a solid chip (BETA badges); ink
|
||||||
function Kit.tag(x, y, w, h, label, color)
|
-- then defaults to PAL.inverse so the label stays readable on the fill.
|
||||||
|
function Kit.tag(x, y, w, h, label, color, opts)
|
||||||
if not G then return end
|
if not G then return end
|
||||||
Theme.strokeRounded(x, y, w, h, color or PAL.line, 0.7, 1)
|
opts = opts or {}
|
||||||
Kit.textCenter("micro", label, x, y + (h - Kit.textHeight("micro")) / 2, w,
|
if opts.fill then
|
||||||
color or PAL.muted)
|
Theme.fillRounded(x, y, w, h, color or PAL.yellow, 1, h / 2)
|
||||||
|
else
|
||||||
|
Theme.strokeRounded(x, y, w, h, color or PAL.line, 0.7, 1)
|
||||||
|
end
|
||||||
|
local ink = opts.ink or (opts.fill and PAL.inverse) or color or PAL.muted
|
||||||
|
local ty = y + (h - Kit.textHeight("micro")) / 2
|
||||||
|
if opts.bold then
|
||||||
|
Kit.textCenterBold("micro", label, x, ty, w, ink)
|
||||||
|
else
|
||||||
|
Kit.textCenter("micro", label, x, ty, w, ink)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Checkbox row. Returns (newChecked, changed).
|
-- Checkbox row. Returns (newChecked, changed).
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
-- Screen-rect check for a touch skin, both generations.
|
||||||
|
--
|
||||||
|
-- POKEPORT_DRIVER=tests/drivers/skin_screen_shot.lua love .
|
||||||
|
-- POKEPORT_GAME=gold POKEPORT_SKIN=my_skin POKEPORT_DRIVER=... love .
|
||||||
|
--
|
||||||
|
-- Gold's cache lives under the DEFAULT save identity, so a POKEPORT_IDENTITY
|
||||||
|
-- sandbox has to be seeded with it first or the boot hangs in the importer:
|
||||||
|
-- cp -R ~/Library/Application\ Support/LOVE/pokemon-love2d/{gold,skins} \
|
||||||
|
-- ~/Library/Application\ Support/LOVE/<identity>/
|
||||||
|
local U = require("tests.drivers.util")
|
||||||
|
local GameVersion = require("src.core.GameVersion")
|
||||||
|
|
||||||
|
local function env(name, fallback)
|
||||||
|
local v = os.getenv(name)
|
||||||
|
if v == nil or v == "" then return fallback end
|
||||||
|
return v
|
||||||
|
end
|
||||||
|
|
||||||
|
local function tap(game, button)
|
||||||
|
game.input.pressQueue[#game.input.pressQueue + 1] = button
|
||||||
|
game.input.state[button] = true
|
||||||
|
U.wait(2)
|
||||||
|
game.input.state[button] = false
|
||||||
|
end
|
||||||
|
|
||||||
|
return function(game)
|
||||||
|
local TouchControls = require("src.core.TouchControls")
|
||||||
|
local out = env("POKEPORT_SHOT_DIR", ".")
|
||||||
|
local gen2 = GameVersion.generation() == 2
|
||||||
|
|
||||||
|
love.window.setMode(tonumber(env("POKEPORT_SHOT_W", 460)),
|
||||||
|
tonumber(env("POKEPORT_SHOT_H", 950)))
|
||||||
|
local skin = env("POKEPORT_SKIN", "gb_anim")
|
||||||
|
local ok, err = TouchControls:selectSkin(skin)
|
||||||
|
assert(ok, "skin " .. skin .. ": " .. tostring(err))
|
||||||
|
|
||||||
|
U.wait(60)
|
||||||
|
if gen2 then
|
||||||
|
local A = require("tests.drivers.gold.adapter")
|
||||||
|
assert(game.world and game.world.map, "gold world did not boot")
|
||||||
|
A.teleport(game, env("POKEPORT_SHOT_MAP", "NEW_BARK_TOWN"), 6, 6)
|
||||||
|
U.wait(120)
|
||||||
|
else
|
||||||
|
local Pokemon = require("src.pokemon.Pokemon")
|
||||||
|
game.save.party = { Pokemon.new(game.data, "CHARIZARD", 50) }
|
||||||
|
U.teleport(game, env("POKEPORT_SHOT_MAP", "PALLET_TOWN"), 10, 8, "down")
|
||||||
|
U.wait(40)
|
||||||
|
end
|
||||||
|
U.shot(game, out .. "/skin_world.png")
|
||||||
|
|
||||||
|
tap(game, "start")
|
||||||
|
U.wait(60)
|
||||||
|
U.shot(game, out .. "/skin_menu.png")
|
||||||
|
|
||||||
|
love.event.quit()
|
||||||
|
while true do coroutine.yield() end
|
||||||
|
end
|
||||||
@@ -316,6 +316,8 @@ check(view:find('"tab-sync"', 1, true) ~= nil,
|
|||||||
local header = view:match("local HEADER_TABS = %{(.-)%}\n")
|
local header = view:match("local HEADER_TABS = %{(.-)%}\n")
|
||||||
check(header and header:find('id = "skins"', 1, true) ~= nil,
|
check(header and header:find('id = "skins"', 1, true) ~= nil,
|
||||||
"and it sits beside the skins tab")
|
"and it sits beside the skins tab")
|
||||||
|
check(header and header:find("beta = true", 1, true) ~= nil,
|
||||||
|
"the skins tab carries a BETA badge too")
|
||||||
check(view:find('"BETA"', 1, true) ~= nil,
|
check(view:find('"BETA"', 1, true) ~= nil,
|
||||||
"the button and the modal are labelled BETA")
|
"the button and the modal are labelled BETA")
|
||||||
check(view:find("buildSyncModal", 1, true) ~= nil,
|
check(view:find("buildSyncModal", 1, true) ~= nil,
|
||||||
|
|||||||
@@ -111,6 +111,25 @@ check(Studio.page().viewport ~= nil, "the SGB cutout cannot be toggled off")
|
|||||||
Studio.setCanvas(#Studio.CANVASES + 1)
|
Studio.setCanvas(#Studio.CANVASES + 1)
|
||||||
eq(Studio.canvasIndex, 1, "canvas selection wraps")
|
eq(Studio.canvasIndex, 1, "canvas selection wraps")
|
||||||
|
|
||||||
|
-- the preview must lay the page out the way the game will, so a preset never
|
||||||
|
-- overwrites the aspect the bezel art (or a cfg) already fixed
|
||||||
|
session()
|
||||||
|
local art = Studio.page()
|
||||||
|
art.aspect, art.aspectFromImage = 0.5625, true
|
||||||
|
Studio.setCanvas(1)
|
||||||
|
near(art.aspect, 0.5625, 1e-9, "bezel art keeps its own aspect on a preset switch")
|
||||||
|
local deckW, deckH = 900, 1700
|
||||||
|
local _, dby, _, dbh = TouchSkin.pageBox(art, deckW, deckH)
|
||||||
|
check(dby > 0 and math.abs(dby + dbh - deckH) < 1e-6,
|
||||||
|
"so a preset taller than the art pins the deck low, as gameplay does")
|
||||||
|
|
||||||
|
session()
|
||||||
|
local plain = Studio.page()
|
||||||
|
plain.aspect, plain.aspectFromImage, plain.aspectFromCfg = nil, nil, nil
|
||||||
|
Studio.setCanvas(1)
|
||||||
|
near(plain.aspect, Studio.canvas().w / Studio.canvas().h, 1e-9,
|
||||||
|
"a page with no art of its own still takes the preset's aspect")
|
||||||
|
|
||||||
Studio.setCanvas(1)
|
Studio.setCanvas(1)
|
||||||
Studio.viewZoom = 1
|
Studio.viewZoom = 1
|
||||||
local cx, cy, cw, ch = Studio.canvasRect(0, 0, 800, 600)
|
local cx, cy, cw, ch = Studio.canvasRect(0, 0, 800, 600)
|
||||||
|
|||||||
@@ -136,11 +136,16 @@ for off = lo, hi do
|
|||||||
end
|
end
|
||||||
Zoom.offset = 0
|
Zoom.offset = 0
|
||||||
|
|
||||||
local capped = select(1, Renderer:worldViewSize())
|
useSkin("0.25,0.1,0.3,0.8")
|
||||||
useSkin("0.25,0.1,0.5,0.6", "overlay0_viewport_expand = true")
|
local tallR = Renderer:frameRects()
|
||||||
local expanded = select(1, Renderer:worldViewSize())
|
local tallVw, tallVh = Renderer:worldViewSize()
|
||||||
check(expanded > capped,
|
local tallSp = Zoom.scale(tallR.Sp)
|
||||||
"viewport_expand lets the survey world fill the cutout instead of the GB box")
|
check(tallVw * tallSp >= tallR.vuw and tallVh * tallSp >= tallR.vuh,
|
||||||
|
"the world pass covers the whole cutout, not just the GB box inside it")
|
||||||
|
check(tallVh * tallSp > tallR.uvph,
|
||||||
|
"so a cutout taller than 160x144 shows map where the UI letterbox ends")
|
||||||
|
check(tallR.uvph < tallR.vuh and tallR.uvpw <= tallR.vuw,
|
||||||
|
"while the UI keeps its whole-pixel letterbox inside that cutout")
|
||||||
useSkin("0.25,0.1,0.5,0.6")
|
useSkin("0.25,0.1,0.5,0.6")
|
||||||
|
|
||||||
setWindow(480, 800)
|
setWindow(480, 800)
|
||||||
@@ -159,22 +164,14 @@ setWindow(1280, 720)
|
|||||||
useSkin("0.25,0.1,0.5,0.6")
|
useSkin("0.25,0.1,0.5,0.6")
|
||||||
local px, py, pw, ph, active = Playfield.rect(1280, 720)
|
local px, py, pw, ph, active = Playfield.rect(1280, 720)
|
||||||
eq(active, true, "Gold sees the cutout too")
|
eq(active, true, "Gold sees the cutout too")
|
||||||
eq(pw, 480, "the playfield is a whole multiple of 160")
|
eq(px, 320, "the playfield is the cutout, at its origin")
|
||||||
eq(ph, 432, "and of 144")
|
eq(py, 72, "on both axes")
|
||||||
check(inside(px, py, pw, ph, 320, 72, 640, 432),
|
eq(pw, 640, "with its full width")
|
||||||
"centred inside the cutout")
|
eq(ph, 432, "and its full height")
|
||||||
eq(Chrome.fitScale(1280, 720), 3, "Chrome fits the playfield")
|
eq(Chrome.fitScale(1280, 720), 3, "Chrome fits whole GB pixels in it")
|
||||||
local cox, coy = Chrome.fitOrigin(1280, 720)
|
local cox, coy = Chrome.fitOrigin(1280, 720)
|
||||||
eq(cox, px, "and centres the panel on it")
|
eq(cox, 320 + 80, "and centres the panel on the cutout")
|
||||||
eq(coy, py, "on both axes")
|
eq(coy, 72, "on both axes")
|
||||||
|
|
||||||
useSkin("0.25,0.1,0.5,0.6", "overlay0_viewport_expand = true")
|
|
||||||
local ex, ey, ew, eh = Playfield.rect(1280, 720)
|
|
||||||
eq(ew, 640, "expand hands the picture the full cutout width")
|
|
||||||
eq(eh, 432, "and its full height")
|
|
||||||
eq(ex, 320, "at the cutout origin")
|
|
||||||
eq(ey, 72, "on both axes")
|
|
||||||
useSkin("0.25,0.1,0.5,0.6")
|
|
||||||
|
|
||||||
local ew2, eh2, ex2, ey2, act2 = Playfield.push(1280, 720)
|
local ew2, eh2, ex2, ey2, act2 = Playfield.push(1280, 720)
|
||||||
eq(act2, true, "push reports the frame is contained")
|
eq(act2, true, "push reports the frame is contained")
|
||||||
@@ -184,12 +181,29 @@ eq(ew2, pw, "and hands the scene the playfield size")
|
|||||||
eq(Playfield.cutout(ew2, eh2), nil, "inside the frame there is no cutout left")
|
eq(Playfield.cutout(ew2, eh2), nil, "inside the frame there is no cutout left")
|
||||||
eq(select(3, Playfield.rect(ew2, eh2)), pw, "so the playfield is the surface")
|
eq(select(3, Playfield.rect(ew2, eh2)), pw, "so the playfield is the surface")
|
||||||
eq(Chrome.fitScale(ew2, eh2), 3, "and Chrome fits it without re-applying")
|
eq(Chrome.fitScale(ew2, eh2), 3, "and Chrome fits it without re-applying")
|
||||||
eq(select(1, Chrome.fitOrigin(ew2, eh2)), 0, "at a local origin")
|
eq(select(1, Chrome.fitOrigin(ew2, eh2)), 80, "centred on that surface alone")
|
||||||
eq(select(1, Playfield.dimensions()), pw, "screens read the playfield as the display")
|
eq(select(1, Playfield.dimensions()), pw, "screens read the playfield as the display")
|
||||||
Playfield.pop()
|
Playfield.pop()
|
||||||
eq(Playfield.entered, false, "pop leaves the frame")
|
eq(Playfield.entered, false, "pop leaves the frame")
|
||||||
eq(select(1, Playfield.cutout(1280, 720)), 320, "and the cutout is visible again")
|
eq(select(1, Playfield.cutout(1280, 720)), 320, "and the cutout is visible again")
|
||||||
|
|
||||||
|
setWindow(960, 1901)
|
||||||
|
useSkin("0,0,1,0.5", "overlay0_aspect_ratio = 0.5625")
|
||||||
|
local deck = TouchSkin.page()
|
||||||
|
local _, dy, _, dh = TouchSkin.pageBox(deck, 960, 1901)
|
||||||
|
check(dy > 0 and math.abs(dy + dh - 1901) < 1,
|
||||||
|
"a portrait deck taller than the display pins to the lower edge")
|
||||||
|
local hx, hy, hw, hh = Playfield.cutout(960, 1901)
|
||||||
|
eq(hy, 0, "and the screen rect it left flush takes the room above it")
|
||||||
|
eq(hx, 0, "without moving sideways")
|
||||||
|
eq(hw, 960, "or changing width")
|
||||||
|
eq(hh, math.floor(dy + dh * 0.5), "growing by exactly the headroom")
|
||||||
|
|
||||||
|
useSkin("0,0.1,1,0.5", "overlay0_aspect_ratio = 0.5625")
|
||||||
|
check(select(2, Playfield.cutout(960, 1901)) > dy,
|
||||||
|
"a screen rect the author inset from the top keeps that bezel margin")
|
||||||
|
|
||||||
|
setWindow(1280, 720)
|
||||||
useSkin("0.4,0.4,0.1,0.1")
|
useSkin("0.4,0.4,0.1,0.1")
|
||||||
local sx, sy, sw, sh = Playfield.rect(1280, 720)
|
local sx, sy, sw, sh = Playfield.rect(1280, 720)
|
||||||
check(inside(sx, sy, sw, sh, 512, 288, 128, 72),
|
check(inside(sx, sy, sw, sh, 512, 288, 128, 72),
|
||||||
|
|||||||
Reference in New Issue
Block a user