Welcome, Guest. Please login or register. Did you miss your activation email?

Author Topic: Win10 Joysticks have more than 32 buttons, can't get status on any of them  (Read 4699 times)

0 Members and 1 Guest are viewing this topic.

lebworuxe

  • Newbie
  • *
  • Posts: 3
    • View Profile
In my SFML based Windows program, I'm trying to get status of some buttons from two flight simulator devices that show up under windows as USB joysticks, but for neither of them does sf::Joystick::isButtonPressed() ever return anything but "false" even when pressed.   The same program has no issues seeing correct status on a traditional joystick that is also connected.  The thing I'm suspicious of is both the flight sim devices have more than 32 buttons which I know DirectX doesn't support, but the buttons I'm interested in all have DirectX ID's less than 32, and for example I can still see the correct button status for the buttons I care about in their Windows properties test popups (e.g. https://www.howtogeek.com/wp-content/uploads/2016/02/xhtx22.png.pagespeed.gp+jp+jw+pj+ws+js+rj+rp+rw+ri+cp+md.ic.Zqbhb1VDNp.png).

sf::Joystick::getIdentification() describes the devices ok, and sf::Joystick::IsConnected() tells me they are both connected, and sf::Joystick::getButtonCount returns 32.   Nonetheless sf::Joystick::isButtonPressed() returns false for all buttons 0-31 no matter what I do.

Any ideas?  Thanks.

lebworuxe

  • Newbie
  • *
  • Posts: 3
    • View Profile
Looking through https://github.com/SFML/SFML/blob/master/src/SFML/Window/Win32/JoystickImpl.cpp. it seems like everything is basically already there for 128 button support that came in the latest DirectInput version.  Is all that's needed a change of https://github.com/SFML/SFML/blob/master/include/SFML/Window/Joystick.hpp#L52 to ButtonCount = 128 ?

If I can figure out https://www.sfml-dev.org/tutorials/2.5/compile-with-cmake.php, I might try it.  If anyone sees this and knows either this won't work or has some other explanation for my issue, I'd appreciate the info to save the effort.

kojack

  • Jr. Member
  • **
  • Posts: 80
    • View Profile
Support for 128 buttons came out in 1997 in DirectInput 5.
But we still have games like Elite Dangerous that refuse to support it.
(It's a pet hate of mine, I've got Virpil hardware with more than 32 buttons and have to use software like Joystick Gremlin and vJoy to redirect my throttle through multiple virtual 32 button devices)

Looking at the SFML joystick code, it seems at least for Windows they may have forgotten to update the counts. Currently it's set to 8 axes and 32 buttons (and 4 POVs, but they don't get a count constant).
But the setup code is using a custom format structure with 32 axes, 32 buttons and 4 POVs.
But then the setup code says the number of objects in that struct is 32 axes, 128 buttons and 4 POVs (with 96 buttons undefined) by saying the format was the same size as DIJOYSTATE2 afterall.

So by the look of it (haven't tested) changing ButtonCount to 128 and AxisCount to 32 in joystick.hpp (and recompiling SFML) should be enough. The joystick setup code is ignoring AxisCount and is hard coded to 32 anyway (just won't let you look at them due to AxisCount), while it does use ButtonCount to set up the buttons.

On a side note, since nothing dynamic is being done there (like allocating exactly the number of axes/buttons on the device by enumerating all controls), the 80+ lines of format setup could be replaced with:
result = m_device->SetDataFormat(&c_dfDIJoystick2);
(c_dfDIJoystick2 is the already set up by DirectInput 32 axis, 128 button, 4 POV format)
Unless I missed something it's doing in there.

I might test it later if I get time.

lebworuxe

  • Newbie
  • *
  • Posts: 3
    • View Profile
The Cmake build of SFML was way easier than I was expecting.  And also changing that one line worked!  :o  It now reports the accurate number of buttons on those devices, and most importantly reflects the status of the buttons I care about.

The only semi-weird thing is that my initial poll of all the button states still says all 0's sometimes when some are pressed.  For my use, that doesn't matter.

Anyway, I'm happy now with my local build for a while, though it would be nice if this could make it into the mainline eventually.


kojack

  • Jr. Member
  • **
  • Posts: 80
    • View Profile
Yay.

I guess the issue with the change is that other platforms might not support it (I don't know, I only do windows dev). It's only in the windows specific implementation that the higher number is used, maybe linux/mac/android/etc wouldn't like it.

Ideally, SFML wouldn't use one set of constants for all joystick devices, but query the devices for exact numbers.

Soon I should receive a Wooting Two Lekker Edition keyboard. It has over 100 analog axes (every key is analog). So even 32 axes can be a little limiting. :)

I haven't checked on the first poll issue. It might depend on the device as to whether it sends initial state of everything on startup or only changes. That's one thing that really annoys me with MIDI programming. There's no way in MIDI to ask a device something like "what is the value of this slider?". Instead you have to wait for the slider to move, then you get an event saying the new value. So you can't get initial state of all controls.

kojack

  • Jr. Member
  • **
  • Posts: 80
    • View Profile
Ok, I was slightly wrong there. SFML does allow you to query how many buttons are really on a joystick, but clamps the value to 32 max. But there's no way to query how many axes or POVs there are.

Another issue, it sets up the Direct Input format for 4 groups of analog values, each having 6 axes and 2 sliders (so 4*(6+2)=32 total). Plus there's 4 POVs. But then says there's only 8 axes possible, and returns a single POV as the 7th and 8th axes, which should be the first 2 sliders.

An example of a common device that would break this limit if fully supported: Playstation controller. A DualShock4 controller has 16 analog axes:
- left thumb x
- left thumb y
- right thumb x
- right thumb y
- left trigger
- right trigger
- touchpad finger 1 x
- touchpad finger 1 y
- touchpad finger 2 x
- touchpad finger 2 y
- IMU gyro pitch
- IMU gyro yaw
- IMU gyro roll
- IMU acceleration x
- IMU acceleration y
- IMU acceleration z

Of course DirectInput only shows the first 6, but the rest are there if you go down to the HID level like I do. :)

Anyway, you got your issue working, I'll stop ranting now. :)