Xbox controllers require JoyHat events to be tracked on windows #86

Merged
Daverball merged 1 commits from controller-fix into master 2014-12-31 17:50:57 +00:00
6 changed files with 130 additions and 6 deletions

View File

@ -38,7 +38,7 @@ uint8_t EventThread::keyStates[] = { false };
EventThread::JoyState EventThread::joyState = EventThread::JoyState EventThread::joyState =
{ {
{ 0 }, { false } { 0 }, { 0 }, { false }
}; };
EventThread::MouseState EventThread::mouseState = EventThread::MouseState EventThread::mouseState =
@ -274,8 +274,12 @@ void EventThread::process(RGSSThreadData &rtData)
joyState.buttons[event.jbutton.button] = false; joyState.buttons[event.jbutton.button] = false;
break; break;
case SDL_JOYHATMOTION :
joyState.hats[event.jhat.hat] = event.jhat.value;
break;
case SDL_JOYAXISMOTION : case SDL_JOYAXISMOTION :
joyState.axis[event.jaxis.axis] = event.jaxis.value; joyState.axes[event.jaxis.axis] = event.jaxis.value;
break; break;
case SDL_JOYDEVICEADDED : case SDL_JOYDEVICEADDED :

View File

@ -46,7 +46,8 @@ public:
struct JoyState struct JoyState
{ {
int axis[256]; int axes[256];
uint8_t hats[256];
bool buttons[256]; bool buttons[256];
}; };

View File

