Simplify Hat handling
* Parse the hat bitfield directly rather than going through an intermediate enum state. * Clean up some of the sdljoy code to use less vertical space.
This commit is contained in:
parent
a56ea0225a
commit
50a1391232
|
@ -14,18 +14,6 @@ enum class wxAxisStatus {
|
||||||
Minus
|
Minus
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class wxHatStatus {
|
|
||||||
Neutral = 0,
|
|
||||||
North,
|
|
||||||
South,
|
|
||||||
West,
|
|
||||||
East,
|
|
||||||
NorthWest,
|
|
||||||
NorthEast,
|
|
||||||
SouthWest,
|
|
||||||
SouthEast
|
|
||||||
};
|
|
||||||
|
|
||||||
wxAxisStatus AxisValueToStatus(const int16_t& x) {
|
wxAxisStatus AxisValueToStatus(const int16_t& x) {
|
||||||
if (x > 0x1fff)
|
if (x > 0x1fff)
|
||||||
return wxAxisStatus::Plus;
|
return wxAxisStatus::Plus;
|
||||||
|
@ -34,29 +22,6 @@ wxAxisStatus AxisValueToStatus(const int16_t& x) {
|
||||||
return wxAxisStatus::Neutral;
|
return wxAxisStatus::Neutral;
|
||||||
}
|
}
|
||||||
|
|
||||||
wxHatStatus HatValueToStatus(const int16_t& x) {
|
|
||||||
switch (x) {
|
|
||||||
case 1:
|
|
||||||
return wxHatStatus::North;
|
|
||||||
case 2:
|
|
||||||
return wxHatStatus::East;
|
|
||||||
case 3:
|
|
||||||
return wxHatStatus::NorthEast;
|
|
||||||
case 4:
|
|
||||||
return wxHatStatus::South;
|
|
||||||
case 6:
|
|
||||||
return wxHatStatus::SouthEast;
|
|
||||||
case 8:
|
|
||||||
return wxHatStatus::West;
|
|
||||||
case 9:
|
|
||||||
return wxHatStatus::NorthWest;
|
|
||||||
case 12:
|
|
||||||
return wxHatStatus::SouthWest;
|
|
||||||
default:
|
|
||||||
return wxHatStatus::Neutral;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
wxJoyControl AxisStatusToJoyControl(const wxAxisStatus& status) {
|
wxJoyControl AxisStatusToJoyControl(const wxAxisStatus& status) {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case wxAxisStatus::Plus:
|
case wxAxisStatus::Plus:
|
||||||
|
@ -71,30 +36,20 @@ wxJoyControl AxisStatusToJoyControl(const wxAxisStatus& status) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set<wxJoyControl> HatStatusToJoyControls(const wxHatStatus& status) {
|
wxJoyControl HatStatusToJoyControl(const uint8_t status) {
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case wxHatStatus::Neutral:
|
case SDL_HAT_UP:
|
||||||
return {};
|
return wxJoyControl::HatNorth;
|
||||||
case wxHatStatus::North:
|
case SDL_HAT_DOWN:
|
||||||
return {wxJoyControl::HatNorth};
|
return wxJoyControl::HatSouth;
|
||||||
case wxHatStatus::South:
|
case SDL_HAT_LEFT:
|
||||||
return {wxJoyControl::HatSouth};
|
return wxJoyControl::HatWest;
|
||||||
case wxHatStatus::West:
|
case SDL_HAT_RIGHT:
|
||||||
return {wxJoyControl::HatWest};
|
return wxJoyControl::HatEast;
|
||||||
case wxHatStatus::East:
|
|
||||||
return {wxJoyControl::HatEast};
|
|
||||||
case wxHatStatus::NorthWest:
|
|
||||||
return {wxJoyControl::HatNorth, wxJoyControl::HatWest};
|
|
||||||
case wxHatStatus::NorthEast:
|
|
||||||
return {wxJoyControl::HatNorth, wxJoyControl::HatEast};
|
|
||||||
case wxHatStatus::SouthWest:
|
|
||||||
return {wxJoyControl::HatSouth, wxJoyControl::HatWest};
|
|
||||||
case wxHatStatus::SouthEast:
|
|
||||||
return {wxJoyControl::HatSouth, wxJoyControl::HatEast};
|
|
||||||
default:
|
default:
|
||||||
// This should never happen.
|
// This should never happen.
|
||||||
assert(false);
|
assert(false);
|
||||||
return {};
|
return wxJoyControl::HatNorth;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -169,13 +124,13 @@ public:
|
||||||
// Returns true if this object was properly initialized.
|
// Returns true if this object was properly initialized.
|
||||||
bool IsValid() const;
|
bool IsValid() const;
|
||||||
|
|
||||||
// Returns true if `sdl_event` should be processed by this object.
|
// Returns true if this object is a game controller.
|
||||||
bool ShouldProcessEvent(uint32_t sdl_event) const;
|
bool is_game_controller() const { return !!game_controller_; }
|
||||||
|
|
||||||
// Processes the corresponding events.
|
// Processes the corresponding events.
|
||||||
void ProcessAxisEvent(uint8_t index, wxAxisStatus status);
|
void ProcessAxisEvent(const uint8_t index, const wxAxisStatus status);
|
||||||
void ProcessButtonEvent(uint8_t index, bool pressed);
|
void ProcessButtonEvent(const uint8_t index, const bool pressed);
|
||||||
void ProcessHatEvent(uint8_t index, wxHatStatus status);
|
void ProcessHatEvent(const uint8_t index, const uint8_t status);
|
||||||
|
|
||||||
// Activates or deactivates rumble.
|
// Activates or deactivates rumble.
|
||||||
void SetRumble(bool activate_rumble);
|
void SetRumble(bool activate_rumble);
|
||||||
|
@ -206,7 +161,7 @@ private:
|
||||||
std::unordered_map<uint8_t, bool> buttons_{};
|
std::unordered_map<uint8_t, bool> buttons_{};
|
||||||
|
|
||||||
// Current state of Joystick HAT. Unused for GameControllers.
|
// Current state of Joystick HAT. Unused for GameControllers.
|
||||||
std::unordered_map<uint8_t, wxHatStatus> hats_{};
|
std::unordered_map<uint8_t, uint8_t> hats_{};
|
||||||
|
|
||||||
// Set to true to activate joystick rumble.
|
// Set to true to activate joystick rumble.
|
||||||
bool rumbling_ = false;
|
bool rumbling_ = false;
|
||||||
|
@ -252,30 +207,7 @@ bool wxSDLJoyState::IsValid() const {
|
||||||
return sdl_joystick_;
|
return sdl_joystick_;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wxSDLJoyState::ShouldProcessEvent(uint32_t sdl_event) const {
|
void wxSDLJoyState::ProcessAxisEvent(const uint8_t index, const wxAxisStatus status) {
|
||||||
switch(sdl_event) {
|
|
||||||
case SDL_CONTROLLERBUTTONDOWN:
|
|
||||||
case SDL_CONTROLLERBUTTONUP:
|
|
||||||
case SDL_CONTROLLERAXISMOTION:
|
|
||||||
case SDL_CONTROLLERDEVICEADDED:
|
|
||||||
case SDL_CONTROLLERDEVICEREMOVED:
|
|
||||||
// Always process game controller events.
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case SDL_JOYBUTTONDOWN:
|
|
||||||
case SDL_JOYBUTTONUP:
|
|
||||||
case SDL_JOYAXISMOTION:
|
|
||||||
case SDL_JOYHATMOTION:
|
|
||||||
// Only process joystick events if this is not a game controller.
|
|
||||||
return !game_controller_;
|
|
||||||
|
|
||||||
default:
|
|
||||||
// Ignore everything else.
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void wxSDLJoyState::ProcessAxisEvent(uint8_t index, wxAxisStatus status) {
|
|
||||||
auto handler = wxGetApp().frame->GetJoyEventHandler();
|
auto handler = wxGetApp().frame->GetJoyEventHandler();
|
||||||
const wxAxisStatus previous_status = axis_[index];
|
const wxAxisStatus previous_status = axis_[index];
|
||||||
|
|
||||||
|
@ -298,7 +230,10 @@ void wxSDLJoyState::ProcessAxisEvent(uint8_t index, wxAxisStatus status) {
|
||||||
if (previous_status != wxAxisStatus::Neutral) {
|
if (previous_status != wxAxisStatus::Neutral) {
|
||||||
// Send the "unpressed" event.
|
// Send the "unpressed" event.
|
||||||
wxQueueEvent(handler, new wxJoyEvent(
|
wxQueueEvent(handler, new wxJoyEvent(
|
||||||
wx_joystick_, AxisStatusToJoyControl(previous_status), index, false));
|
wx_joystick_,
|
||||||
|
AxisStatusToJoyControl(previous_status),
|
||||||
|
index,
|
||||||
|
false));
|
||||||
}
|
}
|
||||||
|
|
||||||
// We already sent the "unpressed" event so nothing more to do.
|
// We already sent the "unpressed" event so nothing more to do.
|
||||||
|
@ -308,11 +243,14 @@ void wxSDLJoyState::ProcessAxisEvent(uint8_t index, wxAxisStatus status) {
|
||||||
|
|
||||||
// Send the "pressed" event.
|
// Send the "pressed" event.
|
||||||
wxQueueEvent(handler, new wxJoyEvent(
|
wxQueueEvent(handler, new wxJoyEvent(
|
||||||
wx_joystick_, AxisStatusToJoyControl(status), index, true));
|
wx_joystick_,
|
||||||
|
AxisStatusToJoyControl(status),
|
||||||
|
index,
|
||||||
|
true));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxSDLJoyState::ProcessButtonEvent(uint8_t index, bool status) {
|
void wxSDLJoyState::ProcessButtonEvent(const uint8_t index, const bool status) {
|
||||||
auto handler = wxGetApp().frame->GetJoyEventHandler();
|
auto handler = wxGetApp().frame->GetJoyEventHandler();
|
||||||
const bool previous_status = buttons_[index];
|
const bool previous_status = buttons_[index];
|
||||||
|
|
||||||
|
@ -337,9 +275,9 @@ void wxSDLJoyState::ProcessButtonEvent(uint8_t index, bool status) {
|
||||||
wx_joystick_, wxJoyControl::Button, index, status));
|
wx_joystick_, wxJoyControl::Button, index, status));
|
||||||
}
|
}
|
||||||
|
|
||||||
void wxSDLJoyState::ProcessHatEvent(uint8_t index, wxHatStatus status) {
|
void wxSDLJoyState::ProcessHatEvent(const uint8_t index, const uint8_t status) {
|
||||||
auto handler = wxGetApp().frame->GetJoyEventHandler();
|
auto handler = wxGetApp().frame->GetJoyEventHandler();
|
||||||
const wxHatStatus previous_status = hats_[index];
|
const uint16_t previous_status = hats_[index];
|
||||||
|
|
||||||
// Nothing to do if no-op.
|
// Nothing to do if no-op.
|
||||||
if (status == previous_status) {
|
if (status == previous_status) {
|
||||||
|
@ -357,27 +295,23 @@ void wxSDLJoyState::ProcessHatEvent(uint8_t index, wxHatStatus status) {
|
||||||
wxLogDebug("Got Hat event: %s ctrl_idx:%d val:%d prev_val:%d",
|
wxLogDebug("Got Hat event: %s ctrl_idx:%d val:%d prev_val:%d",
|
||||||
wx_joystick_.ToString(), index, status, previous_status);
|
wx_joystick_.ToString(), index, status, previous_status);
|
||||||
|
|
||||||
const std::set<wxJoyControl> old_controls = HatStatusToJoyControls(previous_status);
|
// For HATs, the status value is a bit field, where each bit corresponds to
|
||||||
const std::set<wxJoyControl> new_controls = HatStatusToJoyControls(status);
|
// a direction. These are parsed here to send the corresponding "pressed"
|
||||||
|
// and "unpressed" events.
|
||||||
// Send the "unpressed" events.
|
for (uint8_t bit = 0x01; bit != 0x10; bit <<= 1) {
|
||||||
for (const wxJoyControl& control : old_controls) {
|
const bool old_control_pressed = (previous_status & bit) != 0;
|
||||||
if (new_controls.find(control) != new_controls.end()) {
|
const bool new_control_pressed = (status & bit) != 0;
|
||||||
// No need to unpress the old direction.
|
if (old_control_pressed && !new_control_pressed) {
|
||||||
continue;
|
// Send the "unpressed" event.
|
||||||
|
wxQueueEvent(handler, new wxJoyEvent(
|
||||||
|
wx_joystick_, HatStatusToJoyControl(bit), index, false));
|
||||||
}
|
}
|
||||||
wxQueueEvent(handler, new wxJoyEvent(
|
if (!old_control_pressed && new_control_pressed) {
|
||||||
wx_joystick_, control, index, false));
|
// Send the "pressed" event.
|
||||||
}
|
wxQueueEvent(handler, new wxJoyEvent(
|
||||||
|
wx_joystick_, HatStatusToJoyControl(bit), index, true));
|
||||||
|
|
||||||
// Send the "pressed" events.
|
|
||||||
for (const wxJoyControl& control : new_controls) {
|
|
||||||
if (old_controls.find(control) != old_controls.end()) {
|
|
||||||
// No need to press the new direction twice.
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
wxQueueEvent(handler, new wxJoyEvent(
|
|
||||||
wx_joystick_, control, index, true));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -420,29 +354,26 @@ wxJoyPoller::~wxJoyPoller() {
|
||||||
|
|
||||||
void wxJoyPoller::Poll() {
|
void wxJoyPoller::Poll() {
|
||||||
SDL_Event e;
|
SDL_Event e;
|
||||||
|
wxSDLJoyState* joy_state = nullptr;
|
||||||
|
|
||||||
while (SDL_PollEvent(&e)) {
|
while (SDL_PollEvent(&e)) {
|
||||||
switch (e.type) {
|
switch (e.type) {
|
||||||
case SDL_CONTROLLERBUTTONDOWN:
|
case SDL_CONTROLLERBUTTONDOWN:
|
||||||
case SDL_CONTROLLERBUTTONUP:
|
case SDL_CONTROLLERBUTTONUP:
|
||||||
{
|
joy_state = FindJoyState(e.cbutton.which);
|
||||||
wxSDLJoyState* joy_state = FindJoyState(e.cbutton.which);
|
if (joy_state) {
|
||||||
if (joy_state && joy_state->ShouldProcessEvent(e.type)) {
|
|
||||||
joy_state->ProcessButtonEvent(
|
joy_state->ProcessButtonEvent(
|
||||||
e.cbutton.button, e.cbutton.state);
|
e.cbutton.button, e.cbutton.state);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
case SDL_CONTROLLERAXISMOTION:
|
case SDL_CONTROLLERAXISMOTION:
|
||||||
{
|
joy_state = FindJoyState(e.caxis.which);
|
||||||
wxSDLJoyState* joy_state = FindJoyState(e.caxis.which);
|
if (joy_state) {
|
||||||
if (joy_state && joy_state->ShouldProcessEvent(e.type)) {
|
|
||||||
joy_state->ProcessAxisEvent(
|
joy_state->ProcessAxisEvent(
|
||||||
e.caxis.axis, AxisValueToStatus(e.caxis.value));
|
e.caxis.axis, AxisValueToStatus(e.caxis.value));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
case SDL_CONTROLLERDEVICEADDED:
|
case SDL_CONTROLLERDEVICEADDED:
|
||||||
case SDL_CONTROLLERDEVICEREMOVED:
|
case SDL_CONTROLLERDEVICEREMOVED:
|
||||||
|
@ -453,52 +384,38 @@ void wxJoyPoller::Poll() {
|
||||||
// Joystick events for non-GameControllers.
|
// Joystick events for non-GameControllers.
|
||||||
case SDL_JOYBUTTONDOWN:
|
case SDL_JOYBUTTONDOWN:
|
||||||
case SDL_JOYBUTTONUP:
|
case SDL_JOYBUTTONUP:
|
||||||
{
|
joy_state = FindJoyState(e.jbutton.which);
|
||||||
wxSDLJoyState* joy_state = FindJoyState(e.jbutton.which);
|
if (joy_state && !joy_state->is_game_controller()) {
|
||||||
if (joy_state && joy_state->ShouldProcessEvent(e.type)) {
|
|
||||||
joy_state->ProcessButtonEvent(
|
joy_state->ProcessButtonEvent(
|
||||||
e.jbutton.button, e.jbutton.state);
|
e.jbutton.button, e.jbutton.state);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
case SDL_JOYAXISMOTION:
|
case SDL_JOYAXISMOTION:
|
||||||
{
|
joy_state = FindJoyState(e.jaxis.which);
|
||||||
wxSDLJoyState* joy_state = FindJoyState(e.jaxis.which);
|
if (joy_state && !joy_state->is_game_controller()) {
|
||||||
if (joy_state && joy_state->ShouldProcessEvent(e.type)) {
|
|
||||||
joy_state->ProcessAxisEvent(
|
joy_state->ProcessAxisEvent(
|
||||||
e.jaxis.axis, AxisValueToStatus(e.jaxis.value));
|
e.jaxis.axis, AxisValueToStatus(e.jaxis.value));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
case SDL_JOYHATMOTION:
|
case SDL_JOYHATMOTION:
|
||||||
{
|
joy_state = FindJoyState(e.jhat.which);
|
||||||
wxSDLJoyState* joy_state = FindJoyState(e.jhat.which);
|
if (joy_state && !joy_state->is_game_controller()) {
|
||||||
if (joy_state && joy_state->ShouldProcessEvent(e.type)) {
|
|
||||||
joy_state->ProcessHatEvent(
|
joy_state->ProcessHatEvent(
|
||||||
e.jhat.hat, HatValueToStatus(e.jhat.value));
|
e.jhat.hat, e.jhat.value);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
case SDL_JOYDEVICEADDED:
|
case SDL_JOYDEVICEADDED:
|
||||||
{
|
|
||||||
// Always remap all controllers.
|
// Always remap all controllers.
|
||||||
RemapControllers();
|
RemapControllers();
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
case SDL_JOYDEVICEREMOVED:
|
case SDL_JOYDEVICEREMOVED:
|
||||||
{
|
|
||||||
joystick_states_.erase(e.jdevice.which);
|
joystick_states_.erase(e.jdevice.which);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
|
||||||
// Ignore all other events.
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue