Merge pull request #209 from Wintermute0110/master

SDL joystick input handling implementation
This commit is contained in:
Robert Beckebans 2014-11-25 11:37:29 +01:00
commit c6f4ffc7e6
8 changed files with 633 additions and 24 deletions

8
.gitignore vendored
View file

@ -27,3 +27,11 @@ base/sound/
base/strings/
base/video/
base/wads/
GPATH
GRTAGS
GSYMS
GTAGS
HTML/
neo/.kdev4
neo/neo.kdev4

234
README.SDL_Joystick Normal file
View file

@ -0,0 +1,234 @@
This file documents the use of a joystick/gamepad under Linux with RBDoom3-BFG.
Joystick support has been tested with an XBox 360 wireless and a
Logitech F710 wireless gamepads, but in theory should work with any XBox 360
compatible gamepad, either wireless or wired/USB.
To use the gamepad follow this instructions,
a) Make sure your joystick is detected by Linux.
One way to check this is to look for jsN files under /dev/input/, where
N is a number. For example, /dev/input/js0 is the first joystick,
/dev/input/js1 the second one, and so on. Executing the following command you
should see something like this:
$ ls -l /dev/input/js*
crw-rw-r--+ 1 root input 13, 0 Nov 20 04:39 /dev/input/js0
Another way to check is to use the udevadm monitor command. This is what happens
when you connect a USB joystick (launch udevadm and then connect the gamepad or
the wireless receiver):
$ udevadm monitor -u
monitor will print the received events for:
UDEV - the event which udev sends out after rule processing
UDEV [14503.227311] add /devices/pci0000:00/0000:00:1d.0/usb5/5-2 (usb)
UDEV [14504.551280] add /devices/pci0000:00/0000:00:1d.0/usb5/5-2/5-2:1.0 (usb)
UDEV [14504.553328] add /devices/pci0000:00/0000:00:1d.0/usb5/5-2/5-2:1.0/input/input22 (input)
UDEV [14504.555805] add /devices/pci0000:00/0000:00:1d.0/usb5/5-2/5-2:1.0/input/input22/event19 (input)
UDEV [14504.565611] add /devices/pci0000:00/0000:00:1d.0/usb5/5-2/5-2:1.0/input/input22/js0 (input)
The program jstest allows you to check if your joystick works OK:
$ jstest /dev/input/js0
Driver version is 2.1.0.
Joystick (Xbox 360 Wireless Receiver) has 6 axes (X, Y, Z, Rx, Ry, Rz)
and 15 buttons (BtnX, BtnY, BtnTL, BtnTR, BtnTR2, BtnSelect, BtnThumbL, BtnThumbR, ....
Testing ... (interrupt to exit)
Every time you press a button or move an axis you should see the changes printed on
the screen. Press CTRL+C to end jstest.
No matter how many joysticks you have, RBDoom3-BFG only uses the first
joystick named /dev/input/js0.
b) Make sure RBDoom3-BFG detects and is able to use your joystick.
Execute RBDoom3-BFG in a console/terminal to see the messages printed there. If
your joystick is correctly detected you should see something like this:
$ ./RBDoom3BFG
... lots of text ...
----- R_InitOpenGL -----
Initializing OpenGL subsystem
Using 8 color bits, 24 depth, 8 stencil display
Using GLEW 1.10.0
Sys_InitInput: Joystick subsystem init
Sys_InitInput: Joystic - Found 4 joysticks
Opened Joystick 0
Name: Xbox 360 Wireless Receiver
Number of Axes: 6
Number of Buttons: 15
Number of Hats: 0
Number of Balls: 0
... more text ...
If the number of detected joysticks is 0 and none is opened check again
a) and make sure the file /dev/input/js0 is there (for example, if you
are using a wireless joystick make sure the gamepad is ON and not
in sleeping mode when you run RBDoom3-BFG) and that you have permissions
to read that file (for example, in Debian users that want to use the
joystick must be added to the group input).
c) Set the bindings of your joystick.
You can use the Doom3 console to set the bindings. To bind a joystick
button/axis to a game action, press the tilde key (just below ESC) to
show the Doom3 console. Then type:
] bind <key_name> <action>
For example, this binds gamepad button 0 with the action "jump":
] bind JOY1 _moveup
Apendix A gives you a list of the gamepad axis/button names and the
possible actions you can bind to them.
Alternatively, you can use configuration files to set the bindings
automatically. Copy the files joy_righty.cfg, joy_lefty.cfg and joy_360_0.cfg
to your Doom3 base directory. You can find these files in Appendix B at the
bottom of this file.
d) Enjoy!
--------------------------------------------------------------------------
TODO/BUGS
* Only XBox 360 gamepad clones are supported at the moment.
* SDL axis/keycode numbers are hard-coded to Doom3 axis/keycode names.
Depending of your gamepad model maybe this will produce unwanted results.
It is not clear at the moment how to remap this (configuration file, GUI, ...).
--------------------------------------------------------------------------
Apendix A) Doom3 joystick key names and key bindings
This is a list of the supported key/axis names. Note that the names of the
buttons are only valid for the XBox 360 wireless gamepad. Other gamepads
may have different names depending on the gamepad layout and/or more buttons
available so you can map more actions. Also note that RBDoom3-BFG treats
the back triggers like buttons rather that axes.
JOY1 (A button)
JOY2 (B/Circle button)
JOY3 (X/Square button)
JOY4 (Y/Triangle button)
JOY5 (L Shoulder)
JOY6 (R Shoulder)
JOY7 (BACK)
JOY8 (START)
JOY9 (XBOX button)
JOY10 (LEFT ANALOG JOY BUTTON)
JOY11 (RIGHT ANALOG JOY BUTTON)
JOY_TRIGGER1 (LEFT TRIGGER)
JOY_TRIGGER2 (RIGHT TRIGGER)
JOY_DPAD_RIGHT (D-PAD ANALOG JOYSTIC UP)
JOY_DPAD_LEFT (D-PAD ANALOG JOYSTIC DOWN)
JOY_DPAD_UP (D-PAD ANALOG JOYSTIC LEFT)
JOY_DPAD_DOWN (D-PAD ANALOG JOYSTIC RIGHT)
JOY_STICK1_UP (RIGHT ANALOG JOYSTIC UP)
JOY_STICK1_DOWN (RIGHT ANALOG JOYSTIC DOWN)
JOY_STICK1_LEFT (RIGHT ANALOG JOYSTIC LEFT)
JOY_STICK1_RIGHT (RIGHT ANALOG JOYSTIC RIGHT)
JOY_STICK2_UP (LEFT ANALOG JOYSTIC UP)
JOY_STICK2_DOWN (LEFT ANALOG JOYSTIC DOWN)
JOY_STICK2_LEFT (LEFT ANALOG JOYSTIC LEFT)
JOY_STICK2_RIGHT (LEFT ANALOG JOYSTIC RIGHT)
This is a list of commands that can be binded in Doom3. This commands are
only valid in-game, the GUI uses its own set of hard-coded key bindings. Note
that commands having spaces in between (more than one word) must be quoted "":
_impulse0 Fists / Grabber
_impulse2 Pistol
_impulse3 Shotgun / Double shotgun (Doomclassic)
_impulse5 Machinegun
_impulse6 Chaingun
_impulse7 Grenades
_impulse8 Plasma Gun
_impulse9 Rockets
_impulse10 BFG 9000
_impulse12 Soulcube / Artifact
_impulse13 Reload weapon
_impulse14 Previous weapon
_impulse15 Next weapon
_impulse16 Flashlight
_impulse19 PDA / Scoreboard
_attack Fire / Melee
_use Use / Action
_speed Run
_forward Move forward
_back Move backwards
_moveleft Move left
_moveright Move right
_moveup Jump
_movedown Crouch
_left Look left
_right Look right
_lookup Look up
_lookdown Look down
"savegame quick" Quick Save
"loadgame quick" Quick Load
"screenshot" Take screenshot
Apendix B) Joystick bindings
-- joy_righty.cfg --------------------------------------------------------
bind "JOY_STICK1_UP" "_forward"
bind "JOY_STICK1_DOWN" "_back"
bind "JOY_STICK1_LEFT" "_moveleft"
bind "JOY_STICK1_RIGHT" "_moveright"
bind "JOY_STICK2_UP" "_lookup"
bind "JOY_STICK2_DOWN" "_lookdown"
bind "JOY_STICK2_LEFT" "_left"
bind "JOY_STICK2_RIGHT" "_right"
--------------------------------------------------------------------------
-- joy_lefty.cfg ---------------------------------------------------------
bind "JOY_STICK2_UP" "_forward"
bind "JOY_STICK2_DOWN" "_back"
bind "JOY_STICK2_LEFT" "_moveleft"
bind "JOY_STICK2_RIGHT" "_moveright"
bind "JOY_STICK1_UP" "_lookup"
bind "JOY_STICK1_DOWN" "_lookdown"
bind "JOY_STICK1_LEFT" "_left"
bind "JOY_STICK1_RIGHT" "_right"
--------------------------------------------------------------------------
-- joy_360_0.cfg ---------------------------------------------------------
bind "JOY_DPAD_RIGHT" "_impulse5" // Put your favourite weapons here
bind "JOY_DPAD_LEFT" "_impulse12" // for quick access.
bind "JOY_DPAD_UP" "_impulse6"
bind "JOY_DPAD_DOWN" "_impulse8"
bind "JOY_TRIGGER1" "_impulse16"
bind "JOY_TRIGGER2" "_attack"
bind "JOY1" "_moveup" // (A/X button)
bind "JOY2" "" // (B/Circle button)
bind "JOY3" "_impulse13" // (X/Square button)
bind "JOY4" "_use" // (Y/Triangle button)
bind "JOY5" "_impulse15" // (L Shoulder)
bind "JOY6" "_impulse14" // (R Shoulder)
bind "JOY7" "_impulse19" // (BACK)
bind "JOY8" "" // (START) (Used to show the game GUI)
bind "JOY9" "" // (XBOX)
bind "JOY10" "_speed" // (LEFT ANALOG JOY BUTTON)
bind "JOY11" "_movedown" // (RIGHT ANALOG JOY BUTTON)
--------------------------------------------------------------------------

