| Summary: | Release events for triggers receive wrong centered value | ||
|---|---|---|---|
| Product: | SDL | Reporter: | Ryochan7 <nickles.travis> |
| Component: | joystick | Assignee: | Sam Lantinga <slouken> |
| Status: | RESOLVED FIXED | QA Contact: | Sam Lantinga <slouken> |
| Severity: | normal | ||
| Priority: | P2 | CC: | Gert-Jan, rodrigo.alfenas, x414e54 |
| Version: | 2.0.3 | ||
| Hardware: | x86_64 | ||
| OS: | Windows (All) | ||
| Attachments: |
Patch for xinput trigger bug.
Patch to change trigger value if recentering |
||
|
Description
Ryochan7
2014-12-16 16:05:02 UTC
I can confirm this with the testgamecontroller test case in the SDL repo. Testing with both an Xbox controller and PS4 controller the shoulder triggers are both active to start with until they receive the first motion event. I've been looking into this, but I'm not quite sure how to implement a solution. I have a hard time finding where the _SDL_Joystick struct is initialized. Here is what's going on and what I think could be changed to solve this: Sequence of events - The controller is initialized with 0 as it's trigger axis value (all axis are set to 0, which is great except for triggers...). + [Here all axis mapped to SDL_CONTROLLER_AXIS_TRIGGERLEFT or SDL_CONTROLLER_AXIS_TRIGGERRIGHT should be set to -32768] - SDL_gamecontroller.c:1010 blows up the world by adding 16384, normally used to map the trigger to 0 - 32767, but now pulling the trigger halfway to 16384. - When any action is done on the controller SDL_xinputjoystick.c:351 -> SDL_xinputjoystick.c:297 maps the trigger to -32768 to 32767, all is good again, because SDL_gamecontroller.c:1010 will map that to 0 - 32767. - When the controller is disconnected all axis are reset to 0, which again causes one frame of trigger input. + [Here all axis mapped to SDL_CONTROLLER_AXIS_TRIGGERLEFT or SDL_CONTROLLER_AXIS_TRIGGERRIGHT should be set to -32768] We had a lot of problems with this for SpeedRunners so far, as the boost power is mapped to a trigger. Since I replaced plain xinput with SDL_gamecontroller the boost is now regularly stuck. Created attachment 2481 [details]
Patch for xinput trigger bug.
Partial fix for trigger being pressed by default on game controller devices
Oh wow that comment got auto-posted with the attachement, anyway continued: Partial fix for trigger being pressed by default on game controller devices. Normally SDL_PrivateJoystickAxis is used to set these kinds of values, but that won't work here because there is keyboard focus check in there which is not relevant here. It fixes the most common part of this bug, which is the triggers being pressed at startup. It does not fix the bug where the triggers will be pressed for one frame before disconnecting the controller. That issue is a bit more complicated to solve because that trigger press state is set from SDL_events.c:404 -> SDL_joystick.c:691 where there is no reference to a SDL_GameController instance. Therefore we have no mapping, and therefor no idea which axes are triggers. Ideally either SDL_joystick could have a reference to SDL_GameController, or maybe the GameController subsystem should also be informed of a disconnect when it happens. Created attachment 2496 [details]
Patch to change trigger value if recentering
I had worked around this issue in my own program by using two passes for reading the event queue. The first pass would grab all events and determine if events for a gamepad should be considered a pre-removal event. Those generated events would be ignored and the actual device removal event would be used to release all buttons and axes of a gamepad. Looking at the current source code, it seems like the best place to account for this scenario would be in the SDL_GameControllerEventWatcher function. If force_recentering is currently set for an SDL_Joystick instance and the axis is determined to be mapped to a game controller trigger, the final value used when calling SDL_PrivateGameControllerAxis will be 0 instead of 16384 like what happens now. I have done some minor testing by commenting out my workaround and using the SDL tweak instead but adding a small check seems to do the trick.
Fixed, thanks! https://hg.libsdl.org/SDL/rev/612fbaee8e3c |