mirror of https://github.com/xemu-project/xemu.git
input: Use QTAILQ for available controllers list
This commit is contained in:
parent
5233f777cf
commit
64141f90e1
|
@ -198,7 +198,7 @@ static void update_output(USBXIDState *s)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct controller_state *state = xemu_input_get_bound(s->device_index);
|
ControllerState *state = xemu_input_get_bound(s->device_index);
|
||||||
assert(state);
|
assert(state);
|
||||||
state->rumble_l = s->out_state.left_actuator_strength;
|
state->rumble_l = s->out_state.left_actuator_strength;
|
||||||
state->rumble_r = s->out_state.right_actuator_strength;
|
state->rumble_r = s->out_state.right_actuator_strength;
|
||||||
|
@ -212,7 +212,7 @@ static void update_input(USBXIDState *s)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct controller_state *state = xemu_input_get_bound(s->device_index);
|
ControllerState *state = xemu_input_get_bound(s->device_index);
|
||||||
assert(state);
|
assert(state);
|
||||||
|
|
||||||
const int button_map_analog[6][2] = {
|
const int button_map_analog[6][2] = {
|
||||||
|
|
|
@ -85,7 +85,7 @@ void render_meter(
|
||||||
render_decal(s, x, y, width*p, height ,0, 0, 1, 1, 0, 0, color_fg);
|
render_decal(s, x, y, width*p, height ,0, 0, 1, 1, 0, 0, color_fg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void render_controller(float frame_x, float frame_y, uint32_t primary_color, uint32_t secondary_color, struct controller_state *state)
|
void render_controller(float frame_x, float frame_y, uint32_t primary_color, uint32_t secondary_color, ControllerState *state)
|
||||||
{
|
{
|
||||||
// Location within the controller texture of masked button locations,
|
// Location within the controller texture of masked button locations,
|
||||||
// relative to the origin of the controller
|
// relative to the origin of the controller
|
||||||
|
|
|
@ -34,7 +34,7 @@ extern struct fbo *logo_fbo;
|
||||||
|
|
||||||
void initialize_custom_ui_rendering(void);
|
void initialize_custom_ui_rendering(void);
|
||||||
void render_meter(struct decal_shader *s, float x, float y, float width, float height, float p, uint32_t color_bg, uint32_t color_fg);
|
void render_meter(struct decal_shader *s, float x, float y, float width, float height, float p, uint32_t color_bg, uint32_t color_fg);
|
||||||
void render_controller(float frame_x, float frame_y, uint32_t primary_color, uint32_t secondary_color, struct controller_state *state);
|
void render_controller(float frame_x, float frame_y, uint32_t primary_color, uint32_t secondary_color, ControllerState *state);
|
||||||
void render_controller_port(float frame_x, float frame_y, int i, uint32_t port_color);
|
void render_controller_port(float frame_x, float frame_y, int i, uint32_t port_color);
|
||||||
void render_logo(uint32_t time, uint32_t primary_color, uint32_t secondary_color, uint32_t fill_color);
|
void render_logo(uint32_t time, uint32_t primary_color, uint32_t secondary_color, uint32_t fill_color);
|
||||||
|
|
||||||
|
|
|
@ -437,7 +437,7 @@ public:
|
||||||
|
|
||||||
// List available input devices
|
// List available input devices
|
||||||
const char *not_connected = "Not Connected";
|
const char *not_connected = "Not Connected";
|
||||||
struct controller_state *bound_state = xemu_input_get_bound(active);
|
ControllerState *bound_state = xemu_input_get_bound(active);
|
||||||
|
|
||||||
// Get current controller name
|
// Get current controller name
|
||||||
const char *name;
|
const char *name;
|
||||||
|
@ -460,8 +460,8 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle all available input devices
|
// Handle all available input devices
|
||||||
struct controller_state *iter;
|
ControllerState *iter;
|
||||||
for (iter=available_controllers; iter != NULL; iter=iter->next) {
|
QTAILQ_FOREACH(iter, &available_controllers, entry) {
|
||||||
is_selected = bound_state == iter;
|
is_selected = bound_state == iter;
|
||||||
ImGui::PushID(iter);
|
ImGui::PushID(iter);
|
||||||
const char *selectable_label = iter->name;
|
const char *selectable_label = iter->name;
|
||||||
|
@ -501,7 +501,7 @@ public:
|
||||||
device_selected = true;
|
device_selected = true;
|
||||||
render_controller(0, 0, 0x81dc8a00, 0x0f0f0f00, bound_state);
|
render_controller(0, 0, 0x81dc8a00, 0x0f0f0f00, bound_state);
|
||||||
} else {
|
} else {
|
||||||
static struct controller_state state = { 0 };
|
static ControllerState state = { 0 };
|
||||||
render_controller(0, 0, 0x1f1f1f00, 0x0f0f0f00, &state);
|
render_controller(0, 0, 0x1f1f1f00, 0x0f0f0f00, &state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1753,12 +1753,13 @@ void xemu_hud_render(void)
|
||||||
{
|
{
|
||||||
uint32_t now = SDL_GetTicks();
|
uint32_t now = SDL_GetTicks();
|
||||||
bool ui_wakeup = false;
|
bool ui_wakeup = false;
|
||||||
struct controller_state *iter;
|
|
||||||
|
|
||||||
// Combine all controller states to allow any controller to navigate
|
// Combine all controller states to allow any controller to navigate
|
||||||
uint32_t buttons = 0;
|
uint32_t buttons = 0;
|
||||||
int16_t axis[CONTROLLER_AXIS__COUNT] = {0};
|
int16_t axis[CONTROLLER_AXIS__COUNT] = {0};
|
||||||
for (iter=available_controllers; iter != NULL; iter=iter->next) {
|
|
||||||
|
ControllerState *iter;
|
||||||
|
QTAILQ_FOREACH(iter, &available_controllers, entry) {
|
||||||
if (iter->type != INPUT_DEVICE_SDL_GAMECONTROLLER) continue;
|
if (iter->type != INPUT_DEVICE_SDL_GAMECONTROLLER) continue;
|
||||||
buttons |= iter->buttons;
|
buttons |= iter->buttons;
|
||||||
// We simply take any axis that is >10 % activation
|
// We simply take any axis that is >10 % activation
|
||||||
|
|
|
@ -42,8 +42,9 @@
|
||||||
do { } while (0)
|
do { } while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct controller_state *available_controllers;
|
ControllerStateList available_controllers =
|
||||||
struct controller_state *bound_controllers[4] = { NULL, NULL, NULL, NULL };
|
QTAILQ_HEAD_INITIALIZER(available_controllers);
|
||||||
|
ControllerState *bound_controllers[4] = { NULL, NULL, NULL, NULL };
|
||||||
int test_mode;
|
int test_mode;
|
||||||
|
|
||||||
static const enum xemu_settings_keys port_index_to_settings_key_map[] = {
|
static const enum xemu_settings_keys port_index_to_settings_key_map[] = {
|
||||||
|
@ -68,8 +69,8 @@ void xemu_input_init(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the keyboard input (always first)
|
// Create the keyboard input (always first)
|
||||||
struct controller_state *new_con = malloc(sizeof(struct controller_state));
|
ControllerState *new_con = malloc(sizeof(ControllerState));
|
||||||
memset(new_con, 0, sizeof(struct controller_state));
|
memset(new_con, 0, sizeof(ControllerState));
|
||||||
new_con->type = INPUT_DEVICE_SDL_KEYBOARD;
|
new_con->type = INPUT_DEVICE_SDL_KEYBOARD;
|
||||||
new_con->name = "Keyboard";
|
new_con->name = "Keyboard";
|
||||||
new_con->bound = -1;
|
new_con->bound = -1;
|
||||||
|
@ -83,10 +84,10 @@ void xemu_input_init(void)
|
||||||
xemu_queue_notification(buf);
|
xemu_queue_notification(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
available_controllers = new_con;
|
QTAILQ_INSERT_TAIL(&available_controllers, new_con, entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
int xemu_input_get_controller_default_bind_port(struct controller_state *state, int start)
|
int xemu_input_get_controller_default_bind_port(ControllerState *state, int start)
|
||||||
{
|
{
|
||||||
char guid[35] = { 0 };
|
char guid[35] = { 0 };
|
||||||
if (state->type == INPUT_DEVICE_SDL_GAMECONTROLLER) {
|
if (state->type == INPUT_DEVICE_SDL_GAMECONTROLLER) {
|
||||||
|
@ -120,8 +121,8 @@ void xemu_input_process_sdl_events(const SDL_Event *event)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Success! Create a new node to track this controller and continue init
|
// Success! Create a new node to track this controller and continue init
|
||||||
struct controller_state *new_con = malloc(sizeof(struct controller_state));
|
ControllerState *new_con = malloc(sizeof(ControllerState));
|
||||||
memset(new_con, 0, sizeof(struct controller_state));
|
memset(new_con, 0, sizeof(ControllerState));
|
||||||
new_con->type = INPUT_DEVICE_SDL_GAMECONTROLLER;
|
new_con->type = INPUT_DEVICE_SDL_GAMECONTROLLER;
|
||||||
new_con->name = SDL_GameControllerName(sdl_con);
|
new_con->name = SDL_GameControllerName(sdl_con);
|
||||||
new_con->sdl_gamecontroller = sdl_con;
|
new_con->sdl_gamecontroller = sdl_con;
|
||||||
|
@ -136,14 +137,7 @@ void xemu_input_process_sdl_events(const SDL_Event *event)
|
||||||
SDL_JoystickGetGUIDString(new_con->sdl_joystick_guid, guid_buf, sizeof(guid_buf));
|
SDL_JoystickGetGUIDString(new_con->sdl_joystick_guid, guid_buf, sizeof(guid_buf));
|
||||||
DPRINTF("Opened %s (%s)\n", new_con->name, guid_buf);
|
DPRINTF("Opened %s (%s)\n", new_con->name, guid_buf);
|
||||||
|
|
||||||
// Add to the list of controllers
|
QTAILQ_INSERT_TAIL(&available_controllers, new_con, entry);
|
||||||
if (available_controllers == NULL) {
|
|
||||||
available_controllers = new_con;
|
|
||||||
} else {
|
|
||||||
struct controller_state *iter = available_controllers;
|
|
||||||
while (iter->next != NULL) iter = iter->next;
|
|
||||||
iter->next = new_con;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do not replace binding for a currently bound device. In the case that
|
// Do not replace binding for a currently bound device. In the case that
|
||||||
// the same GUID is specified multiple times, on different ports, allow
|
// the same GUID is specified multiple times, on different ports, allow
|
||||||
|
@ -178,8 +172,8 @@ void xemu_input_process_sdl_events(const SDL_Event *event)
|
||||||
} else if (event->type == SDL_CONTROLLERDEVICEREMOVED) {
|
} else if (event->type == SDL_CONTROLLERDEVICEREMOVED) {
|
||||||
DPRINTF("Controller Removed: %d\n", event->cdevice.which);
|
DPRINTF("Controller Removed: %d\n", event->cdevice.which);
|
||||||
int handled = 0;
|
int handled = 0;
|
||||||
struct controller_state *iter, *prev;
|
ControllerState *iter, *next;
|
||||||
for (iter=available_controllers, prev=NULL; iter != NULL; prev = iter, iter = iter->next) {
|
QTAILQ_FOREACH_SAFE(iter, &available_controllers, entry, next) {
|
||||||
if (iter->type != INPUT_DEVICE_SDL_GAMECONTROLLER) continue;
|
if (iter->type != INPUT_DEVICE_SDL_GAMECONTROLLER) continue;
|
||||||
|
|
||||||
if (iter->sdl_joystick_id == event->cdevice.which) {
|
if (iter->sdl_joystick_id == event->cdevice.which) {
|
||||||
|
@ -200,11 +194,7 @@ void xemu_input_process_sdl_events(const SDL_Event *event)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unlink
|
// Unlink
|
||||||
if (prev) {
|
QTAILQ_REMOVE(&available_controllers, iter, entry);
|
||||||
prev->next = iter->next;
|
|
||||||
} else {
|
|
||||||
available_controllers = iter->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deallocate
|
// Deallocate
|
||||||
if (iter->sdl_haptic) {
|
if (iter->sdl_haptic) {
|
||||||
|
@ -229,8 +219,8 @@ void xemu_input_process_sdl_events(const SDL_Event *event)
|
||||||
|
|
||||||
void xemu_input_update_controllers(void)
|
void xemu_input_update_controllers(void)
|
||||||
{
|
{
|
||||||
struct controller_state *iter;
|
ControllerState *iter;
|
||||||
for (iter=available_controllers; iter != NULL; iter=iter->next) {
|
QTAILQ_FOREACH(iter, &available_controllers, entry) {
|
||||||
if (iter->type == INPUT_DEVICE_SDL_KEYBOARD) {
|
if (iter->type == INPUT_DEVICE_SDL_KEYBOARD) {
|
||||||
xemu_input_update_sdl_kbd_controller_state(iter);
|
xemu_input_update_sdl_kbd_controller_state(iter);
|
||||||
} else if (iter->type == INPUT_DEVICE_SDL_GAMECONTROLLER) {
|
} else if (iter->type == INPUT_DEVICE_SDL_GAMECONTROLLER) {
|
||||||
|
@ -240,7 +230,7 @@ void xemu_input_update_controllers(void)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void xemu_input_update_sdl_kbd_controller_state(struct controller_state *state)
|
void xemu_input_update_sdl_kbd_controller_state(ControllerState *state)
|
||||||
{
|
{
|
||||||
state->buttons = 0;
|
state->buttons = 0;
|
||||||
memset(state->axis, 0, sizeof(state->axis));
|
memset(state->axis, 0, sizeof(state->axis));
|
||||||
|
@ -293,7 +283,7 @@ void xemu_input_update_sdl_kbd_controller_state(struct controller_state *state)
|
||||||
if (kbd[SDL_SCANCODE_O]) state->axis[CONTROLLER_AXIS_RTRIG] = 32767;
|
if (kbd[SDL_SCANCODE_O]) state->axis[CONTROLLER_AXIS_RTRIG] = 32767;
|
||||||
}
|
}
|
||||||
|
|
||||||
void xemu_input_update_sdl_controller_state(struct controller_state *state)
|
void xemu_input_update_sdl_controller_state(ControllerState *state)
|
||||||
{
|
{
|
||||||
state->buttons = 0;
|
state->buttons = 0;
|
||||||
memset(state->axis, 0, sizeof(state->axis));
|
memset(state->axis, 0, sizeof(state->axis));
|
||||||
|
@ -338,7 +328,7 @@ void xemu_input_update_sdl_controller_state(struct controller_state *state)
|
||||||
state->axis[CONTROLLER_AXIS_RSTICK_Y] = -1 - state->axis[CONTROLLER_AXIS_RSTICK_Y];
|
state->axis[CONTROLLER_AXIS_RSTICK_Y] = -1 - state->axis[CONTROLLER_AXIS_RSTICK_Y];
|
||||||
}
|
}
|
||||||
|
|
||||||
void xemu_input_update_rumble(struct controller_state *state)
|
void xemu_input_update_rumble(ControllerState *state)
|
||||||
{
|
{
|
||||||
if (state->sdl_haptic == NULL) {
|
if (state->sdl_haptic == NULL) {
|
||||||
// Haptic not supported for this joystick
|
// Haptic not supported for this joystick
|
||||||
|
@ -358,12 +348,12 @@ void xemu_input_update_rumble(struct controller_state *state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct controller_state *xemu_input_get_bound(int index)
|
ControllerState *xemu_input_get_bound(int index)
|
||||||
{
|
{
|
||||||
return bound_controllers[index];
|
return bound_controllers[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
void xemu_input_bind(int index, struct controller_state *state, int save)
|
void xemu_input_bind(int index, ControllerState *state, int save)
|
||||||
{
|
{
|
||||||
// FIXME: Attempt to disable rumble when unbinding so it's not left
|
// FIXME: Attempt to disable rumble when unbinding so it's not left
|
||||||
// in rumble mode
|
// in rumble mode
|
||||||
|
@ -434,7 +424,7 @@ void xemu_input_bind(int index, struct controller_state *state, int save)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
static void xemu_input_print_controller_state(struct controller_state *state)
|
static void xemu_input_print_controller_state(ControllerState *state)
|
||||||
{
|
{
|
||||||
DPRINTF(" A = %d, B = %d, X = %d, Y = %d\n"
|
DPRINTF(" A = %d, B = %d, X = %d, Y = %d\n"
|
||||||
" Left = %d, Up = %d, Right = %d, Down = %d\n"
|
" Left = %d, Up = %d, Right = %d, Down = %d\n"
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#define XEMU_INPUT_H
|
#define XEMU_INPUT_H
|
||||||
|
|
||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
|
#include "qemu/queue.h"
|
||||||
|
|
||||||
enum controller_state_buttons_mask {
|
enum controller_state_buttons_mask {
|
||||||
CONTROLLER_BUTTON_A = (1 << 0),
|
CONTROLLER_BUTTON_A = (1 << 0),
|
||||||
|
@ -62,7 +63,9 @@ enum controller_input_device_type {
|
||||||
INPUT_DEVICE_SDL_GAMECONTROLLER,
|
INPUT_DEVICE_SDL_GAMECONTROLLER,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct controller_state {
|
typedef struct ControllerState {
|
||||||
|
QTAILQ_ENTRY(ControllerState) entry;
|
||||||
|
|
||||||
// Input state
|
// Input state
|
||||||
uint16_t buttons;
|
uint16_t buttons;
|
||||||
int16_t axis[CONTROLLER_AXIS__COUNT];
|
int16_t axis[CONTROLLER_AXIS__COUNT];
|
||||||
|
@ -86,13 +89,11 @@ struct controller_state {
|
||||||
|
|
||||||
int bound; // Which port this input device is bound to
|
int bound; // Which port this input device is bound to
|
||||||
void *device; // DeviceState opaque
|
void *device; // DeviceState opaque
|
||||||
|
} ControllerState;
|
||||||
|
|
||||||
struct controller_state *next;
|
typedef QTAILQ_HEAD(, ControllerState) ControllerStateList;
|
||||||
};
|
extern ControllerStateList available_controllers;
|
||||||
|
extern ControllerState *bound_controllers[4];
|
||||||
extern int num_available_controllers;
|
|
||||||
extern struct controller_state *available_controllers;
|
|
||||||
extern struct controller_state *bound_controllers[4];
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -101,12 +102,12 @@ extern "C" {
|
||||||
void xemu_input_init(void);
|
void xemu_input_init(void);
|
||||||
void xemu_input_process_sdl_events(const SDL_Event *event); // SDL_CONTROLLERDEVICEADDED, SDL_CONTROLLERDEVICEREMOVED
|
void xemu_input_process_sdl_events(const SDL_Event *event); // SDL_CONTROLLERDEVICEADDED, SDL_CONTROLLERDEVICEREMOVED
|
||||||
void xemu_input_update_controllers(void);
|
void xemu_input_update_controllers(void);
|
||||||
void xemu_input_update_sdl_kbd_controller_state(struct controller_state *state);
|
void xemu_input_update_sdl_kbd_controller_state(ControllerState *state);
|
||||||
void xemu_input_update_sdl_controller_state(struct controller_state *state);
|
void xemu_input_update_sdl_controller_state(ControllerState *state);
|
||||||
void xemu_input_update_rumble(struct controller_state *state);
|
void xemu_input_update_rumble(ControllerState *state);
|
||||||
struct controller_state *xemu_input_get_bound(int index);
|
ControllerState *xemu_input_get_bound(int index);
|
||||||
void xemu_input_bind(int index, struct controller_state *state, int save);
|
void xemu_input_bind(int index, ControllerState *state, int save);
|
||||||
int xemu_input_get_controller_default_bind_port(struct controller_state *state, int start);
|
int xemu_input_get_controller_default_bind_port(ControllerState *state, int start);
|
||||||
|
|
||||||
void xemu_input_set_test_mode(int enabled);
|
void xemu_input_set_test_mode(int enabled);
|
||||||
int xemu_input_get_test_mode(void);
|
int xemu_input_get_test_mode(void);
|
||||||
|
|
Loading…
Reference in New Issue