From a5eace5cedc6ac233ceba04f1a6ef69c0544542e Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Sun, 7 Apr 2019 09:26:11 +0200 Subject: [PATCH] Joystick support --- src/libsdl/sdl.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++------ src/libsdl/sdl.h | 3 +- src/mercenary/main.c | 66 ++++++++++++++++++++++++++++++++++++- 3 files changed, 149 insertions(+), 11 deletions(-) diff --git a/src/libsdl/sdl.c b/src/libsdl/sdl.c index 804695c..b10efec 100644 --- a/src/libsdl/sdl.c +++ b/src/libsdl/sdl.c @@ -34,9 +34,12 @@ static const char *device_string = NULL; static SDL_AudioDeviceID audio_devid = 0; static SDL_Window *gl_window = NULL; static SDL_GLContext gl_context = NULL; +static SDL_Joystick *sdl_joystick = NULL; static void (*keyboard_sdl)(int down, enum keycode keycode) = NULL; +static void (*joystick_sdl)(double x, double y, int fire) = NULL; static void (*audio_sdl)(float *data, int len) = NULL; static void (*resize_window_sdl)(int width, int height) = NULL; +static int joystick_y_axis_sdl = 1, joystick_x_axis_sdl = 0, joystick_fire_button_sdl = -1; static void audio_cb(void __attribute__((unused)) *userdata, Uint8 *stream, int len) { @@ -47,22 +50,54 @@ static void audio_cb(void __attribute__((unused)) *userdata, Uint8 *stream, int SDL_MixAudioFormat(stream, (Uint8 *)audio_data, AUDIO_F32, len, SDL_MIX_MAXVOLUME / 2.0); } -int init_sdl(const char *progname, int width, int height, int sound_samplerate, int sound_chunk, void (*keyboard)(int down, enum keycode keycode), void (*audio)(float *data, int len), void (*resize_window)(int width, int height), int multisampling, int vbl_sync, int rift) +void sdl_list_joysticks(void) { - int rc; + int num, i, rc; + + rc = SDL_Init(SDL_INIT_JOYSTICK); + if (rc < 0) { + print_error("Failed to init SDL\n"); + return; + } + + num = SDL_NumJoysticks(); + for (i = 0; i < num; i++) + printf("#%d: %s\n", i, SDL_JoystickNameForIndex(i)); + + SDL_Quit(); +} + +int init_sdl(const char *progname, int width, int height, int sound_samplerate, int sound_chunk, void (*keyboard)(int down, enum keycode keycode), int joysticknum, int joystick_x_axis, int joystick_y_axis, int joystick_fire_button, void (*joystick)(double x, double y, int fire), void (*audio)(float *data, int len), void (*resize_window)(int width, int height), int multisampling, int vbl_sync, int rift) +{ + int rc = -EINVAL; keyboard_sdl = keyboard; + joystick_sdl = joystick; audio_sdl = audio; resize_window_sdl = resize_window; + if (joystick_x_axis >= 0) + joystick_x_axis_sdl = joystick_x_axis; + if (joystick_y_axis >= 0) + joystick_y_axis_sdl = joystick_y_axis; + if (joystick_fire_button >= 0) + joystick_fire_button_sdl = joystick_fire_button; /* init SDL library */ - rc = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO); + rc = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK); if (rc < 0) { print_error("Failed to init SDL\n"); goto error; } sdl_initialized = 1; + SDL_JoystickEventState(SDL_ENABLE); + sdl_joystick = SDL_JoystickOpen((joysticknum < 0) ? 0 : joysticknum); + if (!sdl_joystick && joysticknum >= 0) { + rc = -EIO; + print_error("Failed to open joystick #%d, see help!\n", joysticknum); + goto error; + } + retry_without_multisampling: if (multisampling > 1) { SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); @@ -285,6 +320,22 @@ static enum keycode sdl2keycode(SDL_Keycode sym) } } +static double joystick_x = 0, joystick_y = 0; +static int joystick_fire = 0; + +static void joystick_event(int axis, int value) +{ + double v = (double)value / 32767.0; + + switch (axis) { + case 0: joystick_y = v; break; + case 1: joystick_x = v; break; + case 2: joystick_fire = value; break; + } + + joystick_sdl(joystick_x, joystick_y, joystick_fire); +} + static int key_ctrl = 0, key_f = 0, fullscreen = 0; int event_sdl(void) @@ -293,13 +344,15 @@ int event_sdl(void) SDL_Event event; while (SDL_PollEvent(&event)) { - if (event.type == SDL_QUIT) + switch (event.type) { + case SDL_QUIT: quit = 1; - if (event.type == SDL_WINDOWEVENT) { + break; + case SDL_WINDOWEVENT: if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) resize_window_sdl(event.window.data1, event.window.data2); - } - if (event.type == SDL_KEYDOWN) { + break; + case SDL_KEYDOWN: switch (event.key.keysym.sym) { case SDLK_f: if (key_ctrl && !key_f) { @@ -321,8 +374,8 @@ int event_sdl(void) break; } keyboard_sdl(1, sdl2keycode(event.key.keysym.sym)); - } - if (event.type == SDL_KEYUP) { + break; + case SDL_KEYUP: switch (event.key.keysym.sym) { case SDLK_LCTRL: case SDLK_RCTRL: @@ -333,6 +386,21 @@ int event_sdl(void) break; } keyboard_sdl(0, sdl2keycode(event.key.keysym.sym)); + break; + case SDL_JOYAXISMOTION: + if (event.jaxis.axis == joystick_y_axis_sdl) + joystick_event(0, event.jaxis.value); + if (event.jaxis.axis == joystick_x_axis_sdl) + joystick_event(1, event.jaxis.value); + break; + case SDL_JOYBUTTONDOWN: + if (joystick_fire_button_sdl < 0 || event.jbutton.button == joystick_fire_button_sdl) + joystick_event(2, 1); + break; + case SDL_JOYBUTTONUP: + if (joystick_fire_button_sdl < 0 || event.jbutton.button == joystick_fire_button_sdl) + joystick_event(2, 0); + break; } } @@ -346,6 +414,11 @@ void swap_sdl(void) void exit_sdl(void) { + /* close joystick */ + if (sdl_joystick) { + SDL_JoystickClose(sdl_joystick); + sdl_joystick = NULL; + } /* close window */ if (gl_window) { SDL_DestroyWindow(gl_window); diff --git a/src/libsdl/sdl.h b/src/libsdl/sdl.h index 7307496..cae8ff9 100644 --- a/src/libsdl/sdl.h +++ b/src/libsdl/sdl.h @@ -1,5 +1,6 @@ -int init_sdl(const char *progname, int width, int height, int sound_samplerate, int sound_chunk, void (*keyboard)(int down, enum keycode keycode), void (*audio)(float *data, int len), void (*resize_window)(int width, int height), int multisampling, int vbl_sync, int rift); +void sdl_list_joysticks(void); +int init_sdl(const char *progname, int width, int height, int sound_samplerate, int sound_chunk, void (*keyboard)(int down, enum keycode keycode), int joysticknum, int joystick_x_axis, int joystick_y_axis, int joysytick_fire_button, void (*joystick)(double x, double y, int fire), void (*audio)(float *data, int len), void (*resize_window)(int width, int height), int multisampling, int vbl_sync, int rift); int event_sdl(void); void swap_sdl(void); void exit_sdl(void); diff --git a/src/mercenary/main.c b/src/mercenary/main.c index 6931b29..d4ac4ee 100644 --- a/src/mercenary/main.c +++ b/src/mercenary/main.c @@ -64,6 +64,7 @@ static int config_audio_filter = 1; static int config_render = 1; /* opengl render */ static int config_skip_intro = 0; static int config_multisampling = 8; +static int config_joystick = -1, config_joystick_x = -1, config_joystick_y = -1, config_joystick_fire = -1; #ifdef HAVE_OVR static double config_benson_size = 0.7; static double config_fov = FOV_JOLLY; @@ -171,6 +172,12 @@ int parse_args(int argc, char *argv[]) print_info(" Set field-of-view. Default is %.0f.\n", FOV_NOVAGEN); print_info(" -i --skip-intro\n"); print_info(" Skip intro sequence approaching to Eris space port.\n"); + print_info(" -j --joystick | list\n"); + print_info(" Select given joystick number or show list. (default = 0, if available)\n"); + print_info(" --joystick-x \n"); + print_info(" --joystick-y \n"); + print_info(" --joystick-fire