switch to a (mostly) functioning GameController API

This commit is contained in:
Struma 2022-07-03 21:36:48 -04:00
parent 342f30069f
commit 5f4b644bd0
10 changed files with 1910 additions and 278 deletions

1678
assets/gamecontrollerdb.txt Normal file

File diff suppressed because it is too large Load diff

View file

@ -281,20 +281,20 @@ case SDL_JOYSTICK_POWER_##c: \
v = M_SYMBOL(#c); \
break;
RB_METHOD(inputJoystickInfo) {
RB_METHOD(inputControllerInfo) {
RB_UNUSED_PARAM;
if (!shState->input().getJoystickConnected())
if (!shState->input().getControllerConnected())
return RUBY_Qnil;
VALUE ret = rb_hash_new();
rb_hash_aset(ret, M_SYMBOL("name"),
rb_utf8_str_new_cstr(shState->input().getJoystickName()));
rb_utf8_str_new_cstr(shState->input().getControllerName()));
VALUE power;
switch (shState->input().getJoystickPowerLevel()) {
switch (shState->input().getControllerPowerLevel()) {
POWERCASE(power, MAX);
POWERCASE(power, WIRED);
POWERCASE(power, FULL);
@ -423,7 +423,8 @@ void inputBindingInit() {
_rb_define_module_function(module, "mouse_y", inputMouseY);
_rb_define_module_function(module, "scroll_v", inputScrollV);
_rb_define_module_function(module, "joystick", inputJoystickInfo);
_rb_define_module_function(module, "joystick", inputControllerInfo);
_rb_define_module_function(module, "controller", inputControllerInfo);
_rb_define_module_function(module, "text_input", inputGetMode);
_rb_define_module_function(module, "text_input=", inputSetMode);

View file

@ -158,8 +158,8 @@ typedef NSMutableArray<NSNumber*> BindingIndexArray;
#define checkButtonEnd else { return; }
#define checkButtonElement(e, b, n, min) \
else if (sysver >= min && element == gamepad.e && gamepad.b.isPressed) { \
s.type = JButton; \
s.d.jb = n; \
s.type = CButton; \
s.d.cb = n; \
}
#define checkButtonAlt(b, n, min) checkButtonElement(b, b, n, min)
@ -168,9 +168,9 @@ s.d.jb = n; \
#define setAxisData(a, n) \
GCControllerAxisInput *axis = gamepad.a; \
s.type = JAxis; \
s.d.ja.axis = n; \
s.d.ja.dir = (axis.value >= 0) ? AxisDir::Positive : AxisDir::Negative;
s.type = CAxis; \
s.d.ca.axis = n; \
s.d.ca.dir = (axis.value >= 0) ? AxisDir::Positive : AxisDir::Negative;
#define checkAxis(el, a, n) else if (element == gamepad.el && (gamepad.el.a.value >= 0.5 || gamepad.el.a.value <= -0.5)) { setAxisData(el.a, n); }
@ -184,43 +184,43 @@ s.d.ja.dir = (axis.value >= 0) ? AxisDir::Positive : AxisDir::Negative;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunguarded-availability-new"
checkButtonStart
checkButton(A, 0, 12)
checkButton(B, 1, 12)
checkButton(X, 2, 12)
checkButton(Y, 3, 12)
checkButtonElement(dpad, dpad.up, 11, 12)
checkButtonElement(dpad, dpad.down, 12, 12)
checkButtonElement(dpad, dpad.left, 13, 12)
checkButtonElement(dpad, dpad.right, 14, 12)
checkButtonAlt(leftShoulder, 9, 12)
checkButtonAlt(rightShoulder, 10, 12)
checkButton(A, SDL_CONTROLLER_BUTTON_A, 12)
checkButton(B, SDL_CONTROLLER_BUTTON_B, 12)
checkButton(X, SDL_CONTROLLER_BUTTON_X, 12)
checkButton(Y, SDL_CONTROLLER_BUTTON_Y, 12)
checkButtonElement(dpad, dpad.up, SDL_CONTROLLER_BUTTON_DPAD_UP, 12)
checkButtonElement(dpad, dpad.down, SDL_CONTROLLER_BUTTON_DPAD_DOWN, 12)
checkButtonElement(dpad, dpad.left, SDL_CONTROLLER_BUTTON_DPAD_LEFT, 12)
checkButtonElement(dpad, dpad.right, SDL_CONTROLLER_BUTTON_DPAD_RIGHT, 12)
checkButtonAlt(leftShoulder, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, 12)
checkButtonAlt(rightShoulder, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, 12)
// Requires macOS 10.14.1+
checkButtonAlt(leftThumbstickButton, 7, 14)
checkButtonAlt(rightThumbstickButton, 8, 14)
checkButtonAlt(leftThumbstickButton, SDL_CONTROLLER_BUTTON_LEFTSTICK, 14)
checkButtonAlt(rightThumbstickButton, SDL_CONTROLLER_BUTTON_RIGHTSTICK, 14)
// Requires macOS 10.15+
checkButton(Menu, 6, 15)
checkButton(Options, 4, 15)
checkButton(Menu, SDL_CONTROLLER_BUTTON_START, 15)
checkButton(Options, SDL_CONTROLLER_BUTTON_BACK, 15)
// Requires macOS 11.0+
checkButton(Home, 5, 16)
checkButton(Home, SDL_CONTROLLER_BUTTON_GUIDE, 16)
checkAxis(leftThumbstick, xAxis, 0)
checkAxis(leftThumbstick, yAxis, 1)
checkAxis(rightThumbstick, xAxis, 2)
checkAxis(rightThumbstick, yAxis, 3)
checkAxis(leftThumbstick, xAxis, SDL_CONTROLLER_AXIS_LEFTX)
checkAxis(leftThumbstick, yAxis, SDL_CONTROLLER_AXIS_LEFTY)
checkAxis(rightThumbstick, xAxis, SDL_CONTROLLER_AXIS_RIGHTX)
checkAxis(rightThumbstick, yAxis, SDL_CONTROLLER_AXIS_RIGHTY)
else if (element == gamepad.leftTrigger && (gamepad.leftTrigger.value >= 0.5 || gamepad.leftTrigger.value <= -0.5)) {
s.type = JAxis;
s.d.ja.axis = 4;
s.d.ja.dir = AxisDir::Positive;
s.type = CAxis;
s.d.ca.axis = SDL_CONTROLLER_AXIS_TRIGGERLEFT;
s.d.ca.dir = AxisDir::Positive;
}
else if (element == gamepad.rightTrigger && (gamepad.rightTrigger.value >= 0.5 || gamepad.rightTrigger.value <= -0.5)) {
s.type = JAxis;
s.d.ja.axis = 5;
s.d.ja.dir = AxisDir::Positive;
s.type = CAxis;
s.d.ca.axis = SDL_CONTROLLER_AXIS_TRIGGERRIGHT;
s.d.ca.dir = AxisDir::Positive;
}
checkButtonEnd;
@ -236,30 +236,11 @@ s.d.ja.dir = (axis.value >= 0) ? AxisDir::Positive : AxisDir::Negative;
case Key:
if (desc.d.scan == SDL_SCANCODE_LSHIFT) return @"Shift";
return @(SDL_GetScancodeName(desc.d.scan));
case JHat:
const char *dir;
switch (desc.d.jh.pos) {
case SDL_HAT_UP:
dir = "Up";
break;
case SDL_HAT_DOWN:
dir = "Down";
break;
case SDL_HAT_LEFT:
dir = "Left";
break;
case SDL_HAT_RIGHT:
dir = "Right";
break;
default:
dir = "-";
break;
}
return [NSString stringWithFormat:@"JS Hat %d:%s", desc.d.jh.hat, dir];
case JAxis:
return [NSString stringWithFormat:@"JS Axis %d%s", desc.d.ja.axis, desc.d.ja.dir == Negative ? "-" : "+"];
case JButton:
return [NSString stringWithFormat:@"JS Button %i", desc.d.jb];
case CAxis:
return [NSString stringWithFormat:@"%s%s",
shState->input().getAxisName(desc.d.ca.axis), desc.d.ca.dir == Negative ? "-" : "+"];
case CButton:
return @(shState->input().getButtonName(desc.d.cb));
default:
return @"Invalid";
}

View file

@ -22,7 +22,6 @@
#include "eventthread.h"
#include <SDL_events.h>
#include <SDL_joystick.h>
#include <SDL_messagebox.h>
#include <SDL_timer.h>
#include <SDL_thread.h>
@ -83,7 +82,7 @@ initALCFunctions(ALCdevice *alcDev)
#define HAVE_ALC_DEVICE_PAUSE alc.DevicePause
uint8_t EventThread::keyStates[];
EventThread::JoyState EventThread::joyState;
EventThread::ControllerState EventThread::controllerState;
EventThread::MouseState EventThread::mouseState;
EventThread::TouchState EventThread::touchState;
SDL_atomic_t EventThread::verticalScrollDistance;
@ -122,7 +121,7 @@ bool EventThread::allocUserEvents()
}
EventThread::EventThread()
: js(0),
: ctrl(0),
fullscreen(false),
showCursor(true)
{
@ -164,8 +163,13 @@ void EventThread::process(RGSSThreadData &rtData)
bool terminate = false;
if (SDL_NumJoysticks() > 0)
js = SDL_JoystickOpen(0);
// debug, haven't actually added it to the build systems yet
SDL_GameControllerAddMappingsFromFile("/Users/zorua/Documents/Source/mkxp-z/assets/gamecontrollerdb.txt");
SDL_JoystickUpdate();
if (SDL_NumJoysticks() > 0 && SDL_IsGameController(0)) {
ctrl = SDL_GameControllerOpen(0);
}
char buffer[128];
@ -387,32 +391,28 @@ void EventThread::process(RGSSThreadData &rtData)
keyStates[event.key.keysym.scancode] = false;
break;
case SDL_JOYBUTTONDOWN :
joyState.buttons[event.jbutton.button] = true;
case SDL_CONTROLLERBUTTONDOWN:
controllerState.buttons[event.cbutton.button] = true;
break;
case SDL_JOYBUTTONUP :
joyState.buttons[event.jbutton.button] = false;
case SDL_CONTROLLERBUTTONUP:
controllerState.buttons[event.cbutton.button] = false;
break;
case SDL_JOYHATMOTION :
joyState.hats[event.jhat.hat] = event.jhat.value;
case SDL_CONTROLLERAXISMOTION:
controllerState.axes[event.caxis.axis] = event.caxis.value;
break;
case SDL_JOYAXISMOTION :
joyState.axes[event.jaxis.axis] = event.jaxis.value;
case SDL_CONTROLLERDEVICEADDED:
if (event.cdevice.which > 0)
break;
case SDL_JOYDEVICEADDED :
if (event.jdevice.which > 0)
ctrl = SDL_GameControllerOpen(0);
break;
js = SDL_JoystickOpen(0);
break;
case SDL_JOYDEVICEREMOVED :
case SDL_CONTROLLERDEVICEREMOVED:
resetInputStates();
js = 0;
ctrl = 0;
break;
case SDL_MOUSEBUTTONDOWN :
@ -575,8 +575,8 @@ void EventThread::process(RGSSThreadData &rtData)
/* Just in case */
rtData.syncPoint.resumeThreads();
if (SDL_JoystickGetAttached(js))
SDL_JoystickClose(js);
if (SDL_GameControllerGetAttached(ctrl))
SDL_GameControllerClose(ctrl);
#ifndef MKXPZ_BUILD_XCODE
delete sMenu;
@ -649,7 +649,7 @@ void EventThread::cleanup()
void EventThread::resetInputStates()
{
memset(&keyStates, 0, sizeof(keyStates));
memset(&joyState, 0, sizeof(joyState));
memset(&controllerState, 0, sizeof(controllerState));
memset(&mouseState.buttons, 0, sizeof(mouseState.buttons));
memset(&touchState, 0, sizeof(touchState));
}
@ -778,14 +778,14 @@ bool EventThread::getShowCursor() const
return showCursor;
}
bool EventThread::getJoystickConnected() const
bool EventThread::getControllerConnected() const
{
return js != 0;
return ctrl != 0;
}
SDL_Joystick *EventThread::joystick() const
SDL_GameController *EventThread::controller() const
{
return js;
return ctrl;
}
void EventThread::notifyFrame()

View file

@ -23,10 +23,10 @@
#define EVENTTHREAD_H
#include <SDL_scancode.h>
#include <SDL_joystick.h>
#include <SDL_mouse.h>
#include <SDL_mutex.h>
#include <SDL_atomic.h>
#include <SDL_gamecontroller.h>
#include <string>
@ -47,11 +47,10 @@ union SDL_Event;
class EventThread
{
public:
struct JoyState
{
int axes[256];
uint8_t hats[256];
bool buttons[256];
struct ControllerState {
int axes[SDL_CONTROLLER_AXIS_MAX];
bool buttons[SDL_CONTROLLER_BUTTON_MAX];
};
struct MouseState
@ -73,7 +72,7 @@ public:
};
static uint8_t keyStates[SDL_NUM_SCANCODES];
static JoyState joyState;
static ControllerState controllerState;
static MouseState mouseState;
static TouchState touchState;
static SDL_atomic_t verticalScrollDistance;
@ -106,9 +105,9 @@ public:
bool getFullscreen() const;
bool getShowCursor() const;
bool getJoystickConnected() const;
bool getControllerConnected() const;
SDL_Joystick *joystick() const;
SDL_GameController *controller() const;
void showMessageBox(const char *body, int flags = 0);
@ -129,7 +128,7 @@ private:
bool fullscreen;
bool showCursor;
SDL_Joystick *js;
SDL_GameController *ctrl;
AtomicFlag msgBoxDone;

View file

@ -423,6 +423,39 @@ std::unordered_map<std::string, int> strToScancode{
#undef m
const char *axisNames[] {
"LStick X",
"LStick Y",
"RStick X",
"RStick Y",
"LTrigger",
"RTrigger"
};
const char *buttonNames[] {
"Pad A",
"Pad B",
"Pad X",
"Pad Y",
"Pad Back",
"Pad Guide",
"Pad Start",
"Pad LS",
"Pad RS",
"Pad LB",
"Pad RB",
"Pad Up",
"Pad Down",
"Pad Left",
"Pad Right",
"Pad Misc",
"Pad Paddle1",
"Pad Paddle2",
"Pad Paddle3",
"Pad Paddle4",
"Pad Touchpad"
};
struct ButtonState
{
bool pressed;
@ -493,14 +526,13 @@ struct KbBinding : public Binding
SDL_Scancode source;
};
/* Joystick button binding */
struct JsButtonBinding : public Binding
struct CtrlButtonBinding : public Binding
{
JsButtonBinding() {}
CtrlButtonBinding() {}
bool sourceActive() const
{
return EventThread::joyState.buttons[source];
return EventThread::controllerState.buttons[source];
}
bool sourceRepeatable() const
@ -508,34 +540,27 @@ struct JsButtonBinding : public Binding
return true;
}
uint8_t source;
SDL_GameControllerButton source;
};
/* Joystick axis binding */
struct JsAxisBinding : public Binding
struct CtrlAxisBinding : public Binding
{
JsAxisBinding() {}
CtrlAxisBinding() {}
JsAxisBinding(uint8_t source,
AxisDir dir,
Input::ButtonCode target)
: Binding(target),
source(source),
dir(dir)
{}
CtrlAxisBinding(uint8_t source, AxisDir dir, Input::ButtonCode target)
: Binding(target), source(source), dir(dir) {}
bool sourceActive() const
{
int val = EventThread::joyState.axes[source];
float val = EventThread::controllerState.axes[source];
if (dir == Negative)
return val < -JAXIS_THRESHOLD;
else /* dir == Positive */
else
return val > JAXIS_THRESHOLD;
}
bool sourceRepeatable() const
{
bool sourceRepeatable() const {
return true;
}
@ -543,34 +568,6 @@ struct JsAxisBinding : public Binding
AxisDir dir;
};
/* Joystick hat binding */
struct JsHatBinding : public Binding
{
JsHatBinding() {}
JsHatBinding(uint8_t source,
uint8_t pos,
Input::ButtonCode target)
: Binding(target),
source(source),
pos(pos)
{}
bool sourceActive() const
{
/* For a diagonal input accept it as an input for both the axes */
return (pos & EventThread::joyState.hats[source]) != 0;
}
bool sourceRepeatable() const
{
return true;
}
uint8_t source;
uint8_t pos;
};
/* Mouse button binding */
struct MsBinding : public Binding
{
@ -661,9 +658,8 @@ struct InputPrivate
{
std::vector<KbBinding> kbStatBindings;
std::vector<KbBinding> kbBindings;
std::vector<JsAxisBinding> jsABindings;
std::vector<JsHatBinding> jsHBindings;
std::vector<JsButtonBinding> jsBBindings;
std::vector<CtrlAxisBinding> ctrlABindings;
std::vector<CtrlButtonBinding> ctrlBBindings;
std::vector<MsBinding> msBindings;
/* Collective binding array */
@ -866,9 +862,8 @@ struct InputPrivate
void applyBindingDesc(const BDescVec &d)
{
kbBindings.clear();
jsABindings.clear();
jsHBindings.clear();
jsBBindings.clear();
ctrlABindings.clear();
ctrlBBindings.clear();
for (size_t i = 0; i < d.size(); ++i)
{
@ -891,32 +886,22 @@ struct InputPrivate
break;
}
case JAxis :
case CAxis :
{
JsAxisBinding bind;
bind.source = src.d.ja.axis;
bind.dir = src.d.ja.dir;
CtrlAxisBinding bind;
bind.source = src.d.ca.axis;
bind.dir = src.d.ca.dir;
bind.target = desc.target;
jsABindings.push_back(bind);
ctrlABindings.push_back(bind);
break;
}
case JHat :
case CButton :
{
JsHatBinding bind;
bind.source = src.d.jh.hat;
bind.pos = src.d.jh.pos;
CtrlButtonBinding bind;
bind.source = src.d.cb;
bind.target = desc.target;
jsHBindings.push_back(bind);
break;
}
case JButton :
{
JsButtonBinding bind;
bind.source = src.d.jb;
bind.target = desc.target;
jsBBindings.push_back(bind);
ctrlBBindings.push_back(bind);
break;
}
@ -931,9 +916,8 @@ struct InputPrivate
appendBindings(msBindings);
appendBindings(kbBindings);
appendBindings(jsABindings);
appendBindings(jsHBindings);
appendBindings(jsBBindings);
appendBindings(ctrlABindings);
appendBindings(ctrlBBindings);
}
void initStaticKbBindings()
@ -1193,19 +1177,14 @@ std::vector<std::string> Input::getBindings(ButtonCode code) {
ret.push_back(SDL_GetScancodeName(b.source));
}
for (const auto &b : p->jsBBindings) {
for (const auto &b : p->ctrlBBindings) {
if (b.target != code) continue;
ret.push_back(std::string("JSBUTTON") + std::to_string(b.source));
ret.push_back(std::string("CBUTTON") + std::to_string(b.source));
}
for (const auto &b : p->jsABindings) {
for (const auto &b : p->ctrlABindings) {
if (b.target != code) continue;
ret.push_back(std::string("JSAXIS") + std::to_string(b.source));
}
for (const auto &b : p->jsHBindings) {
if (b.target != code) continue;
ret.push_back(std::string("JSHAT") + std::to_string(b.source));
ret.push_back(std::string("CAXIS") + std::to_string(b.source));
}
return ret;
@ -1322,23 +1301,25 @@ int Input::scrollV()
return p->vScrollDistance;
}
bool Input::getJoystickConnected()
bool Input::getControllerConnected()
{
return shState->eThread().getJoystickConnected();
return shState->eThread().getControllerConnected();
}
const char *Input::getJoystickName()
const char *Input::getControllerName()
{
return (getJoystickConnected()) ?
SDL_JoystickName(shState->eThread().joystick()) :
return (getControllerConnected()) ?
SDL_GameControllerName(shState->eThread().controller()) :
0;
}
int Input::getJoystickPowerLevel()
int Input::getControllerPowerLevel()
{
return (getJoystickConnected()) ?
SDL_JoystickCurrentPowerLevel(shState->eThread().joystick()) :
SDL_JOYSTICK_POWER_UNKNOWN;
if (!getControllerConnected())
return SDL_JOYSTICK_POWER_UNKNOWN;
SDL_Joystick *js = SDL_GameControllerGetJoystick(shState->eThread().controller());
return SDL_JoystickCurrentPowerLevel(js);
}
bool Input::getTextInputMode()
@ -1375,6 +1356,20 @@ void Input::setClipboardText(char *text)
throw Exception(Exception::SDLError, "Failed to set clipboard text: %s", SDL_GetError());
}
const char *Input::getAxisName(SDL_GameControllerAxis axis) {
if (axis < 0 || axis >= SDL_CONTROLLER_AXIS_MAX)
return "Invalid";
return axisNames[axis];
}
const char *Input::getButtonName(SDL_GameControllerButton button) {
if (button < 0 || button >= SDL_CONTROLLER_BUTTON_MAX)
return "Invalid";
return buttonNames[button];
}
Input::~Input()
{
delete p;

View file

@ -23,6 +23,7 @@
#define INPUT_H
#include <unordered_map>
#include <SDL_gamecontroller.h>
#include <string>
#include <vector>
@ -82,9 +83,9 @@ public:
int mouseY();
int scrollV();
bool getJoystickConnected();
const char *getJoystickName();
int getJoystickPowerLevel();
bool getControllerConnected();
const char *getControllerName();
int getControllerPowerLevel();
bool getTextInputMode();
void setTextInputMode(bool mode);
@ -94,6 +95,9 @@ public:
char *getClipboardText();
void setClipboardText(char *text);
const char *getAxisName(SDL_GameControllerAxis axis);
const char *getButtonName(SDL_GameControllerButton button);
private:
Input(const RGSSThreadData &rtData);
~Input();

View file

@ -45,16 +45,16 @@ struct KbBindingData
}
};
struct JsBindingData
struct CtrlBindingData
{
int source;
SDL_GameControllerButton source;
Input::ButtonCode target;
void add(BDescVec &d) const
{
SourceDesc src;
src.type = JButton;
src.d.jb = source;
src.type = CButton;
src.d.cb = source;
BindingDesc desc;
desc.src = src;
@ -102,40 +102,31 @@ static elementsN(defaultKbBindings);
static elementsN(defaultKbBindings1);
static elementsN(defaultKbBindings2);
static const JsBindingData defaultJsBindings[] =
static const CtrlBindingData defaultCtrlBindings[] =
{
{ 3, Input::A },
{ 0, Input::B },
{ 1, Input::C },
{ 2, Input::X },
{ 4, Input::Y },
{ 5, Input::Z },
{ 9, Input::L },
{ 10, Input::R }
{ SDL_CONTROLLER_BUTTON_X, Input::A },
{ SDL_CONTROLLER_BUTTON_B, Input::B },
{ SDL_CONTROLLER_BUTTON_A, Input::C },
{ SDL_CONTROLLER_BUTTON_Y, Input::X },
{ SDL_CONTROLLER_BUTTON_LEFTSTICK, Input::Y },
{ SDL_CONTROLLER_BUTTON_RIGHTSTICK, Input::Z },
{ SDL_CONTROLLER_BUTTON_LEFTSHOULDER, Input::L },
{ SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, Input::R },
{ SDL_CONTROLLER_BUTTON_DPAD_UP, Input::Up },
{ SDL_CONTROLLER_BUTTON_DPAD_DOWN, Input::Down },
{ SDL_CONTROLLER_BUTTON_DPAD_LEFT, Input::Left },
{ SDL_CONTROLLER_BUTTON_DPAD_RIGHT, Input::Right }
};
static elementsN(defaultJsBindings);
static elementsN(defaultCtrlBindings);
static void addAxisBinding(BDescVec &d, uint8_t axis, AxisDir dir, Input::ButtonCode target)
static void addAxisBinding(BDescVec &d, SDL_GameControllerAxis axis, AxisDir dir, Input::ButtonCode target)
{
SourceDesc src;
src.type = JAxis;
src.d.ja.axis = axis;
src.d.ja.dir = dir;
BindingDesc desc;
desc.src = src;
desc.target = target;
d.push_back(desc);
}
static void addHatBinding(BDescVec &d, uint8_t hat, uint8_t pos, Input::ButtonCode target)
{
SourceDesc src;
src.type = JHat;
src.d.jh.hat = hat;
src.d.jh.pos = pos;
src.type = CAxis;
src.d.ca.axis = axis;
src.d.ca.dir = dir;
BindingDesc desc;
desc.src = src;
@ -158,23 +149,18 @@ BDescVec genDefaultBindings(const Config &conf)
for (size_t i = 0; i < defaultKbBindings2N; ++i)
defaultKbBindings2[i].add(d);
for (size_t i = 0; i < defaultJsBindingsN; ++i)
defaultJsBindings[i].add(d);
for (size_t i = 0; i < defaultCtrlBindingsN; ++i)
defaultCtrlBindings[i].add(d);
addAxisBinding(d, 0, Negative, Input::Left );
addAxisBinding(d, 0, Positive, Input::Right);
addAxisBinding(d, 1, Negative, Input::Up );
addAxisBinding(d, 1, Positive, Input::Down );
addHatBinding(d, 0, SDL_HAT_LEFT, Input::Left );
addHatBinding(d, 0, SDL_HAT_RIGHT, Input::Right);
addHatBinding(d, 0, SDL_HAT_UP, Input::Up );
addHatBinding(d, 0, SDL_HAT_DOWN, Input::Down );
addAxisBinding(d, SDL_CONTROLLER_AXIS_LEFTX, Negative, Input::Left );
addAxisBinding(d, SDL_CONTROLLER_AXIS_LEFTX, Positive, Input::Right);
addAxisBinding(d, SDL_CONTROLLER_AXIS_LEFTY, Negative, Input::Up );
addAxisBinding(d, SDL_CONTROLLER_AXIS_LEFTY, Positive, Input::Down );
return d;
}
#define FORMAT_VER 2
#define FORMAT_VER 3
struct Header
{
@ -265,14 +251,12 @@ static bool verifyDesc(const BindingDesc &desc)
return true;
case Key:
return src.d.scan < SDL_NUM_SCANCODES;
case JButton:
case CButton:
return true;
case JHat:
/* Only accept single directional binds */
return src.d.jh.pos == SDL_HAT_LEFT || src.d.jh.pos == SDL_HAT_RIGHT ||
src.d.jh.pos == SDL_HAT_UP || src.d.jh.pos == SDL_HAT_DOWN;
case JAxis:
return src.d.ja.dir == Negative || src.d.ja.dir == Positive;
case CAxis:
return src.d.ca.dir == Negative || src.d.ca.dir == Positive;
default:
return false;
}

View file

@ -25,7 +25,7 @@
#include "input.h"
#include <SDL_scancode.h>
#include <SDL_joystick.h>
#include <SDL_gamecontroller.h>
#include <stdint.h>
#include <assert.h>
#include <vector>
@ -40,9 +40,8 @@ enum SourceType
{
Invalid,
Key,
JButton,
JAxis,
JHat
CButton,
CAxis
};
struct SourceDesc
@ -54,21 +53,14 @@ struct SourceDesc
/* Keyboard scancode */
SDL_Scancode scan;
/* Joystick button index */
uint8_t jb;
SDL_GameControllerButton cb;
struct
{
/* Joystick axis index */
uint8_t axis;
SDL_GameControllerAxis axis;
/* Joystick axis direction */
AxisDir dir;
} ja;
struct
{
/* Joystick axis index */
uint8_t hat;
/* Joystick axis direction */
uint8_t pos;
} jh;
} ca;
} d;
bool operator==(const SourceDesc &o) const
@ -82,12 +74,10 @@ struct SourceDesc
return true;
case Key:
return d.scan == o.d.scan;
case JButton:
return d.jb == o.d.jb;
case JAxis:
return (d.ja.axis == o.d.ja.axis) && (d.ja.dir == o.d.ja.dir);
case JHat:
return (d.jh.hat == o.d.jh.hat) && (d.jh.pos == o.d.jh.pos);
case CButton:
return d.cb == o.d.cb;
case CAxis:
return (d.ca.axis == o.d.ca.axis) && (d.ca.dir == o.d.ca.dir);
default:
assert(!"unreachable");
return false;

View file

@ -210,7 +210,7 @@ int main(int argc, char *argv[]) {
#endif
/* initialize SDL first */
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) < 0) {
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER) < 0) {
showInitError(std::string("Error initializing SDL: ") + SDL_GetError());
return 0;
}