diff --git a/src/d_clisrv.c b/src/d_clisrv.c index 340bab98f..1ea0d21b0 100644 --- a/src/d_clisrv.c +++ b/src/d_clisrv.c @@ -1968,6 +1968,7 @@ static boolean CL_ServerConnectionTicker(const char *tmpsave, tic_t *oldtic, tic { for (; eventtail != eventhead; eventtail = (eventtail+1) & (MAXEVENTS-1)) { + HandleGamepadDeviceEvents(&events[eventtail]); G_MapEventsToControls(&events[eventtail]); } diff --git a/src/d_main.c b/src/d_main.c index 7a69925b5..cf24bdf37 100644 --- a/src/d_main.c +++ b/src/d_main.c @@ -203,7 +203,7 @@ static void HandleGamepadDeviceRemoved(event_t *ev) } /// Respond to added/removed device events, for bookkeeping available gamepads. -static void HandleGamepadDeviceEvents(event_t *ev) +void HandleGamepadDeviceEvents(event_t *ev) { I_Assert(ev != NULL); diff --git a/src/f_finale.c b/src/f_finale.c index 12ffa1d0f..c53650f62 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -26,6 +26,7 @@ #include "w_wad.h" #include "z_zone.h" #include "i_system.h" +#include "i_joy.h" #include "i_threads.h" #include "dehacked.h" #include "g_input.h" @@ -480,40 +481,48 @@ boolean F_IntroResponder(event_t *event) INT32 key = event->data1; // remap virtual keys (mouse & joystick buttons) - switch (key) + if (event->type == ev_gamepad_axis && key >= JOYANALOGS + && (abs(event->data2) > JOYAXISRANGE/2 || abs(event->data3) > JOYAXISRANGE/2)) { - case KEY_MOUSE1: - key = KEY_ENTER; - break; - case KEY_MOUSE1 + 1: - key = KEY_BACKSPACE; - break; - case KEY_JOY1: - case KEY_JOY1 + 2: - key = KEY_ENTER; - break; - case KEY_JOY1 + 3: - key = 'n'; - break; - case KEY_JOY1 + 1: - key = KEY_BACKSPACE; - break; - case KEY_HAT1: - key = KEY_UPARROW; - break; - case KEY_HAT1 + 1: - key = KEY_DOWNARROW; - break; - case KEY_HAT1 + 2: - key = KEY_LEFTARROW; - break; - case KEY_HAT1 + 3: - key = KEY_RIGHTARROW; - break; + key = KEY_ENTER; } + else + { + switch (key) + { + case KEY_MOUSE1: + key = KEY_ENTER; + break; + case KEY_MOUSE1 + 1: + key = KEY_BACKSPACE; + break; + case KEY_JOY1: + case KEY_JOY1 + 2: + key = KEY_ENTER; + break; + case KEY_JOY1 + 3: + key = 'n'; + break; + case KEY_JOY1 + 1: + key = KEY_BACKSPACE; + break; + case KEY_HAT1: + key = KEY_UPARROW; + break; + case KEY_HAT1 + 1: + key = KEY_DOWNARROW; + break; + case KEY_HAT1 + 2: + key = KEY_LEFTARROW; + break; + case KEY_HAT1 + 3: + key = KEY_RIGHTARROW; + break; + } - if (event->type != ev_keydown && key != 301) - return false; + if (event->type != ev_keydown && key != 301) + return false; + } if (key != 27 && key != KEY_ENTER && key != KEY_SPACE && key != KEY_BACKSPACE) return false; diff --git a/src/g_game.c b/src/g_game.c index b2d7b933c..c2f31a035 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -870,12 +870,12 @@ INT16 G_SoftwareClipAimingPitch(INT32 *aiming) static INT32 G_GetValueFromControlTable(INT32 deviceID, INT32 deadzone, INT32 *controltable) { - INT32 i; + INT32 i, failret = NO_BINDS_REACHABLE; if (deviceID <= UNASSIGNED_DEVICE) { // An invalid device can't have any binds! - return 0; + return failret; } for (i = 0; i < MAXINPUTMAPPING; i++) @@ -895,10 +895,12 @@ static INT32 G_GetValueFromControlTable(INT32 deviceID, INT32 deadzone, INT32 *c { return value; } + + failret = 0; } // Not pressed. - return 0; + return failret; } INT32 G_PlayerInputAnalog(UINT8 p, INT32 gc, UINT8 menuPlayers) @@ -911,6 +913,7 @@ INT32 G_PlayerInputAnalog(UINT8 p, INT32 gc, UINT8 menuPlayers) INT32 value = -1; INT32 avail_gamepad_id = 0; INT32 i; + boolean bind_was_reachable = false; if (p >= MAXSPLITSCREENPLAYERS) { @@ -952,6 +955,10 @@ INT32 G_PlayerInputAnalog(UINT8 p, INT32 gc, UINT8 menuPlayers) { return value; } + if (value != NO_BINDS_REACHABLE) + { + bind_was_reachable = true; + } // If you're on gamepad in 1P, and you didn't have a gamepad bind for this, then try your keyboard binds. if (main_player == true && keyboard_player == -1 && deviceID > KEYBOARD_MOUSE_DEVICE) @@ -961,6 +968,10 @@ INT32 G_PlayerInputAnalog(UINT8 p, INT32 gc, UINT8 menuPlayers) { return value; } + if (value != NO_BINDS_REACHABLE) + { + bind_was_reachable = true; + } } if (in_menu == true) @@ -997,15 +1008,22 @@ INT32 G_PlayerInputAnalog(UINT8 p, INT32 gc, UINT8 menuPlayers) { return value; } + if (value != NO_BINDS_REACHABLE) + { + bind_was_reachable = true; + } } } } - // Still nothing bound after everything. Try default gamepad controls. - value = G_GetValueFromControlTable(deviceID, deadzone, &(gamecontroldefault[gc][0])); - if (value > 0) + if (bind_was_reachable == false) { - return value; + // Still nothing bound after everything. Try default gamepad controls. + value = G_GetValueFromControlTable(deviceID, deadzone, &(gamecontroldefault[gc][0])); + if (value > 0) + { + return value; + } } } @@ -1653,7 +1671,11 @@ boolean G_Responder(event_t *ev) if (gameaction == ga_nothing && !demo.quitafterplaying && ((demo.playback && !modeattacking && !demo.title && !multiplayer) || gamestate == GS_TITLESCREEN)) { - if (ev->type == ev_keydown) + if (ev->type == ev_keydown + || (ev->type == ev_gamepad_axis && ev->data1 >= JOYANALOGS + && ((abs(ev->data2) > JOYAXISRANGE/2 + || abs(ev->data3) > JOYAXISRANGE/2)) + )) { M_StartControlPanel(); return true; diff --git a/src/g_input.c b/src/g_input.c index bdb6bbb9a..c920b4da7 100644 --- a/src/g_input.c +++ b/src/g_input.c @@ -362,6 +362,7 @@ static INT32 AssignDeviceToFirstUnassignedPlayer(INT32 device) void G_MapEventsToControls(event_t *ev) { INT32 i; + INT32 *DeviceGameKeyDownArray; if (ev->device >= 0) { @@ -383,12 +384,17 @@ void G_MapEventsToControls(event_t *ev) return; } + DeviceGameKeyDownArray = G_GetDeviceGameKeyDownArray(ev->device); + + if (!DeviceGameKeyDownArray) + return; + switch (ev->type) { case ev_keydown: if (ev->data1 < NUMINPUTS) { - G_GetDeviceGameKeyDownArray(ev->device)[ev->data1] = JOYAXISRANGE; + DeviceGameKeyDownArray[ev->data1] = JOYAXISRANGE; if (AutomaticControllerReassignmentIsAllowed(ev->device)) { @@ -410,7 +416,7 @@ void G_MapEventsToControls(event_t *ev) case ev_keyup: if (ev->data1 < NUMINPUTS) { - G_GetDeviceGameKeyDownArray(ev->device)[ev->data1] = 0; + DeviceGameKeyDownArray[ev->data1] = 0; } #ifdef PARANOIA else @@ -425,28 +431,28 @@ void G_MapEventsToControls(event_t *ev) if (ev->data2 < 0) { // Left - G_GetDeviceGameKeyDownArray(ev->device)[KEY_MOUSEMOVE + 2] = abs(ev->data2); - G_GetDeviceGameKeyDownArray(ev->device)[KEY_MOUSEMOVE + 3] = 0; + DeviceGameKeyDownArray[KEY_MOUSEMOVE + 2] = abs(ev->data2); + DeviceGameKeyDownArray[KEY_MOUSEMOVE + 3] = 0; } else { // Right - G_GetDeviceGameKeyDownArray(ev->device)[KEY_MOUSEMOVE + 2] = 0; - G_GetDeviceGameKeyDownArray(ev->device)[KEY_MOUSEMOVE + 3] = abs(ev->data2); + DeviceGameKeyDownArray[KEY_MOUSEMOVE + 2] = 0; + DeviceGameKeyDownArray[KEY_MOUSEMOVE + 3] = abs(ev->data2); } // Y axis if (ev->data3 < 0) { // Up - G_GetDeviceGameKeyDownArray(ev->device)[KEY_MOUSEMOVE] = abs(ev->data3); - G_GetDeviceGameKeyDownArray(ev->device)[KEY_MOUSEMOVE + 1] = 0; + DeviceGameKeyDownArray[KEY_MOUSEMOVE] = abs(ev->data3); + DeviceGameKeyDownArray[KEY_MOUSEMOVE + 1] = 0; } else { // Down - G_GetDeviceGameKeyDownArray(ev->device)[KEY_MOUSEMOVE] = 0; - G_GetDeviceGameKeyDownArray(ev->device)[KEY_MOUSEMOVE + 1] = abs(ev->data3); + DeviceGameKeyDownArray[KEY_MOUSEMOVE] = 0; + DeviceGameKeyDownArray[KEY_MOUSEMOVE + 1] = abs(ev->data3); } break; @@ -466,14 +472,24 @@ void G_MapEventsToControls(event_t *ev) // The trigger axes are handled specially. i -= JOYANALOGS; + if (AutomaticControllerReassignmentIsAllowed(ev->device) + && (abs(ev->data2) > JOYAXISRANGE/2 || abs(ev->data3) > JOYAXISRANGE/2)) + { + INT32 assigned = AssignDeviceToFirstUnassignedPlayer(ev->device); + if (assigned >= 0) + { + CONS_Alert(CONS_NOTICE, "Player %d device was reassigned\n", assigned + 1); + } + } + if (ev->data2 != INT32_MAX) { - G_GetDeviceGameKeyDownArray(ev->device)[KEY_AXIS1 + (JOYANALOGS * 4) + (i * 2)] = max(0, ev->data2); + DeviceGameKeyDownArray[KEY_AXIS1 + (JOYANALOGS * 4) + (i * 2)] = max(0, ev->data2); } if (ev->data3 != INT32_MAX) { - G_GetDeviceGameKeyDownArray(ev->device)[KEY_AXIS1 + (JOYANALOGS * 4) + (i * 2) + 1] = max(0, ev->data3); + DeviceGameKeyDownArray[KEY_AXIS1 + (JOYANALOGS * 4) + (i * 2) + 1] = max(0, ev->data3); } } else @@ -484,14 +500,14 @@ void G_MapEventsToControls(event_t *ev) if (ev->data2 < 0) { // Left - G_GetDeviceGameKeyDownArray(ev->device)[KEY_AXIS1 + (i * 4)] = abs(ev->data2); - G_GetDeviceGameKeyDownArray(ev->device)[KEY_AXIS1 + (i * 4) + 1] = 0; + DeviceGameKeyDownArray[KEY_AXIS1 + (i * 4)] = abs(ev->data2); + DeviceGameKeyDownArray[KEY_AXIS1 + (i * 4) + 1] = 0; } else { // Right - G_GetDeviceGameKeyDownArray(ev->device)[KEY_AXIS1 + (i * 4)] = 0; - G_GetDeviceGameKeyDownArray(ev->device)[KEY_AXIS1 + (i * 4) + 1] = abs(ev->data2); + DeviceGameKeyDownArray[KEY_AXIS1 + (i * 4)] = 0; + DeviceGameKeyDownArray[KEY_AXIS1 + (i * 4) + 1] = abs(ev->data2); } } @@ -500,14 +516,14 @@ void G_MapEventsToControls(event_t *ev) if (ev->data3 < 0) { // Up - G_GetDeviceGameKeyDownArray(ev->device)[KEY_AXIS1 + (i * 4) + 2] = abs(ev->data3); - G_GetDeviceGameKeyDownArray(ev->device)[KEY_AXIS1 + (i * 4) + 3] = 0; + DeviceGameKeyDownArray[KEY_AXIS1 + (i * 4) + 2] = abs(ev->data3); + DeviceGameKeyDownArray[KEY_AXIS1 + (i * 4) + 3] = 0; } else { // Down - G_GetDeviceGameKeyDownArray(ev->device)[KEY_AXIS1 + (i * 4) + 2] = 0; - G_GetDeviceGameKeyDownArray(ev->device)[KEY_AXIS1 + (i * 4) + 3] = abs(ev->data3); + DeviceGameKeyDownArray[KEY_AXIS1 + (i * 4) + 2] = 0; + DeviceGameKeyDownArray[KEY_AXIS1 + (i * 4) + 3] = abs(ev->data3); } } } @@ -809,20 +825,20 @@ INT32 G_KeyStringtoNum(const char *keystr) void G_DefineDefaultControls(void) { - // These defaults are bad & temporary. + // These defaults are less bad than they used to be. // Keyboard controls gamecontroldefault[gc_up ][0] = KEY_UPARROW; gamecontroldefault[gc_down ][0] = KEY_DOWNARROW; gamecontroldefault[gc_left ][0] = KEY_LEFTARROW; gamecontroldefault[gc_right ][0] = KEY_RIGHTARROW; - gamecontroldefault[gc_a ][0] = 'z'; - gamecontroldefault[gc_b ][0] = 'x'; - gamecontroldefault[gc_c ][0] = 'c'; - gamecontroldefault[gc_x ][0] = 'a'; - gamecontroldefault[gc_y ][0] = 's'; - gamecontroldefault[gc_z ][0] = 'd'; - gamecontroldefault[gc_l ][0] = 'q'; - gamecontroldefault[gc_r ][0] = 'e'; + gamecontroldefault[gc_a ][0] = 'f'; + gamecontroldefault[gc_b ][0] = 'a'; + gamecontroldefault[gc_c ][0] = 'v'; + gamecontroldefault[gc_x ][0] = 's'; + gamecontroldefault[gc_y ][0] = 'x'; + gamecontroldefault[gc_z ][0] = 'c'; + gamecontroldefault[gc_l ][0] = KEY_SPACE; + gamecontroldefault[gc_r ][0] = 'd'; gamecontroldefault[gc_start ][0] = KEY_ESCAPE; gamecontroldefault[gc_rankings][0] = KEY_TAB; @@ -832,20 +848,24 @@ void G_DefineDefaultControls(void) gamecontroldefault[gc_left ][1] = KEY_HAT1+2; // D-Pad Left gamecontroldefault[gc_right][1] = KEY_HAT1+3; // D-Pad Right gamecontroldefault[gc_a ][1] = KEY_JOY1+0; // A - gamecontroldefault[gc_b ][1] = KEY_JOY1+2; // X + gamecontroldefault[gc_b ][1] = KEY_JOY1+1; // B gamecontroldefault[gc_c ][1] = KEY_JOY1+3; // Y - gamecontroldefault[gc_x ][1] = KEY_JOY1+1; // B - gamecontroldefault[gc_y ][1] = KEY_JOY1+6; - gamecontroldefault[gc_z ][1] = KEY_JOY1+8; - gamecontroldefault[gc_l ][1] = KEY_JOY1+4; // LB - gamecontroldefault[gc_r ][1] = KEY_JOY1+5; // RB - gamecontroldefault[gc_start][1] = KEY_JOY1+7; // Start + gamecontroldefault[gc_x ][1] = KEY_JOY1+2; // X + gamecontroldefault[gc_y ][1] = KEY_JOY1+9; // LB + gamecontroldefault[gc_z ][1] = KEY_JOY1+10; // RB + gamecontroldefault[gc_l ][1] = KEY_AXIS1+8; // LT + gamecontroldefault[gc_r ][1] = KEY_AXIS1+9; // RT + gamecontroldefault[gc_start][1] = KEY_JOY1+6; // Start gamecontroldefault[gc_up ][2] = KEY_AXIS1+2; // Axis Y- gamecontroldefault[gc_down ][2] = KEY_AXIS1+3; // Axis Y+ gamecontroldefault[gc_left ][2] = KEY_AXIS1+0; // Axis X- gamecontroldefault[gc_right][2] = KEY_AXIS1+1; // Axis X+ + #ifdef DEVELOP + gamecontroldefault[gc_console][0] = '`'; + #endif + // Menu reserved controls menucontrolreserved[gc_up ][0] = KEY_UPARROW; menucontrolreserved[gc_down ][0] = KEY_DOWNARROW; diff --git a/src/g_input.h b/src/g_input.h index 610c3afdc..70a6b4e73 100644 --- a/src/g_input.h +++ b/src/g_input.h @@ -109,6 +109,7 @@ extern consvar_t cv_controlperkey; #define MAXDEVICES (MAXGAMEPADS + 1) // Gamepads + keyboard & mouse #define KEYBOARD_MOUSE_DEVICE (0) #define UNASSIGNED_DEVICE (-1) +#define NO_BINDS_REACHABLE (-1) extern INT32 gamekeydown[MAXDEVICES][NUMINPUTS]; // several key codes (or virtual key) per game control @@ -165,6 +166,8 @@ boolean G_IsDeviceResponding(INT32 device); void G_SetDeviceResponding(INT32 device, boolean responding); void G_ResetAllDeviceResponding(void); +void HandleGamepadDeviceEvents(event_t *ev); + // remaps the input event to a game control. void G_MapEventsToControls(event_t *ev); diff --git a/src/sdl/i_system.c b/src/sdl/i_system.c index 23189b741..852b8c8c5 100644 --- a/src/sdl/i_system.c +++ b/src/sdl/i_system.c @@ -871,10 +871,15 @@ INT32 I_GetKey (void) event_t *ev; INT32 rc = 0; + G_ResetAllDeviceResponding(); + // return the first keypress from the event queue for (; eventtail != eventhead; eventtail = (eventtail+1)&(MAXEVENTS-1)) { ev = &events[eventtail]; + + HandleGamepadDeviceEvents(ev); + if (ev->type == ev_keydown || ev->type == ev_console) { rc = ev->data1; diff --git a/src/sdl12/i_system.c b/src/sdl12/i_system.c index b388a9bf5..7c0abb998 100644 --- a/src/sdl12/i_system.c +++ b/src/sdl12/i_system.c @@ -910,10 +910,15 @@ INT32 I_GetKey (void) event_t *ev; INT32 rc = 0; + G_ResetAllDeviceResponding(); + // return the first keypress from the event queue for (; eventtail != eventhead; eventtail = (eventtail+1)&(MAXEVENTS-1)) { ev = &events[eventtail]; + + HandleGamepadDeviceEvents(ev); + if (ev->type == ev_keydown || ev->type == ev_console) { rc = ev->data1; diff --git a/src/win32ce/win_sys.c b/src/win32ce/win_sys.c index 091171b52..b261a7a50 100644 --- a/src/win32ce/win_sys.c +++ b/src/win32ce/win_sys.c @@ -3067,9 +3067,12 @@ INT32 I_GetKey(void) { event_t *ev; + G_ResetAllDeviceResponding(); + if (eventtail != eventhead) { ev = &events[eventtail]; + HandleGamepadDeviceEvents(ev); eventtail = (eventtail+1) & (MAXEVENTS-1); if (ev->type == ev_keydown || ev->type == ev_console) return ev->data1;