Merge pull request #318 from libretro/inputconfig

RGUI Inputconfig
This commit is contained in:
Hans-Kristian Arntzen 2013-09-30 10:48:48 -07:00
commit 3ab42b7e90
16 changed files with 509 additions and 120 deletions

View File

@ -565,7 +565,6 @@ static const struct retro_keybind retro_keybinds_1[] = {
{ true, RETRO_DEVICE_ID_JOYPAD_L3, RETRO_LBL_JOYPAD_L3, RETROK_UNKNOWN, RETRO_DEF_JOYPAD_L3, 0, AXIS_NONE },
{ true, RETRO_DEVICE_ID_JOYPAD_R3, RETRO_LBL_JOYPAD_R3, RETROK_UNKNOWN, RETRO_DEF_JOYPAD_R3, 0, AXIS_NONE },
{ true, RARCH_TURBO_ENABLE, RETRO_LBL_TURBO_ENABLE, RETROK_UNKNOWN, NO_BTN, 0, AXIS_NONE },
{ true, RARCH_ANALOG_LEFT_X_PLUS, RETRO_LBL_ANALOG_LEFT_X_PLUS, RETROK_UNKNOWN, NO_BTN, 0, AXIS_NONE },
{ true, RARCH_ANALOG_LEFT_X_MINUS, RETRO_LBL_ANALOG_LEFT_X_MINUS, RETROK_UNKNOWN, NO_BTN, 0, AXIS_NONE },
{ true, RARCH_ANALOG_LEFT_Y_PLUS, RETRO_LBL_ANALOG_LEFT_Y_PLUS, RETROK_UNKNOWN, NO_BTN, 0, AXIS_NONE },
@ -585,6 +584,7 @@ static const struct retro_keybind retro_keybinds_1[] = {
{ true, RARCH_ANALOG_RIGHT_Y_DPAD_DOWN, RETRO_LBL_ANALOG_RIGHT_Y_DPAD_D,RETROK_UNKNOWN, RETRO_DEF_ANALOGR_DPAD_DOWN, 0, AXIS_NONE },
#endif
{ true, RARCH_TURBO_ENABLE, RETRO_LBL_TURBO_ENABLE, RETROK_UNKNOWN, NO_BTN, 0, AXIS_NONE },
{ true, RARCH_FAST_FORWARD_KEY, RETRO_LBL_FAST_FORWARD_KEY, RETROK_SPACE, NO_BTN, 0, AXIS_NONE },
{ true, RARCH_FAST_FORWARD_HOLD_KEY, RETRO_LBL_FAST_FORWARD_HOLD_KEY,RETROK_l, NO_BTN, 0, AXIS_NONE },
{ true, RARCH_LOAD_STATE_KEY, RETRO_LBL_LOAD_STATE_KEY, RETROK_F4, NO_BTN, 0, AXIS_NONE },
@ -640,7 +640,6 @@ static const struct retro_keybind retro_keybinds_rest[] = {
{ true, RETRO_DEVICE_ID_JOYPAD_L3, RETRO_LBL_JOYPAD_L3, RETROK_UNKNOWN, NO_BTN, 0, AXIS_NONE },
{ true, RETRO_DEVICE_ID_JOYPAD_R3, RETRO_LBL_JOYPAD_R3, RETROK_UNKNOWN, NO_BTN, 0, AXIS_NONE },
{ true, RARCH_TURBO_ENABLE, RETRO_LBL_TURBO_ENABLE, RETROK_UNKNOWN, NO_BTN, 0, AXIS_NONE },
{ true, RARCH_ANALOG_LEFT_X_PLUS, RETRO_LBL_ANALOG_LEFT_X_PLUS, RETROK_UNKNOWN, NO_BTN, 0, AXIS_NONE },
{ true, RARCH_ANALOG_LEFT_X_MINUS, RETRO_LBL_ANALOG_LEFT_X_MINUS, RETROK_UNKNOWN, NO_BTN, 0, AXIS_NONE },
{ true, RARCH_ANALOG_LEFT_Y_PLUS, RETRO_LBL_ANALOG_LEFT_Y_PLUS, RETROK_UNKNOWN, NO_BTN, 0, AXIS_NONE },
@ -659,6 +658,7 @@ static const struct retro_keybind retro_keybinds_rest[] = {
{ true, RARCH_ANALOG_RIGHT_Y_DPAD_UP, RETRO_LBL_ANALOG_RIGHT_Y_DPAD_U,RETROK_UNKNOWN, NO_BTN, 0, AXIS_NONE },
{ true, RARCH_ANALOG_RIGHT_Y_DPAD_DOWN, RETRO_LBL_ANALOG_RIGHT_Y_DPAD_D,RETROK_UNKNOWN, NO_BTN, 0, AXIS_NONE },
#endif
{ true, RARCH_TURBO_ENABLE, RETRO_LBL_TURBO_ENABLE, RETROK_UNKNOWN, NO_BTN, 0, AXIS_NONE },
};
#endif

View File

@ -56,11 +56,8 @@ extern "C" {
enum // RetroArch specific bind IDs.
{
// Custom binds that extend the scope of RETRO_DEVICE_JOYPAD for RetroArch specifically.
// Turbo
RARCH_TURBO_ENABLE = RARCH_FIRST_CUSTOM_BIND,
// Analogs (RETRO_DEVICE_ANALOG)
RARCH_ANALOG_LEFT_X_PLUS,
RARCH_ANALOG_LEFT_X_PLUS = RARCH_FIRST_CUSTOM_BIND,
RARCH_ANALOG_LEFT_X_MINUS,
RARCH_ANALOG_LEFT_Y_PLUS,
RARCH_ANALOG_LEFT_Y_MINUS,
@ -69,6 +66,7 @@ enum // RetroArch specific bind IDs.
RARCH_ANALOG_RIGHT_Y_PLUS,
RARCH_ANALOG_RIGHT_Y_MINUS,
#ifdef RARCH_CONSOLE
// D-pad emulation
RARCH_ANALOG_LEFT_X_DPAD_LEFT,
RARCH_ANALOG_LEFT_X_DPAD_RIGHT,
RARCH_ANALOG_LEFT_Y_DPAD_UP,
@ -79,6 +77,9 @@ enum // RetroArch specific bind IDs.
RARCH_ANALOG_RIGHT_Y_DPAD_DOWN,
#endif
// Turbo
RARCH_TURBO_ENABLE,
RARCH_CUSTOM_BIND_LIST_END,
// Command binds. Not related to game input, only usable for port 0.
@ -323,6 +324,8 @@ enum keybind_set_id
KEYBINDS_ACTION_LAST
};
typedef struct rarch_joypad_driver rarch_joypad_driver_t;
typedef struct input_driver
{
void *(*init)(void);
@ -336,6 +339,7 @@ typedef struct input_driver
void (*grab_mouse)(void *data, bool state);
bool (*set_rumble)(void *data, unsigned port, enum retro_rumble_effect effect, uint16_t state);
const rarch_joypad_driver_t *(*get_joypad_driver)(void *data);
} input_driver_t;
struct rarch_viewport;

View File

@ -215,6 +215,12 @@ int main_entry(int argc, char *argv[])
driver_set_rumble_state(i, RETRO_RUMBLE_WEAK, 0);
}
// Override keyboard callback to redirect to menu instead.
// We'll use this later for something ...
// FIXME: This should probably be moved to menu_common somehow.
retro_keyboard_event_t key_event = g_extern.system.key_event;
g_extern.system.key_event = menu_key_event;
if (driver.audio_data)
audio_stop_func();
@ -236,6 +242,9 @@ int main_entry(int argc, char *argv[])
}
g_extern.lifecycle_mode_state &= ~(1ULL << MODE_MENU);
// Restore libretro keyboard callback.
g_extern.system.key_event = key_event;
}
else
break;

View File

@ -22,8 +22,10 @@
#include "menu_common.h"
#include "../../performance.h"
#include "../../driver.h"
#include "../../file.h"
#include "menu_context.h"
#include "../../input/input_common.h"
#include "../../compat/posix_string.h"
@ -786,4 +788,135 @@ bool menu_save_new_config(void)
return ret;
}
void menu_poll_bind_state(struct rgui_bind_state *state)
{
memset(state->state, 0, sizeof(state->state));
state->skip = input_input_state_func(NULL, 0, RETRO_DEVICE_KEYBOARD, 0, RETROK_RETURN);
const rarch_joypad_driver_t *joypad = NULL;
if (driver.input && driver.input_data && driver.input->get_joypad_driver)
joypad = driver.input->get_joypad_driver(driver.input_data);
if (!joypad)
{
RARCH_ERR("Cannot poll raw joypad state.");
return;
}
input_joypad_poll(joypad);
for (unsigned p = 0; p < MAX_PLAYERS; p++)
{
for (unsigned b = 0; b < RGUI_MAX_BUTTONS; b++)
state->state[p].buttons[b] = input_joypad_button_raw(joypad, p, b);
for (unsigned a = 0; a < RGUI_MAX_AXES; a++)
state->state[p].axes[a] = input_joypad_axis_raw(joypad, p, a);
for (unsigned h = 0; h < RGUI_MAX_HATS; h++)
{
state->state[p].hats[h] |= input_joypad_hat_raw(joypad, p, HAT_UP_MASK, h) ? HAT_UP_MASK : 0;
state->state[p].hats[h] |= input_joypad_hat_raw(joypad, p, HAT_DOWN_MASK, h) ? HAT_DOWN_MASK : 0;
state->state[p].hats[h] |= input_joypad_hat_raw(joypad, p, HAT_LEFT_MASK, h) ? HAT_LEFT_MASK : 0;
state->state[p].hats[h] |= input_joypad_hat_raw(joypad, p, HAT_RIGHT_MASK, h) ? HAT_RIGHT_MASK : 0;
}
}
}
void menu_poll_bind_get_rested_axes(struct rgui_bind_state *state)
{
const rarch_joypad_driver_t *joypad = NULL;
if (driver.input && driver.input_data && driver.input->get_joypad_driver)
joypad = driver.input->get_joypad_driver(driver.input_data);
if (!joypad)
{
RARCH_ERR("Cannot poll raw joypad state.");
return;
}
for (unsigned p = 0; p < MAX_PLAYERS; p++)
for (unsigned a = 0; a < RGUI_MAX_AXES; a++)
state->axis_state[p].rested_axes[a] = input_joypad_axis_raw(joypad, p, a);
}
static bool menu_poll_find_trigger_pad(struct rgui_bind_state *state, struct rgui_bind_state *new_state, unsigned p)
{
const struct rgui_bind_state_port *n = &new_state->state[p];
const struct rgui_bind_state_port *o = &state->state[p];
for (unsigned b = 0; b < RGUI_MAX_BUTTONS; b++)
{
if (n->buttons[b] && !o->buttons[b])
{
state->target->joykey = b;
state->target->joyaxis = AXIS_NONE;
return true;
}
}
// Axes are a bit tricky ...
for (unsigned a = 0; a < RGUI_MAX_AXES; a++)
{
int locked_distance = abs(n->axes[a] - new_state->axis_state[p].locked_axes[a]);
int rested_distance = abs(n->axes[a] - new_state->axis_state[p].rested_axes[a]);
if (abs(n->axes[a]) >= 20000 &&
locked_distance >= 20000 &&
rested_distance >= 20000) // Take care of case where axis rests on +/- 0x7fff (e.g. 360 controller on Linux)
{
state->target->joyaxis = n->axes[a] > 0 ? AXIS_POS(a) : AXIS_NEG(a);
state->target->joykey = NO_BTN;
// Lock the current axis.
new_state->axis_state[p].locked_axes[a] = n->axes[a] > 0 ? 0x7fff : -0x7fff;
return true;
}
if (locked_distance >= 20000) // Unlock the axis.
new_state->axis_state[p].locked_axes[a] = 0;
}
for (unsigned h = 0; h < RGUI_MAX_HATS; h++)
{
uint16_t trigged = n->hats[h] & (~o->hats[h]);
uint16_t sane_trigger = 0;
if (trigged & HAT_UP_MASK)
sane_trigger = HAT_UP_MASK;
else if (trigged & HAT_DOWN_MASK)
sane_trigger = HAT_DOWN_MASK;
else if (trigged & HAT_LEFT_MASK)
sane_trigger = HAT_LEFT_MASK;
else if (trigged & HAT_RIGHT_MASK)
sane_trigger = HAT_RIGHT_MASK;
if (sane_trigger)
{
state->target->joykey = HAT_MAP(h, sane_trigger);
state->target->joyaxis = AXIS_NONE;
return true;
}
}
return false;
}
bool menu_poll_find_trigger(struct rgui_bind_state *state, struct rgui_bind_state *new_state)
{
for (unsigned p = 0; p < MAX_PLAYERS; p++)
{
if (menu_poll_find_trigger_pad(state, new_state, p))
{
g_settings.input.joypad_map[state->player] = p; // Update the joypad mapping automatically. More friendly that way.
return true;
}
}
return false;
}
void menu_key_event(bool down, unsigned keycode, uint32_t character, uint16_t key_modifiers)
{
// TODO: Do something with this. Stub for now.
(void)down;
(void)keycode;
(void)character;
(void)key_modifiers;
}

