[GTK3] Accept input from all connected controllers
Rumble will be used on the most recently used controller.
This commit is contained in:
parent
3fe57f976c
commit
8c3154a061
7
Makefile
7
Makefile
@ -126,6 +126,13 @@ ifeq ($(SDL_AUDIO_DRIVER),sdl)
|
|||||||
GTK_OPTIONS += -DUSE_SDL_AUDIO
|
GTK_OPTIONS += -DUSE_SDL_AUDIO
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# Use SDL’s haptic feedback subsystem by default, although
|
||||||
|
# some controllers only work with the simpler SDL_GameControllerRumble / SDL_JoystickRumble,
|
||||||
|
# but SDL’s WUP-028 (Wii U GameCube Controller Adapter) driver rumble handling seems to make the adapter lock up after a while.
|
||||||
|
ifneq ($(USE_SDL_HAPTIC),0)
|
||||||
|
GTK_OPTIONS += -DUSE_SDL_HAPTIC
|
||||||
|
endif
|
||||||
|
|
||||||
GTK3_CFLAGS := $(shell $(PKG_CONFIG) --cflags gio-2.0 gtk+-3.0 epoxy) $(GTK_OPTIONS)
|
GTK3_CFLAGS := $(shell $(PKG_CONFIG) --cflags gio-2.0 gtk+-3.0 epoxy) $(GTK_OPTIONS)
|
||||||
GTK3_LDFLAGS := $(shell $(PKG_CONFIG) --libs gio-2.0 gtk+-3.0 epoxy)
|
GTK3_LDFLAGS := $(shell $(PKG_CONFIG) --libs gio-2.0 gtk+-3.0 epoxy)
|
||||||
|
|
||||||
|
111
gtk3/main.c
111
gtk3/main.c
@ -126,6 +126,7 @@ typedef struct GuiData {
|
|||||||
SDL_Haptic *haptic;
|
SDL_Haptic *haptic;
|
||||||
} *controllers;
|
} *controllers;
|
||||||
unsigned controller_count;
|
unsigned controller_count;
|
||||||
|
struct Controller_t *last_used_controller; // Used for rumble
|
||||||
} GuiData;
|
} GuiData;
|
||||||
|
|
||||||
// Initialize the GuiData
|
// Initialize the GuiData
|
||||||
@ -448,18 +449,20 @@ static gboolean init_controllers(void) {
|
|||||||
g_debug("Compiled against SDL version %d.%d.%d", compiled.major, compiled.minor, compiled.patch);
|
g_debug("Compiled against SDL version %d.%d.%d", compiled.major, compiled.minor, compiled.patch);
|
||||||
g_debug("Linked against SDL version %d.%d.%d", linked.major, linked.minor, linked.patch);
|
g_debug("Linked against SDL version %d.%d.%d", linked.major, linked.minor, linked.patch);
|
||||||
|
|
||||||
|
g_debug("Initializing game controllers");
|
||||||
if (SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) < 0) {
|
if (SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) < 0) {
|
||||||
g_warning("Failed to initialize game controller support: %s", SDL_GetError());
|
g_warning("Failed to initialize game controller support: %s", SDL_GetError());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef USE_SDL_HAPTIC
|
||||||
|
g_debug("Initializing haptic feedback");
|
||||||
if (SDL_InitSubSystem(SDL_INIT_HAPTIC) < 0) {
|
if (SDL_InitSubSystem(SDL_INIT_HAPTIC) < 0) {
|
||||||
g_warning("Failed to initialize haptic feedback support: %s", SDL_GetError());
|
g_warning("Failed to initialize haptic feedback support: %s", SDL_GetError());
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
SDL_QuitSubSystem(SDL_INIT_EVENTS);
|
g_debug("Loading custom game controller database");
|
||||||
SDL_GameControllerEventState(SDL_ENABLE);
|
|
||||||
|
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
GBytes *db_f = g_resources_lookup_data(RESOURCE_PREFIX "gamecontrollerdb.txt", G_RESOURCE_LOOKUP_FLAGS_NONE, &error);
|
GBytes *db_f = g_resources_lookup_data(RESOURCE_PREFIX "gamecontrollerdb.txt", G_RESOURCE_LOOKUP_FLAGS_NONE, &error);
|
||||||
|
|
||||||
@ -482,7 +485,6 @@ static gboolean init_controllers(void) {
|
|||||||
// In the “worst” case all joysticks are valid game controllers
|
// In the “worst” case all joysticks are valid game controllers
|
||||||
gui_data.controllers = g_malloc0(sizeof(struct Controller_t) * SDL_NumJoysticks());
|
gui_data.controllers = g_malloc0(sizeof(struct Controller_t) * SDL_NumJoysticks());
|
||||||
|
|
||||||
// Open the first available controller
|
|
||||||
for (int i = 0; i < SDL_NumJoysticks(); ++i) {
|
for (int i = 0; i < SDL_NumJoysticks(); ++i) {
|
||||||
if (SDL_IsGameController(i)) {
|
if (SDL_IsGameController(i)) {
|
||||||
struct Controller_t *s = &gui_data.controllers[i];
|
struct Controller_t *s = &gui_data.controllers[i];
|
||||||
@ -492,17 +494,29 @@ static gboolean init_controllers(void) {
|
|||||||
SDL_Joystick *joystick = SDL_GameControllerGetJoystick(s->controller);
|
SDL_Joystick *joystick = SDL_GameControllerGetJoystick(s->controller);
|
||||||
SDL_JoystickPowerLevel power_level = SDL_JoystickCurrentPowerLevel(joystick);
|
SDL_JoystickPowerLevel power_level = SDL_JoystickCurrentPowerLevel(joystick);
|
||||||
|
|
||||||
|
#ifdef USE_SDL_HAPTIC
|
||||||
|
if (SDL_JoystickIsHaptic(joystick)) {
|
||||||
s->haptic = SDL_HapticOpenFromJoystick(joystick);
|
s->haptic = SDL_HapticOpenFromJoystick(joystick);
|
||||||
|
|
||||||
if (s->haptic) {
|
if (s->haptic && SDL_HapticRumbleSupported(s->haptic)) {
|
||||||
SDL_HapticRumbleInit(s->haptic);
|
SDL_HapticRumbleInit(s->haptic);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
if (s->haptic == NULL) {
|
||||||
|
g_warning("%s", SDL_GetError());
|
||||||
|
}
|
||||||
|
|
||||||
|
SDL_HapticClose(s->haptic);
|
||||||
|
s->haptic = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
char guid_str[33];
|
char guid_str[33];
|
||||||
SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
|
SDL_JoystickGUID guid = SDL_JoystickGetGUID(joystick);
|
||||||
SDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str));
|
SDL_JoystickGetGUIDString(guid, guid_str, sizeof(guid_str));
|
||||||
|
|
||||||
g_message("Controller #%u (%s): %s; Power level: %s", i, guid_str, SDL_GameControllerName(s->controller), get_sdl_joystick_power_level_name(power_level));
|
g_message("Controller #%u (%s): %s; Haptic Feedback: %d; Power level: %s; Player index: %u; Instance ID: %u", i, guid_str, SDL_GameControllerName(s->controller), s->haptic != NULL, get_sdl_joystick_power_level_name(power_level), SDL_JoystickGetPlayerIndex(joystick), SDL_JoystickInstanceID(joystick));
|
||||||
gui_data.controller_count++;
|
gui_data.controller_count++;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -522,12 +536,12 @@ static gboolean init_audio(void) {
|
|||||||
gui_data.audio_initialized = false;
|
gui_data.audio_initialized = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_SDL_AUDIO
|
#ifdef USE_SDL_AUDIO
|
||||||
if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
|
if (SDL_InitSubSystem(SDL_INIT_AUDIO) < 0) {
|
||||||
g_warning("Failed to initialize audio: %s", SDL_GetError());
|
g_warning("Failed to initialize audio: %s", SDL_GetError());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
GB_audio_init(gui_data.sample_rate);
|
GB_audio_init(gui_data.sample_rate);
|
||||||
GB_set_sample_rate(&gb, GB_audio_get_sample_rate());
|
GB_set_sample_rate(&gb, GB_audio_get_sample_rate());
|
||||||
@ -582,11 +596,11 @@ static void gb_audio_callback(GB_gameboy_t *gb, GB_sample_t *sample) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void rumble_callback(GB_gameboy_t *gb, double amp) {
|
static void rumble_callback(GB_gameboy_t *gb, double amp) {
|
||||||
if (gui_data.controllers == NULL || gui_data.controller_count == 0) return;
|
if (!gui_data.controllers || gui_data.controller_count == 0 || !gui_data.last_used_controller) return;
|
||||||
|
|
||||||
// TODO
|
struct Controller_t *s = gui_data.last_used_controller;
|
||||||
struct Controller_t *s = &gui_data.controllers[0];
|
|
||||||
|
|
||||||
|
#ifdef USE_SDL_HAPTIC
|
||||||
if (s->haptic) {
|
if (s->haptic) {
|
||||||
if (amp > 0.0) {
|
if (amp > 0.0) {
|
||||||
SDL_HapticRumblePlay(s->haptic, amp, 100.0);
|
SDL_HapticRumblePlay(s->haptic, amp, 100.0);
|
||||||
@ -595,6 +609,15 @@ static void rumble_callback(GB_gameboy_t *gb, double amp) {
|
|||||||
SDL_HapticRumbleStop(s->haptic);
|
SDL_HapticRumbleStop(s->haptic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
if (amp == 0.0) {
|
||||||
|
SDL_GameControllerRumble(s->controller, 0, 0, 0);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Uint16 intensity = (float) 0xFFFF * amp;
|
||||||
|
SDL_GameControllerRumble(s->controller, intensity, intensity, 100);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clear_sidebar(void) {
|
static void clear_sidebar(void) {
|
||||||
@ -1229,32 +1252,69 @@ static void handle_events(GB_gameboy_t *gb) {
|
|||||||
|
|
||||||
uint8_t controller_state = 0;
|
uint8_t controller_state = 0;
|
||||||
|
|
||||||
if (gui_data.controllers && gui_data.controllers[0].controller) {
|
for (unsigned i = 0; i < gui_data.controller_count; i++) {
|
||||||
int16_t x_axis = SDL_GameControllerGetAxis(gui_data.controllers[0].controller, SDL_CONTROLLER_AXIS_LEFTX);
|
struct Controller_t *s = &gui_data.controllers[i];
|
||||||
int16_t y_axis = SDL_GameControllerGetAxis(gui_data.controllers[0].controller, SDL_CONTROLLER_AXIS_LEFTY);
|
|
||||||
|
int16_t x_axis = SDL_GameControllerGetAxis(s->controller, SDL_CONTROLLER_AXIS_LEFTX);
|
||||||
|
int16_t y_axis = SDL_GameControllerGetAxis(s->controller, SDL_CONTROLLER_AXIS_LEFTY);
|
||||||
|
|
||||||
if (x_axis >= JOYSTICK_HIGH) {
|
if (x_axis >= JOYSTICK_HIGH) {
|
||||||
|
gui_data.last_used_controller = s;
|
||||||
controller_state |= BUTTON_MASK_RIGHT;
|
controller_state |= BUTTON_MASK_RIGHT;
|
||||||
}
|
}
|
||||||
else if (x_axis <= -JOYSTICK_HIGH) {
|
else if (x_axis <= -JOYSTICK_HIGH) {
|
||||||
|
gui_data.last_used_controller = s;
|
||||||
controller_state |= BUTTON_MASK_LEFT;
|
controller_state |= BUTTON_MASK_LEFT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (y_axis >= JOYSTICK_HIGH) {
|
if (y_axis >= JOYSTICK_HIGH) {
|
||||||
|
gui_data.last_used_controller = s;
|
||||||
controller_state |= BUTTON_MASK_DOWN;
|
controller_state |= BUTTON_MASK_DOWN;
|
||||||
}
|
}
|
||||||
else if (y_axis <= -JOYSTICK_HIGH) {
|
else if (y_axis <= -JOYSTICK_HIGH) {
|
||||||
|
gui_data.last_used_controller = s;
|
||||||
controller_state |= BUTTON_MASK_UP;
|
controller_state |= BUTTON_MASK_UP;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (SDL_GameControllerGetButton(gui_data.controllers[0].controller, SDL_CONTROLLER_BUTTON_DPAD_RIGHT)) controller_state |= BUTTON_MASK_RIGHT;
|
if (SDL_GameControllerGetButton(s->controller, SDL_CONTROLLER_BUTTON_DPAD_RIGHT)) {
|
||||||
if (SDL_GameControllerGetButton(gui_data.controllers[0].controller, SDL_CONTROLLER_BUTTON_DPAD_LEFT)) controller_state |= BUTTON_MASK_LEFT;
|
gui_data.last_used_controller = s;
|
||||||
if (SDL_GameControllerGetButton(gui_data.controllers[0].controller, SDL_CONTROLLER_BUTTON_DPAD_UP)) controller_state |= BUTTON_MASK_UP;
|
controller_state |= BUTTON_MASK_RIGHT;
|
||||||
if (SDL_GameControllerGetButton(gui_data.controllers[0].controller, SDL_CONTROLLER_BUTTON_DPAD_DOWN)) controller_state |= BUTTON_MASK_DOWN;
|
}
|
||||||
if (SDL_GameControllerGetButton(gui_data.controllers[0].controller, SDL_CONTROLLER_BUTTON_A)) controller_state |= BUTTON_MASK_A;
|
|
||||||
if (SDL_GameControllerGetButton(gui_data.controllers[0].controller, SDL_CONTROLLER_BUTTON_B)) controller_state |= BUTTON_MASK_B;
|
if (SDL_GameControllerGetButton(s->controller, SDL_CONTROLLER_BUTTON_DPAD_LEFT)) {
|
||||||
if (SDL_GameControllerGetButton(gui_data.controllers[0].controller, SDL_CONTROLLER_BUTTON_BACK)) controller_state |= BUTTON_MASK_SELECT;
|
gui_data.last_used_controller = s;
|
||||||
if (SDL_GameControllerGetButton(gui_data.controllers[0].controller, SDL_CONTROLLER_BUTTON_START)) controller_state |= BUTTON_MASK_START;
|
controller_state |= BUTTON_MASK_LEFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SDL_GameControllerGetButton(s->controller, SDL_CONTROLLER_BUTTON_DPAD_UP)) {
|
||||||
|
gui_data.last_used_controller = s;
|
||||||
|
controller_state |= BUTTON_MASK_UP;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SDL_GameControllerGetButton(s->controller, SDL_CONTROLLER_BUTTON_DPAD_DOWN)) {
|
||||||
|
gui_data.last_used_controller = s;
|
||||||
|
controller_state |= BUTTON_MASK_DOWN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SDL_GameControllerGetButton(s->controller, SDL_CONTROLLER_BUTTON_A)) {
|
||||||
|
gui_data.last_used_controller = s;
|
||||||
|
controller_state |= BUTTON_MASK_A;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SDL_GameControllerGetButton(s->controller, SDL_CONTROLLER_BUTTON_B)) {
|
||||||
|
gui_data.last_used_controller = s;
|
||||||
|
controller_state |= BUTTON_MASK_B;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SDL_GameControllerGetButton(s->controller, SDL_CONTROLLER_BUTTON_BACK)) {
|
||||||
|
gui_data.last_used_controller = s;
|
||||||
|
controller_state |= BUTTON_MASK_SELECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SDL_GameControllerGetButton(s->controller, SDL_CONTROLLER_BUTTON_START)) {
|
||||||
|
gui_data.last_used_controller = s;
|
||||||
|
controller_state |= BUTTON_MASK_START;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GB_set_key_state(gb, GB_KEY_RIGHT, (gui_data.pressed_buttons & BUTTON_MASK_RIGHT) | (controller_state & BUTTON_MASK_RIGHT));
|
GB_set_key_state(gb, GB_KEY_RIGHT, (gui_data.pressed_buttons & BUTTON_MASK_RIGHT) | (controller_state & BUTTON_MASK_RIGHT));
|
||||||
@ -1512,7 +1572,10 @@ static void quit(void) {
|
|||||||
for (unsigned i = 0; i < gui_data.controller_count; i++) {
|
for (unsigned i = 0; i < gui_data.controller_count; i++) {
|
||||||
struct Controller_t *s = &gui_data.controllers[i];
|
struct Controller_t *s = &gui_data.controllers[i];
|
||||||
|
|
||||||
|
#ifdef USE_SDL_HAPTIC
|
||||||
SDL_HapticClose(s->haptic);
|
SDL_HapticClose(s->haptic);
|
||||||
|
#endif
|
||||||
|
|
||||||
SDL_GameControllerClose(s->controller);
|
SDL_GameControllerClose(s->controller);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1864,14 +1927,14 @@ static void startup(GApplication *app, gpointer null_ptr) {
|
|||||||
g_action_change_state(action, g_variant_new_string(gui_data.cli_options.prefix));
|
g_action_change_state(action, g_variant_new_string(gui_data.cli_options.prefix));
|
||||||
}
|
}
|
||||||
|
|
||||||
#if NDEBUG
|
#if NDEBUG
|
||||||
// Disable when not compiled in debug mode
|
// Disable when not compiled in debug mode
|
||||||
action_set_enabled(app, "open_gtk_debugger", false);
|
action_set_enabled(app, "open_gtk_debugger", false);
|
||||||
|
|
||||||
// Remove the menubar override
|
// Remove the menubar override
|
||||||
gtk_widget_destroy(builder_get(GTK_WIDGET, "menubar_override_selector_label"));
|
gtk_widget_destroy(builder_get(GTK_WIDGET, "menubar_override_selector_label"));
|
||||||
gtk_widget_destroy(builder_get(GTK_WIDGET, "menubar_override_selector"));
|
gtk_widget_destroy(builder_get(GTK_WIDGET, "menubar_override_selector"));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
gui_data.preferences = GTK_WINDOW(get_object("preferences"));
|
gui_data.preferences = GTK_WINDOW(get_object("preferences"));
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user