Discussion:
[SDL] SDL_Controller design
Ed Phillips
2016-12-01 17:22:30 UTC
Permalink
Hello,

I think I'm missing something when it comes to the basic reasoning behind
the design of the SDL_Controller stuff, and the documentation on the Wiki
that I can see doesn't go into any discussion on the design decisions.

When I first looked at the "mapping" capabilities of SDL_Controller, I
thought, HEY!, this was a way to give names to each of the buttons/axes on
any device, so you can pass them through to the application/game and it
can present these names to the user when they are setting up their
controller configuration. Cool! Oh look, they already have a database of
these name mappings! Great!

However, the more I started looking at it, I began to see that this is not
the case at all. It seems to be a way to turn the raw button/axis numbers
on a non-XInput device into an XInput control like "leftshoulder" or
"righty"?

So really, this is just a way to make every controller work like an XBox
controller (even if it doesn't have the same physical controls or the same
names on the buttons, etc.), and doesn't really address the issue of
mapping the names of the actual physical controls on a particular device
to the button/axis numbers normally received in SDL_Joystick calls?

I guess if you don't want your game/application to treat every device like
an XBox 360 Controller, then the SDL_Controller stuff is not for you?

How does Steam's controller API play into things? There is mention of
Steam here (and nowhere else I can find):

http://wiki.libsdl.org/CategoryGameController

It states:

"If you are running your game from Steam, the game controller mapping is
automatically provided for your game."

I'm not sure what that means. Steam controller mappings take a list of
"actions" defined for a game, and allow the developer and/or user to
configure which controls on their devices will invoke these actions. A
game using the controller API will see "actions" and not raw inputs... so
I'm not sure how the SDL_Controller stuff plays into this. Also, in order
to use the Steam controller API, you have to call functions in the Steam
runtime, and I'm not sure if SDL can/would be doing that, and it won't
provide an SDL_Controller mapping.

Any help regarding these concepts would be greatly appreciated!

Thanks,

Ed

Ed Phillips <***@udel.edu> University of Delaware (302) 831-6082
Systems Programmer IV, Network and Systems Services
Daniel Gibson
2016-12-01 18:20:30 UTC
Permalink
Hi Ed,

SDL_GameController is for game controllers aka gamepads, which tend to
be similar to the xbox360 or PS2/3/4 pad (one DPAD on the left, two
analog sticks, 4 buttons for the right thumb, 2 shoulder buttons on each
side that may be trigger axes and those "back" and "start" buttons in
the middle, maybe even an "xbox" button or similar).
I think the main purposes are
1. making it easy(er) to port XInput code to SDL, esp. for Linux/Mac
2. allowing game developers to set default bindings for gamepads that
make sense with most gamepads.

Usually you use SDL_GameController with the corresponding events
(SDL_CONTROLLER*), I think, but you *can* also use it to set the
displayed names etc of normal SDL_Joystick buttons, if the joystick
happens to be a known game controller.
SDL_IsGameController(joystick) tells you if a joystick is a know game
controller, SDL_GameControllerGetBindForAxis() and
SDL_GameControllerGetBindForButton() tell you how things are mapped.
(I've used it that way so I don't have to handle game controller events
separately, but still get the mapping)

Regarding Steam: The documentation is referring to the gamepad
configuration in the Steam (Linux?) Big Picture settings, that lets you
create a mapping from your gamepad's buttons/axes to the xbox controller
model. I think Steam then sets the SDL_GAMECONTROLLERCONFIG environment
variable with the mapping string, which SDL2 then uses for games that
use SDL2 and are launched from Steam.

So "mapping" refers to "Button 3 corresponds to SDL_CONTROLLER_BUTTON_A,
Axis 2 corresponds to SDL_CONTROLLER_AXIS_RIGHTX" and so on, not to
standard actions.
No idea if standard action mappings are available on Steam/Linux, but if
they are that's something provided by Steamworks SDK, not by SDL2.

BTW:
https://joostdevblog.blogspot.de/2012/08/the-craziness-that-is-joysticks-on-pc.html
is an interesting read about how handling joysticks and similar input
devices sucks (only difference is that now with SDL2 it's a a bit better
for gamepads).