View File

@ -147,22 +147,38 @@ typedef enum
RGUI_SETTINGS_BIND_DEVICE,
RGUI_SETTINGS_BIND_DEVICE_TYPE,
RGUI_SETTINGS_BIND_DPAD_EMULATION,
// Match up with libretro order for simplicity.
RGUI_SETTINGS_BIND_BEGIN,
RGUI_SETTINGS_BIND_B = RGUI_SETTINGS_BIND_BEGIN,
RGUI_SETTINGS_BIND_Y,
RGUI_SETTINGS_BIND_SELECT,
RGUI_SETTINGS_BIND_START,
RGUI_SETTINGS_BIND_UP,
RGUI_SETTINGS_BIND_DOWN,
RGUI_SETTINGS_BIND_LEFT,
RGUI_SETTINGS_BIND_RIGHT,
RGUI_SETTINGS_BIND_A,
RGUI_SETTINGS_BIND_B,
RGUI_SETTINGS_BIND_X,
RGUI_SETTINGS_BIND_Y,
RGUI_SETTINGS_BIND_START,
RGUI_SETTINGS_BIND_SELECT,
RGUI_SETTINGS_BIND_L,
RGUI_SETTINGS_BIND_R,
RGUI_SETTINGS_BIND_L2,
RGUI_SETTINGS_BIND_R2,
RGUI_SETTINGS_BIND_L3,
RGUI_SETTINGS_BIND_R3,
RGUI_SETTINGS_BIND_ANALOG_LEFT_X_PLUS,
RGUI_SETTINGS_BIND_ANALOG_LEFT_X_MINUS,
RGUI_SETTINGS_BIND_ANALOG_LEFT_Y_PLUS,
RGUI_SETTINGS_BIND_ANALOG_LEFT_Y_MINUS,
RGUI_SETTINGS_BIND_ANALOG_RIGHT_X_PLUS,
RGUI_SETTINGS_BIND_ANALOG_RIGHT_X_MINUS,
RGUI_SETTINGS_BIND_ANALOG_RIGHT_Y_PLUS,
RGUI_SETTINGS_BIND_ANALOG_RIGHT_Y_MINUS,
RGUI_SETTINGS_BIND_LAST = RGUI_SETTINGS_BIND_ANALOG_RIGHT_Y_MINUS,
RGUI_SETTINGS_BIND_MENU_TOGGLE = RGUI_SETTINGS_BIND_BEGIN + RARCH_MENU_TOGGLE,
RGUI_SETTINGS_CUSTOM_BIND,
RGUI_SETTINGS_CUSTOM_BIND_ALL,
RGUI_SETTINGS_CUSTOM_BIND_DEFAULT_ALL,
RGUI_SETTINGS_CORE_OPTION_NONE = 0xffff,
RGUI_SETTINGS_CORE_OPTION_START = 0x10000
@ -186,6 +202,38 @@ typedef enum
RGUI_ACTION_NOOP
} rgui_action_t;
#define RGUI_MAX_BUTTONS 32
#define RGUI_MAX_AXES 32
#define RGUI_MAX_HATS 4
struct rgui_bind_state_port
{
bool buttons[RGUI_MAX_BUTTONS];
int16_t axes[RGUI_MAX_AXES];
uint16_t hats[RGUI_MAX_HATS];
};
struct rgui_bind_axis_state
{
// Default axis state.
int16_t rested_axes[RGUI_MAX_AXES];
// Locked axis state. If we configured an axis, avoid having the same axis state trigger something again right away.
int16_t locked_axes[RGUI_MAX_AXES];
};
struct rgui_bind_state
{
struct retro_keybind *target;
unsigned begin;
unsigned last;
unsigned player;
struct rgui_bind_state_port state[MAX_PLAYERS];
struct rgui_bind_axis_state axis_state[MAX_PLAYERS];
bool skip;
};
void menu_poll_bind_get_rested_axes(struct rgui_bind_state *state);
void menu_poll_bind_state(struct rgui_bind_state *state);
bool menu_poll_find_trigger(struct rgui_bind_state *state, struct rgui_bind_state *new_state);
#ifdef GEKKO
enum
@ -264,6 +312,8 @@ typedef struct
rom_history_t *history;
rarch_time_t last_time; // Used to throttle RGUI in case VSync is broken.
struct rgui_bind_state binds;
} rgui_handle_t;
extern rgui_handle_t *rgui;
@ -303,7 +353,8 @@ bool menu_replace_config(const char *path);
bool menu_save_new_config(void);
int menu_set_settings(unsigned setting, unsigned action);
extern const unsigned rgui_controller_lut[];
void menu_key_event(bool down, unsigned keycode, uint32_t character, uint16_t key_modifiers);
#ifdef __cplusplus
}

