BGE: Fix T43883 joystick Xbox does not work properly since Blender 2.73 in Windows
AbandonedPublic

Authored by Jorge Bernal (lordloki) on Aug 25 2015, 1:35 AM.

Details

Summary

The issue comes with the migration to SDL2. SDL2 uses Xinput library for Windows and it works different from old mm and dinput libraries.

To mitigate this issue SDL2 implements a new Game Controller API. This new API use a intermediate file (gamecontrollerdb.txt) where the joysticks are mapped to follow a similar configuration than Xbox 360 game controller.

To perform this mapping there are several tools availables (Steam Big Mode, controllermapping in SDL2 test sources and antimicro).

I have tested this patch in Linux/Windows with a Xbox 360 controller and a PS2 clone. Xbox 360 worked out the box and for the PS2 clone I had to do the mapping using a controllermapping program. After this, it works like a charm. The behaviour was consistent between linux and windows (not as now).

This patch is NOT BACKWARD COMPATIBLE due to new API. Between other things the new API has not "hat" concept and it processes "hat/dpad" control as any other button (BUTTON_DPAD_UP, BUTTON_DPAD_DOWN, BUTTON_DPAD_LEFT and BUTTON_DPAD_RIGHT). Also, it implement Shoulder trigger buttons (left/right) as independent axis.

Moreover, to implement a "do_version" it is very hard because we would have to differentiate between MacOS&Linux and Windows, and between Joysticks and Game Controllers. The only way to make it compatible with previous versions is to compile SDL2 disabling XINPUT and enabling MM/DINPUT but this way we would loose hottpluggin, haptic (vibration) and standatization (at last) features.

To clarify a little how it works now regarding our unintuitive Joystick sensor:
A Game Controller is composed of:

6 axis availables (in order from 0 to 5):
AXIS_LEFTSTICK_X, AXIS_LEFTSTICK_Y, AXIS_RIGHTSTICK_X, AXIS_RIGHTSTICK_Y, AXIS_TRIGGERLEFT and AXIS_TRIGGERRIGHT.

and 15 buttons availables (in order from 0 to 14):
BUTTON_A, BUTTON_B, BUTTON_X, BUTTON_Y, BUTTON_BACK, BUTTON_GUIDE, BUTTON_START, BUTTON_LEFTSTICK, BUTTON_RIGHTSTICK, BUTTON_LEFTSHOULDER, BUTTON_RIGHTSHOULDER, BUTTON_DPAD_UP, BUTTON_DPAD_DOWN, BUTTON_DPAD_LEFT and BUTTON_DPAD_RIGHT.

Then with a game controller we would expect the following behaviour:

  • Event type = Single Axis:

  • "Index" means joystick/device
  • Axis Number 1 -> Left Stick horizontal movement
  • Axis Number 2 -> Left Stick vertical movement
  • Axis Number 3 -> Right Stick horizontal movement
  • Axis Number 4 -> Right Stick vertical movement
  • Axis Number 5 -> Left Shoulder trigger movement
  • Axis Number 6 -> Right Soulder trigger movement
  • Event type = Hat:

There is no Hat concept in new game controller API. It is treaty as a normal button

  • Hat Number 1 or 2 (left or right) -> Only Hat Number 1 is simulated through the buttons
  • Hat direction (8 directions) -> Now you only have 4 buttons (BUTTON_DPAD_UP, BUTTON_DPAD_DOWN, BUTTON_DPAD_LEFT and BUTTON_DPAD_RIGHT), if you want to check a diagonal direction (i.e top/left) you will have to add 2 sensors (BUTTON_DPAD_LEFT and BUTTON_DPAD_UP) with an AND controller to simulate the same behaviour.

Having said that, this mode will not work in current patch.

  • Event type = Axis

