Files
gen1recomp/tests/engine/pad_speed_binding_bug1922.lua
T

159 lines
5.7 KiB
Lua

package.path = "./?.lua;./?/init.lua;" .. package.path
local T = require("tests.harness")
local check, eq = T.check, T.eq
love = love or require("tests.love_stub")
local Input = require("src.core.Input")
local Strings = require("src.core.Strings")
local BindingsMenu = require("src.ui.BindingsMenu")
local function newGame()
local game = { save = { options = {} }, data = {}, wroteOptions = 0 }
game.stack = {
states = {},
push = function(self, s) table.insert(self.states, s) end,
pop = function(self) return table.remove(self.states) end,
top = function(self) return self.states[#self.states] end,
}
game.input = {
queue = {},
wasPressed = function(self, btn) return self.queue[btn] or false end,
isDown = function() return false end,
}
function game:writeOptions() self.wroteOptions = self.wroteOptions + 1 end
return game
end
local function press(state, btn)
state.game.input.queue = { [btn] = true }
state:update(1 / 60)
state.game.input.queue = {}
end
local ROW_A, ROW_SPEED_DOWN, ROW_SPEED_UP = 5, 9, 10
Input:init()
eq(Input:padAction("rightshoulder"), "speedUp", "R1 speeds up by default")
eq(Input:padAction("leftshoulder"), "speedDown", "L1 slows down by default")
eq(Input:padAction("righttrigger"), "speedUp", "R2 alongside it")
eq(Input:padAction("lefttrigger"), "speedDown", "L2 alongside it")
eq(Input:padAction("a"), nil, "a face button is not a pad action")
check(Input.padBindings["rightshoulder"] == nil,
"a pad action never enters the Game Boy button map")
eq(Input.padBindings["a"], "a", "which is otherwise untouched")
Input:gamepadpressed(nil, "rightshoulder")
Input:step()
local held = 0
for _ in pairs(Input.state) do held = held + 1 end
eq(held, 0, "pressing R1 presses no Game Boy button")
Input:applyBindings({ speedUp = { pad = "y" } })
eq(Input:padAction("y"), "speedUp", "the overlay moves SPEED + to Y")
eq(Input:padAction("rightshoulder"), nil, "and leaves R1 inert")
eq(Input:padAction("righttrigger"), nil, "including its trigger alias")
eq(Input:padAction("leftshoulder"), "speedDown", "SPEED - keeps its default")
check(Input.padBindings["y"] == nil,
"the moved action does not press a Game Boy button either")
Input:applyBindings({ speedUp = false, speedDown = false, a = { pad = "y" } })
eq(Input:padAction("rightshoulder"), nil, "unbound: R1 does nothing")
eq(Input:padAction("leftshoulder"), nil, "unbound: L1 does nothing")
eq(Input:padAction("righttrigger"), nil, "unbound: R2 does nothing")
eq(Input.padBindings["y"], "a", "a GB rebind in the same overlay still lands")
Input:init()
local game = newGame()
local bm = BindingsMenu.new(game)
game.stack:push(bm)
eq(#bm.items, 10, "CONTROLS grew two rows")
eq(bm.items[ROW_SPEED_UP].right, "RB", "SPEED + shows its default shoulder")
eq(bm.items[ROW_SPEED_DOWN].right, "LB", "SPEED - shows its own")
bm.index = ROW_SPEED_UP
press(bm, "a")
eq(bm.capture, bm.items[ROW_SPEED_UP], "A arms the SPEED + row")
bm:onGamepadPressed("y")
bm:onGamepadReleased("y")
eq(game.save.options.bindings.speedUp.pad, "y", "the release stores pad Y")
eq(bm.items[ROW_SPEED_UP].right, "Y", "and the row redraws")
local writes = game.wroteOptions
press(bm, "select")
eq(game.save.options.bindings.speedUp, false, "SELECT unbinds the action")
eq(bm.items[ROW_SPEED_UP].right, Strings("OFF"), "the row reads OFF")
eq(game.wroteOptions, writes + 1, "clearing writes once")
press(bm, "select")
eq(game.wroteOptions, writes + 1, "SELECT on an already-OFF row writes nothing")
bm:commitBindings()
eq(Input:padAction("rightshoulder"), nil, "closing applies the OFF state")
eq(Input:padAction("y"), nil, "the moved button is inert too")
bm.index = ROW_SPEED_DOWN
press(bm, "a")
bm:onGamepadPressed("leftshoulder")
bm:onGamepadReleased("leftshoulder")
eq(bm.items[ROW_SPEED_DOWN].right, "LB", "SPEED - is back on L1")
bm.index = ROW_A
press(bm, "a")
bm:onGamepadPressed("leftshoulder")
bm:onGamepadReleased("leftshoulder")
eq(game.save.options.bindings.a.pad, "leftshoulder", "GB A takes L1")
eq(game.save.options.bindings.speedDown, false,
"and the speed action yields rather than trading for a face button")
eq(bm.items[ROW_SPEED_DOWN].right, Strings("OFF"), "the row shows it")
bm:commitBindings()
eq(Input.padBindings["leftshoulder"], "a", "applied: L1 is Game Boy A")
eq(Input:padAction("leftshoulder"), nil, "and no longer a speed shortcut")
bm.index = ROW_SPEED_UP
press(bm, "a")
bm:onKeyPressed("q")
check(bm.capture == nil, "a key cancels an armed pad-action row")
if bm.onKeyReleased then bm:onKeyReleased("q") end
eq(game.save.options.bindings.speedUp, false, "and stores nothing")
game.save.options.bindings = nil
for _, it in ipairs(bm.items) do it.right = nil end
local fresh = BindingsMenu.new(game)
eq(fresh.items[ROW_SPEED_UP].right, "RB", "a cleared overlay restores SPEED +")
Input:applyBindings(nil)
eq(Input:padAction("rightshoulder"), "speedUp", "and the live map with it")
local SaveData = require("src.core.SaveData")
local files = {}
local fs = {
write = function(path, content) files[path] = content return true end,
read = function(path) return files[path] end,
remove = function(path) files[path] = nil return true end,
getInfo = function(path)
if files[path] ~= nil then return { type = "file" } end
return nil
end,
}
local full = SaveData.defaultOptions()
full.bindings = { speedUp = false, a = { pad = "y" } }
check(SaveData.saveOptions(full, fs) ~= nil, "options with an OFF row write")
local reloaded = SaveData.loadOptions(fs)
eq(reloaded.bindings.speedUp, false, "false round-trips as false, not nil")
eq(reloaded.bindings.a.pad, "y", "beside an ordinary GB rebind")
Input:applyBindings(reloaded.bindings)
eq(Input:padAction("rightshoulder"), nil, "a reloaded OFF row stays off")
Input:init()
T.finish("pad_speed_binding_bug1922")