View File

@ -26,25 +26,6 @@
#define MAX_GAMMA_SETTING 1
#endif
const unsigned rgui_controller_lut[] = {
RETRO_DEVICE_ID_JOYPAD_UP,
RETRO_DEVICE_ID_JOYPAD_DOWN,
RETRO_DEVICE_ID_JOYPAD_LEFT,
RETRO_DEVICE_ID_JOYPAD_RIGHT,
RETRO_DEVICE_ID_JOYPAD_A,
RETRO_DEVICE_ID_JOYPAD_B,
RETRO_DEVICE_ID_JOYPAD_X,
RETRO_DEVICE_ID_JOYPAD_Y,
RETRO_DEVICE_ID_JOYPAD_START,
RETRO_DEVICE_ID_JOYPAD_SELECT,
RETRO_DEVICE_ID_JOYPAD_L,
RETRO_DEVICE_ID_JOYPAD_R,
RETRO_DEVICE_ID_JOYPAD_L2,
RETRO_DEVICE_ID_JOYPAD_R2,
RETRO_DEVICE_ID_JOYPAD_L3,
RETRO_DEVICE_ID_JOYPAD_R3,
};
#ifdef HAVE_SHADER_MANAGER
static enum rarch_shader_type shader_manager_get_type(const struct gfx_shader *shader)
{
@ -486,6 +467,30 @@ int menu_set_settings(unsigned setting, unsigned action)
keybind_action);
}
break;
case RGUI_SETTINGS_CUSTOM_BIND_ALL:
if (action == RGUI_ACTION_OK)
{
rgui->binds.target = &g_settings.input.binds[port][0];
rgui->binds.begin = RGUI_SETTINGS_BIND_BEGIN;
rgui->binds.last = RGUI_SETTINGS_BIND_LAST;
rgui_list_push(rgui->menu_stack, "", RGUI_SETTINGS_CUSTOM_BIND, rgui->selection_ptr);
menu_poll_bind_get_rested_axes(&rgui->binds);
menu_poll_bind_state(&rgui->binds);
}
break;
case RGUI_SETTINGS_CUSTOM_BIND_DEFAULT_ALL:
if (action == RGUI_ACTION_OK)
{
struct retro_keybind *target = &g_settings.input.binds[port][0];
rgui->binds.begin = RGUI_SETTINGS_BIND_BEGIN;
rgui->binds.last = RGUI_SETTINGS_BIND_LAST;
for (unsigned i = RGUI_SETTINGS_BIND_BEGIN; i <= RGUI_SETTINGS_BIND_LAST; i++, target++)
{
target->joykey = NO_BTN;
target->joyaxis = AXIS_NONE;
}
}
break;
case RGUI_SETTINGS_BIND_UP:
case RGUI_SETTINGS_BIND_DOWN:
case RGUI_SETTINGS_BIND_LEFT:
@ -502,6 +507,15 @@ int menu_set_settings(unsigned setting, unsigned action)
case RGUI_SETTINGS_BIND_R2:
case RGUI_SETTINGS_BIND_L3:
case RGUI_SETTINGS_BIND_R3:
case RGUI_SETTINGS_BIND_ANALOG_LEFT_X_PLUS:
case RGUI_SETTINGS_BIND_ANALOG_LEFT_X_MINUS:
case RGUI_SETTINGS_BIND_ANALOG_LEFT_Y_PLUS:
case RGUI_SETTINGS_BIND_ANALOG_LEFT_Y_MINUS:
case RGUI_SETTINGS_BIND_ANALOG_RIGHT_X_PLUS:
case RGUI_SETTINGS_BIND_ANALOG_RIGHT_X_MINUS:
case RGUI_SETTINGS_BIND_ANALOG_RIGHT_Y_PLUS:
case RGUI_SETTINGS_BIND_ANALOG_RIGHT_Y_MINUS:
case RGUI_SETTINGS_BIND_MENU_TOGGLE:
if (driver.input->set_keybinds)
{
unsigned keybind_action = KEYBINDS_ACTION_NONE;
@ -513,10 +527,31 @@ int menu_set_settings(unsigned setting, unsigned action)
else if (action == RGUI_ACTION_RIGHT)
keybind_action = (1ULL << KEYBINDS_ACTION_INCREMENT_BIND);
// FIXME: The array indices here look totally wrong ... Fixed it so it looks kind of sane for now.
if (keybind_action != KEYBINDS_ACTION_NONE)
driver.input->set_keybinds(driver.input_data, g_settings.input.device[setting - RGUI_SETTINGS_BIND_UP], port,
rgui_controller_lut[setting - RGUI_SETTINGS_BIND_UP], keybind_action);
driver.input->set_keybinds(driver.input_data, g_settings.input.device[port], port,
setting - RGUI_SETTINGS_BIND_BEGIN, keybind_action);
}
else
{
struct retro_keybind *bind = &g_settings.input.binds[port][setting - RGUI_SETTINGS_BIND_BEGIN];
if (action == RGUI_ACTION_OK)
{
rgui->binds.begin = setting;
rgui->binds.last = setting;
rgui->binds.target = bind;
rgui->binds.player = port;
rgui_list_push(rgui->menu_stack, "", RGUI_SETTINGS_CUSTOM_BIND, rgui->selection_ptr);
menu_poll_bind_get_rested_axes(&rgui->binds);
menu_poll_bind_state(&rgui->binds);
}
else if (action == RGUI_ACTION_START)
{
bind->joykey = NO_BTN;
bind->joyaxis = AXIS_NONE;
}
}
break;
case RGUI_BROWSER_DIR_PATH:
if (action == RGUI_ACTION_START)
{

View File

@ -33,6 +33,7 @@
#include "../../compat/posix_string.h"
#include "../../gfx/shader_parse.h"
#include "../../performance.h"
#include "../../input/input_common.h"
#ifdef HAVE_OPENGL
#include "../../gfx/gl_common.h"
@ -527,25 +528,49 @@ static void rgui_settings_controller_populate_entries(rgui_handle_t *rgui)
rgui_list_push(rgui->selection_buf, "Device Type", RGUI_SETTINGS_BIND_DEVICE_TYPE, 0);
if (driver.input && driver.input->set_keybinds)
{
rgui_list_push(rgui->selection_buf, "DPad Emulation", RGUI_SETTINGS_BIND_DPAD_EMULATION, 0);
rgui_list_push(rgui->selection_buf, "Up", RGUI_SETTINGS_BIND_UP, 0);
rgui_list_push(rgui->selection_buf, "Down", RGUI_SETTINGS_BIND_DOWN, 0);
rgui_list_push(rgui->selection_buf, "Left", RGUI_SETTINGS_BIND_LEFT, 0);
rgui_list_push(rgui->selection_buf, "Right", RGUI_SETTINGS_BIND_RIGHT, 0);
rgui_list_push(rgui->selection_buf, "A", RGUI_SETTINGS_BIND_A, 0);
rgui_list_push(rgui->selection_buf, "B", RGUI_SETTINGS_BIND_B, 0);
rgui_list_push(rgui->selection_buf, "X", RGUI_SETTINGS_BIND_X, 0);
rgui_list_push(rgui->selection_buf, "Y", RGUI_SETTINGS_BIND_Y, 0);
rgui_list_push(rgui->selection_buf, "Start", RGUI_SETTINGS_BIND_START, 0);
rgui_list_push(rgui->selection_buf, "Select", RGUI_SETTINGS_BIND_SELECT, 0);
rgui_list_push(rgui->selection_buf, "L", RGUI_SETTINGS_BIND_L, 0);
rgui_list_push(rgui->selection_buf, "R", RGUI_SETTINGS_BIND_R, 0);
rgui_list_push(rgui->selection_buf, "L2", RGUI_SETTINGS_BIND_L2, 0);
rgui_list_push(rgui->selection_buf, "R2", RGUI_SETTINGS_BIND_R2, 0);
rgui_list_push(rgui->selection_buf, "L3", RGUI_SETTINGS_BIND_L3, 0);
rgui_list_push(rgui->selection_buf, "R3", RGUI_SETTINGS_BIND_R3, 0);
else
{
rgui_list_push(rgui->selection_buf, "Configure All (RetroPad)", RGUI_SETTINGS_CUSTOM_BIND_ALL, 0); // This doesn't make sense on anything else than PC.
rgui_list_push(rgui->selection_buf, "Default All (RetroPad)", RGUI_SETTINGS_CUSTOM_BIND_DEFAULT_ALL, 0); // This doesn't make sense on anything else than PC.
}
if (rgui->current_pad == 0)
rgui_list_push(rgui->selection_buf, "RGUI Menu Toggle", RGUI_SETTINGS_BIND_MENU_TOGGLE, 0);
unsigned last = (driver.input && driver.input->set_keybinds) ? RGUI_SETTINGS_BIND_R3 : RGUI_SETTINGS_BIND_LAST;
for (unsigned i = RGUI_SETTINGS_BIND_BEGIN; i <= last; i++)
rgui_list_push(rgui->selection_buf, input_config_bind_map[i - RGUI_SETTINGS_BIND_BEGIN].desc, i, 0);
}
// This only makes sense for PC so far.
// Consoles use set_keybind callbacks instead.
static int rgui_custom_bind_iterate(rgui_handle_t *rgui, rgui_action_t action)
{
(void)action; // Have to ignore action here. Only bind that should work here is Quit RetroArch or something like that.
render_text(rgui);
char msg[256];
snprintf(msg, sizeof(msg), "[%s]\npress joypad\n(RETURN to skip)", input_config_bind_map[rgui->binds.begin - RGUI_SETTINGS_BIND_BEGIN].desc);
render_messagebox(rgui, msg);
struct rgui_bind_state binds = rgui->binds;
menu_poll_bind_state(&binds);
if ((binds.skip && !rgui->binds.skip) || menu_poll_find_trigger(&rgui->binds, &binds))
{
binds.begin++;
if (binds.begin <= binds.last)
binds.target++;
else
rgui_list_pop(rgui->menu_stack, &rgui->selection_ptr);
// Avoid new binds triggering things right away.
rgui->trigger_state = 0;
rgui->old_input_state = -1ULL;
}
rgui->binds = binds;
return 0;
}
static int rgui_viewport_iterate(rgui_handle_t *rgui, rgui_action_t action)
@ -1032,6 +1057,8 @@ static int rgui_iterate(void *data, unsigned action)
return rgui_settings_iterate(rgui, action);
else if (menu_type == RGUI_SETTINGS_CUSTOM_VIEWPORT || menu_type == RGUI_SETTINGS_CUSTOM_VIEWPORT_2)
return rgui_viewport_iterate(rgui, action);
else if (menu_type == RGUI_SETTINGS_CUSTOM_BIND)
return rgui_custom_bind_iterate(rgui, action);
if (rgui->need_refresh && action != RGUI_ACTION_MESSAGE)
action = RGUI_ACTION_NOOP;

View File

@ -145,17 +145,36 @@ static void render_messagebox(rgui_handle_t *rgui, const char *message)
if (!message || !*message)
return;
char *msg = strdup(message);
if (strlen(msg) > TERM_WIDTH)
struct string_list *list = string_split(message, "\n");
if (!list)
return;
if (list->elems == 0)
{
msg[TERM_WIDTH - 2] = '.';
msg[TERM_WIDTH - 1] = '.';
msg[TERM_WIDTH - 0] = '.';
msg[TERM_WIDTH + 1] = '\0';
string_list_free(list);
return;
}
unsigned width = strlen(msg) * FONT_WIDTH_STRIDE - 1 + 6 + 10;
unsigned height = FONT_HEIGHT + 6 + 10;
unsigned width = 0;
unsigned glyphs_width = 0;
for (size_t i = 0; i < list->size; i++)
{
char *msg = list->elems[i].data;
unsigned msglen = strlen(msg);
if (msglen > TERM_WIDTH)
{
msg[TERM_WIDTH - 2] = '.';
msg[TERM_WIDTH - 1] = '.';
msg[TERM_WIDTH - 0] = '.';
msg[TERM_WIDTH + 1] = '\0';
msglen = TERM_WIDTH;
}
unsigned line_width = msglen * FONT_WIDTH_STRIDE - 1 + 6 + 10;
width = max(width, line_width);
glyphs_width = max(glyphs_width, msglen);
}
unsigned height = FONT_HEIGHT_STRIDE * list->size + 6 + 10;
int x = (RGUI_WIDTH - width) / 2;
int y = (RGUI_HEIGHT - height) / 2;
@ -174,8 +193,15 @@ static void render_messagebox(rgui_handle_t *rgui, const char *message)
fill_rect(rgui->frame_buf, rgui->frame_buf_pitch,
x, y + 5, 5, height - 5, green_filler);
blit_line(rgui, x + 8, y + 8, msg, false);
free(msg);
for (size_t i = 0; i < list->size; i++)
{
const char *msg = list->elems[i].data;
int offset_x = FONT_WIDTH_STRIDE * (glyphs_width - strlen(msg)) / 2;
int offset_y = FONT_HEIGHT_STRIDE * i;
blit_line(rgui, x + 8 + offset_x, y + 8 + offset_y, msg, false);
}
string_list_free(list);
}
static void render_text(rgui_handle_t *rgui)
@ -230,6 +256,7 @@ static void render_text(rgui_handle_t *rgui)
(menu_type == RGUI_SETTINGS_PATH_OPTIONS) ||
(menu_type == RGUI_SETTINGS_OPTIONS) ||
(menu_type == RGUI_SETTINGS_CUSTOM_VIEWPORT || menu_type == RGUI_SETTINGS_CUSTOM_VIEWPORT_2) ||
menu_type == RGUI_SETTINGS_CUSTOM_BIND ||
menu_type == RGUI_SETTINGS)
snprintf(title, sizeof(title), "MENU %s", dir);
else if (menu_type == RGUI_SETTINGS_OPEN_HISTORY)
@ -303,7 +330,13 @@ static void render_text(rgui_handle_t *rgui)
rgui_list_get_at_offset(rgui->selection_buf, i, &path, &type);
char message[256];
char type_str[256];
unsigned w = (menu_type == RGUI_SETTINGS_INPUT_OPTIONS || menu_type == RGUI_SETTINGS_PATH_OPTIONS) ? 24 : 19;
unsigned w = 19;
if (menu_type == RGUI_SETTINGS_INPUT_OPTIONS || menu_type == RGUI_SETTINGS_CUSTOM_BIND)
w = 21;
else if (menu_type == RGUI_SETTINGS_PATH_OPTIONS)
w = 24;
unsigned port = rgui->current_pad;
#ifdef HAVE_SHADER_MANAGER
@ -533,6 +566,8 @@ static void render_text(rgui_handle_t *rgui)
case RGUI_SETTINGS_INPUT_OPTIONS:
case RGUI_SETTINGS_PATH_OPTIONS:
case RGUI_SETTINGS_OPTIONS:
case RGUI_SETTINGS_CUSTOM_BIND_ALL:
case RGUI_SETTINGS_CUSTOM_BIND_DEFAULT_ALL:
strlcpy(type_str, "...", sizeof(type_str));
break;
#ifdef HAVE_OVERLAY
@ -624,18 +659,33 @@ static void render_text(rgui_handle_t *rgui)
case RGUI_SETTINGS_BIND_R2:
case RGUI_SETTINGS_BIND_L3:
case RGUI_SETTINGS_BIND_R3:
case RGUI_SETTINGS_BIND_ANALOG_LEFT_X_PLUS:
case RGUI_SETTINGS_BIND_ANALOG_LEFT_X_MINUS:
case RGUI_SETTINGS_BIND_ANALOG_LEFT_Y_PLUS:
case RGUI_SETTINGS_BIND_ANALOG_LEFT_Y_MINUS:
case RGUI_SETTINGS_BIND_ANALOG_RIGHT_X_PLUS:
case RGUI_SETTINGS_BIND_ANALOG_RIGHT_X_MINUS:
case RGUI_SETTINGS_BIND_ANALOG_RIGHT_Y_PLUS:
case RGUI_SETTINGS_BIND_ANALOG_RIGHT_Y_MINUS:
case RGUI_SETTINGS_BIND_MENU_TOGGLE:
{
unsigned id = type - RGUI_SETTINGS_BIND_B;
struct platform_bind key_label;
strlcpy(key_label.desc, "Unknown", sizeof(key_label.desc));
key_label.joykey = g_settings.input.binds[port][id].joykey;
if (driver.input->set_keybinds)
{
unsigned id = rgui_controller_lut[type - RGUI_SETTINGS_BIND_UP];
struct platform_bind key_label;
strlcpy(key_label.desc, "Unknown", sizeof(key_label.desc));
key_label.joykey = g_settings.input.binds[port][id].joykey;
if (driver.input->set_keybinds)
driver.input->set_keybinds(&key_label, 0, 0, 0, (1ULL << KEYBINDS_ACTION_GET_BIND_LABEL));
driver.input->set_keybinds(&key_label, 0, 0, 0, (1ULL << KEYBINDS_ACTION_GET_BIND_LABEL));
strlcpy(type_str, key_label.desc, sizeof(type_str));
}
else
{
const struct retro_keybind *bind = &g_settings.input.binds[port][type - RGUI_SETTINGS_BIND_BEGIN];
input_get_bind_string(type_str, bind, sizeof(type_str));
}
break;
}
default:
type_str[0] = 0;
w = 0;
@ -679,3 +729,4 @@ static void render_text(rgui_handle_t *rgui)
render_messagebox(rgui, message_queue);
#endif
}