5
neo/cmake-linux-debug.sh Executable file
View file

@ -0,0 +1,5 @@
cd ..
rm -rf build
mkdir build
cd build
cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Debug ../neo

View file

@ -2,4 +2,4 @@ cd ..
rm -rf build
mkdir build
cd build
cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DSDL2=OFF ../neo
cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=Release -DONATIVE=ON ../neo

View file

@ -551,6 +551,19 @@ void idCmdSystemLocal::ExecuteTokenizedString( const idCmdArgs& args )
return; // no tokens
}
// DEBUG: print commands executed by the console
/*
if(args.Argc() == 1) {
common->Printf("idCmdSystemLocal::ExecuteTokenizedString: '%s'\n", args.Argv( 0 ));
}
else if(args.Argc() == 2) {
common->Printf("idCmdSystemLocal::ExecuteTokenizedString: '%s' '%s'\n", args.Argv( 0 ), args.Argv( 1 ));
}
else if(args.Argc() == 3) {
common->Printf("idCmdSystemLocal::ExecuteTokenizedString: '%s' '%s' '%s'\n", args.Argv( 0 ), args.Argv( 1 ), args.Argv( 2 ));
}
*/
// check registered command functions
for( prev = &commands; *prev; prev = &cmd->next )
{

View file

@ -436,11 +436,13 @@ void idPlayerProfile::ExecConfig( bool save, bool forceDefault )
if( leftyFlip )
{
cmdSystem->AppendCommandText( "exec joy_lefty.cfg" );
cmdSystem->AppendCommandText( "exec joy_lefty.cfg\n" );
cmdSystem->AppendCommandText( "exec joy_360_0.cfg\n" );
}
else
{
cmdSystem->AppendCommandText( "exec joy_righty.cfg" );
cmdSystem->AppendCommandText( "exec joy_righty.cfg\n" );
cmdSystem->AppendCommandText( "exec joy_360_0.cfg\n" );
}
cmdSystem->ExecuteCommandBuffer();

View file

@ -1423,7 +1423,11 @@ idUsercmdGenLocal::Joystick
void idUsercmdGenLocal::Joystick( int deviceNum )
{
int numEvents = Sys_PollJoystickInputEvents( deviceNum );
// if(numEvents) {
// common->Printf("idUsercmdGenLocal::Joystick: numEvents = %i\n", numEvents);
// }
// Study each of the buffer elements and process them.
for( int i = 0; i < numEvents; i++ )
{
@ -1431,6 +1435,8 @@ void idUsercmdGenLocal::Joystick( int deviceNum )
int value;
if( Sys_ReturnJoystickInputEvent( i, action, value ) )
{
// common->Printf("idUsercmdGenLocal::Joystick: i = %i / action = %i / value = %i\n", i, action, value);
if( action >= J_ACTION1 && action <= J_ACTION_MAX )
{
int joyButton = K_JOY1 + ( action - J_ACTION1 );

View file

@ -116,6 +116,25 @@ struct mouse_poll_t
static idList<kbd_poll_t> kbd_polls;
static idList<mouse_poll_t> mouse_polls;
struct joystick_poll_t
{
int action;
int value;
joystick_poll_t()
{
}
joystick_poll_t( int a, int v )
{
action = a;
value = v;
}
};
static idList<joystick_poll_t> joystick_polls;
SDL_Joystick *joy = NULL;
int SDL_joystick_has_hat = 0;
// RB begin
static int SDL_KeyToDoom3Key( SDL_Keycode key, bool& isChar )
{
@ -551,6 +570,8 @@ Sys_InitInput
*/
void Sys_InitInput()
{
int numJoysticks, i;
kbd_polls.SetGranularity( 64 );
mouse_polls.SetGranularity( 64 );
@ -558,8 +579,54 @@ void Sys_InitInput()
SDL_EnableUNICODE( 1 );
SDL_EnableKeyRepeat( SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL );
#endif
in_keyboard.SetModified();
// WM0110: Initialise SDL Joystick
common->Printf( "Sys_InitInput: Joystick subsystem init\n" );
if( SDL_Init(SDL_INIT_JOYSTICK) ) {
common->Printf( "Sys_InitInput: Joystic Init ERROR!\n");
}
numJoysticks = SDL_NumJoysticks();
common->Printf( "Sys_InitInput: Joystic - Found %i joysticks\n", numJoysticks);
#if !SDL_VERSION_ATLEAST(2, 0, 0)
for(i=0; i<numJoysticks; i++)
common->Printf(" Joystick %i name '%s'\n", i, SDL_JoystickName(i));
#endif
// Open first available joystick and use it
if(SDL_NumJoysticks() > 0) {
joy = SDL_JoystickOpen(0);
if(joy) {
int num_hats;
num_hats = SDL_JoystickNumHats(joy);
common->Printf("Opened Joystick number 0\n");
#if SDL_VERSION_ATLEAST(2, 0, 0)
common->Printf("Name: %s\n", SDL_JoystickName(joy));
#else
common->Printf("Name: %s\n", SDL_JoystickName(0));
#endif
common->Printf("Number of Axes: %d\n", SDL_JoystickNumAxes(joy));
common->Printf("Number of Buttons: %d\n", SDL_JoystickNumButtons(joy));
common->Printf("Number of Hats: %d\n", num_hats);
common->Printf("Number of Balls: %d\n", SDL_JoystickNumBalls(joy));
SDL_joystick_has_hat = 0;
if(num_hats) {
SDL_joystick_has_hat = 1;
}
}
else {
joy = NULL;
common->Printf("Couldn't open Joystick 0\n");
}
}
else {
joy = NULL;
}
// WM0110
}
/*
@ -571,6 +638,15 @@ void Sys_ShutdownInput()
{
kbd_polls.Clear();
mouse_polls.Clear();
joystick_polls.Clear();
// Close any opened SDL Joystic
if(joy) {
common->Printf("Sys_ShutdownInput: closing SDL joystick.\n");
SDL_JoystickClose(joy);
} else {
common->Printf("Sys_ShutdownInput: SDL joystick not initialized. Nothing to close.\n");
}
}
/*
@ -681,9 +757,11 @@ sysEvent_t Sys_GetEvent()
SDL_Event ev;
sysEvent_t res = { };
int key;
static const sysEvent_t res_none = { SE_NONE, 0, 0, 0, NULL };
// WM0110: previous state of joystick hat
static int previous_hat_state = SDL_HAT_CENTERED;
#if SDL_VERSION_ATLEAST(2, 0, 0)
static char* s = NULL;
static size_t s_pos = 0;
@ -870,7 +948,7 @@ sysEvent_t Sys_GetEvent()
// DG end
#endif
// fall through
// fall through
case SDL_KEYUP:
{
bool isChar;
@ -990,7 +1068,7 @@ sysEvent_t Sys_GetEvent()
case SDL_MOUSEBUTTONDOWN:
case SDL_MOUSEBUTTONUP:
res.evType = SE_KEY;
switch( ev.button.button )
{
case SDL_BUTTON_LEFT:
@ -1019,15 +1097,264 @@ sysEvent_t Sys_GetEvent()
break;
#endif
}
res.evValue2 = ev.button.state == SDL_PRESSED ? 1 : 0;
return res;
// WM0110
// NOTE: it seems that the key bindings for the GUI and for the game are
// totally independant. I think the event returned by this function seems to work
// on the GUI and the event returned by Sys_ReturnJoystickInputEvent() works on
// the game.
// Also, remember that joystick keys must be binded to actions in order to work!
case SDL_JOYBUTTONDOWN:
case SDL_JOYBUTTONUP:
// sys_public.h: evValue is an axis number and evValue2 is the current state (-127 to 127)
// WM0110: joystick ranges must be between (-32769, 32768)!
res.evType = SE_KEY;
switch( ev.jbutton.button )
{
case 0:
res.evValue = K_JOY1;
joystick_polls.Append( joystick_poll_t( J_ACTION1, ev.jbutton.state == SDL_PRESSED ? 1 : 0 ) );
break;
case 1:
res.evValue = K_JOY2;
joystick_polls.Append( joystick_poll_t( J_ACTION2, ev.jbutton.state == SDL_PRESSED ? 1 : 0 ) );
break;
case 2:
res.evValue = K_JOY3;
joystick_polls.Append( joystick_poll_t( J_ACTION3, ev.jbutton.state == SDL_PRESSED ? 1 : 0 ) );
break;
case 3:
res.evValue = K_JOY4;
joystick_polls.Append( joystick_poll_t( J_ACTION4, ev.jbutton.state == SDL_PRESSED ? 1 : 0 ) );
break;
case 4:
res.evValue = K_JOY5;
joystick_polls.Append( joystick_poll_t( J_ACTION5, ev.jbutton.state == SDL_PRESSED ? 1 : 0 ) );
break;
case 5:
res.evValue = K_JOY6;
joystick_polls.Append( joystick_poll_t( J_ACTION6, ev.jbutton.state == SDL_PRESSED ? 1 : 0 ) );
break;
case 6:
res.evValue = K_JOY7;
joystick_polls.Append( joystick_poll_t( J_ACTION7, ev.jbutton.state == SDL_PRESSED ? 1 : 0 ) );
break;
case 7:
res.evValue = K_JOY8;
joystick_polls.Append( joystick_poll_t( J_ACTION8, ev.jbutton.state == SDL_PRESSED ? 1 : 0 ) );
break;
case 8:
res.evValue = K_JOY9;
joystick_polls.Append( joystick_poll_t( J_ACTION9, ev.jbutton.state == SDL_PRESSED ? 1 : 0 ) );
break;
case 9:
res.evValue = K_JOY10;
joystick_polls.Append( joystick_poll_t( J_ACTION10, ev.jbutton.state == SDL_PRESSED ? 1 : 0 ) );
break;
case 10:
res.evValue = K_JOY11;
joystick_polls.Append( joystick_poll_t( J_ACTION11, ev.jbutton.state == SDL_PRESSED ? 1 : 0 ) );
break;
// D-PAD left (XBox 360 wireless)
case 11:
// If joystick has a hat, then use the hat as D-PAD. If not, D-PAD is mapped
// to buttons.
if(SDL_joystick_has_hat) {
res.evValue = K_JOY12;
joystick_polls.Append( joystick_poll_t( J_ACTION12, ev.jbutton.state == SDL_PRESSED ? 1 : 0 ) );
} else {
res.evValue = K_JOY_DPAD_LEFT;
joystick_polls.Append( joystick_poll_t( J_DPAD_LEFT, ev.jbutton.state == SDL_PRESSED ? 1 : 0 ) );
}
break;
// D-PAD right
case 12:
if(SDL_joystick_has_hat) {
res.evValue = K_JOY13;
joystick_polls.Append( joystick_poll_t( J_ACTION13, ev.jbutton.state == SDL_PRESSED ? 1 : 0 ) );
} else {
res.evValue = K_JOY_DPAD_RIGHT;
joystick_polls.Append( joystick_poll_t( J_DPAD_RIGHT, ev.jbutton.state == SDL_PRESSED ? 1 : 0 ) );
}
break;
// D-PAD up
case 13:
if(SDL_joystick_has_hat) {
res.evValue = K_JOY14;
joystick_polls.Append( joystick_poll_t( J_ACTION14, ev.jbutton.state == SDL_PRESSED ? 1 : 0 ) );
} else {
res.evValue = K_JOY_DPAD_UP;
joystick_polls.Append( joystick_poll_t( J_DPAD_UP, ev.jbutton.state == SDL_PRESSED ? 1 : 0 ) );
}
break;
// D-PAD down
case 14:
if(SDL_joystick_has_hat) {
res.evValue = K_JOY15;
joystick_polls.Append( joystick_poll_t( J_ACTION15, ev.jbutton.state == SDL_PRESSED ? 1 : 0 ) );
} else {
res.evValue = K_JOY_DPAD_DOWN;
joystick_polls.Append( joystick_poll_t( J_DPAD_DOWN, ev.jbutton.state == SDL_PRESSED ? 1 : 0 ) );
}
break;
default:
common->Warning( "Sys_GetEvent(): Unknown joystick button number %i\n", ev.jbutton.button );
return res_none;
}
res.evValue2 = ev.jbutton.state == SDL_PRESSED ? 1 : 0;
return res;
case SDL_JOYHATMOTION:
// If this is not the first hat, ignore this event.
if(ev.jhat.which != 0)
return res_none;
res.evType = SE_KEY;
if(ev.jhat.value & SDL_HAT_UP) {
res.evValue = K_JOY_DPAD_UP;
joystick_polls.Append( joystick_poll_t( J_DPAD_UP, 1 ) );
res.evValue2 = 1;
previous_hat_state = J_DPAD_UP;
}
else if (ev.jhat.value & SDL_HAT_DOWN) {
res.evValue = K_JOY_DPAD_DOWN;
joystick_polls.Append( joystick_poll_t( J_DPAD_DOWN, 1 ) );
res.evValue2 = 1;
previous_hat_state = J_DPAD_DOWN;
}
else if (ev.jhat.value & SDL_HAT_RIGHT) {
res.evValue = K_JOY_DPAD_RIGHT;
joystick_polls.Append( joystick_poll_t( J_DPAD_RIGHT, 1 ) );
res.evValue2 = 1;
previous_hat_state = J_DPAD_RIGHT;
}
else if (ev.jhat.value & SDL_HAT_LEFT) {
res.evValue = K_JOY_DPAD_LEFT;
joystick_polls.Append( joystick_poll_t( J_DPAD_LEFT, 1 ) );
res.evValue2 = 1;
previous_hat_state = J_DPAD_LEFT;
}
// SDL_HAT_CENTERED is defined as 0
else if (ev.jhat.value == SDL_HAT_CENTERED) {
// We need to know the previous state to know which event to send.
if(previous_hat_state == J_DPAD_UP) {
res.evValue = K_JOY_DPAD_UP;
joystick_polls.Append( joystick_poll_t( J_DPAD_UP, 0 ) );
res.evValue2 = 0;
}
else if(previous_hat_state == J_DPAD_DOWN) {
res.evValue = K_JOY_DPAD_DOWN;
joystick_polls.Append( joystick_poll_t( J_DPAD_DOWN, 0 ) );
res.evValue2 = 0;
}
else if(previous_hat_state == J_DPAD_RIGHT) {
res.evValue = K_JOY_DPAD_RIGHT;
joystick_polls.Append( joystick_poll_t( J_DPAD_RIGHT, 0 ) );
res.evValue2 = 0;
}
else if(previous_hat_state == J_DPAD_LEFT) {
res.evValue = K_JOY_DPAD_LEFT;
joystick_polls.Append( joystick_poll_t( J_DPAD_LEFT, 0 ) );
res.evValue2 = 0;
}
else if(previous_hat_state == SDL_HAT_CENTERED) {
common->Warning( "Sys_GetEvent(): SDL_JOYHATMOTION: previous state SDL_HAT_CENTERED repeated!\n" );
return res_none;
}
else {
common->Warning( "Sys_GetEvent(): SDL_JOYHATMOTION: unknown previous hat state %i\n", previous_hat_state );
return res_none;
}
previous_hat_state = SDL_HAT_CENTERED;
}
else {
common->Warning( "Sys_GetEvent(): Unknown SDL_JOYHATMOTION value %i\n", ev.jhat.value );
return res_none;
}
return res;
case SDL_JOYAXISMOTION:
res.evType = SE_JOYSTICK;
// SDL joystick range is: -32768 to 32767, which is what is expected
// in void idUsercmdGenLocal::Joystick( int deviceNum ).
switch( ev.jaxis.axis )
{
int trigger_value;
// LEFT trigger
case 2:
// Convert TRIGGER value from space (-32768, 32767) to (0, 32767)
trigger_value = (ev.jaxis.value + 32768) / 2;
// common->Printf("Sys_GetEvent: LEFT trigger value = %i / converted value = %i\n", ev.jaxis.value, trigger_value);
res.evValue = J_AXIS_LEFT_TRIG;
joystick_polls.Append( joystick_poll_t( J_AXIS_LEFT_TRIG, trigger_value ) );
break;
// Right trigger
case 5:
trigger_value = (ev.jaxis.value + 32768) / 2;
// common->Printf("Sys_GetEvent: RIGHT trigger value = %i / converted value = %i\n", ev.jaxis.value, trigger_value);
res.evValue = J_AXIS_RIGHT_TRIG;
joystick_polls.Append( joystick_poll_t( J_AXIS_RIGHT_TRIG, trigger_value ) );
break;
// LEFT X
case 0:
res.evValue = J_AXIS_LEFT_X;
joystick_polls.Append( joystick_poll_t( J_AXIS_LEFT_X, ev.jaxis.value ) );
break;
// LEFT Y
case 1:
res.evValue = J_AXIS_LEFT_Y;
joystick_polls.Append( joystick_poll_t( J_AXIS_LEFT_Y, ev.jaxis.value ) );
break;
// RIGHT X
case 3:
res.evValue = J_AXIS_RIGHT_X;
joystick_polls.Append( joystick_poll_t( J_AXIS_RIGHT_X, ev.jaxis.value ) );
break;
// RIGHT Y
case 4:
res.evValue = J_AXIS_RIGHT_Y;
joystick_polls.Append( joystick_poll_t( J_AXIS_RIGHT_Y, ev.jaxis.value ) );
break;
default:
common->Warning( "Sys_GetEvent(): Unknown joystick axis number %i\n", ev.jaxis.axis );
return res_none;
}
return res;
// WM0110
case SDL_QUIT:
PushConsoleEvent( "quit" );
return res_none;
case SDL_USEREVENT:
switch( ev.user.code )
{
@ -1036,16 +1363,18 @@ sysEvent_t Sys_GetEvent()
res.evPtrLength = ( intptr_t )ev.user.data1;
res.evPtr = ev.user.data2;
return res;
default:
common->Warning( "unknown user event %u", ev.user.code );
common->Warning( "Sys_GetEvent: unknown SDL_USEREVENT %u", ev.user.code );
return res_none;
}
default:
common->Warning( "unknown event %u", ev.type );
common->Warning( "Sys_GetEvent: unknown SDL event %u", ev.type );
return res_none;
}
}
return res_none;
}
@ -1150,25 +1479,37 @@ int Sys_PollMouseInputEvents( int mouseEvents[MAX_MOUSE_EVENTS][2] )
void Sys_SetRumble( int device, int low, int hi )
{
// TODO;
// SDL 2.0 required (SDL Haptic subsystem)
}
int Sys_PollJoystickInputEvents( int deviceNum )
{
// TODO;
return 0;
int numEvents = joystick_polls.Num();
return numEvents;
}
// This funcion called by void idUsercmdGenLocal::Joystick( int deviceNum ) in
// file UsercmdGen.cpp
// action - must have values belonging to enum sys_jEvents (sys_public.h)
// value - must be 1/0 for button or DPAD pressed/released
// for joystick axes must be in the range (-32769, 32768)
// for joystick trigger must be in the range (0, 32768)
int Sys_ReturnJoystickInputEvent( const int n, int& action, int& value )
{
// TODO;
return 0;
// Get last element of the list and copy into argument references
const joystick_poll_t& mp = joystick_polls[n];
action = mp.action;
value = mp.value;
return 1;
}
// This funcion called by void idUsercmdGenLocal::Joystick( int deviceNum ) in
// file UsercmdGen.cpp
void Sys_EndJoystickInputEvents()
{
// Empty the joystick event container. This is called after
// all joystick events have been read using Sys_ReturnJoystickInputEvent()
joystick_polls.SetNum( 0 );
}