Similar to Single Axis mode but taken the Axis in pairs and after splitting them in 4 directions (Up/Down/Left/Right).

  • Axis Number 1 -> Left Stick (Up/Down/Left/Right)
  • Axis Number 2 -> Right Stick (Up/Down/Left/Right)
  • Axis Number 3 -> Both Shoulder triggers. Left/Right -> Left trigger (active when unpressed / active when pressed), Up/Down Right trigger (active when unpressed / active when pressed).
  • Event type = Button

  • Button number 0 -> BUTTON_A
  • Button number 1 -> BUTTON_B
  • Button number 2 -> BUTTON_X
  • Button number 3 -> BUTTON_Y
  • Button number 4 -> BUTTON_BACK
  • Button number 5 -> BUTTON_GUIDE
  • Button number 6 -> BUTTON_START
  • Button number 7 -> BUTTON_LEFTSTICK
  • Button number 8 -> BUTTON_RIGHTSTICK
  • Button number 9 -> BUTTON_LEFTSHOULDER
  • Button number 10 -> BUTTON_RIGHTSHOULDER
  • Button number 11 -> BUTTON_DPAD_UP
  • Button number 12 -> BUTTON_DPAD_DOWN
  • Button number 13 -> BUTTON_DPAD_LEFT
  • Button number 14 -> BUTTON_DPAD_RIGHT

TODO:

  • I have no tested in MacOsX yet

Diff Detail

Repository
rB Blender
Branch
bge-bug-SDL2gamecontroller
Jorge Bernal (lordloki) updated the summary for this revision. (Show Details)Aug 25 2015, 1:38 AM
Jorge Bernal (lordloki) updated the summary for this revision. (Show Details)Aug 25 2015, 1:55 AM
Porteries Tristan (panzergame) requested changes to this revision.Aug 25 2015, 1:55 PM
Porteries Tristan (panzergame) added inline comments.
source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp
122

errrmhh, can you use relative path ?

This revision now requires changes to proceed.Aug 25 2015, 1:55 PM
source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp
122

No, i can't because datafiles folder is under 2.7X folder which name changes in every release. I think that the proper way is to use the BKE function but i can't compile it.

Thomas Szepe (hg1) requested changes to this revision.Aug 27 2015, 9:51 PM

I have tested your patch with my changes. The patch looks OK and there is no load error with SDL_GameControllerAddMappingsFromFile.
But the axis are still not correct on my Windows PC (broken since Blender 2.73a). It seems that there is no X360 Controller mapping in the gamecontrollerdb.txt for windows.

I can upload my changed patch, if you want (I removed also some whitespace only changes for the patch).

source/gameengine/GameLogic/Joystick/SCA_Joystick.cpp
43–45

You need to change this, otherwise BKE_appdir_folder_id will not compile.

#if SDL_VERSION_ATLEAST(2, 0, 0)
extern "C" {
#  include "BKE_appdir.h"
}
#endif
122

You need to use relative path, otherwise it will not compile on other PC's.

	const char *path = BKE_appdir_folder_id(BLENDER_DATAFILES, "gamecontroller");
	if (path) {
		char fullpath[FILE_MAX];
		BLI_join_dirfile(fullpath, sizeof(fullpath), path, "gamecontrollerdb.txt");

		if ((SDL_GameControllerAddMappingsFromFile(fullpath)) == -1) {
			JOYSTICK_ECHO("gamecontrollerdb.txt not loaded");
		}
	}
Jorge Bernal (lordloki) marked 4 inline comments as done.Aug 28 2015, 12:44 AM

Thanks for the fixes @Thomas Szepe (hg1). Now it is obvious but I was ofuscated with library linking order :-).

Regarding to Windows testing. Tomorrow I hope to have time to test/compile the patch in windows. I will come back with the results.

I have tested your patch with my changes. The patch looks OK and there is no load error with SDL_GameControllerAddMappingsFromFile.
But the axis are still not correct on my Windows PC (broken since Blender 2.73a). It seems that there is no X360 Controller mapping in the gamecontrollerdb.txt for windows.