View File

@ -61,32 +61,6 @@ const char* const input_builtin_autoconfs[] =
"input_driver = \"winxinput\" \n"
XINPUT_DEFAULT_BINDS,
"input_device = \"Dual Trigger 3-in-1\" \n"
"input_driver = \"dinput\" \n"
DECL_BTN(a, 2)
DECL_BTN(b, 1)
DECL_BTN(x, 3)
DECL_BTN(y, 0)
DECL_BTN(start, 9)
DECL_BTN(select, 8)
DECL_BTN(up, h0up)
DECL_BTN(down, h0down)
DECL_BTN(left, h0left)
DECL_BTN(right, h0right)
DECL_BTN(l, 4)
DECL_BTN(r, 5)
DECL_BTN(l2, 6)
DECL_BTN(r2, 7)
DECL_BTN(l3, 10)
DECL_BTN(r3, 11)
DECL_AXIS(l_x_plus, +0)
DECL_AXIS(l_x_minus, -0)
DECL_AXIS(l_y_plus, +1)
DECL_AXIS(l_y_minus, -1)
DECL_AXIS(r_x_plus, +2)
DECL_AXIS(r_x_minus, -2)
DECL_AXIS(r_y_plus, +5)
DECL_AXIS(r_y_minus, -5),
NULL
};

