mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-15 07:41:21 +02:00
102 lines
3.4 KiB
Lua
102 lines
3.4 KiB
Lua
-- Rebinding over the logical Game Boy buttons (gap C2's file-12 half,
|
|
-- 12-ui-extensibility 4.4): one row per button, A arms a "PRESS A BUTTON"
|
|
-- capture and the captured key or pad button lands in
|
|
-- save.options.bindings, which Input:applyBindings layers over its fixed
|
|
-- default map (see src/core/Input.lua and Game:applyOptions).
|
|
|
|
local Font = require("src.render.Font")
|
|
local ListMenu = require("src.ui.ListMenu")
|
|
local Input = require("src.core.Input")
|
|
|
|
local BindingsMenu = setmetatable({}, { __index = ListMenu })
|
|
BindingsMenu.__index = BindingsMenu
|
|
|
|
-- Input.lua's map, primary key first where several keys share a button
|
|
local BUTTONS = {
|
|
{ id = "up", label = "UP", key = "up" },
|
|
{ id = "down", label = "DOWN", key = "down" },
|
|
{ id = "left", label = "LEFT", key = "left" },
|
|
{ id = "right", label = "RIGHT", key = "right" },
|
|
{ id = "a", label = "A", key = "z" },
|
|
{ id = "b", label = "B", key = "x" },
|
|
{ id = "start", label = "START", key = "escape" },
|
|
{ id = "select", label = "SELECT", key = "rshift" },
|
|
}
|
|
|
|
-- a binding is a plain key string or { key, pad }; absent = the fixed
|
|
-- map, so a vanilla save renders today's keys byte-identically
|
|
local function boundKey(overlay, def)
|
|
local b = overlay and overlay[def.id]
|
|
if type(b) == "table" then return b.key or def.key end
|
|
if type(b) == "string" then return b end
|
|
return def.key
|
|
end
|
|
|
|
function BindingsMenu.new(game)
|
|
local overlay = game.save and game.save.options
|
|
and game.save.options.bindings
|
|
local items = {}
|
|
for i, def in ipairs(BUTTONS) do
|
|
items[i] = { label = def.label,
|
|
right = boundKey(overlay, def):upper(), button = def }
|
|
end
|
|
local self = setmetatable(ListMenu.new(game, "CONTROLS", items, {}),
|
|
BindingsMenu)
|
|
self.onChoose = function(item) self:beginCapture(item) end
|
|
return self
|
|
end
|
|
|
|
-- the capture handlers are per-instance slots, so Game's raw-input
|
|
-- routing only ever sees this screen while a capture is armed
|
|
function BindingsMenu:beginCapture(item)
|
|
self.capture = item
|
|
self.onKeyPressed = BindingsMenu.captureKey
|
|
self.onGamepadPressed = BindingsMenu.capturePad
|
|
end
|
|
|
|
function BindingsMenu:captureKey(key)
|
|
self:storeBinding("key", key)
|
|
end
|
|
|
|
function BindingsMenu:capturePad(button)
|
|
self:storeBinding("pad", button)
|
|
end
|
|
|
|
function BindingsMenu:storeBinding(slot, value)
|
|
local item = self.capture
|
|
self.capture = nil
|
|
self.onKeyPressed = nil
|
|
self.onGamepadPressed = nil
|
|
local game = self.game
|
|
if not (item and value and game.save and game.save.options) then return end
|
|
local opts = game.save.options
|
|
opts.bindings = opts.bindings or {}
|
|
local b = opts.bindings[item.button.id]
|
|
if type(b) ~= "table" then
|
|
-- keep a direct-edited plain key string when only the pad changes
|
|
b = { key = type(b) == "string" and b or nil }
|
|
end
|
|
b[slot] = value
|
|
opts.bindings[item.button.id] = b
|
|
item.right = boundKey(opts.bindings, item.button):upper()
|
|
Input:applyBindings(opts.bindings)
|
|
if game.writeOptions then game:writeOptions() end
|
|
end
|
|
|
|
function BindingsMenu:update(dt)
|
|
if self.capture then return end -- the raw capture owns the input
|
|
ListMenu.update(self, dt)
|
|
end
|
|
|
|
function BindingsMenu:draw()
|
|
ListMenu.draw(self)
|
|
if self.capture then
|
|
Font.drawBox(1, 6, 18, 4)
|
|
love.graphics.setColor(0, 0, 0, 1)
|
|
Font.draw("PRESS A BUTTON", 24, 60)
|
|
love.graphics.setColor(1, 1, 1, 1)
|
|
end
|
|
end
|
|
|
|
return BindingsMenu
|