Skip to content

Commit

Permalink
ui: Support changing controller/keyboard mappings
Browse files Browse the repository at this point in the history
  • Loading branch information
antangelo committed Nov 9, 2023
1 parent b3fc80b commit 35244d8
Show file tree
Hide file tree
Showing 13 changed files with 736 additions and 99 deletions.
85 changes: 85 additions & 0 deletions config_spec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,91 @@ input:
rtrigger:
type: integer
default: 18 # w
gamepad_mappings:
type: array
items:
gamepad_id: string
enable_rumble:
type: bool
default: true
# steel_battalion_mapping:
# ...
controller_mapping:
a:
type: integer
default: 0
b:
type: integer
default: 1
x:
type: integer
default: 2
y:
type: integer
default: 3
back:
type: integer
default: 4
guide:
type: integer
default: 5
start:
type: integer
default: 6
lstick_btn:
type: integer
default: 7
rstick_btn:
type: integer
default: 8
lshoulder:
type: integer
default: 9
rshoulder:
type: integer
default: 10
dpad_up:
type: integer
default: 11
dpad_down:
type: integer
default: 12
dpad_left:
type: integer
default: 13
dpad_right:
type: integer
default: 14
axis_left_x:
type: integer
default: 0
axis_left_y:
type: integer
default: 1
axis_right_x:
type: integer
default: 2
axis_right_y:
type: integer
default: 3
axis_trigger_left:
type: integer
default: 4
axis_trigger_right:
type: integer
default: 5
invert_axis_left_x:
type: bool
default: false
invert_axis_left_y:
type: bool
default: false
invert_axis_right_x:
type: bool
default: false
invert_axis_right_y:
type: bool
default: false

display:
quality:
Expand Down
2 changes: 1 addition & 1 deletion genconfig
1 change: 1 addition & 0 deletions ui/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ xemu_ss.add(files(
'xemu-monitor.c',
'xemu-net.c',
'xemu-settings.cc',
'xemu-controllers.cc',

'xemu.c',
'xemu-data.c',
Expand Down
102 changes: 102 additions & 0 deletions ui/xemu-controllers.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* xemu Controller Binding Management
*
* Copyright (C) 2020-2023 Matt Borgerson
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#include "xemu-controllers.h"
#include "xemu-settings.h"
#include <assert.h>
#include <limits>
#include <string>

std::pair<bool, bool>
ControllerKeyboardRebindingMap::ConsumeRebindEvent(SDL_Event *event)
{
if (event->type == SDL_KEYDOWN) {
*(g_keyboard_scancode_map[table_row]) = event->key.keysym.scancode;

return { true, true };
}

return { false, false };
}

std::pair<bool, bool>
ControllerGamepadRebindingMap::ConsumeRebindEvent(SDL_Event *event)
{
if (event->type == SDL_CONTROLLERDEVICEREMOVED) {
if (state->sdl_joystick_id == event->cdevice.which) {
return { false, true };
}
} else if (event->type == SDL_CONTROLLERBUTTONUP && table_row < 15 &&
seen_key_down) {
// Bind on controller up ensures the UI does not immediately respond
// once the new binding is applied

if (state->sdl_joystick_id != event->cbutton.which) {
return { false, false };
}

int *button_map[15] = {
&state->controller_map->controller_mapping.a,
&state->controller_map->controller_mapping.b,
&state->controller_map->controller_mapping.x,
&state->controller_map->controller_mapping.y,
&state->controller_map->controller_mapping.back,
&state->controller_map->controller_mapping.guide,
&state->controller_map->controller_mapping.start,
&state->controller_map->controller_mapping.lstick_btn,
&state->controller_map->controller_mapping.rstick_btn,
&state->controller_map->controller_mapping.lshoulder,
&state->controller_map->controller_mapping.rshoulder,
&state->controller_map->controller_mapping.dpad_up,
&state->controller_map->controller_mapping.dpad_down,
&state->controller_map->controller_mapping.dpad_left,
&state->controller_map->controller_mapping.dpad_right,
};

*(button_map[table_row]) = event->cbutton.button;

return { true, true };
} else if (event->type == SDL_CONTROLLERBUTTONDOWN && table_row < 15) {
// If we are rebinding with a controller, we should not consume the key
// up event from activating the button
seen_key_down = true;
} else if (event->type == SDL_CONTROLLERAXISMOTION && table_row >= 15 &&
std::abs(event->caxis.value >> 1) >
std::numeric_limits<Sint16>::max() >> 2) {
// FIXME: Allow face buttons to map to axes
if (state->sdl_joystick_id != event->caxis.which) {
return { false, false };
}

int *axis_map[6] = {
&state->controller_map->controller_mapping.axis_left_x,
&state->controller_map->controller_mapping.axis_left_y,
&state->controller_map->controller_mapping.axis_right_x,
&state->controller_map->controller_mapping.axis_right_y,
&state->controller_map->controller_mapping.axis_trigger_left,
&state->controller_map->controller_mapping.axis_trigger_right,
};

*(axis_map[table_row - 15]) = event->caxis.axis;

return { true, true };
}

return { false, false };
}
82 changes: 82 additions & 0 deletions ui/xemu-controllers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
/*
* xemu Settings Management
*
* Copyright (C) 2020-2023 Matt Borgerson
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef XEMU_CONTROLLERS_H
#define XEMU_CONTROLLERS_H

#include "xemu-input.h"
#include "xemu-settings.h"
#include <SDL.h>

#ifdef __cplusplus

struct RebindingMap {
// Returns [consume, cancel]:
// consume: Whether the SDL_Event should not propagate to the UI
// cancel: Whether this rebinding map should be cancelled
virtual std::pair<bool, bool> ConsumeRebindEvent(SDL_Event *event) = 0;

int GetTableRow() const
{
return table_row;
}

virtual ~RebindingMap()
{
}

protected:
int table_row;
RebindingMap(int table_row) : table_row{ table_row }
{
}
};

struct ControllerKeyboardRebindingMap : public virtual RebindingMap {
std::pair<bool, bool> ConsumeRebindEvent(SDL_Event *event) override;

ControllerKeyboardRebindingMap(int table_row) : RebindingMap(table_row)
{
}
};

class ControllerGamepadRebindingMap : public virtual RebindingMap {
ControllerState *state;
bool seen_key_down;

public:
std::pair<bool, bool> ConsumeRebindEvent(SDL_Event *event) override;
ControllerGamepadRebindingMap(int table_row, ControllerState *state)
: RebindingMap(table_row), state{ state }, seen_key_down{ false }
{
}
};

extern "C" {
#endif

extern int *g_keyboard_scancode_map[25];

GamepadMappings *xemu_settings_load_gamepad_mapping(const char *guid);

#ifdef __cplusplus
}
#endif

#endif
Loading

0 comments on commit 35244d8

Please sign in to comment.