Cheers,
Daniel
Post by Ed Phillips
Hello,
I think I'm missing something when it comes to the basic reasoning
behind the design of the SDL_Controller stuff, and the documentation on
the Wiki that I can see doesn't go into any discussion on the design
decisions.
When I first looked at the "mapping" capabilities of SDL_Controller, I
thought, HEY!, this was a way to give names to each of the buttons/axes
on any device, so you can pass them through to the application/game and
it can present these names to the user when they are setting up their
controller configuration. Cool! Oh look, they already have a database
of these name mappings! Great!
However, the more I started looking at it, I began to see that this is
not the case at all. It seems to be a way to turn the raw button/axis
numbers on a non-XInput device into an XInput control like
"leftshoulder" or "righty"?
So really, this is just a way to make every controller work like an XBox
controller (even if it doesn't have the same physical controls or the
same names on the buttons, etc.), and doesn't really address the issue
of mapping the names of the actual physical controls on a particular
device to the button/axis numbers normally received in SDL_Joystick calls?
I guess if you don't want your game/application to treat every device
like an XBox 360 Controller, then the SDL_Controller stuff is not for you?
How does Steam's controller API play into things? There is mention of
http://wiki.libsdl.org/CategoryGameController
"If you are running your game from Steam, the game controller mapping is
automatically provided for your game."
I'm not sure what that means. Steam controller mappings take a list of
"actions" defined for a game, and allow the developer and/or user to
configure which controls on their devices will invoke these actions. A
game using the controller API will see "actions" and not raw inputs...
so I'm not sure how the SDL_Controller stuff plays into this. Also, in
order to use the Steam controller API, you have to call functions in the
Steam runtime, and I'm not sure if SDL can/would be doing that, and it
won't provide an SDL_Controller mapping.
Any help regarding these concepts would be greatly appreciated!
Thanks,
Ed
Systems Programmer IV, Network and Systems Services
_______________________________________________
SDL mailing list
http://lists.libsdl.org/listinfo.cgi/sdl-libsdl.org
Ed Phillips
2016-12-19 16:23:23 UTC
Permalink
Hi Daniel,
Post by Daniel Gibson
Hi Ed,
SDL_GameController is for game controllers aka gamepads, which tend to be
similar to the xbox360 or PS2/3/4 pad (one DPAD on the left, two analog
sticks, 4 buttons for the right thumb, 2 shoulder buttons on each side that
may be trigger axes and those "back" and "start" buttons in the middle, maybe
even an "xbox" button or similar).
I think the main purposes are
1. making it easy(er) to port XInput code to SDL, esp. for Linux/Mac
2. allowing game developers to set default bindings for gamepads that make
sense with most gamepads.
Okay, so this basically provides a way for a game using SDL to turn every
device into an ABXY input device, hide the details from the user and have
them plug it in and figure out on their own which controls act like "A",
"RT", "RS", etc. That's certainly useful.
Post by Daniel Gibson
Usually you use SDL_GameController with the corresponding events
(SDL_CONTROLLER*), I think, but you *can* also use it to set the displayed
names etc of normal SDL_Joystick buttons, if the joystick happens to be a
known game controller.
SDL_IsGameController(joystick) tells you if a joystick is a know game
controller, SDL_GameControllerGetBindForAxis() and
SDL_GameControllerGetBindForButton() tell you how things are mapped.
(I've used it that way so I don't have to handle game controller events
separately, but still get the mapping)
That's useful too. I'm porting some code that has it's own "action"
mapping system that maps the SDL joystick number (v1.2) + control changes
(button 0 down, axis 0 right, hat left) to game actions... so to work with
this I need to still use the SDL_Joystickxxxx() calls but I'm trying to
take advantage of the knowledge available in the SDL_GameController
mappings to respond to "button A down" instead of "button n down" (where X
varies depending on device). Also, when setting up the mappings, if I
have a game controller mapping in SDL, I'd like to display "button A" in
the mapping GUI instead of "button 0", at least for XINPUT devices. I'm
thinking that, for DINPUT devices, showing the game controller mapped
names will just add to the confusion for non-XINPUT devices that might
have a button named X on them, but it's not anywhere near where the X
button is on an XBox gamepad.
Post by Daniel Gibson
Regarding Steam: The documentation is referring to the gamepad configuration
in the Steam (Linux?) Big Picture settings, that lets you create a mapping
from your gamepad's buttons/axes to the xbox controller model. I think Steam
then sets the SDL_GAMECONTROLLERCONFIG environment variable with the mapping
string, which SDL2 then uses for games that use SDL2 and are launched from
Steam.
Yeah, I'm a bit confused regarding the BPM controller mapping GUI. With a
Steam Controller, it seems to allow me to remap things even for a game
that has no Steam game "action map" file published. For other
controllers, on SteamOS, it seems to not let me do ANY remapping for even,
say, a Wireless XB360 controller. This weirdness makes it difficult to
test, and makes me feel like I'm missing something basic.

