gamepad options menu improvements

This commit is contained in:
Andrei "Akari" Alexeyev 2017-02-28 00:58:47 +02:00
parent 3fb8d9efca
commit 671f3b8d3a
6 changed files with 94 additions and 35 deletions

View file

@ -45,7 +45,9 @@ typedef enum {
// EF_Gamepad
E_GamepadKeyDown,
E_GamepadKeyUp
E_GamepadKeyUp,
E_GamepadAxis,
E_GamepadAxisValue,
} EventType;
typedef void(*EventHandler)(EventType, int, void*);

View file

@ -15,7 +15,7 @@
static struct {
int initialized;
SDL_Joystick *device;
int axis[GAMEPAD_AXES];
signed char *axis;
} gamepad;
void gamepad_init(void) {
@ -51,6 +51,8 @@ void gamepad_init(void) {
return;
}
gamepad.axis = malloc(SDL_JoystickNumAxes(gamepad.device));
printf("gamepad_init(): using device #%i: %s\n", dev, gamepad_devicename(dev));
SDL_JoystickEventState(SDL_ENABLE);
gamepad.initialized = 1;
@ -66,6 +68,9 @@ void gamepad_shutdown(void) {
if(gamepad.device)
SDL_JoystickClose(gamepad.device);
free(gamepad.axis);
gamepad.axis = NULL;
SDL_JoystickEventState(SDL_IGNORE);
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
gamepad.initialized = 0;
@ -125,17 +130,13 @@ float gamepad_axis_sens(int id) {
}
void gamepad_axis(int id, int raw, EventHandler handler, EventFlags flags, void *arg) {
int *a = gamepad.axis;
int val = AXISVAL(raw);
int free = config_get_int(CONFIG_GAMEPAD_AXIS_FREE);
signed char *a = gamepad.axis;
signed char val = AXISVAL(raw);
bool free = config_get_int(CONFIG_GAMEPAD_AXIS_FREE);
int menu = flags & EF_Menu;
int game = flags & EF_Game;
if(id >= GAMEPAD_AXES) {
warnx("gamepad_axis(): axis %i is out of range (%i axes supported)", id, GAMEPAD_AXES);
return;
}
bool menu = flags & EF_Menu;
bool game = flags & EF_Game;
bool gp = flags & EF_Gamepad;
//printf("axis: %i %i %i\n", id, val, raw);
@ -145,12 +146,12 @@ void gamepad_axis(int id, int raw, EventHandler handler, EventFlags flags, void
double sens = gamepad_axis_sens(id);
int sens_sign = SIGN(sens);
double x = raw / (double)GAMEPAD_AXIS_RANGE;
double x = raw / (double)GAMEPAD_AXIS_MAX;
int in_sign = SIGN(x);
x = pow(fabs(x), 1.0 / fabs(sens)) * in_sign * sens_sign;
x = x ? x : 0;
x = clamp(x * GAMEPAD_AXIS_RANGE, -GAMEPAD_AXIS_RANGE-1, GAMEPAD_AXIS_RANGE);
x = clamp(x * GAMEPAD_AXIS_MAX, GAMEPAD_AXIS_MIN, GAMEPAD_AXIS_MAX);
handler(evt, x, arg);
}
@ -179,6 +180,12 @@ void gamepad_axis(int id, int raw, EventHandler handler, EventFlags flags, void
}
a[id] = AXISVAL_NULL;
}
if(gp) {
// we probably need a better way to pass more than an int to the handler...
handler(E_GamepadAxis, id, arg);
handler(E_GamepadAxisValue, raw, arg);
}
}
void gamepad_button(int button, int state, EventHandler handler, EventFlags flags, void *arg) {
@ -227,7 +234,7 @@ void gamepad_event(SDL_Event *event, EventHandler handler, EventFlags flags, voi
return;
int val;
int sens = clamp(config_get_float(CONFIG_GAMEPAD_AXIS_DEADZONE), 0, 1) * GAMEPAD_AXIS_RANGE;
int sens = clamp(config_get_float(CONFIG_GAMEPAD_AXIS_DEADZONE), 0, 1) * GAMEPAD_AXIS_MAX;
switch(event->type) {
case SDL_JOYAXISMOTION:

View file

@ -41,8 +41,8 @@ enum {
AXISVAL_NULL = 0
};
#define GAMEPAD_AXES 8
#define GAMEPAD_AXIS_RANGE 32767
#define GAMEPAD_AXIS_MAX 32767
#define GAMEPAD_AXIS_MIN -32768
#define AXISVAL SIGN
#endif

View file

@ -77,6 +77,16 @@ OptionBinding* bind_gpbinding(int cfgentry) {
return bind;
}
// BT_GamepadAxisBinding: gamepad axis mapping options
OptionBinding* bind_gpaxisbinding(int cfgentry) {
OptionBinding *bind = bind_new();
bind->configentry = cfgentry;
bind->type = BT_GamepadAxisBinding;
return bind;
}
// BT_StrValue: with a half-assed "textbox"
OptionBinding* bind_stroption(ConfigIndex cfgentry) {
OptionBinding *bind = bind_new();
@ -442,27 +452,27 @@ void options_sub_gamepad(MenuData *parent, void *arg) {
add_menu_separator(m);
add_menu_entry(m, "UD axis (Vertical)", do_nothing,
b = bind_option(CONFIG_GAMEPAD_AXIS_UD, bind_common_intget, bind_common_intset)
); bind_setvaluerange_fancy(b, GAMEPAD_AXES-1);
add_menu_entry(m, "X axis", do_nothing,
b = bind_gpaxisbinding(CONFIG_GAMEPAD_AXIS_LR)
);
add_menu_entry(m, "LR axis (Horizontal)", do_nothing,
b = bind_option(CONFIG_GAMEPAD_AXIS_LR, bind_common_intget, bind_common_intset)
); bind_setvaluerange_fancy(b, GAMEPAD_AXES-1);
add_menu_entry(m, "Y axis", do_nothing,
b = bind_gpaxisbinding(CONFIG_GAMEPAD_AXIS_UD)
);
add_menu_entry(m, "Axes mode", do_nothing,
b = bind_option(CONFIG_GAMEPAD_AXIS_FREE, bind_common_onoffget, bind_common_onoffset)
); bind_addvalue(b, "free");
bind_addvalue(b, "restricted");
add_menu_entry(m, "UD axis sensitivity", do_nothing,
b = bind_scale(CONFIG_GAMEPAD_AXIS_UD_SENS, -2, 2, 0.05)
); bind_setdependence(b, gamepad_sens_depencence);
add_menu_entry(m, "LR axis sensitivity", do_nothing,
add_menu_entry(m, "X axis sensitivity", do_nothing,
b = bind_scale(CONFIG_GAMEPAD_AXIS_LR_SENS, -2, 2, 0.05)
); bind_setdependence(b, gamepad_sens_depencence);
add_menu_entry(m, "Y axis sensitivity", do_nothing,
b = bind_scale(CONFIG_GAMEPAD_AXIS_UD_SENS, -2, 2, 0.05)
); bind_setdependence(b, gamepad_sens_depencence);
add_menu_entry(m, "Dead zone", do_nothing,
b = bind_scale(CONFIG_GAMEPAD_AXIS_DEADZONE, 0, 1, 0.01)
);
@ -694,13 +704,19 @@ void draw_options_menu(MenuData *menu) {
break;
}
case BT_GamepadKeyBinding: {
case BT_GamepadKeyBinding:
case BT_GamepadAxisBinding: {
bool is_axis = (bind->type == BT_GamepadAxisBinding);
if(bind->blockinput) {
glColor4f(0.5, 1, 0.5, 1);
draw_text(AL_Right, origin, 20*i, "Press a button to assign, ESC to cancel", _fonts.standard);
draw_text(AL_Right, origin, 20*i,
is_axis ? "Move an axis to assign, press any button to cancel"
: "Press a button to assign, move an axis to cancel",
_fonts.standard);
} else if(config_get_int(bind->configentry) >= 0) {
char tmp[32];
snprintf(tmp, 32, "Button %i", config_get_int(bind->configentry) + 1);
snprintf(tmp, 32, is_axis ? "Axis %i" : "Button %i", config_get_int(bind->configentry) + 1);
draw_text(AL_Right, origin, 20*i, tmp, _fonts.standard);
} else {
draw_text(AL_Right, origin, 20*i, "Unbound", _fonts.standard);
@ -787,7 +803,7 @@ void bind_input_event(EventType type, int state, void *arg) {
switch(type) {
case E_KeyDown: {
int esc = scan == SDL_SCANCODE_ESCAPE;
if(b->type == BT_GamepadKeyBinding) {
if(b->type == BT_GamepadKeyBinding || b->type == BT_GamepadAxisBinding) {
if(esc)
b->blockinput = false;
break;
@ -808,6 +824,12 @@ void bind_input_event(EventType type, int state, void *arg) {
}
case E_GamepadKeyDown: {
if(b->type != BT_GamepadKeyBinding) {
if(b->type == BT_GamepadAxisBinding)
b->blockinput = false;
break;
}
for(int i = CONFIG_GAMEPAD_KEY_FIRST; i <= CONFIG_GAMEPAD_KEY_LAST; ++i) {
if(config_get_int(i) == scan) {
config_set_int(i, config_get_int(b->configentry));
@ -819,6 +841,30 @@ void bind_input_event(EventType type, int state, void *arg) {
break;
}
case E_GamepadAxis: {
if(b->type == BT_GamepadKeyBinding) {
b->blockinput = false;
break;
}
if(b->type == BT_GamepadAxisBinding) {
if(b->configentry == CONFIG_GAMEPAD_AXIS_UD) {
if(config_get_int(CONFIG_GAMEPAD_AXIS_LR) == state) {
config_set_int(CONFIG_GAMEPAD_AXIS_LR, config_get_int(CONFIG_GAMEPAD_AXIS_UD));
}
} else if(b->configentry == CONFIG_GAMEPAD_AXIS_LR) {
if(config_get_int(CONFIG_GAMEPAD_AXIS_UD) == state) {
config_set_int(CONFIG_GAMEPAD_AXIS_UD, config_get_int(CONFIG_GAMEPAD_AXIS_LR));
}
}
config_set_int(b->configentry, state);
b->blockinput = false;
}
break;
}
case E_CharTyped: {
if(c != ':') {
char s[] = {c, 0};
@ -907,7 +953,9 @@ static void options_input_event(EventType type, int state, void *arg) {
menu->selected = menu->cursor;
if(bind) switch(bind->type) {
case BT_KeyBinding: case BT_GamepadKeyBinding:
case BT_KeyBinding:
case BT_GamepadKeyBinding:
case BT_GamepadAxisBinding:
bind->blockinput = true;
break;
@ -944,6 +992,7 @@ void options_menu_input(MenuData *menu) {
case BT_StrValue: flags = EF_Text; break;
case BT_KeyBinding: flags = EF_Keyboard; break;
case BT_GamepadKeyBinding: flags = EF_Gamepad | EF_Keyboard; break;
case BT_GamepadAxisBinding: flags = EF_Gamepad | EF_Keyboard; break;
default: break;
}

View file

@ -26,7 +26,8 @@ typedef enum BindingType {
BT_StrValue,
BT_Resolution,
BT_Scale,
BT_GamepadKeyBinding
BT_GamepadKeyBinding,
BT_GamepadAxisBinding,
} BindingType;
typedef struct OptionBinding {

View file

@ -339,7 +339,7 @@ bool player_applymovement_gamepad(Player *plr) {
return false;
}
complex direction = (plr->axis_lr + plr->axis_ud*I) / (double)GAMEPAD_AXIS_RANGE;
complex direction = (plr->axis_lr + plr->axis_ud*I) / (double)GAMEPAD_AXIS_MAX;
if(cabs(direction) > 1)
direction /= cabs(direction);