View File

@ -340,6 +340,12 @@ static bool dinput_set_rumble(void *data, unsigned port, enum retro_rumble_effec
return input_joypad_set_rumble(di->joypad, port, effect, strength);
}
static const rarch_joypad_driver_t *dinput_get_joypad_driver(void *data)
{
struct dinput_input *di = (struct dinput_input*)data;
return di->joypad;
}
const input_driver_t input_dinput = {
dinput_init,
dinput_poll,
@ -351,6 +357,7 @@ const input_driver_t input_dinput = {
dinput_grab_mouse,
dinput_set_rumble,
dinput_get_joypad_driver,
};
// Keep track of which pad indexes are 360 controllers

View File

@ -642,6 +642,29 @@ enum retro_key input_translate_keysym_to_rk(unsigned sym)
return RETROK_UNKNOWN;
}
void input_translate_rk_to_str(enum retro_key key, char *buf, size_t size)
{
rarch_assert(size >= 2);
*buf = '\0';
if (key >= RETROK_a && key <= RETROK_z)
{
buf[0] = (key - RETROK_a) + 'a';
buf[1] = '\0';
}
else
{
for (unsigned i = 0; input_config_key_map[i].str; i++)
{
if (input_config_key_map[i].key == key)
{
strlcpy(buf, input_config_key_map[i].str, size);
break;
}
}
}
}
unsigned input_translate_rk_to_keysym(enum retro_key key)
{
return rarch_keysym_lut[key];
@ -672,13 +695,12 @@ const struct input_bind_map input_config_bind_map[RARCH_BIND_LIST_END_NULL] = {
DECLARE_BIND(right, RETRO_DEVICE_ID_JOYPAD_RIGHT, "Right D-pad"),
DECLARE_BIND(a, RETRO_DEVICE_ID_JOYPAD_A, "A button (right)"),
DECLARE_BIND(x, RETRO_DEVICE_ID_JOYPAD_X, "X button (top)"),
DECLARE_BIND(l, RETRO_DEVICE_ID_JOYPAD_L, "L button (left shoulder)"),
DECLARE_BIND(r, RETRO_DEVICE_ID_JOYPAD_R, "R button (right shoulder)"),
DECLARE_BIND(l2, RETRO_DEVICE_ID_JOYPAD_L2, "L2 button (left shoulder #2)"),
DECLARE_BIND(r2, RETRO_DEVICE_ID_JOYPAD_R2, "R2 button (right shoulder #2)"),
DECLARE_BIND(l3, RETRO_DEVICE_ID_JOYPAD_L3, "L3 button (left analog button)"),
DECLARE_BIND(r3, RETRO_DEVICE_ID_JOYPAD_R3, "R3 button (right analog button)"),
DECLARE_BIND(turbo, RARCH_TURBO_ENABLE, "Turbo enable"),
DECLARE_BIND(l, RETRO_DEVICE_ID_JOYPAD_L, "L button (shoulder)"),
DECLARE_BIND(r, RETRO_DEVICE_ID_JOYPAD_R, "R button (shoulder)"),
DECLARE_BIND(l2, RETRO_DEVICE_ID_JOYPAD_L2, "L2 button (trigger)"),
DECLARE_BIND(r2, RETRO_DEVICE_ID_JOYPAD_R2, "R2 button (trigger)"),
DECLARE_BIND(l3, RETRO_DEVICE_ID_JOYPAD_L3, "L3 button (thumb)"),
DECLARE_BIND(r3, RETRO_DEVICE_ID_JOYPAD_R3, "R3 button (thumb)"),
DECLARE_BIND(l_x_plus, RARCH_ANALOG_LEFT_X_PLUS, "Left analog X+ (right)"),
DECLARE_BIND(l_x_minus, RARCH_ANALOG_LEFT_X_MINUS, "Left analog X- (left)"),
DECLARE_BIND(l_y_plus, RARCH_ANALOG_LEFT_Y_PLUS, "Left analog Y+ (down)"),
@ -688,6 +710,20 @@ const struct input_bind_map input_config_bind_map[RARCH_BIND_LIST_END_NULL] = {
DECLARE_BIND(r_y_plus, RARCH_ANALOG_RIGHT_Y_PLUS, "Right analog Y+ (down)"),
DECLARE_BIND(r_y_minus, RARCH_ANALOG_RIGHT_Y_MINUS, "Right analog Y- (up)"),
// FIXME: Unsure what to do here.
// The D-pad emulation concept really needs a rethink ...
#ifdef RARCH_CONSOLE
DECLARE_BIND(dpad_l_x_l, RARCH_ANALOG_LEFT_X_DPAD_LEFT, "Left analog D-pad left"),
DECLARE_BIND(dpad_l_x_r, RARCH_ANALOG_LEFT_X_DPAD_RIGHT, "Left analog D-pad right"),
DECLARE_BIND(dpad_l_y_u, RARCH_ANALOG_LEFT_Y_DPAD_UP, "Left analog D-pad up"),
DECLARE_BIND(dpad_l_y_d, RARCH_ANALOG_LEFT_Y_DPAD_DOWN, "Left analog D-pad down"),
DECLARE_BIND(dpad_r_x_l, RARCH_ANALOG_RIGHT_X_DPAD_LEFT, "Right analog D-pad left"),
DECLARE_BIND(dpad_r_x_r, RARCH_ANALOG_RIGHT_X_DPAD_RIGHT, "Right analog D-pad right"),
DECLARE_BIND(dpad_r_y_u, RARCH_ANALOG_RIGHT_Y_DPAD_UP, "Right analog D-pad up"),
DECLARE_BIND(dpad_r_y_d, RARCH_ANALOG_RIGHT_Y_DPAD_DOWN, "Right analog D-pad down"),
#endif
DECLARE_BIND(turbo, RARCH_TURBO_ENABLE, "Turbo enable"),
DECLARE_META_BIND(1, toggle_fast_forward, RARCH_FAST_FORWARD_KEY, "Fast forward toggle"),
DECLARE_META_BIND(2, hold_fast_forward, RARCH_FAST_FORWARD_HOLD_KEY, "Fast forward hold"),
DECLARE_META_BIND(1, load_state, RARCH_LOAD_STATE_KEY, "Load state"),
@ -794,6 +830,54 @@ const struct input_key_map input_config_key_map[] = {
{ NULL, RETROK_UNKNOWN },
};
void input_get_bind_string(char *buf, const struct retro_keybind *bind, size_t size)
{
*buf = '\0';
if (bind->joykey != NO_BTN)
{
if (GET_HAT_DIR(bind->joykey))
{
const char *dir;
switch (GET_HAT_DIR(bind->joykey))
{
case HAT_UP_MASK: dir = "up"; break;
case HAT_DOWN_MASK: dir = "down"; break;
case HAT_LEFT_MASK: dir = "left"; break;
case HAT_RIGHT_MASK: dir = "right"; break;
default: dir = "?"; break;
}
snprintf(buf, size, "Hat #%u %s ", (unsigned)GET_HAT(bind->joykey), dir);
}
else
snprintf(buf, size, "%u (btn) ", (unsigned)bind->joykey);
}
else if (bind->joyaxis != AXIS_NONE)
{
unsigned axis = 0;
char dir = '\0';
if (AXIS_NEG_GET(bind->joyaxis) != AXIS_DIR_NONE)
{
dir = '-';
axis = AXIS_NEG_GET(bind->joyaxis);
}
else if (AXIS_POS_GET(bind->joyaxis) != AXIS_DIR_NONE)
{
dir = '+';
axis = AXIS_POS_GET(bind->joyaxis);
}
snprintf(buf, size, "%c%u (axis) ", dir, axis);
}
char key[64];
input_translate_rk_to_str(bind->key, key, sizeof(key));
if (!strcmp(key, "nul"))
*key = '\0';
char keybuf[64];
snprintf(keybuf, sizeof(keybuf), "(Key: %s)", key);
strlcat(buf, keybuf, size);
}
static enum retro_key find_sk_bind(const char *str)
{
for (size_t i = 0; input_config_key_map[i].str; i++)

View File

@ -132,14 +132,18 @@ struct input_bind_map
const char *desc;
unsigned retro_key;
};
extern const struct input_bind_map input_config_bind_map[];
void input_get_bind_string(char *buf, const struct retro_keybind *bind, size_t size);
struct input_key_map
{
const char *str;
enum retro_key key;
};
extern const struct input_key_map input_config_key_map[];
void input_translate_rk_to_str(enum retro_key key, char *buf, size_t size);
extern const char* const input_builtin_autoconfs[];

View File

@ -291,6 +291,12 @@ static bool linuxraw_set_rumble(void *data, unsigned port, enum retro_rumble_eff
return input_joypad_set_rumble(linuxraw->joypad, port, effect, strength);
}
static const rarch_joypad_driver_t *linuxraw_get_joypad_driver(void *data)
{
linuxraw_input_t *linuxraw = (linuxraw_input_t*)data;
return linuxraw->joypad;
}
static void linuxraw_input_poll(void *data)
{
linuxraw_input_t *linuxraw = (linuxraw_input_t*)data;
@ -325,4 +331,5 @@ const input_driver_t input_linuxraw = {
"linuxraw",
NULL,
linuxraw_set_rumble,
linuxraw_get_joypad_driver,
};

View File

@ -220,6 +220,12 @@ static bool sdl_set_rumble(void *data, unsigned port, enum retro_rumble_effect e
return input_joypad_set_rumble(sdl->joypad, port, effect, strength);
}
static const rarch_joypad_driver_t *sdl_get_joypad_driver(void *data)
{
sdl_input_t *sdl = (sdl_input_t*)data;
return sdl->joypad;
}
static void sdl_poll_mouse(sdl_input_t *sdl)
{
Uint8 btn = SDL_GetRelativeMouseState(&sdl->mouse_x, &sdl->mouse_y);
@ -248,5 +254,6 @@ const input_driver_t input_sdl = {
"sdl",
NULL,
sdl_set_rumble,
sdl_get_joypad_driver,
};

View File

@ -275,6 +275,12 @@ static bool x_set_rumble(void *data, unsigned port, enum retro_rumble_effect eff
return input_joypad_set_rumble(x11->joypad, port, effect, strength);
}
static const rarch_joypad_driver_t *x_get_joypad_driver(void *data)
{
x11_input_t *x11 = (x11_input_t*)data;
return x11->joypad;
}
const input_driver_t input_x = {
x_input_init,
x_input_poll,
@ -285,5 +291,6 @@ const input_driver_t input_x = {
"x",
x_grab_mouse,
x_set_rumble,
x_get_joypad_driver,
};

View File

@ -879,23 +879,8 @@ static void save_keybind_key(config_file_t *conf, const char *prefix, const char
char key[64];
snprintf(key, sizeof(key), "%s_%s", prefix, base);
char ascii[2] = {0};
const char *btn = ascii;
if (bind->key >= RETROK_a && bind->key <= RETROK_z)
ascii[0] = 'a' + (bind->key - RETROK_a);
else
{
for (unsigned i = 0; input_config_key_map[i].str; i++)
{
if (input_config_key_map[i].key == bind->key)
{
btn = input_config_key_map[i].str;
break;
}
}
}
char btn[64];
input_translate_rk_to_str(bind->key, btn, sizeof(btn));
config_set_string(conf, key, btn);
}
@ -1119,11 +1104,15 @@ bool config_save_file(const char *path)
config_set_int(conf, cfg, g_settings.input.libretro_device[i]);
}
for (unsigned i = 0; i < MAX_PLAYERS; i++)
save_keybinds_player(conf, i);
bool ret = config_file_write(conf, path);
config_file_free(conf);
return ret;
}
// FIXME: This is probably obsolete now.
bool config_save_keybinds(const char *path)
{
config_file_t *conf = config_file_new(path);
@ -1179,7 +1168,7 @@ void settings_set(uint64_t settings)
}
if (settings & (1ULL << S_DEF_INPUT_OVERLAY_SCALE))
g_settings.input.overlay_opacity = 1.0f;
g_settings.input.overlay_scale = 1.0f;
#endif
if (settings & (1ULL << S_REWIND_GRANULARITY_INCREMENT))