Gamepad issue with registering both analog trigger pulls at the same time
Background:
I'm on the road and took my gamepad instead of sticks. So I'm a bit bogged down trying to figure out how to do something specific. Game I'm targeting is Star Citizen but this issue is generic.
My controller (Gamesir T4 Pro, seen as an Xbox controller by Windows) has 2 analog triggers. With the changeover to xinput awhile back it seems like the trigger axes are merged where in the past they were separate axes.
Status:
I've been able to make a remap where each press a button by remapping ranges of the axes using the virtual button option (-1 to -0.1 on gamepad Axis3 pushes Button1 on the vjoy, 0.1 to 1.0 presses Button2). That's all good. I can fire 1 group with the left, and another group with the right.
Problem:
But. When both triggers are pressed, the axis gets set to 0, which means pressing both triggers won't actuate either fire button.
Other applications
Looking at a couple of other polling methods:
- sees both triggers being pulled at the same time
- shows the %axis for each independently on B6 and B7
JoyToKey
- sees Axis5 >0 and Axis5 <0 independently (showing both lit up when both triggers are being pressed)
- shows any press of left as a simultaneous Button11 (to Axis5 >0) and right as simultaneous Button12 (to Axis5 <0).
Back to the problem:
Joystick Gremlin only shows up through Button10 for the gamepad device, so I can't use Button11/Button12 (which may be JoyToKey hackery or dependent on something I'm not clear on). And Gremlin doesn't -seem- to have a way to send both buttons at the same time.
There are times where pressing both fire buttons really is wanted, and there's almost never a time where being a little heavy on one button should stop the other from firing.
Question:
Am I missing the right method here?
If not, this is either a bug report or a feature request, whichever you want to consider it :)
Possible Solutions:
I'm not sure how plausible any of these are. I'm not looking to change the current default behavior and therefor possibly break existing gamepad configurations. Instead these might be exposed as "Settings" for gamepads (I see the vJoy devices in Settings but nothing for the physical devices so that might be a good spot).
- Detect the >0 and <0 on the trigger axes independently rather than combined so that both triggers can be used at the same time (either as -1.0 to 0 on one and 0 to 1.0 on the other ... or ... split them up as virtual -1 to 1 on both mapped to the actual values)
- Expose 2 buttons, even if "fake" as a virtual button, for the triggers in addition to the axes (possibly Button11 and Button12, mimicing JoyToKey) to function like digital buttons that can be pressed at the same time.
- Tell me this is a problem vJoy has to tackle and I'll try to find the right place to report that
- Tell me there already is a way to do this and give me a pointer to where please :)
Addendum:
I want to use Gremlin for this config for some more advanced stuff later on, as well as to get away from just remapping the gamepad. SC's gamepad support is languishing (pp_resortdevices only works on sticks, and interaction mode on the gamepads is pretty broken on newer interactibles).
This isn't so much a problem in Gremlin but with dill which I wrote to handle inputs. That library purely uses DirectInput and has no notion of what Xinput is and thus is at the mercy of whatever Xinput to DirectInput conversion Windows decides to use. I don't know what the other tools use as their API but I suspect at least some would use XInput.
So really the solution is to implement XInput support in dill which would make these issues disappear as well as other weird problems that lack of XInput support causes.
You can grab this file https://github.com/WhiteMagic/dill/releases/download/v1.3/dill_1.3.zip and run the example programs to see the raw information Gremlin is provided with. If there the two triggers are seen as a single axis there is nothing you can do inside Gremlin to solve the ambiguity of their presses.
TL;DR: found a method to separate the axes that your raw DLL can see, but causes error within JG.
Follow-up:
Confirmed from the raw input example that JG is only seeing the R axis.
I played a little bit with XInputPlus with a little guide from Steam Community to get started.
If I enable DirectInput using XInputPlus (with xinput either enabled or disabled, didn't matter), it just ... confuses your DLL :) But ... only when the triggers are pressed. Other axes and buttons still work in this mode.
If it's something you're at all interested in, install XinputPlus and target JG's .exe and apply (run XinputPlus in admin mode so it can add to the ProgramFiles without permission error). Enable DirectInput, apply, then start JG. You should hear a tone if XinputPlus applies when JG loads.
The error I get on pressing a trigger after doing the above:
Uncaught exception:
Traceback (most recent call last):
File "joystick_gremlin.py", line 800, in _joystick_input_selection
File "gremlin\ui\input_item.py", line 270, in select_item
File "gremlin\ui\input_item.py", line 155, in event_to_index
KeyError: 3
HOWEVER
Applying XInputPlus to your raw DLL example.exe ... it DOES see 2 separate axes at this point. Right trigger as Axis3 and Left trigger as Axis6.
I looked for a couple minutes to see if I could find the referenced .py files in the error (knowing almost nothing about Python) but didn't find them.
Might be good breadcrumbs for figuring out a replacement DLL for gamepad input. Unfortunately XinputPlus is in Japanese and I don't think the source is available.
...
Other Methods:
Not presenting these as "use this entire 3rd party app", rather, for investigating their Xinput DLL to see if it might work as a replacement for yours.
- AutoHotkey + xinput DLL change (might actually be the same method but an alternative download)
- AutoHotkey + EvilC's DLL
- UCR (uses the evilC libraries but skips AutoHotkey, seems promising for me for now possibly in conjunction with JG for some other stuff)
...
I'm going to see if I can get what I wanted working with UCR for now. But ... I'll be happy to retest Gremlin if updates to the Xinput DLL and/or when UI update comes out.
Feel free to close when you know you're either not going to have time to work on this and/or have a plan for changes.
I would suspect that the error you're getting with xinputplus is due to it not honouring DirectInput properly. The error you get is caused by the index to axis offset not being properly populated. That map contains the information about which axis an index corresponds to, e.g. a T16000.M has 4 axes with indices 1, 2, 3, 4 but the logical "named" axis are 1, 2, 6, 8 and there is an error (or just missing data) in the mapping provided by xinputplus.
Implementing Xinput support should not actually be all that hard, especially since SDL2 has a good implementation of it which would most likely be what I'd be looking at for reference if I need one, since both DirectInput and XInput are not really complicated from an API point of view. It's just yet another thing on a very long list of things to do.