That aside, the environment variable mapping string... doesn't it include
mappings for ALL the game controllers that have configs for the game? Or
does it include all connected game controllers that have configs for the
game? If I don't have my controller plugged in, and I fire up the game
and connect my controller, will there be a config for it, or will the user
have to restart the game?
Post by Daniel Gibson
So "mapping" refers to "Button 3 corresponds to SDL_CONTROLLER_BUTTON_A,
Axis 2 corresponds to SDL_CONTROLLER_AXIS_RIGHTX" and so on, not to
standard actions. No idea if standard action mappings are available on
Steam/Linux, but if they are that's something provided by Steamworks
SDK, not by SDL2.
Steam configuration of a controller allows the user to map "actions" (the
things in the actions file like "strafe left", "fire missle", "toggle
shield mode", etc.) to controls on their device. The game sees no input
controls... only triggered actions and readings from axis/mouse
inputs/trackpad inputs. However, for games without an "actions" file, I'm
not sure what it's supposed to do... the Steam Controller is obviously
special, it can be set up like an XBox gamepad with or without a mouse
control via the right trackpad and DPAD control via the left trackpad,
etc. It doesn't seem to let me do this kind of thing for any other type
of device tho'.

So, the fact that the BPM controller config stuff can't deal with ALL
devices leads me to needing to keep my game's controller mapping GUI, and
try to at least make things work automatically as best as possible for
XBox Gamepad-like devices (or those with SDL mappings to make it seem like
an XBox Gamepad), and let them "deep dive" and customize mappings if they
want.

Players these days will connect a device and start pressing buttons,
expecting it to work just like the game they were just playing, even if
that makes no logical sense.
Post by Daniel Gibson
https://joostdevblog.blogspot.de/2012/08/the-craziness-that-is-joysticks-on-pc.html
is an interesting read about how handling joysticks and similar input devices
sucks (only difference is that now with SDL2 it's a a bit better for
gamepads).
YES! That is a complete hoot to read! I've been dealing with all of that
kind of stuff for years, and the guy is right, most of it has never made
a lick of sense.

Ed

Ed Phillips <***@udel.edu> University of Delaware (302) 831-6082
Systems Programmer IV, Network and Systems Services
Alex Szpakowski
2016-12-01 21:20:31 UTC
Permalink
The SDL_GameController API is so your code can determine that e.g. the left trigger on a controller is held down, no matter what controller-like device is used and no matter what OS or drivers are used (for example the button and axis indices reported by the Xbox 360 controller on Windows are different than those reported when using the Tattiebogle driver for the 360 on macOS).

The latest SDL source code has an API in SDL_Joystick to get the vendor and product IDs of a joystick. That’s what you’d want to use if you want to display different button prompts (images and text) depending on what controller is actually used.
Alex Szpakowski
2016-12-19 17:19:47 UTC
Permalink
I don’t believe the XInput API gives that information.
There needs to be a way to tell the "type" of device, but also which plugged-in-device is which (existing "XInput Controller #2" scheme vs. something identifiable to the user like "Logitech F310 Gamepad in XINPUT mode”).
Ed Phillips
2016-12-19 18:15:17 UTC
Permalink
Hi Alex,
I don’t believe the XInput API gives that information.
There needs to be a way to tell the "type" of device, but also which
plugged-in-device is which (existing "XInput Controller #2" scheme vs.
something identifiable to the user like "Logitech F310 Gamepad in
XINPUT mode”).
I agree and that's unfortunate. <rant> It's just another indication that
Microsoft made XINPUT specifically for their own devices, then decided to
"abandon" DINPUT, which forced everyone else to either dumb down their
controllers to be like an Xpad, or support the legacy DINPUT way instead
(steering wheels and flight controllers and trackballs and such) and thus
be "incompatible" with all the games that only support XINPUT. It boils
down to, unless your game is suited for Xpad-style gameplay, you're going
to need DINPUT device support. </rant>

Thanks goodness for SDL!

Side note: It really is the "dark ages" of game controllers these days...
isn't it? Remember when you could walk into a store and buy one of dozens
of different game controllers that all just worked with your games?

Anyway... so in order to differentiate between different XINPUT devices,
we'd need to key off of the Vendor/Product IDs, and the data that is
available for the product names of these devices like "usb.ids" here:

https://usb-ids.gowdy.us/

That could work.

Really, we need some kind of controller identifier (product name, or
unique ID or something similar) to avoid situations like the following:

Perhaps your XBox-compatible gamepad has buttons instead of analog LT/RT
so you want to map them differently in your game - for example,
brake/throttle for a racing game. Putting the pedal to the metal every
time you want to accelerate may not work very well (burn outs, spin outs).
It would be useful for the player to be able to remap this function for
this particular controller, but not his real Xpad. If it's a head-to-head
game, one person remaps all the controls for everyone playing? You could
get around this by prompting each player to press a button on their
controller before configuring but then how do we save the mapping so they
don't have to redo it every game session? Maybe XINPUT guarantees that if
the controllers stay plugged into the same ports, even if they fall
asleep, they won't get renumbered, so controller #2's config could be
saved (LT/RT remapping) and auto-applied next game session?

Thanks,

Ed

Ed Phillips <***@udel.edu> University of Delaware (302) 831-6082
Systems Programmer IV, Network and Systems Services

Continue reading on narkive:
Loading...