diff --git a/src/eventthread.cpp b/src/eventthread.cpp index 6000dad..478eb8b 100644 --- a/src/eventthread.cpp +++ b/src/eventthread.cpp @@ -38,7 +38,7 @@ uint8_t EventThread::keyStates[] = { false }; EventThread::JoyState EventThread::joyState = { - { 0 }, { false } + { 0 }, { 0 }, { false } }; EventThread::MouseState EventThread::mouseState = @@ -274,8 +274,12 @@ void EventThread::process(RGSSThreadData &rtData) joyState.buttons[event.jbutton.button] = false; break; + case SDL_JOYHATMOTION : + joyState.hats[event.jhat.hat] = event.jhat.value; + break; + case SDL_JOYAXISMOTION : - joyState.axis[event.jaxis.axis] = event.jaxis.value; + joyState.axes[event.jaxis.axis] = event.jaxis.value; break; case SDL_JOYDEVICEADDED : diff --git a/src/eventthread.h b/src/eventthread.h index 15d4f63..9f7f508 100644 --- a/src/eventthread.h +++ b/src/eventthread.h @@ -46,7 +46,8 @@ public: struct JoyState { - int axis[256]; + int axes[256]; + uint8_t hats[256]; bool buttons[256]; }; diff --git a/src/input.cpp b/src/input.cpp index 1cae58a..d7978bd 100644 --- a/src/input.cpp +++ b/src/input.cpp @@ -133,7 +133,7 @@ struct JsAxisBinding : public Binding bool sourceActive() const { - int val = EventThread::joyState.axis[source]; + int val = EventThread::joyState.axes[source]; if (dir == Negative) return val < -JAXIS_THRESHOLD; @@ -150,6 +150,34 @@ 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 { @@ -241,6 +269,7 @@ struct InputPrivate std::vector kbStatBindings; std::vector kbBindings; std::vector jsABindings; + std::vector jsHBindings; std::vector jsBBindings; std::vector msBindings; @@ -348,6 +377,7 @@ struct InputPrivate { kbBindings.clear(); jsABindings.clear(); + jsHBindings.clear(); jsBBindings.clear(); for (size_t i = 0; i < d.size(); ++i) @@ -381,6 +411,16 @@ struct InputPrivate break; } + case JHat : + { + JsHatBinding bind; + bind.source = src.d.jh.hat; + bind.pos = src.d.jh.pos; + bind.target = desc.target; + jsHBindings.push_back(bind); + + break; + } case JButton : { JsButtonBinding bind; @@ -402,6 +442,7 @@ struct InputPrivate appendBindings(kbBindings); appendBindings(jsABindings); + appendBindings(jsHBindings); appendBindings(jsBBindings); } diff --git a/src/keybindings.cpp b/src/keybindings.cpp index 6f54f9c..49d2a71 100644 --- a/src/keybindings.cpp +++ b/src/keybindings.cpp @@ -129,6 +129,20 @@ static void addAxisBinding(BDescVec &d, uint8_t axis, AxisDir dir, Input::Button 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; + + BindingDesc desc; + desc.src = src; + desc.target = target; + + d.push_back(desc); +} + BDescVec genDefaultBindings(const Config &conf) { BDescVec d; @@ -150,11 +164,16 @@ BDescVec genDefaultBindings(const Config &conf) 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 ); return d; } -#define FORMAT_VER 1 +#define FORMAT_VER 2 struct Header { @@ -247,6 +266,10 @@ static bool verifyDesc(const BindingDesc &desc) return src.d.scan < SDL_NUM_SCANCODES; case JButton: 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; default: diff --git a/src/keybindings.h b/src/keybindings.h index 9bd6c43..3d437c9 100644 --- a/src/keybindings.h +++ b/src/keybindings.h @@ -25,6 +25,7 @@ #include "input.h" #include +#include #include #include #include @@ -40,7 +41,8 @@ enum SourceType Invalid, Key, JButton, - JAxis + JAxis, + JHat }; struct SourceDesc @@ -60,6 +62,13 @@ struct SourceDesc /* Joystick axis direction */ AxisDir dir; } ja; + struct + { + /* Joystick axis index */ + uint8_t hat; + /* Joystick axis direction */ + uint8_t pos; + } jh; } d; bool operator==(const SourceDesc &o) const @@ -77,6 +86,8 @@ struct SourceDesc 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); default: assert(!"unreachable"); return false; diff --git a/src/settingsmenu.cpp b/src/settingsmenu.cpp index a734ffa..dbf6cc6 100644 --- a/src/settingsmenu.cpp +++ b/src/settingsmenu.cpp @@ -81,6 +81,7 @@ static elementsN(vButtons); std::string sourceDescString(const SourceDesc &src) { char buf[128]; + char pos; switch (src.type) { @@ -104,6 +105,32 @@ std::string sourceDescString(const SourceDesc &src) snprintf(buf, sizeof(buf), "JS %d", src.d.jb); return buf; + case JHat: + switch(src.d.jh.pos) + { + case SDL_HAT_UP: + pos = 'U'; + break; + + case SDL_HAT_DOWN: + pos = 'D'; + break; + + case SDL_HAT_LEFT: + pos = 'L'; + break; + + case SDL_HAT_RIGHT: + pos = 'R'; + break; + + default: + pos = '-'; + } + snprintf(buf, sizeof(buf), "Hat %d:%c", + src.d.jh.hat, pos); + return buf; + case JAxis: snprintf(buf, sizeof(buf), "Axis %d%c", src.d.ja.axis, src.d.ja.dir == Negative ? '-' : '+'); @@ -616,6 +643,21 @@ struct SettingsMenuPrivate desc.d.jb = event.jbutton.button; break; + case SDL_JOYHATMOTION: + { + int v = event.jhat.value; + + /* Only register if single directional input */ + if (v != SDL_HAT_LEFT && v != SDL_HAT_RIGHT && + v != SDL_HAT_UP && v != SDL_HAT_DOWN) + return true; + + desc.type = JHat; + desc.d.jh.hat = event.jhat.hat; + desc.d.jh.pos = v; + break; + } + case SDL_JOYAXISMOTION: { int v = event.jaxis.value; @@ -1011,6 +1053,7 @@ bool SettingsMenu::onEvent(const SDL_Event &event) case SDL_JOYBUTTONDOWN : case SDL_JOYBUTTONUP : + case SDL_JOYHATMOTION : case SDL_JOYAXISMOTION : if (!p->hasFocus) return false; @@ -1087,6 +1130,7 @@ bool SettingsMenu::onEvent(const SDL_Event &event) } case SDL_JOYBUTTONDOWN: + case SDL_JOYHATMOTION: case SDL_JOYAXISMOTION: if (p->state != AwaitingInput) return true;