@ -133,7 +133,7 @@ struct JsAxisBinding : public Binding
bool sourceActive() const bool sourceActive() const
{ {
int val = EventThread::joyState.axis[source]; int val = EventThread::joyState.axes[source];
if (dir == Negative) if (dir == Negative)
return val < -JAXIS_THRESHOLD; return val < -JAXIS_THRESHOLD;
@ -150,6 +150,34 @@ struct JsAxisBinding : public Binding
AxisDir dir; 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 */ /* Mouse button binding */
struct MsBinding : public Binding struct MsBinding : public Binding
{ {
@ -241,6 +269,7 @@ struct InputPrivate
std::vector<KbBinding> kbStatBindings; std::vector<KbBinding> kbStatBindings;
std::vector<KbBinding> kbBindings; std::vector<KbBinding> kbBindings;
std::vector<JsAxisBinding> jsABindings; std::vector<JsAxisBinding> jsABindings;
std::vector<JsHatBinding> jsHBindings;
std::vector<JsButtonBinding> jsBBindings; std::vector<JsButtonBinding> jsBBindings;
std::vector<MsBinding> msBindings; std::vector<MsBinding> msBindings;
@ -348,6 +377,7 @@ struct InputPrivate
{ {
kbBindings.clear(); kbBindings.clear();
jsABindings.clear(); jsABindings.clear();
jsHBindings.clear();
jsBBindings.clear(); jsBBindings.clear();
for (size_t i = 0; i < d.size(); ++i) for (size_t i = 0; i < d.size(); ++i)
@ -381,6 +411,16 @@ struct InputPrivate
break; 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 : case JButton :
{ {
JsButtonBinding bind; JsButtonBinding bind;
@ -402,6 +442,7 @@ struct InputPrivate
appendBindings(kbBindings); appendBindings(kbBindings);
appendBindings(jsABindings); appendBindings(jsABindings);
appendBindings(jsHBindings);
appendBindings(jsBBindings); appendBindings(jsBBindings);
} }

View File

@ -129,6 +129,20 @@ static void addAxisBinding(BDescVec &d, uint8_t axis, AxisDir dir, Input::Button
d.push_back(desc); 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 genDefaultBindings(const Config &conf)
{ {
BDescVec d; BDescVec d;
@ -150,11 +164,16 @@ BDescVec genDefaultBindings(const Config &conf)
addAxisBinding(d, 0, Positive, Input::Right); addAxisBinding(d, 0, Positive, Input::Right);
addAxisBinding(d, 1, Negative, Input::Up ); addAxisBinding(d, 1, Negative, Input::Up );
addAxisBinding(d, 1, Positive, Input::Down ); 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; return d;
} }
#define FORMAT_VER 1 #define FORMAT_VER 2
struct Header struct Header
{ {
@ -247,6 +266,10 @@ static bool verifyDesc(const BindingDesc &desc)
return src.d.scan < SDL_NUM_SCANCODES; return src.d.scan < SDL_NUM_SCANCODES;
case JButton: case JButton:
return true; 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: case JAxis:
return src.d.ja.dir == Negative || src.d.ja.dir == Positive; return src.d.ja.dir == Negative || src.d.ja.dir == Positive;
default: default:

View File

@ -25,6 +25,7 @@
#include "input.h" #include "input.h"
#include <SDL_scancode.h> #include <SDL_scancode.h>
#include <SDL_joystick.h>
#include <stdint.h> #include <stdint.h>
#include <assert.h> #include <assert.h>
#include <vector> #include <vector>
@ -40,7 +41,8 @@ enum SourceType
Invalid, Invalid,
Key, Key,
JButton, JButton,
JAxis JAxis,
JHat
}; };
struct SourceDesc struct SourceDesc
@ -60,6 +62,13 @@ struct SourceDesc
/* Joystick axis direction */ /* Joystick axis direction */
AxisDir dir; AxisDir dir;
} ja; } ja;
struct
{
/* Joystick axis index */
uint8_t hat;
/* Joystick axis direction */
uint8_t pos;
} jh;
} d; } d;
bool operator==(const SourceDesc &o) const bool operator==(const SourceDesc &o) const
@ -77,6 +86,8 @@ struct SourceDesc
return d.jb == o.d.jb; return d.jb == o.d.jb;
case JAxis: case JAxis:
return (d.ja.axis == o.d.ja.axis) && (d.ja.dir == o.d.ja.dir); 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: default:
assert(!"unreachable"); assert(!"unreachable");
return false; return false;

View File

@ -81,6 +81,7 @@ static elementsN(vButtons);
std::string sourceDescString(const SourceDesc &src) std::string sourceDescString(const SourceDesc &src)
{ {
char buf[128]; char buf[128];
char pos;
switch (src.type) switch (src.type)
{ {
@ -104,6 +105,32 @@ std::string sourceDescString(const SourceDesc &src)
snprintf(buf, sizeof(buf), "JS %d", src.d.jb); snprintf(buf, sizeof(buf), "JS %d", src.d.jb);
return buf; 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: case JAxis:
snprintf(buf, sizeof(buf), "Axis %d%c", snprintf(buf, sizeof(buf), "Axis %d%c",
src.d.ja.axis, src.d.ja.dir == Negative ? '-' : '+'); src.d.ja.axis, src.d.ja.dir == Negative ? '-' : '+');
@ -616,6 +643,21 @@ struct SettingsMenuPrivate
desc.d.jb = event.jbutton.button; desc.d.jb = event.jbutton.button;
break; 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: case SDL_JOYAXISMOTION:
{ {
int v = event.jaxis.value; int v = event.jaxis.value;
@ -1008,6 +1050,7 @@ bool SettingsMenu::onEvent(const SDL_Event &event)
case SDL_JOYBUTTONDOWN : case SDL_JOYBUTTONDOWN :
case SDL_JOYBUTTONUP : case SDL_JOYBUTTONUP :
case SDL_JOYHATMOTION :
case SDL_JOYAXISMOTION : case SDL_JOYAXISMOTION :
if (!p->hasFocus) if (!p->hasFocus)
return false; return false;
@ -1084,6 +1127,7 @@ bool SettingsMenu::onEvent(const SDL_Event &event)
} }
case SDL_JOYBUTTONDOWN: case SDL_JOYBUTTONDOWN:
case SDL_JOYHATMOTION:
case SDL_JOYAXISMOTION: case SDL_JOYAXISMOTION:
if (p->state != AwaitingInput) if (p->state != AwaitingInput)
return true; return true;