From 5d7b7adb57af828580a0a465e8a87b8dbeda62f9 Mon Sep 17 00:00:00 2001 From: fgsfds Date: Sun, 26 Nov 2023 19:26:07 +0100 Subject: [PATCH] port: expose FirstGamepadNum as checkbox in ext options menu --- port/include/input.h | 3 ++ port/src/input.c | 71 +++++++++++++++++++++++++++++------------- port/src/optionsmenu.c | 21 +++++++++++++ 3 files changed, 73 insertions(+), 22 deletions(-) diff --git a/port/include/input.h b/port/include/input.h index 5e90a6abe..60c7a73ef 100644 --- a/port/include/input.h +++ b/port/include/input.h @@ -107,6 +107,9 @@ void inputControllerSetAxisScale(s32 cidx, s32 stick, s32 axis, f32 value); f32 inputControllerGetAxisDeadzone(s32 cidx, s32 stick, s32 axis); void inputControllerSetAxisDeadzone(s32 cidx, s32 stick, s32 axis, f32 value); +void inputControllerSetFirstIndex(s32 cidx); +s32 inputControllerGetFirstIndex(void); + // vk is a value from the virtkey enum above s32 inputKeyPressed(u32 vk); diff --git a/port/src/input.c b/port/src/input.c index 4c49f7f48..9fe2a67b9 100644 --- a/port/src/input.c +++ b/port/src/input.c @@ -311,6 +311,44 @@ static inline s32 inputControllerGetIndex(SDL_GameController *ctrl) { return -1; } +static inline void inputShutdownAllControllers(void) +{ + for (s32 cidx = 0; cidx < INPUT_MAX_CONTROLLERS; ++cidx) { + if (pads[cidx]) { + SDL_GameControllerClose(pads[cidx]); + pads[cidx] = NULL; + } + } + + connectedMask = 1; // always report first controller as connected +} + +static inline void inputInitAllControllers(void) +{ + SDL_GameControllerUpdate(); + + const s32 numJoys = SDL_NumJoysticks(); + + connectedMask = 1; // always report first controller as connected + + // if firstController is set to 1, keyboard will count as a separate controller on its own, + // so the first connected gamepad will go to player 2 instead of player 1 + for (s32 jidx = 0, cidx = firstController; jidx < numJoys && cidx < INPUT_MAX_CONTROLLERS; ++jidx) { + if (SDL_IsGameController(jidx)) { + pads[cidx] = SDL_GameControllerOpen(jidx); + if (pads[cidx]) { + inputInitController(cidx); + ++cidx; + } + } + } + + const s32 overrideMask = (1 << fakeControllers) - 1; + if (overrideMask) { + connectedMask = overrideMask; + } +} + static int inputEventFilter(void *data, SDL_Event *event) { switch (event->type) { @@ -514,23 +552,7 @@ s32 inputInit(void) SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC); } - SDL_GameControllerUpdate(); - - const s32 numJoys = SDL_NumJoysticks(); - - connectedMask = 1; // always report first controller as connected - - // if firstController is set to 1, keyboard will count as a separate controller on its own, - // so the first connected gamepad will go to player 2 instead of player 1 - for (s32 jidx = 0, cidx = firstController; jidx < numJoys && cidx < INPUT_MAX_CONTROLLERS; ++jidx) { - if (SDL_IsGameController(jidx)) { - pads[cidx] = SDL_GameControllerOpen(jidx); - if (pads[cidx]) { - inputInitController(cidx); - ++cidx; - } - } - } + inputInitAllControllers(); // since the main event loop is elsewhere, we can receive some events we need using a watcher SDL_AddEventWatch(inputEventFilter, NULL); @@ -549,11 +571,6 @@ s32 inputInit(void) inputControllerSetSticksSwapped(i, padsCfg[i].swapSticks); } - const s32 overrideMask = (1 << fakeControllers) - 1; - if (overrideMask) { - connectedMask = overrideMask; - } - inputLoadBinds(); return connectedMask; @@ -795,6 +812,16 @@ void inputControllerSetAxisDeadzone(s32 cidx, s32 stick, s32 axis, f32 value) padsCfg[cidx].deadzone[stick * 2 + axis] = value * 32767.f; } +void inputControllerSetFirstIndex(s32 cidx) { + firstController = cidx; + inputShutdownAllControllers(); + inputInitAllControllers(); +} + +s32 inputControllerGetFirstIndex(void) { + return firstController; +} + void inputKeyBind(s32 idx, u32 ck, s32 bind, u32 vk) { if (idx < 0 || idx >= INPUT_MAX_CONTROLLERS || bind >= INPUT_MAX_BINDS || ck >= CK_TOTAL_COUNT) { diff --git a/port/src/optionsmenu.c b/port/src/optionsmenu.c index bf9b74e8d..46d720066 100644 --- a/port/src/optionsmenu.c +++ b/port/src/optionsmenu.c @@ -520,6 +520,19 @@ static MenuItemHandlerResult menuhandlerSwapSticks(s32 operation, struct menuite return 0; } +static MenuItemHandlerResult menuhandlerFirstController(s32 operation, struct menuitem *item, union handlerdata *data) +{ + switch (operation) { + case MENUOP_GET: + return (inputControllerGetFirstIndex() == g_ExtMenuPlayer); + case MENUOP_SET: + inputControllerSetFirstIndex(g_ExtMenuPlayer); + break; + } + + return 0; +} + struct menuitem g_ExtendedControllerMenuItems[] = { { MENUITEMTYPE_CHECKBOX, @@ -537,6 +550,14 @@ struct menuitem g_ExtendedControllerMenuItems[] = { 0, menuhandlerSwapSticks, }, + { + MENUITEMTYPE_CHECKBOX, + 0, + MENUITEMFLAG_LITERAL_TEXT, + (uintptr_t)"Assign First Controller", + 0, + menuhandlerFirstController, + }, { MENUITEMTYPE_SELECTABLE, 0,