Add gamepad number, background options (#122)

Added two options, one which lets user choose which gamepad to use, and one
which allows game to be played with gamepad while in the background.

These two features together allow for "splitscreen" (sort of) multiplayer by
starting up instances and joining them together and selecting different
gamepads for each one.

Gamepad choices are 0-7. If a number is chosen that does not correspond to a
gamepad, the previous gamepad (last number you were on this session that had
a working gamepad) is used.
This commit is contained in:
HunterHeard 2022-06-05 21:16:24 -05:00 committed by GitHub
parent e0e1d2e1a8
commit de60a0ae44
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 55 additions and 13 deletions

1
.gitignore vendored
View file

@ -52,6 +52,7 @@
*.swp
.vscode/*
.idea/*
*.code-workspace
# General project-specific ignores
doxygen/doxygen/*

View file

@ -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

View file

@ -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

View file

@ -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,17 +222,18 @@ 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;
}
}

View file

@ -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);