-- 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