Hi @Thomas Szepe (hg1), I have just tested in windows with a X360 controller and with a Ps2 clone joystick and the behaviour is correct but I see what you are saying. There is no mapping for X360 Controllers because they are XInput compatibles and they don't need the mapping.

WARNING: I have updated the description pointing out which should be the expected behaviour as this patch is NOT backward compatible. The patch makes the behaviour consistent between linux and windows (and I hope Mac) and follows the expected process of standarization performed by SDL (rather STEAM).

In my point of view we should discard the old API and to use only the new API (reworking the Joystick sensor) but we can wait to 2.8 updating process.

Jorge Bernal (lordloki) updated the summary for this revision. (Show Details)Aug 29 2015, 2:26 AM

There is no mapping for X360 Controllers because they are XInput compatibles and they don't need the mapping.

I thought something like this. The problem is that the actual assignment is different to the old one and so the old files are not working any more.
You should mentioned this in the Blender 2.77 release notes.

Old behaviour:
Axis Number 3 -> Left Shoulder trigger movement -32768 to 0 / Right Shoulder trigger movement 0 to +32767
Axis Number 5 -> Right Stick horizontal movement

Please remove these files from the patch. Because there is no code change, there are only whitespace changes in this files. Such changes should be done in an cleanup patch.
source/blenderplayer/CMakeLists.txt
source/gameengine/GameLogic/Joystick/SCA_Joystick.h

  • Remove whitespaces

I don't know how discard the blenderplayer/CMakeLists.txt "change". I have compared it against old one and they are the same file.

I don't know how discard the blenderplayer/CMakeLists.txt "change". I have compared it against old one and they are the same file.

In the old there was one space after ge_player_common and on after ge_converter.

You can visualize the changes in the Phabricator if you choose "Show All" in "Whitespace Changes:" and update the view with the Show Diff button.

I am using SourceTree, with it is much easier to do such things. But there is no Linux version available.

  • Remove unwanted CMakeLists.txt whitespace changes

Talked over IRC.

For release we can aparently build SDL without Xinput support on Windows, to get the same kind of compatibility we had w/ SDL1.2.

For 2.76 release I think this is the best option.

@Martijn Berger (juicyfruit), since you build SDL last... is this something you're able to do before release?

Talked over IRC.

For release we can aparently build SDL without Xinput support on Windows, to get the same kind of compatibility we had w/ SDL1.2.

For 2.76 release I think this is the best option.

@Martijn Berger (juicyfruit), since you build SDL last... is this something you're able to do before release?

@Martijn Berger (juicyfruit),

the changes would be:

at SDL_config_windows.h in include dir:

- #define SDL_JOYSTICK_DINPUT 1
- #define SDL_JOYSTICK_XINPUT 1
- #define SDL_HAPTIC_DINPUT   1
- #define SDL_HAPTIC_XINPUT   1
---
+ #define SDL_HAPTIC_DISABLED 1
+ #define SDL_JOYSTICK_WINMM 1

what is the status here?

Basically:

  • There is no clear deal about the use of gamecontrollerdb.txt (external file or datatoc) yet
  • Nowadays, I'm doing a refactor of SDL Joystick code to convert it completely to the new SDL Game Controller API. To finish this refactor I will need 2-3 more weeks at least.

This refactor will include in at first stage:

  1. Hotpluggin (not done)
  2. Joystick sensor rework (done)
  3. New Joystick actuator to load an external gamecontrollerdb.txt and to be able to generate a mapping (partially done)

At second stage:

  1. Add support for force feedback.

I will update the diff after I finish each stage

Any luck with this?

I was going to add Xbox controls to wrectified soon :D

Closing.
Current changes have been incorporated in UPBGE Joystick refactor (including hotpluggin and vibration not present here). They will available after future merge.
With respect to extern gamecontrollerdb.txt extern file controversy exposed here, we converted the gamecontrollerdb.txt in a char* and added it into joystick sources. This way no extern file is necessary.
Thanks for reviewing