164 lines
5.5 KiB
Text
164 lines
5.5 KiB
Text
-- Input: every device the engine can see, its kind, slot and identity, the live state of every
|
|
-- axis and button of each, the dead zone and trigger threshold in force, and whether the stick is
|
|
-- driving the mouse. Every device Singe opens is a gamepad, an unrecognised one through a mapping
|
|
-- Singe writes for it, so there is one family to report and not two.
|
|
--
|
|
-- The phases are timed on the wall clock so a test harness can attach a device, press something on
|
|
-- it and take it away again while the scene is running.
|
|
dofile("Singe/Framework.singe")
|
|
|
|
local font = fontLoad("Singe/FreeSansBold.ttf", 11)
|
|
local width, height = 0, 0
|
|
local shot = 0
|
|
local started = os.clock()
|
|
local mouseX = -1
|
|
local mouseY = -1
|
|
local mouseMoves = 0
|
|
local disconnects = 0
|
|
|
|
local LINE = 14
|
|
local AXIS_FULL = 32767 -- What SDL reports at full deflection, and what DEAD_ZONE counts in
|
|
local PANEL_HEIGHT = 350
|
|
local SHOT_TIMES = { 2, 6, 10, 16 }
|
|
local QUIT_TIME = 18
|
|
local PADS = { GAMEPAD_0, GAMEPAD_1, GAMEPAD_2, GAMEPAD_3 }
|
|
local AXES = 6
|
|
local BUTTONS = {
|
|
"BUTTON_A", "BUTTON_B", "BUTTON_X", "BUTTON_Y", "BUTTON_BACK", "BUTTON_GUIDE", "BUTTON_START",
|
|
"BUTTON_LEFT_STICK", "BUTTON_RIGHT_STICK", "BUTTON_LEFT_BUMPER", "BUTTON_RIGHT_BUMPER",
|
|
"DPAD_UP", "DPAD_DOWN", "DPAD_LEFT", "DPAD_RIGHT"
|
|
}
|
|
|
|
-- Every mapped switch by name, so what a dead zone let through can be read off the screen.
|
|
local SWITCHES = {
|
|
[SWITCH_UP] = "UP", [SWITCH_LEFT] = "LEFT", [SWITCH_DOWN] = "DOWN", [SWITCH_RIGHT] = "RIGHT",
|
|
[SWITCH_START1] = "START1", [SWITCH_START2] = "START2", [SWITCH_BUTTON1] = "BUTTON1",
|
|
[SWITCH_BUTTON2] = "BUTTON2", [SWITCH_BUTTON3] = "BUTTON3", [SWITCH_BUTTON4] = "BUTTON4",
|
|
[SWITCH_COIN1] = "COIN1", [SWITCH_COIN2] = "COIN2", [SWITCH_SKILL1] = "SKILL1",
|
|
[SWITCH_SKILL2] = "SKILL2", [SWITCH_SKILL3] = "SKILL3", [SWITCH_SERVICE] = "SERVICE",
|
|
[SWITCH_TEST] = "TEST", [SWITCH_RESET] = "RESET", [SWITCH_SCREENSHOT] = "SCREENSHOT",
|
|
[SWITCH_QUIT] = "QUIT", [SWITCH_PAUSE] = "PAUSE", [SWITCH_CONSOLE] = "CONSOLE",
|
|
[SWITCH_TILT] = "TILT", [SWITCH_GRAB] = "GRAB", [SWITCH_MOUSE_DISCONNECT] = "MOUSE_DISCONNECT"
|
|
}
|
|
local held = {}
|
|
|
|
overlaySetResolution(720, 480)
|
|
width, height = overlayGetWidth(), overlayGetHeight()
|
|
fontSelect(font)
|
|
discPlay()
|
|
|
|
|
|
-- Every button of one pad as a string of 0s and 1s, in SDL's own button order.
|
|
function buttonBits(slot)
|
|
local bits = ""
|
|
local b = 0
|
|
|
|
for b = 1, #BUTTONS do
|
|
bits = bits .. (controllerGetButton(slot, PADS[slot + 1][BUTTONS[b]].value) and "1" or "0")
|
|
end
|
|
|
|
return bits
|
|
end
|
|
|
|
|
|
function onMouseMoved(x, y, xr, yr, mouse)
|
|
mouseX = x
|
|
mouseY = y
|
|
mouseMoves = mouseMoves + 1
|
|
end
|
|
|
|
|
|
function onInputPressed(switch)
|
|
held[switch] = true
|
|
if switch == SWITCH_MOUSE_DISCONNECT then
|
|
disconnects = disconnects + 1
|
|
end
|
|
end
|
|
|
|
|
|
function onInputReleased(switch)
|
|
held[switch] = nil
|
|
end
|
|
|
|
|
|
function onOverlayUpdate()
|
|
local elapsed = os.clock() - started
|
|
local line = 0
|
|
local slot = 0
|
|
local axis = 0
|
|
local text = ""
|
|
|
|
overlayClear()
|
|
|
|
-- A dark panel behind the text, so every line reads over whatever the disc is showing.
|
|
colorForeground(0, 0, 40)
|
|
for line = 0, PANEL_HEIGHT do
|
|
overlayLine(4, 4 + line, width - 5, 4 + line)
|
|
end
|
|
colorForeground(0, 255, 0)
|
|
overlayBox(4, 4, width - 5, 4 + PANEL_HEIGHT)
|
|
colorForeground(255, 255, 255)
|
|
|
|
line = 16
|
|
fontPrint(12, line, string.format("scene49 input t=%.1f", elapsed))
|
|
line = line + LINE * 2
|
|
|
|
fontPrint(12, line, string.format("DEAD_ZONE %d TRIGGER_THRESHOLD %d raw (%.1f%% of full travel) joyMouseIsEnabled %s",
|
|
SINGE_DEAD_ZONE, SINGE_TRIGGER_THRESHOLD, SINGE_TRIGGER_THRESHOLD * 100.0 / AXIS_FULL, tostring(joyMouseIsEnabled())))
|
|
line = line + LINE * 2
|
|
|
|
-- Gamepads. Every device Singe opens is one of these, whatever it started life as.
|
|
for slot = 0, SINGE_MAX_CONTROLLERS - 1 do
|
|
if controllerIsValid(slot) then
|
|
fontPrint(12, line, string.format("gamepad slot %d \"%s\"", slot, tostring(controllerGetName(slot))))
|
|
line = line + LINE
|
|
text = ""
|
|
for axis = 0, AXES - 1 do
|
|
text = text .. string.format(" a%d=%-7d", axis, controllerGetAxis(slot, axis))
|
|
end
|
|
fontPrint(28, line, "axes " .. text)
|
|
line = line + LINE
|
|
fontPrint(28, line, "buttons " .. buttonBits(slot) .. " (A B X Y Back Guide Start LS RS LB RB DpU DpD DpL DpR)")
|
|
line = line + LINE
|
|
else
|
|
fontPrint(12, line, string.format("gamepad slot %d empty", slot))
|
|
line = line + LINE
|
|
end
|
|
end
|
|
line = line + LINE
|
|
|
|
-- Mice, which are their own family: ManyMouse names them, and mouseHowMany counts them.
|
|
fontPrint(12, line, string.format("mice %d", mouseHowMany()))
|
|
line = line + LINE
|
|
for slot = 0, SINGE_MAX_MICE - 1 do
|
|
if slot < mouseHowMany() then
|
|
fontPrint(28, line, string.format("mouse %d \"%s\"", slot, tostring(mouseGetName(slot))))
|
|
line = line + LINE
|
|
end
|
|
end
|
|
fontPrint(28, line, string.format("last position %d,%d after %d movements", mouseX, mouseY, mouseMoves))
|
|
line = line + LINE
|
|
fontPrint(28, line, string.format("SWITCH_MOUSE_DISCONNECT seen %d times", disconnects))
|
|
line = line + LINE * 2
|
|
|
|
fontPrint(12, line, string.format("keyboard mode %d last down %d", keyboardGetMode(), keyboardGetLastDown()))
|
|
line = line + LINE
|
|
|
|
text = ""
|
|
for slot = 0, #SWITCHES do
|
|
if held[slot] then
|
|
text = text .. " " .. SWITCHES[slot]
|
|
end
|
|
end
|
|
fontPrint(12, line, "switches held " .. ((text == "") and "(none)" or text))
|
|
|
|
if (shot < #SHOT_TIMES) and (elapsed >= SHOT_TIMES[shot + 1]) then
|
|
shot = shot + 1
|
|
singeScreenshot()
|
|
end
|
|
if elapsed >= QUIT_TIME then
|
|
singeQuit()
|
|
end
|
|
|
|
return OVERLAY_UPDATED
|
|
end
|