mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-10-02 07:50:13 -04:00
314 lines
11 KiB
Lua
314 lines
11 KiB
Lua
local U = require("tests.drivers.util")
|
|
return function(game)
|
|
U.wait(20)
|
|
package.path = package.path .. ";./tools/save-editor/?.lua;./tools/save-editor/panels/?.lua"
|
|
local App = require("tools.save-editor.App")
|
|
local Ops = require("Ops")
|
|
local Gen = require("Gen")
|
|
local SD = require("src.core.SaveData")
|
|
local Chooser = require("Chooser")
|
|
local Kit = require("Kit")
|
|
local Paint = require("src.ui.kit.Button")
|
|
local realPaint, navigationRects = Paint.draw, {}
|
|
local labelFailures, labelChecks = {}, 0
|
|
local function labelCheck(ok, message)
|
|
if not ok then
|
|
labelFailures[#labelFailures + 1] = message
|
|
end
|
|
assert(ok, message)
|
|
end
|
|
Paint.draw = function(owner, x, y, w, h, label, opts, hot, focused)
|
|
if owner == Kit and label and label ~= "" then
|
|
labelCheck(opts.labelLayout, "missing complete button label " .. label)
|
|
local layout = opts.labelLayout
|
|
labelCheck(opts.fullLabel, "truncated button label " .. label)
|
|
labelCheck(layout.width <= layout.available + 1, "button word does not fit " .. label)
|
|
labelCheck(layout.height <= h - 4 * Kit.scale + 1, "button label does not fit " .. label)
|
|
labelCheck(table.concat(layout.lines, " ") == label, "button text shortened " .. label)
|
|
labelChecks = labelChecks + 1
|
|
end
|
|
if owner == Kit and opts.id and opts.id:match("^navigate%-") then
|
|
navigationRects[opts.id:sub(10)] = { x = x, y = y, w = w, h = h }
|
|
end
|
|
return realPaint(owner, x, y, w, h, label, opts, hot, focused)
|
|
end
|
|
local version = os.getenv("POKEPORT_VERSION") or "red"
|
|
local path = os.tmpname() .. "-editor-preview.lua"
|
|
local seed = Gen.newGame(version)
|
|
local f = assert(io.open(path, "wb"))
|
|
f:write(SD.encode(seed))
|
|
f:close()
|
|
App.load(path, { version = version, embedded = true })
|
|
local S = App.getState()
|
|
assert(S.save and not S.loadError, S.status)
|
|
Ops.partyAdd(S)
|
|
Ops.selectParty(S, 1)
|
|
Ops.addToBag(S, S.cat.items[1])
|
|
Ops.addToBag(S, S.cat.items[2])
|
|
Ops.boxAdd(S)
|
|
Ops.selectParty(S, 1)
|
|
local dim, safe = love.graphics.getDimensions, love.window.getSafeArea
|
|
local dir = assert(os.getenv("POKEPORT_SHOT_DIR"))
|
|
-- Check rendered pixels with MSAA disabled, not only the options passed
|
|
-- to the painter. Both bright fills must leave all four corner cutouts
|
|
-- and have a smooth arc, including small icon actions and hover states.
|
|
local function cornerProbe(w, h, opts, hot)
|
|
local canvas = love.graphics.newCanvas(w + 16, h + 16, { msaa = 0 })
|
|
love.graphics.push("all")
|
|
love.graphics.setCanvas(canvas)
|
|
love.graphics.origin()
|
|
love.graphics.setScissor()
|
|
love.graphics.setShader()
|
|
love.graphics.clear(0, 0, 0, 0)
|
|
Kit.beginFrame(hot and 20 or -1, hot and 20 or -1, false, 0)
|
|
Kit.button(8, 8, w, h, "", opts)
|
|
Kit.endFrame()
|
|
love.graphics.setCanvas()
|
|
love.graphics.pop()
|
|
local pixels = canvas:newImageData()
|
|
canvas:release()
|
|
local function alpha(x, y)
|
|
local _, _, _, a = pixels:getPixel(x, y)
|
|
return a
|
|
end
|
|
local rounded = alpha(10, 10) < 0.02
|
|
and alpha(w + 5, 10) < 0.02
|
|
and alpha(10, h + 5) < 0.02
|
|
and alpha(w + 5, h + 5) < 0.02
|
|
assert(alpha(8 + math.floor(w / 2), 8 + math.floor(h / 2)) > 0.3, "missing button body")
|
|
local smooth = false
|
|
for py = 8, 21 do
|
|
for px = 8, 21 do
|
|
local a = alpha(px, py)
|
|
smooth = smooth or (a > 0.02 and a < 0.98)
|
|
end
|
|
end
|
|
pixels:release()
|
|
return rounded, smooth
|
|
end
|
|
local control = require("Theme").CONTROL
|
|
local newRadius = control.radius
|
|
control.radius = 8
|
|
local oldRounded = cornerProbe(100, 44, { kind = "accent" }, false)
|
|
control.radius = newRadius
|
|
assert(not oldRounded, "old corner regression was not reproduced")
|
|
local paints = {
|
|
{ kind = "accent" },
|
|
{ kind = "good" },
|
|
{ kind = "primary" },
|
|
{ kind = "ghost" },
|
|
{ kind = "danger" },
|
|
{ face = "selection", active = true },
|
|
{ face = "selection", active = false },
|
|
{ face = "invert" },
|
|
{ kind = "accent", enabled = false },
|
|
{ kind = "good", enabled = false },
|
|
}
|
|
local cornerChecks = 0
|
|
for _, size in ipairs({ { 44, 44 }, { 100, 44 }, { 320, 44 }, { 160, 64 } }) do
|
|
for _, opts in ipairs(paints) do
|
|
for _, hot in ipairs({ false, true }) do
|
|
local rounded, smooth = cornerProbe(size[1], size[2], opts, hot)
|
|
assert(rounded, "squared button corner: " .. (opts.kind or opts.face))
|
|
if opts.enabled ~= false then
|
|
assert(smooth, "aliased button arc: " .. (opts.kind or opts.face))
|
|
end
|
|
cornerChecks = cornerChecks + 1
|
|
end
|
|
end
|
|
end
|
|
print("PASS rendered corner checks: " .. cornerChecks .. " button variants, old shape reproduced")
|
|
local function shot(name, W, H, settle)
|
|
local canvas = love.graphics.newCanvas(W, H)
|
|
love.graphics.getDimensions = function()
|
|
return W, H
|
|
end
|
|
love.window.getSafeArea = function()
|
|
return 0, 0, W, H
|
|
end
|
|
love.graphics.push("all")
|
|
love.graphics.setCanvas(canvas)
|
|
love.graphics.origin()
|
|
love.graphics.setScissor()
|
|
love.graphics.setShader()
|
|
require("src.render.GameViewport").reset()
|
|
love.graphics.clear(0, 0, 0, 1)
|
|
App.draw()
|
|
if settle then
|
|
settle()
|
|
end
|
|
App.draw()
|
|
love.graphics.setCanvas()
|
|
love.graphics.pop()
|
|
local bytes = canvas:newImageData():encode("png"):getString()
|
|
local out = assert(io.open(dir .. "/" .. version .. "-" .. name .. ".png", "wb"))
|
|
out:write(bytes)
|
|
out:close()
|
|
canvas:release()
|
|
love.graphics.getDimensions, love.window.getSafeArea = dim, safe
|
|
print("PASS captured " .. name)
|
|
U.wait(1)
|
|
end
|
|
local function popupShot(name, W, H, key)
|
|
Chooser.close(S)
|
|
navigationRects = {}
|
|
shot(name, W, H, function()
|
|
local rect = assert(navigationRects[key], "missing dropdown " .. key)
|
|
App.mousepressed(rect.x + rect.w / 2, rect.y + rect.h / 2, 1)
|
|
App.draw()
|
|
assert(S.navPopup and S.navPopup.key == key, "dropdown did not open " .. key)
|
|
end)
|
|
Chooser.close(S)
|
|
end
|
|
for _, tab in ipairs({ "party", "boxes", "items", "events", "dex", "map", "trainer", "legality" }) do
|
|
S.tab = tab
|
|
S.pageScroll = {}
|
|
S.inspectorScroll = 0
|
|
S.monSection = "main"
|
|
S.mobileInspector = true
|
|
shot(tab, 360, 640)
|
|
shot("full-label-" .. tab, 320, 568)
|
|
end
|
|
S.tab = "dex"
|
|
S.pageScroll = {}
|
|
shot("pokedex-full-labels", 390, 844)
|
|
shot("pokedex-small-phone", 320, 568)
|
|
popupShot("pokedex-actions", 390, 844, "dexActions")
|
|
popupShot("pokedex-actions-small-phone", 320, 568, "dexActions")
|
|
-- Audit complete labels on armed confirmations and every inventory mode,
|
|
-- including the state whose longer label used to overflow a small chip.
|
|
S.tab = "items"
|
|
for _, view in ipairs({ "bag", "pc", "wallet", "badges" }) do
|
|
S.itemView = view
|
|
shot("full-label-items-" .. view, 320, 568)
|
|
end
|
|
S.itemView = "bag"
|
|
local bagId = require("src.inventory.Bag").order(S.save, S.data)[1]
|
|
if bagId then
|
|
Ops.arm(S, "bag-drop-" .. tostring(bagId))
|
|
shot("full-label-item-confirmation", 320, 568)
|
|
Ops.disarm(S)
|
|
end
|
|
S.tab = "boxes"
|
|
for _, view in ipairs({ "storage", "party" }) do
|
|
S.boxView = view
|
|
shot("full-label-boxes-" .. view, 320, 568)
|
|
end
|
|
S.boxView = "storage"
|
|
Ops.arm(S, "box-release")
|
|
shot("full-label-box-confirmation", 320, 568)
|
|
Ops.disarm(S)
|
|
if Gen.ofState(S) == 3 and S.game3Events and S.game3Events.story[1] then
|
|
local flag = S.game3Events.story[1]
|
|
Gen.setFlag(S.save, flag.name or flag.id, true)
|
|
S.tab = "events"
|
|
shot("selected-events", 390, 844)
|
|
end
|
|
S.tab = "map"
|
|
for _, section in ipairs({ "maps", "view", "spawn" }) do
|
|
S.mapSection = section
|
|
shot("map-" .. section, 360, 640)
|
|
shot("map-" .. section .. "-landscape", 640, 360)
|
|
end
|
|
S.mapSection, S.mapFocused = "view", true
|
|
shot("map-focus-landscape", 640, 360)
|
|
S.mapFocused = false
|
|
S.tab = "party"
|
|
S.mobileInspector = false
|
|
shot("party-roster", 360, 640)
|
|
S.mobileInspector = true
|
|
for _, section in ipairs({ "stats", "moves", "origin", "extras", "checks" }) do
|
|
S.monSection = section
|
|
S.inspectorScroll = 0
|
|
shot(section, 390, 844)
|
|
shot("full-label-" .. section, 320, 568)
|
|
end
|
|
if Gen.ofState(S) == 3 then
|
|
for _, choice in ipairs({
|
|
{ "main", "nature" },
|
|
{ "origin", "language" },
|
|
{ "origin", "pokeball" },
|
|
{ "origin", "metGame" },
|
|
}) do
|
|
S.monSection, S.propertyChoice, S.inspectorScroll = choice[1], choice[2], 300
|
|
shot("full-label-choice-" .. choice[2], 320, 568)
|
|
end
|
|
S.monSection, S.propertyChoice, S.inspectorScroll = "origin", "language", 500
|
|
shot("language-choices", 390, 844, function()
|
|
S.inspectorScroll = 500
|
|
end)
|
|
S.propertyChoice, S.inspectorScroll = nil, 0
|
|
end
|
|
S.monSection = "main"
|
|
shot("selected-buttons", 390, 844)
|
|
shot("rounded-buttons", 390, 844)
|
|
S.tab = "dex"
|
|
shot("rounded-actions", 390, 844)
|
|
S.tab = "party"
|
|
shot("desktop", 1280, 800)
|
|
shot("landscape", 640, 360)
|
|
popupShot("tab-menu", 360, 640, "tab")
|
|
popupShot("page-popup-desktop", 1280, 800, "tab")
|
|
popupShot("page-popup-landscape", 640, 360, "tab")
|
|
popupShot("section-popup", 390, 844, "monSection")
|
|
popupShot("section-popup-desktop", 1280, 800, "monSection")
|
|
for _, entry in ipairs({
|
|
{ "items", "itemView" },
|
|
{ "boxes", "boxView" },
|
|
{ "events", "eventsTab" },
|
|
{ "map", "mapSection" },
|
|
}) do
|
|
S.tab = entry[1]
|
|
S.pageScroll = {}
|
|
popupShot(entry[1] .. "-popup", 390, 844, entry[2])
|
|
end
|
|
S.tab = "party"
|
|
S.chromeMenu = true
|
|
shot("more-menu", 360, 640)
|
|
S.chromeMenu = false
|
|
for _, picker in ipairs({ "species", "move", "held" }) do
|
|
if picker == "species" then
|
|
Ops.openSpeciesPicker(S, require("Kit"))
|
|
elseif picker == "move" then
|
|
Ops.openMovePicker(S, require("Kit"), 1)
|
|
else
|
|
Ops.openItemPicker(S, require("Kit"), "held")
|
|
end
|
|
shot("picker-" .. picker, 360, 640)
|
|
Ops.closeSpeciesPicker(S, require("Kit"))
|
|
Ops.closeMovePicker(S, require("Kit"))
|
|
Ops.closeItemPicker(S, require("Kit"))
|
|
end
|
|
assert(App.save(), "scratch save writes for saved-button preview")
|
|
shot("saved-button", 390, 844)
|
|
S.allowSave = false
|
|
shot("locked-save-button", 390, 844)
|
|
S.allowSave = true
|
|
local Motion = require("Motion")
|
|
local Transition = require("src.ui.kit.Transition")
|
|
local oldClock = love.timer.getTime
|
|
local clock = 100
|
|
love.timer.getTime = function()
|
|
return clock
|
|
end
|
|
Transition.armed = true
|
|
Transition.reduceMotion = false
|
|
Motion.change(S, "monSection", "stats", 1)
|
|
clock = 100.045
|
|
shot("section-slide", 390, 844)
|
|
clock = 100.20
|
|
Motion.update()
|
|
require("Kit").blockClicks = false
|
|
Motion.change(S, "tab", "items", 1)
|
|
clock = 100.245
|
|
shot("tab-slide", 390, 844)
|
|
Motion.reset()
|
|
love.timer.getTime = oldClock
|
|
assert(#labelFailures == 0, table.concat(labelFailures, "\n"))
|
|
print("PASS complete button labels: " .. labelChecks .. " real-font layouts audited")
|
|
App.unload()
|
|
Paint.draw = realPaint
|
|
os.remove(path)
|
|
love.event.quit(0)
|
|
end
|