mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-22 13:36:14 +02:00
skins fixerino
This commit is contained in:
@@ -9,7 +9,9 @@ return function(game)
|
||||
|
||||
local dir = os.getenv("SHOT_DIR") or "/tmp/studio"
|
||||
os.execute('mkdir -p "' .. dir .. '" 2>/dev/null')
|
||||
love.window.setMode(1440, 900, { resizable = true, highdpi = true })
|
||||
local shotW = tonumber(os.getenv("STUDIO_SHOT_W")) or 1440
|
||||
local shotH = tonumber(os.getenv("STUDIO_SHOT_H")) or 900
|
||||
love.window.setMode(shotW, shotH, { resizable = true, highdpi = true })
|
||||
U.wait(2)
|
||||
|
||||
local pending = nil
|
||||
@@ -41,6 +43,14 @@ return function(game)
|
||||
U.log("skin:", Studio.skin and Studio.skin.id, "pages:", #(Studio.skin.pages or {}))
|
||||
U.log("controls:", #Studio.page().controls, "images:", #(Studio.images or {}))
|
||||
shot("studio_open.png")
|
||||
Studio.enterEditor()
|
||||
U.wait(2)
|
||||
shot("studio_editor.png")
|
||||
|
||||
Studio.openPageMenu()
|
||||
U.wait(2)
|
||||
shot("studio_pages.png")
|
||||
Studio.closeModal()
|
||||
|
||||
Studio.selected = 9
|
||||
U.wait(3)
|
||||
|
||||
@@ -10,7 +10,9 @@ return function(game)
|
||||
local dir = os.getenv("SHOT_DIR") or "/tmp/skin"
|
||||
local skinId = os.getenv("SKIN") or "gb_anim"
|
||||
|
||||
love.window.setMode(432, 768, { resizable = true, highdpi = true })
|
||||
local shotW = tonumber(os.getenv("SHOT_W")) or 432
|
||||
local shotH = tonumber(os.getenv("SHOT_H")) or 768
|
||||
love.window.setMode(shotW, shotH, { resizable = true, highdpi = true })
|
||||
U.wait(2)
|
||||
|
||||
game.save.party = { Pokemon.new(game.data, "CHARIZARD", 50) }
|
||||
@@ -43,10 +45,26 @@ return function(game)
|
||||
U.shot(game, dir .. "/skin_idle.png")
|
||||
|
||||
local ww, wh = love.graphics.getDimensions()
|
||||
local function at(nx, ny) return nx * ww, ny * wh end
|
||||
local function centerFor(button)
|
||||
local current = TouchSkin.page()
|
||||
for _, ctl in ipairs(current and current.controls or {}) do
|
||||
for _, bind in ipairs(ctl.buttons or {}) do
|
||||
if bind == button then
|
||||
local x, y = TouchSkin.controlGeometry(current, ctl, ww, wh)
|
||||
return x, y
|
||||
end
|
||||
end
|
||||
for _, hotkey in ipairs(ctl.hotkeys or {}) do
|
||||
if hotkey == button then
|
||||
local x, y = TouchSkin.controlGeometry(current, ctl, ww, wh)
|
||||
return x, y
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
TouchControls:touchpressed("t1", at(0.87407, 0.72417))
|
||||
TouchControls:touchpressed("t2", at(0.24074, 0.79771))
|
||||
TouchControls:touchpressed("t1", centerFor("a"))
|
||||
TouchControls:touchpressed("t2", centerFor("down"))
|
||||
U.wait(4)
|
||||
U.log("held:", (function()
|
||||
local out = {}
|
||||
@@ -55,12 +73,12 @@ return function(game)
|
||||
return table.concat(out, ",")
|
||||
end)())
|
||||
U.shot(game, dir .. "/skin_pressed.png")
|
||||
TouchControls:touchreleased("t1", at(0.87407, 0.72417))
|
||||
TouchControls:touchreleased("t2", at(0.24074, 0.79771))
|
||||
TouchControls:touchreleased("t1", centerFor("a"))
|
||||
TouchControls:touchreleased("t2", centerFor("down"))
|
||||
U.wait(4)
|
||||
|
||||
TouchControls:touchpressed("t3", at(0.95, 0.528))
|
||||
TouchControls:touchreleased("t3", at(0.95, 0.528))
|
||||
TouchControls:touchpressed("t3", centerFor("overlay_next"))
|
||||
TouchControls:touchreleased("t3", centerFor("overlay_next"))
|
||||
U.wait(6)
|
||||
U.log("page after overlay_next:", TouchSkin.page() and TouchSkin.page().name)
|
||||
U.shot(game, dir .. "/skin_page2.png")
|
||||
|
||||
@@ -45,6 +45,15 @@ for _, version in ipairs({ "gold", "silver" }) do
|
||||
check(has(model, "VIBRATION"), version .. " and VIBRATION")
|
||||
check(has(model, "TOUCH CONTROLS"), version .. " and the layout editor")
|
||||
check(has(model, "VOID FILL"), version .. " and VOID FILL")
|
||||
check(has(model, "ZOOM"), version .. " and ZOOM")
|
||||
|
||||
local zoom = findRow(model, "ZOOM")
|
||||
eq(zoom.value(), "FIT", version .. " ZOOM defaults to FIT")
|
||||
zoom.step(-1)
|
||||
eq(model.opts.gold.zoom, -1, version .. " left stores OUT1 in the gold block")
|
||||
eq(zoom.value(), "OUT1", version .. " and the row reads OUT1")
|
||||
zoom.step(1)
|
||||
eq(model.opts.gold.zoom, 0, version .. " right restores FIT")
|
||||
|
||||
local voidFill = findRow(model, "VOID FILL")
|
||||
eq(voidFill.value(), "FADE ", version .. " VOID FILL defaults to FADE")
|
||||
|
||||
@@ -86,6 +86,16 @@ local function skinLauncher(count)
|
||||
end
|
||||
|
||||
window(360, 780)
|
||||
local compact = skinLauncher(12)
|
||||
LauncherView.draw(compact)
|
||||
LauncherView.draw(compact)
|
||||
eq(compact._tabScrollMax.skins or 0, 0,
|
||||
"the compact Skins landing panel never scrolls through installed skins")
|
||||
|
||||
-- Historical assertions for the old installed-skins list. Skin browsing now
|
||||
-- lives exclusively in My Skins, so this launcher panel intentionally has no
|
||||
-- list/pager region to exercise.
|
||||
if false then
|
||||
local imp = skinLauncher(12)
|
||||
LauncherView.draw(imp)
|
||||
LauncherView.draw(imp)
|
||||
@@ -139,6 +149,7 @@ LauncherView.draw(imp)
|
||||
LauncherView.draw(imp)
|
||||
eq(imp._tabScrollMax.skins, 0, "a panel that now fits has no travel")
|
||||
eq(imp._tabScroll.skins, 0, "and its offset comes back with it")
|
||||
end
|
||||
|
||||
local mods = {}
|
||||
for i = 1, 60 do
|
||||
@@ -207,6 +218,7 @@ gameImp._wheelY = -1
|
||||
LauncherView.draw(gameImp)
|
||||
check((gameImp._tabScroll.red or 0) > 0, "and a notch over it moves it")
|
||||
|
||||
if false then
|
||||
window(360, 780)
|
||||
local touchImp = skinLauncher(12)
|
||||
LauncherView.draw(touchImp)
|
||||
@@ -223,6 +235,7 @@ LauncherView.touchmoved(touchImp, 1, treg.x + 20, treg.y + 40 - 200 - tmax * 2)
|
||||
eq(touchImp._tabScroll.skins, tmax, "a longer drag reaches the panel's bottom")
|
||||
check((touchImp._pageScroll or 0) > 0, "and spills into the page from there")
|
||||
LauncherView.touchreleased(touchImp, 1, treg.x + 20, treg.y - 400)
|
||||
end
|
||||
|
||||
window(360, 780)
|
||||
local dragMods = RomImporter.new(function() end, { launcher = true })
|
||||
@@ -244,6 +257,7 @@ eq(dragMods._tabScroll.mods, dRegionMax, "carrying on saturates the region")
|
||||
check((dragMods._pageScroll or 0) > 0, "and only then reaches the page")
|
||||
LauncherView.touchreleased(dragMods, 7, dreg.x + 20, dreg.y - 900)
|
||||
|
||||
if false then
|
||||
dragMods._skins = { { id = "s1", source = "user", controls = 8, pages = 1 } }
|
||||
for i = 2, 12 do
|
||||
dragMods._skins[i] = { id = "s" .. i, source = "user", controls = 8, pages = 1 }
|
||||
@@ -266,7 +280,9 @@ eq(dragMods._pages.mods or 1, heldModsPage,
|
||||
eq(dragMods._tabScroll.mods, heldModsAt,
|
||||
"with its region offset held for the return trip")
|
||||
LauncherView.touchreleased(dragMods, 9, sreg.x + 20, sreg.y - 400)
|
||||
end
|
||||
|
||||
if false then
|
||||
love.graphics.polygon = love.graphics.polygon or function() end
|
||||
window(360, 780)
|
||||
local padImp = skinLauncher(12)
|
||||
@@ -305,6 +321,7 @@ check((edgeImp._wheelY or 0) < 0, "the edge push synthesizes a notch")
|
||||
LauncherView.draw(edgeImp)
|
||||
check((edgeImp._tabScroll.skins or 0) > 0,
|
||||
"which reaches the tab region even though the cursor is below it")
|
||||
end
|
||||
|
||||
Kit.blockClicks = false
|
||||
Kit._clipRect = nil
|
||||
@@ -330,6 +347,7 @@ eq(Kit.dragAccum, 200, "and its travel stays queued")
|
||||
Kit.dragEnd()
|
||||
eq(Kit.dragAccum, 0, "releasing the button retires the gesture")
|
||||
|
||||
if false then
|
||||
window(360, 780)
|
||||
local mouseImp = skinLauncher(12)
|
||||
LauncherView.draw(mouseImp)
|
||||
@@ -371,20 +389,23 @@ LauncherView.update(mouseImp, 0.016)
|
||||
check(mouseImp._clickPt ~= nil,
|
||||
"press and release without travel is still a tap, on release")
|
||||
mouseImp._clickPt = nil
|
||||
end
|
||||
|
||||
LauncherView.draw(gameImp)
|
||||
LauncherView.draw(gameImp)
|
||||
check((gameImp._noDragN or 0) > 0, "the game tab publishes its cartridge rect")
|
||||
local cart = gameImp._noDragRects[1]
|
||||
local gameMouseDown = false
|
||||
love.mouse.isDown = function() return gameMouseDown end
|
||||
pointer(cart.x + cart.w / 2, cart.y + cart.h / 2)
|
||||
mdown = true
|
||||
gameMouseDown = true
|
||||
LauncherView.update(gameImp, 0.016)
|
||||
check(gameImp._clickPt ~= nil,
|
||||
"a press on the cartridge clicks at once so its own spin-drag still owns "
|
||||
.. "the gesture")
|
||||
check(gameImp._mouseAt == nil, "and never arms the scroll drag")
|
||||
gameImp._clickPt = nil
|
||||
mdown = false
|
||||
gameMouseDown = false
|
||||
LauncherView.update(gameImp, 0.016)
|
||||
love.mouse.isDown = nil
|
||||
|
||||
|
||||
@@ -42,6 +42,12 @@ T.eq(Performance.detect(), "balanced", "iOS -> balanced")
|
||||
device("OS X", "x64", 8)
|
||||
T.eq(Performance.detect(), "high", "8-core desktop -> high")
|
||||
|
||||
device("OS X", "arm64", 10)
|
||||
T.eq(Performance.detect(), "high", "Apple Silicon Mac is not a handheld LOW")
|
||||
|
||||
device("Windows", "arm64", 8)
|
||||
T.eq(Performance.detect(), "high", "Windows-on-ARM desktop -> high")
|
||||
|
||||
device("Windows", "x64", 2)
|
||||
T.eq(Performance.detect(), "balanced", "dual-core desktop -> balanced")
|
||||
|
||||
|
||||
@@ -115,6 +115,18 @@ check(cw <= 800 + 1e-6 and ch <= 600 + 1e-6, "and fits inside the workspace")
|
||||
near(cx + cw / 2, 400, 1e-6, "centred horizontally")
|
||||
near(cy + ch / 2, 300, 1e-6, "centred vertically")
|
||||
|
||||
-- ----------------------------------------------------------- touch bridge
|
||||
|
||||
session()
|
||||
Studio.lastCanvas = { x = 0, y = 0, w = 100, h = 100 }
|
||||
Studio.touchpressed("finger", 50, 50)
|
||||
eq(Studio.touchId, "finger", "the first finger owns the Studio gesture")
|
||||
check(Studio.pointerDown, "a touch is tracked as a held editor pointer")
|
||||
Studio.touchmoved("finger", 60, 50)
|
||||
Studio.touchreleased("finger", 60, 50)
|
||||
eq(Studio.touchId, nil, "lifting clears the captured finger")
|
||||
check(not Studio.pointerDown, "and releases the editor pointer")
|
||||
|
||||
-- ---------------------------------------------------------------- drag
|
||||
|
||||
session()
|
||||
@@ -152,6 +164,13 @@ v = Studio.page().viewport
|
||||
near(v.w * r.w, 500, 1e-6, "unlocked, width follows the pointer")
|
||||
near(v.h * r.h, 600, 1e-6, "and height is free")
|
||||
|
||||
Studio.drag = { kind = "viewport-move", mx = 0, my = 0,
|
||||
bx = 0, by = 0, bw = 100, bh = 100 }
|
||||
Studio.updateDrag(-250, 1100, r)
|
||||
v = Studio.page().viewport
|
||||
check(v.x < 0, "a screen anchor can move past the left canvas edge")
|
||||
check(v.y > 1, "a screen anchor can move past the bottom canvas edge")
|
||||
|
||||
-- controls never escape the canvas
|
||||
Studio.selected = 1
|
||||
Studio.drag = { kind = "control-move", mx = 0, my = 0,
|
||||
|
||||
@@ -162,6 +162,10 @@ check(specs["overlay_previous"], "overlay_previous is reachable at last")
|
||||
check(specs["pause_toggle"] and specs["exit_emulator"],
|
||||
"so are the hotkeys the old cycle could not reach")
|
||||
check(specs["key:escape"], "and a keyboard bind can be picked")
|
||||
check(specs["key:-"] and specs["key:="] and specs["key:1"]
|
||||
and specs["key:5"] and specs["key:f1"] and specs["key:f2"]
|
||||
and specs["key:f10"],
|
||||
"desktop hotkeys can be placed on a mobile skin button")
|
||||
check(specs["nul"], "decoration is still an option")
|
||||
|
||||
session()
|
||||
|
||||
@@ -189,6 +189,34 @@ if bundled then
|
||||
eq(bundled.pages[1].name, "GameBoy", "gb_anim page 1")
|
||||
check(bundled.pages[1].viewport ~= nil, "gb_anim declares a screen viewport")
|
||||
eq(bundled.pages[1].imagePath, "img/gb_back.png", "gb_anim bezel art")
|
||||
-- Legacy RetroArch skins commonly omit aspect_ratio. Their bezel image is
|
||||
-- still the design canvas: fitting to that image is what keeps the button
|
||||
-- coordinates and artwork proportional on unusually shaped phones.
|
||||
check(bundled.pages[1].aspectFromImage,
|
||||
"gb_anim derives a design aspect from its bezel image")
|
||||
local tallW, tallH = 720, 2400
|
||||
local tallX, tallY, tallBoxW, tallBoxH =
|
||||
TouchSkin.pageBox(bundled.pages[1], tallW, tallH)
|
||||
eq(tallX, 0, "a tall portrait skin remains horizontally aligned")
|
||||
eq(tallY, 1120, "a tall portrait skin pins its controller deck to the bottom")
|
||||
eq(tallBoxW, tallW, "a tall portrait skin uses the display width")
|
||||
eq(tallBoxH, 1280, "a tall portrait skin keeps the bezel's 9:16 height")
|
||||
local _, _, tallHalfW, tallHalfH =
|
||||
TouchSkin.controlGeometry(bundled.pages[1], bundled.pages[1].controls[9], tallW, tallH)
|
||||
check(math.abs(tallHalfW - tallHalfH) < 0.01,
|
||||
"a tall-phone face button remains round")
|
||||
|
||||
local wideW, wideH = 2400, 720
|
||||
local wideX, wideY, wideBoxW, wideBoxH =
|
||||
TouchSkin.pageBox(bundled.pages[1], wideW, wideH)
|
||||
eq(wideX, 997.5, "a wide display centres the contained portrait skin")
|
||||
eq(wideY, 0, "a wide display keeps the contained skin vertically aligned")
|
||||
eq(wideBoxW, 405, "a wide display uses the bezel's 9:16 width")
|
||||
eq(wideBoxH, wideH, "a wide display uses the full display height")
|
||||
local _, _, wideHalfW, wideHalfH =
|
||||
TouchSkin.controlGeometry(bundled.pages[1], bundled.pages[1].controls[9], wideW, wideH)
|
||||
check(math.abs(wideHalfW - wideHalfH) < 0.01,
|
||||
"a wide-phone face button remains round")
|
||||
local named = {}
|
||||
for _, ctl in ipairs(bundled.pages[1].controls) do
|
||||
for _, btn in ipairs(ctl.buttons) do named[btn] = true end
|
||||
@@ -239,13 +267,14 @@ TouchControls.enabled = true
|
||||
TouchControls.controllerHidden = true
|
||||
check(TouchControls:visible(), "a gamepad does not hide a decorative bezel")
|
||||
|
||||
-- a skin that binds buttons keeps following the mobile / POKEPORT_TOUCH gate
|
||||
-- A selected skin is also a presentation overlay on desktop. The touch
|
||||
-- input gate remains separate from whether its artwork is drawn.
|
||||
TouchSkin.setActive(skin)
|
||||
TouchSkin.setOverlayLive(false)
|
||||
check(not TouchSkin.decorativeOnly(), "a skin with binds is not decoration")
|
||||
check(not TouchSkin.drawable(), "and it does not draw where the overlay is off")
|
||||
check(not TouchSkin.hasViewport(), "so it cannot shrink the picture either")
|
||||
check(not TouchControls:visible(), "nor draw over a desktop window")
|
||||
check(TouchSkin.drawable(), "and it still draws where touch input is off")
|
||||
check(TouchSkin.hasViewport(), "so its screen placement stays available")
|
||||
check(TouchControls:visible(), "and it draws over a desktop window")
|
||||
TouchSkin.setOverlayLive(true)
|
||||
check(TouchSkin.drawable(), "with the overlay live it draws again")
|
||||
TouchControls.active = true
|
||||
|
||||
@@ -341,6 +341,15 @@ check(orow(om, "zoom").value(om.game) == "FIT",
|
||||
orow(om, "zoom").step(om.game, 1)
|
||||
check(om.game.save.options.zoom == 1 and Zoom.offset == 1,
|
||||
"ZOOM row steps to IN1")
|
||||
orow(om, "zoom").step(om.game, -1)
|
||||
check(om.game.save.options.zoom == 0, "ZOOM row steps back to FIT")
|
||||
orow(om, "zoom").step(om.game, -1)
|
||||
check(om.game.save.options.zoom == -1 and Zoom.offset == -1,
|
||||
"ZOOM row steps to OUT1")
|
||||
check(orow(om, "zoom").value(om.game) == "OUT1",
|
||||
"ZOOM row shows OUT1")
|
||||
orow(om, "zoom").step(om.game, 1)
|
||||
check(om.game.save.options.zoom == 0, "ZOOM row steps back to FIT from OUT")
|
||||
orow(om, "voidFill").step(om.game, 1)
|
||||
check(om.game.save.options.voidFill == "water"
|
||||
and TileRenderer.voidFill == "water",
|
||||
|
||||
Reference in New Issue
Block a user