diff --git a/.gitignore b/.gitignore index c3130ebf..e816aad6 100644 --- a/.gitignore +++ b/.gitignore @@ -52,6 +52,7 @@ *.swp .vscode/* .idea/* +*.code-workspace # General project-specific ignores doxygen/doxygen/* diff --git a/src/pc/configfile.c b/src/pc/configfile.c index 0a6fd784..11cb6905 100644 --- a/src/pc/configfile.c +++ b/src/pc/configfile.c @@ -140,6 +140,8 @@ unsigned int configDrawDistance = 5; bool configDisablePopups = 0; bool configDisableDownloadedModels = 0; unsigned int configInterpolationMode = 1; +unsigned int configGamepadNumber = 0; +bool configBackgroundGamepad = 1; static const struct ConfigOption options[] = { {.name = "fullscreen", .type = CONFIG_TYPE_BOOL, .boolValue = &configWindow.fullscreen}, @@ -221,7 +223,9 @@ static const struct ConfigOption options[] = { {.name = "share_lives", .type = CONFIG_TYPE_BOOL , .boolValue = &configShareLives}, {.name = "disable_popups", .type = CONFIG_TYPE_BOOL , .boolValue = &configDisablePopups}, {.name = "disable_downloaded_models", .type = CONFIG_TYPE_BOOL , .boolValue = &configDisableDownloadedModels}, - {.name = "interpolation_mode", .type = CONFIG_TYPE_UINT , .uintValue = &configInterpolationMode} + {.name = "interpolation_mode", .type = CONFIG_TYPE_UINT , .uintValue = &configInterpolationMode}, + {.name = "gamepad_number", .type = CONFIG_TYPE_UINT , .uintValue = &configGamepadNumber}, + {.name = "background_gamepad", .type = CONFIG_TYPE_UINT , .boolValue = &configBackgroundGamepad} }; // FunctionConfigOption functions diff --git a/src/pc/configfile.h b/src/pc/configfile.h index fa7e3762..8ad9fff0 100644 --- a/src/pc/configfile.h +++ b/src/pc/configfile.h @@ -52,6 +52,8 @@ extern unsigned int configKeyDLeft[]; extern unsigned int configKeyDRight[]; extern unsigned int configStickDeadzone; extern unsigned int configRumbleStrength; +extern unsigned int configGamepadNumber; +extern bool configBackgroundGamepad; #ifdef EXTERNAL_DATA extern bool configPrecacheRes; #endif diff --git a/src/pc/controller/controller_sdl2.c b/src/pc/controller/controller_sdl2.c index c7eb3feb..f7417c45 100644 --- a/src/pc/controller/controller_sdl2.c +++ b/src/pc/controller/controller_sdl2.c @@ -52,6 +52,7 @@ static bool joy_buttons[MAX_JOYBUTTONS] = { false }; static u32 mouse_buttons = 0; static u32 last_mouse = VK_INVALID; static u32 last_joybutton = VK_INVALID; +static u32 last_gamepad = 0; static inline void controller_add_binds(const u32 mask, const u32 *btns) { for (u32 i = 0; i < MAX_BINDS; ++i) { @@ -98,6 +99,11 @@ static void controller_sdl_bind(void) { } static void controller_sdl_init(void) { + // Allows game to be controlled by gamepad when not in focus + if (configBackgroundGamepad) { + SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1"); + } + if (SDL_Init(SDL_INIT_GAMECONTROLLER | SDL_INIT_EVENTS) != 0) { fprintf(stderr, "SDL init error: %s\n", SDL_GetError()); return; @@ -216,21 +222,22 @@ static void controller_sdl_read(OSContPad *pad) { sdl_haptic = NULL; } - if (sdl_cntrl == NULL) { - for (int i = 0; i < SDL_NumJoysticks(); i++) { - if (SDL_IsGameController(i)) { - sdl_cntrl = SDL_GameControllerOpen(i); - if (sdl_cntrl != NULL) { - sdl_haptic = controller_sdl_init_haptics(i); - break; - } + if (sdl_cntrl == NULL || last_gamepad != configGamepadNumber) { + if (SDL_IsGameController(configGamepadNumber)) { + sdl_cntrl = SDL_GameControllerOpen(configGamepadNumber); + if (sdl_cntrl != NULL) { + sdl_haptic = controller_sdl_init_haptics(configGamepadNumber); + last_gamepad = configGamepadNumber; } - } - if (sdl_cntrl == NULL) { + if (sdl_cntrl == NULL) { + return; + } + } else { + sdl_cntrl = NULL; return; } } - + int16_t leftx = SDL_GameControllerGetAxis(sdl_cntrl, SDL_CONTROLLER_AXIS_LEFTX); int16_t lefty = SDL_GameControllerGetAxis(sdl_cntrl, SDL_CONTROLLER_AXIS_LEFTY); int16_t rightx = SDL_GameControllerGetAxis(sdl_cntrl, SDL_CONTROLLER_AXIS_RIGHTX); diff --git a/src/pc/djui/djui_panel_controls.c b/src/pc/djui/djui_panel_controls.c index 13603ae6..739281f4 100644 --- a/src/pc/djui/djui_panel_controls.c +++ b/src/pc/djui/djui_panel_controls.c @@ -2,13 +2,14 @@ #include "src/pc/utils/misc.h" #include "src/pc/configfile.h" #include "src/pc/controller/controller_api.h" +#include "src/pc/controller/controller_sdl.h" void djui_panel_controls_value_change(UNUSED struct DjuiBase* caller) { controller_reconfigure(); } void djui_panel_controls_create(struct DjuiBase* caller) { - f32 bodyHeight = 16 * 5 + 32 * 2 + 64 * 3; + f32 bodyHeight = 16 * 6 + 32 * 2 + 64 * 4; struct DjuiBase* defaultBase = NULL; struct DjuiThreePanel* panel = djui_panel_menu_create(bodyHeight, "\\#ff0800\\C\\#1be700\\O\\#00b3ff\\N\\#ffef00\\T\\#ff0800\\R\\#1be700\\O\\#00b3ff\\L\\#ffef00\\S"); @@ -25,6 +26,33 @@ void djui_panel_controls_create(struct DjuiBase* caller) { djui_base_set_size(&button2->base, 1.0f, 64); djui_interactable_hook_click(&button2->base, djui_panel_controls_extra_create); + struct DjuiCheckbox* checkboxGB = djui_checkbox_create(&body->base, "Background Gamepad (must restart)", &configBackgroundGamepad); + djui_base_set_size_type(&checkboxGB->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE); + djui_base_set_size(&checkboxGB->base, 1.0f, 32); + // djui_interactable_hook_value_change(&checkboxGB->base, djui_panel_display_uncapped_change); + + int numJoys = SDL_NumJoysticks(); + if (numJoys == 0) { numJoys = 1; } + if (numJoys > 100) { numJoys = 100; } + int strSize = numJoys * 2; + if (numJoys > 10) { + strSize += (numJoys - 10); + } + char* gamepadChoices[numJoys]; + char gamepadChoicesLong[strSize]; + for (int i = 0; i < numJoys; i++) { + int index = i * 2; + if (i > 9) { + index += (i - 9); + } + sprintf(&gamepadChoicesLong[index], "%d\0", i); + gamepadChoices[i] = &gamepadChoicesLong[index]; + } + // char* gamepadChoices[16] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15"}; + struct DjuiSelectionbox* selectionboxGamepad = djui_selectionbox_create(&body->base, "Gamepad", gamepadChoices, numJoys, &configGamepadNumber); + djui_base_set_size_type(&selectionboxGamepad->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE); + djui_base_set_size(&selectionboxGamepad->base, 1.0f, 32); + struct DjuiSlider* slider1 = djui_slider_create(&body->base, "Deadzone", &configStickDeadzone, 0, 100); djui_base_set_size_type(&slider1->base, DJUI_SVT_RELATIVE, DJUI_SVT_ABSOLUTE); djui_base_set_size(&slider1->base, 1.0f, 32);