Files
gen1recomp/tests/engine/game3_shaderfx_options_test.lua
T

189 lines
7.8 KiB
Lua

package.path = "./?.lua;./?/init.lua;" .. package.path
if not _G.love then _G.love = require("tests.love_stub") end
local T = require("tests.harness")
local check, eq = T.check, T.eq
local ShaderFX = require("src.render.ShaderFX")
local Pipelines = require("src.render.Pipelines")
local RomText = require("src.core.game3.rom_text")
local Rows = require("src.ui.game3.option_rows")
local ShaderFXMenu = require("src.ui.game3.shaderfx_menu")
local saved = {}
local function stub(mod, key, fn)
saved[#saved + 1] = { mod, key, mod[key] }
mod[key] = fn
end
stub(RomText, "at", function() return "ROW" end)
stub(RomText, "count", function() return 3 end)
stub(RomText, "plain", function() return "TEXT" end)
local fake = { name = "fake-lcd.slangp", converted = true }
local active = {}
local activated = {}
stub(ShaderFX, "list", function() return { fake } end)
stub(ShaderFX, "canConvert", function() return false end)
stub(ShaderFX, "clearBridgeQuarantine", function() end)
stub(ShaderFX, "activeEntry", function(slot) return active[slot] end)
stub(ShaderFX, "activate", function(slot, entry)
activated[#activated + 1] = slot
active[slot] = entry
return true
end)
stub(ShaderFX, "deactivate", function(slot)
if slot then active[slot] = nil else active = {} end
end)
local function ids(list)
local out = {}
for _, r in ipairs(list) do out[r.id] = r end
return out
end
do
local rows = ids(Rows.build({ options = {} }))
check(rows.shaderfx ~= nil, "Gen 3 OPTION lists SHADER FX")
check(rows.shaderfx2 ~= nil, "Gen 3 OPTION lists SHADER FX 2")
local grouped
for _, g in ipairs(Rows.GROUPS) do
if g.id == "group.graphics" then grouped = table.concat(g.members, ",") end
end
check(grouped and grouped:find("shaderfx2", 1, true) ~= nil,
"both shader rows sit under GRAPHICS")
eq(rows.shaderfx.value(), "OFF", "an empty slot reads OFF")
end
local function input(keys)
local pressed = {}
for _, k in ipairs(keys) do pressed[k] = true end
return { wasPressed = function(_, k) return pressed[k] == true end }
end
do
local writes = 0
local game = { options = {}, writeOptions = function() writes = writes + 1 end }
ShaderFXMenu.show({ game = game, slot = "main" })
check(ShaderFXMenu.isOpen(), "A on SHADER FX opens the picker")
ShaderFXMenu.handleInput(input({ "down" }))
ShaderFXMenu.handleInput(input({ "a" }))
eq(activated[1], "main", "A on a converted preset activates the main slot")
eq(game.options.shaderfx, "fake-lcd.slangp", "the choice persists under options.shaderfx")
check(writes >= 1, "the choice is written to options storage")
check(not ShaderFXMenu.isOpen(), "choosing closes the picker back to OPTION")
eq(ShaderFXMenu.slotLabel("main"), "FAKE-LCD", "the row shows the preset name")
end
do
local game = { options = { shaderfxSecondary = "fake-lcd.slangp" }, writeOptions = function() end }
active.secondary = fake
ShaderFXMenu.show({ game = game })
ShaderFXMenu.handleInput(input({ "down" }))
ShaderFXMenu.handleInput(input({ "a" }))
check(ShaderFXMenu.isOpen(), "the slot list opens the SHADER FX 2 picker")
ShaderFXMenu.handleInput(input({ "up" }))
ShaderFXMenu.handleInput(input({ "a" }))
check(active.secondary == nil, "OFF clears the secondary slot")
eq(game.options.shaderfxSecondary, nil, "OFF clears options.shaderfxSecondary")
check(ShaderFXMenu.isOpen(), "the slot list stays open after a pick")
ShaderFXMenu.handleInput(input({ "b" }))
check(not ShaderFXMenu.isOpen(), "B on the slot list closes it")
end
do
local data = { render_pipelines = {
grade = { label = "GRADE", present = function(c) return c end },
voxel = { label = "VOXEL", drawWorld = function() end },
} }
Pipelines.install(data)
local rows = ids(Rows.build({ options = {} }))
check(rows["pipeline:grade"] ~= nil, "a mod post-process pipeline gets a Gen 3 row")
check(rows["pipeline:voxel"] == nil, "a world-only pipeline is not offered on Gen 3")
local opts = {}
rows["pipeline:grade"].step({ options = opts }, 1)
eq(opts.pipelines and opts.pipelines.grade, 1, "the row persists its level")
check(Pipelines.wantsPresent(), "the Gen 3 present pass picks the pipeline up")
Pipelines.install(nil)
end
do
local Kit = require("src.ui.game3.rse.scene_kit")
local Stack = require("src.ui.game3.stack")
local Chrome = require("src.ui.game3.chrome")
local rsRows = {}
for i, t in ipairs({ "TEXT SPEED", "BATTLE SCENE", "BATTLE STYLE", "SOUND", "BUTTON MODE", "FRAME", "CANCEL" }) do
rsRows[i] = { text = t, x = 32, y = 24 + i * 16, choices = {} }
end
stub(Kit, "manifest", function(sub)
if sub == "rse/menus" then return { layout = "rs", option = { rows = rsRows, title = "OPTION" } } end
end)
stub(Stack, "push", function() end)
stub(Stack, "pop", function() end)
stub(Chrome, "setFrameType", function() end)
local Menu = require("src.ui.game3.rs.option_menu")
local writes = 0
local game = { options = {}, writeOptions = function() writes = writes + 1 end }
Menu.show({ game = game, session = { version = "ruby", engineOptions = game.options } })
for _ = 1, 40 do Menu.update() end
local top = Menu._pages[1]
local seen = {}
for i, r in ipairs(top.rows) do seen[r.id] = i end
local order = {}
for _, id in ipairs(Rows.ORDER) do if seen[id] then order[#order + 1] = id end end
for i, id in ipairs(order) do eq(top.rows[i].id, id, "RS OPTION top row " .. i .. " follows Emerald's grouped order") end
check(seen["group.speed"] and seen["group.graphics"] and seen["group.audio"] and seen["group.battle"]
and seen["controls"] and seen["mods"], "RS OPTION carries the Emerald pages")
check(seen["textSpeed"] == nil and seen["sound"] == nil and seen["frameType"] == nil,
"RS cart rows move into their Emerald groups")
eq(top.rows[seen["buttonMode"]].native, 5, "BUTTON MODE stays a native cart row on the top page")
check(seen["eventTickets"] == nil, "RS skips Emerald-only rows")
Menu.handleInput(input({ "select" }))
check(not ShaderFXMenu.isOpen(), "SELECT is not a hidden SHADER FX shortcut")
for _ = 1, seen["group.graphics"] - 1 do Menu.handleInput(input({ "down" })) end
Menu.handleInput(input({ "a" }))
local graphics = Menu._pages[#Menu._pages]
check(#Menu._pages == 2, "A on GRAPHICS opens its page")
local si, fi
for i, r in ipairs(graphics.rows) do
if r.id == "shaderfx" then si = i end
if r.id == "frameType" and r.native == 6 then fi = i end
end
check(fi ~= nil, "RS GRAPHICS carries the native FRAME row")
check(si ~= nil, "RS GRAPHICS lists SHADER FX")
for _ = 1, (fi or 1) - 1 do Menu.handleInput(input({ "down" })) end
Menu.handleInput(input({ "right" }))
eq(Menu._pending.frameType, 1, "RIGHT on the grouped FRAME row steps the pending frame")
graphics.index = 1
for _ = 1, (si or 1) - 1 do Menu.handleInput(input({ "down" })) end
Menu.handleInput(input({ "a" }))
check(ShaderFXMenu.isOpen(), "A on the visible SHADER FX row opens the picker")
ShaderFXMenu.close()
Menu.handleInput(input({ "b" }))
check(#Menu._pages == 1, "B on a port page returns to the native list")
Menu.handleInput(input({ "b" }))
for _ = 1, 40 do Menu.update() end
check(not Menu.isOpen(), "B on the native list saves and closes")
end
do
local Game3 = require("src.core.Game3")
local applied, deactivated = 0, false
local okApply = ShaderFX.applyOptions
local okDeact = ShaderFX.deactivate
ShaderFX.applyOptions = function() applied = applied + 1 return false end
ShaderFX.deactivate = function() deactivated = true end
local game = setmetatable({ options = { performance = "low" } }, { __index = Game3 })
pcall(Game3.applyOptions, game, game.options)
eq(applied, 1, "Game3:applyOptions restores the persisted shader presets")
check(deactivated, "a performance tier without SHADER FX switches it off live")
ShaderFX.applyOptions, ShaderFX.deactivate = okApply, okDeact
end
for i = #saved, 1, -1 do
local s = saved[i]
s[1][s[2]] = s[3]
end
T.finish("game3 shaderfx options")