I get mapped input, but it’s incomplete and in the wrong position. E.g. the left trigger might display as rpad down, and rpad left might not be detected at all.
My app would show e.g. for rpad down that it was a button of index 1. That’s what I put in my mapping:
However they output as GAMEPAD_LSTICK_DOWN and GAMEPAD_RSTICK_DOWN.
I was also holding down RPAD_LEFT (not when I took the picture though, but the output mapping is stored). This is showing button index 3 in my raw output on the screenshot. The mapping for RPAD_LEFT:
--pre-hash
local GAMEPAD_LSTICK_LEFT = hash("gamepad_lstick_left")
local GAMEPAD_LSTICK_RIGHT = hash("gamepad_lstick_right")
local GAMEPAD_LSTICK_DOWN = hash("gamepad_lstick_down")
local GAMEPAD_LSTICK_UP = hash("gamepad_lstick_up")
local GAMEPAD_LSTICK_CLICK = hash("gamepad_lstick_click")
local GAMEPAD_LTRIGGER = hash("gamepad_ltrigger")
local GAMEPAD_LSHOULDER = hash("gamepad_lshoulder")
local GAMEPAD_LPAD_LEFT = hash("gamepad_lpad_left")
local GAMEPAD_LPAD_RIGHT = hash("gamepad_lpad_right")
local GAMEPAD_LPAD_DOWN = hash("gamepad_lpad_down")
local GAMEPAD_LPAD_UP = hash("gamepad_lpad_up")
local GAMEPAD_RSTICK_LEFT = hash("gamepad_rstick_left")
local GAMEPAD_RSTICK_RIGHT = hash("gamepad_rstick_right")
local GAMEPAD_RSTICK_DOWN = hash("gamepad_rstick_down")
local GAMEPAD_RSTICK_UP = hash("gamepad_rstick_up")
local GAMEPAD_RSTICK_CLICK = hash("gamepad_rstick_click")
local GAMEPAD_RTRIGGER = hash("gamepad_rtrigger")
local GAMEPAD_RSHOULDER = hash("gamepad_rshoulder")
local GAMEPAD_RPAD_LEFT = hash("gamepad_rpad_left")
local GAMEPAD_RPAD_RIGHT = hash("gamepad_rpad_right")
local GAMEPAD_RPAD_DOWN = hash("gamepad_rpad_down")
local GAMEPAD_RPAD_UP = hash("gamepad_rpad_up")
local GAMEPAD_START = hash("gamepad_start")
local GAMEPAD_BACK = hash("gamepad_back")
local GAMEPAD_GUIDE = hash("gamepad_guide")
local hash_to_text = {
[GAMEPAD_LSTICK_LEFT] = "GAMEPAD_LSTICK_LEFT",
[GAMEPAD_LSTICK_RIGHT] = "GAMEPAD_LSTICK_RIGHT",
[GAMEPAD_LSTICK_DOWN] = "GAMEPAD_LSTICK_DOWN",
[GAMEPAD_LSTICK_UP] = "GAMEPAD_LSTICK_UP",
[GAMEPAD_LSTICK_CLICK] = "GAMEPAD_LSTICK_CLICK",
[GAMEPAD_LTRIGGER] = "GAMEPAD_LTRIGGER",
[GAMEPAD_LSHOULDER] = "GAMEPAD_LSHOULDER",
[GAMEPAD_LPAD_LEFT] = "GAMEPAD_LPAD_LEFT",
[GAMEPAD_LPAD_RIGHT] = "GAMEPAD_LPAD_RIGHT",
[GAMEPAD_LPAD_DOWN] = "GAMEPAD_LPAD_DOWN",
[GAMEPAD_LPAD_UP] = "GAMEPAD_LPAD_UP",
[GAMEPAD_RSTICK_LEFT] = "GAMEPAD_RSTICK_LEFT",
[GAMEPAD_RSTICK_RIGHT] = "GAMEPAD_RSTICK_RIGHT",
[GAMEPAD_RSTICK_DOWN] = "GAMEPAD_RSTICK_DOWN",
[GAMEPAD_RSTICK_UP] = "GAMEPAD_RSTICK_UP",
[GAMEPAD_RSTICK_CLICK] = "GAMEPAD_RSTICK_CLICK",
[GAMEPAD_RTRIGGER] = "GAMEPAD_RTRIGGER",
[GAMEPAD_RSHOULDER] = "GAMEPAD_RSHOULDER",
[GAMEPAD_RPAD_LEFT] = "GAMEPAD_RPAD_LEFT",
[GAMEPAD_RPAD_RIGHT] = "GAMEPAD_RPAD_RIGHT",
[GAMEPAD_RPAD_DOWN] = "GAMEPAD_RPAD_DOWN",
[GAMEPAD_RPAD_UP] = "GAMEPAD_RPAD_UP",
[GAMEPAD_START] = "GAMEPAD_START",
[GAMEPAD_BACK] = "GAMEPAD_BACK",
[GAMEPAD_GUIDE] = "GAMEPAD_GUIDE",
}
function init(self)
msg.post(".", "acquire_input_focus")
self.mappings = {}
end
function update(self, dt)
--display gamepad name
if self.gamepad_name then
label.set_text("#gamepad_name", "Gamepad name: " .. self.gamepad_name)
else
label.set_text("#gamepad_name", "No gamepad detected.")
end
--display raw input
if self.previous_raw then
local txt = ""
for category, data in pairs(self.previous_raw) do
if category == "gamepad_buttons" then
for id, value in pairs(data) do
if value ~= 0 then
txt = txt .. "Button: " .. id .. "\n"
end
end
end
if category == "gamepad_hats" then
for id, value in pairs(data) do
if value ~= 0 then
txt = txt .. "Hat: " .. id .. "\n"
end
end
end
if category == "gamepad_axis" then
for id, value in pairs(data) do
if math.abs(value) > 0.5 then
txt = txt .. "Axis: " .. id .. " Value: " .. math.ceil(value*100)/100 .. "\n"
end
end
end
end
label.set_text("#unmapped", txt)
end
--display mapped input
local txt = ""
for name, _ in pairs(self.mappings) do
txt = txt .. name .. "\n"
end
label.set_text("#mapping", txt)
end
function on_input(self, action_id, action)
--capture gamepad name
if action_id == hash("gamepad_connected") then
self.gamepad_name = action.gamepad_name
end
if action_id == hash("gamepad_raw") then
--capture raw data to display
self.previous_raw = action
elseif action_id then
if action.pressed then
--try to map action to a known action_id and convert it to text
local name = hash_to_text[action_id]
--store mapping to be displayed
if name then
self.mappings[name] = true
end
end
end
end
My .gamepads file, with no other bindings included
I don’t understand this. If the .gamepads file you created is anything to go by GAMEPAD_LSTICK_DOWN and GAMEPAD_RSTICK_DOWN are mapped to AXIS and index 2 and 5. How can they output to something else then?
Keep in mind that the raw input is giving you values for buttons, axis and hats in an order that is fixed for the controller. It is not guaranteed that all controllers have their buttons and sticks mapped to the same indices. This is why the .gamepad file mappings exist. To translate the raw values to a predefined set of buttons and axis such that the mapping of gamepad input in a game is controller agnostic.
What you see in the screenshot. If I don’t touch the triggers they constantly output -1 on axis 3 and 1 on axis 6. Do you mean something else? If I press the triggers, the values invert (1 and -1, respectively).
When I receive raw input, I store the entire action table in self.previous_raw. I then iterate over that entire table and display each value on the left of the screenshot.
Yes, I don’t understand this either!
Yes - I created this mapping myself by pushing each of the buttons on the Deck and noting down the button/axis/hat.
Either something very weird is going on, or I have made a fundamental mistake in my script.
What if you try your script with a gamepad that is known to work and where there are existing bindings you can compare with? Are you able to reproduce the gamepad binding from the raw input?
Good idea. I get exactly the same behaviour from my own Xbox controller that normally works. I guess user error? But I really have no idea what I’m doing wrong.
Oh, I think I’ve found your problem. The .gamepads file is 0-indexed, although the raw inputs you get in Lua are 1-indexed (for easy iteration with ipairs). You need to subtract 1 from the values when you create your definitions in the .gamepads file.
I am having some issues with Steam Deck when external input is being used, for example when the Deck is in a dock or an external controller is connected. The core of the issue is that input is duplicated.
One user found a similar issue on a Linux desktop. They found that disabling SteamInput solved the issue in that context. The same user then tried to reproduce the issue on the Steam Deck, and provided me with this:
I tried on the Steam Deck to see how it behaves.
I don’t have a “dock”, but I have a basic usb-c hub with an hdmi output which should be similar enough. And indeed, I have the same behaviour when I use a controller instead of the embedded controls : the menu skips a step, and the screens turns black when I try to enter any menu. However, I didn’t see any option to disable SteamInput on the Deck… so I don’t think it’s possible to use the same workaround as on desktop.
It doesn’t happen with the Deck embedded controls, even when using an external monitor. In that case, it works fine.
For SteamInput, I think Steam sets environment variables so SDL will ignore controllers except the virtual one created for SteamInput. I don’t know which engine your game is built on, does it rely on SDL for controller input ? If so, maybe it ignores the environment variables Steam sets, and we get one input for the “real” controller, and one for the virtual one.
The key here seems to be the last paragraph, and something about SDL. I am not familiar with it - seems to be a low level library for handling multiple things, including input. https://wiki.libsdl.org/
Ping @britzl - does any of this make sense to you? Thanks for any help!
I was going to post this issue on the steamworks repo, but of course it’s not actually related to the steamworks extension, so I’m bumping here instead. I’m still getting bug reports from my players about this. My game is not playable when docked on the Steam Deck.
Yeah, I’m not sure this is related to the Steamworks SDK to be honest. It’s more likely related to our controller implementation. Please create a ticket in the main Defold repo!