Abstract player_index into wxJoystick

* Add wxJoystick to abstract what was previously referred to as
  |player_index|. This is a first step towards a larger refactor of
  input handling.
* Remove "SDL" from types that are not directly SDL-related, namely
  "wxSDLJoyEvent", "wxSDLControl".
* Rename "wxSDLJoy" into "wxJoyPoller". This clarifies the use of this
  class.

Issue: #745
This commit is contained in:
Fabrice de Gans-Riberi 2021-04-25 18:14:36 -07:00 committed by Rafael Kitover
parent 37dc95b930
commit f132e15511
9 changed files with 194 additions and 115 deletions

View File

@ -2581,11 +2581,12 @@ void MainFrame::set_global_accels()
// the menus will be added now
// first, zero out menu item on all accels
std::unordered_set<unsigned> needed_joysticks;
std::set<wxJoystick> needed_joysticks;
for (size_t i = 0; i < accels.size(); ++i) {
accels[i].Set(accels[i].GetUkey(), accels[i].GetJoystick(), accels[i].GetFlags(), accels[i].GetKeyCode(), accels[i].GetCommand());
if (accels[i].GetJoystick()) {
needed_joysticks.insert(accels[i].GetJoystick());
needed_joysticks.insert(
wxJoystick::FromLegacyPlayerIndex(accels[i].GetJoystick()));
}
}
joy.PollJoysticks(needed_joysticks);

View File

@ -1399,11 +1399,11 @@ void GameArea::OnSize(wxSizeEvent& ev)
ev.Skip();
}
void GameArea::OnSDLJoy(wxSDLJoyEvent& ev)
void GameArea::OnSDLJoy(wxJoyEvent& ev)
{
int key = ev.control_index();
int mod = wxJoyKeyTextCtrl::DigitalButton(ev);
int joy = ev.player_index();
int joy = ev.joystick().player_index();
// mutually exclusive key types unpress their opposite
if (mod == WXJB_AXIS_PLUS) {

View File

@ -239,7 +239,7 @@ void systemStopGamePlayback()
mf->enable_menus();
}
// updates the joystick data (done in background using wxSDLJoy)
// updates the joystick data (done in background using wxJoyPoller)
bool systemReadJoypads()
{
return true;

View File

@ -17,17 +17,17 @@ wxJoyKeyBinding newWxJoyKeyBinding(int key, int mod, int joy)
return tmp;
}
int wxJoyKeyTextCtrl::DigitalButton(wxSDLJoyEvent& event)
int wxJoyKeyTextCtrl::DigitalButton(wxJoyEvent& event)
{
int16_t sdlval = event.control_value();
wxSDLControl sdltype = event.control();
wxJoyControl sdltype = event.control();
switch (sdltype) {
case WXSDLJOY_AXIS:
case wxJoyControl::Axis:
// for val = 0 return arbitrary direction; val means "off"
return sdlval > 0 ? WXJB_AXIS_PLUS : WXJB_AXIS_MINUS;
case WXSDLJOY_HAT:
case wxJoyControl::Hat:
/* URDL = 1248 */
switch (sdlval) {
@ -59,7 +59,7 @@ int wxJoyKeyTextCtrl::DigitalButton(wxSDLJoyEvent& event)
return WXJB_HAT_N; // arbitrary direction; val = 0 means "off"
}
case WXSDLJOY_BUTTON:
case wxJoyControl::Button:
return WXJB_BUTTON;
default:
@ -68,23 +68,23 @@ int wxJoyKeyTextCtrl::DigitalButton(wxSDLJoyEvent& event)
}
}
void wxJoyKeyTextCtrl::OnJoy(wxSDLJoyEvent& event)
void wxJoyKeyTextCtrl::OnJoy(wxJoyEvent& event)
{
static wxLongLong last_event = 0;
int16_t val = event.control_value();
wxSDLControl type = event.control();
wxJoyControl type = event.control();
// Filter consecutive axis motions within 300ms, as this adds two bindings
// +1/-1 instead of the one intended.
if (type == WXSDLJOY_AXIS && wxGetUTCTimeMillis() - last_event < 300)
if (type == wxJoyControl::Axis && wxGetUTCTimeMillis() - last_event < 300)
return;
last_event = wxGetUTCTimeMillis();
int mod = DigitalButton(event);
uint8_t key = event.control_index();
unsigned joy = event.player_index();
unsigned joy = event.joystick().player_index();
if (!val || mod < 0)
return;

View File

@ -47,15 +47,51 @@ const wxLongLong kPollTimeInterval(25);
// For testing a GameController as a Joystick:
//#define SDL_IsGameController(x) false
DEFINE_EVENT_TYPE(wxEVT_SDLJOY)
DEFINE_EVENT_TYPE(wxEVT_JOY)
wxSDLJoyEvent::wxSDLJoyEvent(
unsigned player_index,
wxSDLControl control,
// static
wxJoystick wxJoystick::Invalid() {
return wxJoystick(kInvalidSdlIndex);
}
// static
wxJoystick wxJoystick::FromLegacyPlayerIndex(unsigned player_index) {
assert(player_index != 0);
return wxJoystick(player_index - 1);
}
wxString wxJoystick::ToString() {
return wxString::Format("Joy%d", sdl_index_ + 1);
}
bool wxJoystick::operator==(const wxJoystick& other) const {
return sdl_index_ == other.sdl_index_;
}
bool wxJoystick::operator!=(const wxJoystick& other) const {
return !(*this == other);
}
bool wxJoystick::operator<(const wxJoystick& other) const {
return sdl_index_ < other.sdl_index_;
}
bool wxJoystick::operator<=(const wxJoystick& other) const {
return !(*this > other);
}
bool wxJoystick::operator>(const wxJoystick& other) const {
return other < *this;
}
bool wxJoystick::operator>=(const wxJoystick& other) const {
return !(*this < other);
}
wxJoystick::wxJoystick(int sdl_index) : sdl_index_(sdl_index) {}
wxJoyEvent::wxJoyEvent(
wxJoystick joystick,
wxJoyControl control,
uint8_t control_index,
int16_t control_value) :
wxCommandEvent(wxEVT_SDLJOY),
player_index_(player_index),
wxCommandEvent(wxEVT_JOY),
joystick_(joystick),
control_(control),
control_index_(control_index),
control_value_(control_value) {}
@ -66,6 +102,7 @@ wxSDLJoyEvent::wxSDLJoyEvent(
class wxSDLJoyState : public wxTimer {
public:
explicit wxSDLJoyState(int sdl_index);
explicit wxSDLJoyState(wxJoystick joystick);
~wxSDLJoyState() override;
// Disable copy constructor and assignment. This is to prevent double
@ -94,8 +131,8 @@ private:
// Used to rumble on a timer.
void Notify() override;
// The Joystick player index.
unsigned player_index_;
// The Joystick abstraction for UI events.
wxJoystick wx_joystick_;
// SDL Joystick ID used for events.
SDL_JoystickID joystick_id_;
@ -104,7 +141,7 @@ private:
SDL_GameController* game_controller_ = nullptr;
// The SDL Joystick instance.
SDL_Joystick* joystick_ = nullptr;
SDL_Joystick* sdl_joystick_ = nullptr;
// Current state of Joystick axis.
std::unordered_map<uint8_t, int16_t> axis_{};
@ -120,47 +157,50 @@ private:
};
wxSDLJoyState::wxSDLJoyState(int sdl_index)
: player_index_(sdl_index + 1) {
: wxSDLJoyState(wxJoystick(sdl_index)) {}
wxSDLJoyState::wxSDLJoyState(wxJoystick joystick) : wx_joystick_(joystick) {
int sdl_index = wx_joystick_.sdl_index_;
if (SDL_IsGameController(sdl_index)) {
game_controller_ = SDL_GameControllerOpen(sdl_index);
if (game_controller_)
joystick_ = SDL_GameControllerGetJoystick(game_controller_);
sdl_joystick_ = SDL_GameControllerGetJoystick(game_controller_);
} else {
joystick_ = SDL_JoystickOpen(sdl_index);
sdl_joystick_ = SDL_JoystickOpen(sdl_index);
}
if (!joystick_)
if (!sdl_joystick_)
return;
joystick_id_ = SDL_JoystickInstanceID(joystick_);
joystick_id_ = SDL_JoystickInstanceID(sdl_joystick_);
systemScreenMessage(
wxString::Format(_("Connected joystick %d: %s"),
player_index_, SDL_JoystickNameForIndex(sdl_index)));
wxString::Format(_("Connected %s: %s"),
wx_joystick_.ToString(), SDL_JoystickNameForIndex(sdl_index)));
}
wxSDLJoyState::~wxSDLJoyState() {
// Nothing to do if this object is not initialized.
if (!joystick_)
if (!sdl_joystick_)
return;
if (game_controller_)
SDL_GameControllerClose(game_controller_);
else
SDL_JoystickClose(joystick_);
SDL_JoystickClose(sdl_joystick_);
systemScreenMessage(
wxString::Format(_("Disconnected joystick %d"), player_index_));
wxString::Format(_("Disconnected %s"), wx_joystick_.ToString()));
}
bool wxSDLJoyState::IsValid() const {
return joystick_;
return sdl_joystick_;
}
void wxSDLJoyState::ProcessEvent(int32_t event_type,
uint8_t control_index,
int16_t control_value) {
int16_t previous_value = 0;
wxSDLControl control;
wxJoyControl control;
bool value_changed = false;
switch (event_type) {
@ -173,7 +213,7 @@ void wxSDLJoyState::ProcessEvent(int32_t event_type,
// Fallhrough.
case SDL_CONTROLLERBUTTONDOWN:
case SDL_CONTROLLERBUTTONUP:
control = wxSDLControl::WXSDLJOY_BUTTON;
control = wxJoyControl::Button;
previous_value = buttons_[control_index];
if (previous_value != control_value) {
buttons_[control_index] = control_value;
@ -186,7 +226,7 @@ void wxSDLJoyState::ProcessEvent(int32_t event_type,
if (game_controller_) {
return;
}
control = wxSDLControl::WXSDLJOY_HAT;
control = wxJoyControl::Hat;
previous_value = hats_[control_index];
if (previous_value != control_value) {
hats_[control_index] = control_value;
@ -201,7 +241,7 @@ void wxSDLJoyState::ProcessEvent(int32_t event_type,
}
// Fallhrough.
case SDL_CONTROLLERAXISMOTION:
control = wxSDLControl::WXSDLJOY_AXIS;
control = wxJoyControl::Axis;
previous_value = axis_[control_index];
if (previous_value != control_value) {
axis_[control_index] = control_value;
@ -216,17 +256,18 @@ void wxSDLJoyState::ProcessEvent(int32_t event_type,
}
if (value_changed) {
wxLogDebug("GOT %s: joy:%d ctrl_idx:%d val:%d prev_val:%d",
SDLEventTypeToDebugString(event_type), player_index_,
control_index, control_value, previous_value);
wxLogDebug("GOT %s: %s ctrl_idx:%d val:%d prev_val:%d",
SDLEventTypeToDebugString(event_type),
wx_joystick_.ToString(), control_index, control_value,
previous_value);
auto handler = wxGetApp().frame->GetJoyEventHandler();
if (!handler)
return;
wxQueueEvent(handler,
new wxSDLJoyEvent(
player_index_, control, control_index, control_value));
new wxJoyEvent(
wx_joystick_, control, control_index, control_value));
}
}
@ -255,26 +296,26 @@ void wxSDLJoyState::Poll() {
ProcessEvent(SDL_CONTROLLERAXISMOTION, axis, current_value);
}
} else {
for (uint8_t but = 0; but < SDL_JoystickNumButtons(joystick_); but++) {
for (uint8_t but = 0; but < SDL_JoystickNumButtons(sdl_joystick_); but++) {
uint16_t previous_value = buttons_[but];
uint16_t current_value = SDL_JoystickGetButton(joystick_, but);
uint16_t current_value = SDL_JoystickGetButton(sdl_joystick_, but);
if (previous_value != current_value)
ProcessEvent(SDL_JOYBUTTONUP, but, current_value);
}
for (uint8_t axis = 0; axis < SDL_JoystickNumAxes(joystick_); axis++) {
for (uint8_t axis = 0; axis < SDL_JoystickNumAxes(sdl_joystick_); axis++) {
uint16_t previous_value = axis_[axis];
uint16_t current_value =
AxisValueToDirection(SDL_JoystickGetButton(joystick_, axis));
AxisValueToDirection(SDL_JoystickGetButton(sdl_joystick_, axis));
if (previous_value != current_value)
ProcessEvent(SDL_JOYAXISMOTION, axis, current_value);
}
for (uint8_t hat = 0; hat < SDL_JoystickNumHats(joystick_); hat++) {
for (uint8_t hat = 0; hat < SDL_JoystickNumHats(sdl_joystick_); hat++) {
uint16_t previous_value = hats_[hat];
uint16_t current_value = SDL_JoystickGetHat(joystick_, hat);
uint16_t current_value = SDL_JoystickGetHat(sdl_joystick_, hat);
if (previous_value != current_value)
ProcessEvent(SDL_JOYHATMOTION, hat, current_value);
@ -304,7 +345,7 @@ void wxSDLJoyState::Notify() {
SetRumble(rumbling_);
}
wxSDLJoy::wxSDLJoy() {
wxJoyPoller::wxJoyPoller() {
// Start up joystick if not already started
// FIXME: check for errors
SDL_Init(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER);
@ -312,14 +353,14 @@ wxSDLJoy::wxSDLJoy() {
SDL_JoystickEventState(SDL_ENABLE);
}
wxSDLJoy::~wxSDLJoy() {
wxJoyPoller::~wxJoyPoller() {
// It is necessary to free all SDL resources before quitting SDL.
joystick_states_.clear();
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
SDL_QuitSubSystem(SDL_INIT_GAMECONTROLLER);
}
void wxSDLJoy::Poll() {
void wxJoyPoller::Poll() {
SDL_Event e;
bool got_event = false;
@ -421,7 +462,7 @@ void wxSDLJoy::Poll() {
}
}
void wxSDLJoy::RemapControllers() {
void wxJoyPoller::RemapControllers() {
if (!is_polling_active_) {
// Nothing to do when we're not actively polling.
return;
@ -429,7 +470,7 @@ void wxSDLJoy::RemapControllers() {
joystick_states_.clear();
if (requested_sdl_indexes_.empty()) {
if (requested_joysticks_.empty()) {
// Connect all joysticks.
for (int i = 0; i < SDL_NumJoysticks(); i++) {
std::unique_ptr<wxSDLJoyState> joy_state(new wxSDLJoyState(i));
@ -440,9 +481,9 @@ void wxSDLJoy::RemapControllers() {
}
} else {
// Only attempt to add the joysticks we care about.
for (const int& sdl_index : requested_sdl_indexes_) {
for (const wxJoystick& joystick : requested_joysticks_) {
std::unique_ptr<wxSDLJoyState> joy_state(
new wxSDLJoyState(sdl_index));
new wxSDLJoyState(joystick));
if (joy_state->IsValid()) {
joystick_states_.emplace(
joy_state->joystick_id(), std::move(joy_state));
@ -451,45 +492,41 @@ void wxSDLJoy::RemapControllers() {
}
}
wxSDLJoyState* wxSDLJoy::FindJoyState(const SDL_JoystickID& joy_id) {
wxSDLJoyState* wxJoyPoller::FindJoyState(const SDL_JoystickID& joy_id) {
const auto iter = joystick_states_.find(joy_id);
if (iter == joystick_states_.end())
return nullptr;
return iter->second.get();
}
void wxSDLJoy::PollJoysticks(std::unordered_set<unsigned> indexes) {
void wxJoyPoller::PollJoysticks(std::set<wxJoystick> joysticks) {
// Reset the polling state.
StopPolling();
if (indexes.empty()) {
if (joysticks.empty()) {
// Nothing to poll. Return early.
return;
}
is_polling_active_ = true;
std::for_each(
indexes.begin(), indexes.end(),
[&](const unsigned& player_index) {
requested_sdl_indexes_.insert(player_index - 1);
});
requested_joysticks_ = joysticks;
RemapControllers();
}
void wxSDLJoy::PollAllJoysticks() {
void wxJoyPoller::PollAllJoysticks() {
// Reset the polling state.
StopPolling();
is_polling_active_ = true;
RemapControllers();
}
void wxSDLJoy::StopPolling() {
void wxJoyPoller::StopPolling() {
joystick_states_.clear();
requested_sdl_indexes_.clear();
requested_joysticks_.clear();
is_polling_active_ = false;
}
void wxSDLJoy::SetRumble(bool activate_rumble) {
void wxJoyPoller::SetRumble(bool activate_rumble) {
if (joystick_states_.empty())
return;

View File

@ -48,8 +48,8 @@ public:
// key is event.GetControlIndex(), and joy is event.GetJoy() + 1
// mod is derived from GetControlValue() and GetControlType():
// convert wxSDLJoyEvent's type+val into mod (WXJB_*)
static int DigitalButton(wxSDLJoyEvent& event);
// convert wxJoyEvent's type+val into mod (WXJB_*)
static int DigitalButton(wxJoyEvent& event);
// convert mod+key to accel string, separated by -
static wxString ToString(int mod, int key, int joy, bool isConfig = false);
// convert multiple keys, separated by multikey
@ -68,7 +68,7 @@ public:
static wxString FromAccelToString(wxAcceleratorEntry_v keys, wxChar sep = wxT(','), bool isConfig = false);
protected:
void OnJoy(wxSDLJoyEvent&);
void OnJoy(wxJoyEvent&);
DECLARE_DYNAMIC_CLASS(wxJoyKeyTextCtrl);
DECLARE_EVENT_TABLE();

View File

@ -1,8 +1,9 @@
#ifndef JOYEVT_H
#define JOYEVT_H
#ifndef _WX_SDLJOY_H
#define _WX_SDLJOY_H
#include <memory>
#include <unordered_set>
#include <set>
#include <map>
#include <unordered_map>
#include <wx/time.h>
#include <wx/event.h>
@ -10,60 +11,99 @@
#include <SDL_gamecontroller.h>
#include <SDL_events.h>
// Forward declarations.
class wxSDLJoyState;
class wxJoyPoller;
// The different types of supported controls.
enum wxSDLControl {
WXSDLJOY_AXIS, // Control value is signed 16
WXSDLJOY_HAT, // Control value is bitmask NESW/URDL
WXSDLJOY_BUTTON // Control value is 0 or 1
enum class wxJoyControl {
Axis = 0, // Control value is signed 16
Hat, // Control value is bitmask NESW/URDL
Button // Control value is 0 or 1
};
// Abstraction for a single joystick. In the current implementation, this
// encapsulates an |sdl_index_|. Creation of these objects should only be
// handled by wxSDLJoyState, with the exception of the legacy player_index
// constructor, which should eventually go away.
class wxJoystick {
public:
static wxJoystick Invalid();
// TODO: Remove this constructor once the transition to the new UserInput
// type is complete.
static wxJoystick FromLegacyPlayerIndex(unsigned player_index);
virtual ~wxJoystick() = default;
wxString ToString();
// TODO: Remove this API once the transition to the new UserInput type is
// complete.
unsigned player_index() { return sdl_index_ + 1; }
bool operator==(const wxJoystick& other) const;
bool operator!=(const wxJoystick& other) const;
bool operator<(const wxJoystick& other) const;
bool operator<=(const wxJoystick& other) const;
bool operator>(const wxJoystick& other) const;
bool operator>=(const wxJoystick& other) const;
private:
static const int kInvalidSdlIndex = -1;
friend class wxSDLJoyState;
wxJoystick() = delete;
wxJoystick(int sdl_index);
int sdl_index_;
};
// Represents a Joystick event.
class wxSDLJoyEvent : public wxCommandEvent {
class wxJoyEvent : public wxCommandEvent {
public:
wxSDLJoyEvent(
unsigned player_index,
wxSDLControl control,
wxJoyEvent(
wxJoystick joystick,
wxJoyControl control,
uint8_t control_index,
int16_t control_value);
virtual ~wxSDLJoyEvent() = default;
virtual ~wxJoyEvent() = default;
unsigned player_index() const { return player_index_; }
wxSDLControl control() const { return control_; }
wxJoystick joystick() const { return joystick_; }
wxJoyControl control() const { return control_; }
uint8_t control_index() const { return control_index_; }
int16_t control_value() const { return control_value_; }
private:
unsigned player_index_;
wxSDLControl control_;
wxJoystick joystick_;
wxJoyControl control_;
uint8_t control_index_;
int16_t control_value_;
};
class wxSDLJoyState;
// This is my own SDL-based joystick handler, since wxJoystick is brain-dead.
// It's geared towards keyboard emulation.
//
// After initilization, use PollJoystick() or PollAllJoysticks() for the
// joysticks you wish to monitor. The target window will then receive
// EVT_SDLJOY events of type wxSDLJoyEvent.
// Handling of the player_index() value is different depending on the polling
// mode. After calls to PollJoysticks(), that value will remain constant for a
// given device, even if other joysticks disconnect. This ensures the joystick
// remains active during gameplay even if other joysticks disconnect.
// joysticks you wish to monitor. The target window will then receive EVT_SDLJOY
// events of type wxJoyEvent.
// Handling of the wxJoystick value is different depending on the polling mode.
// After calls to PollJoysticks(), that value will remain constant for a given
// device, even if other joysticks disconnect. This ensures the joystick remains
// active during gameplay even if other joysticks disconnect.
// However, after calls to PollAllJoysticks(), all joysticks are re-connected
// on joystick connect/disconnect. This ensures the right player_index() value
// is sent to the UI during input event configuration.
class wxSDLJoy {
// on joystick connect/disconnect. This ensures the right wxJoystick value is
// sent to the UI during input event configuration.
class wxJoyPoller {
public:
wxSDLJoy();
~wxSDLJoy();
wxJoyPoller();
~wxJoyPoller();
// Adds a set of joysticks to the list of polled joysticks.
// This will disconnect every active joysticks, and reactivates the ones
// matching an index in |indexes|. Missing joysticks will be connected if
// matching an index in |joysticks|. Missing joysticks will be connected if
// they connect later on.
void PollJoysticks(std::unordered_set<unsigned> indexes);
void PollJoysticks(std::set<wxJoystick> joysticks);
// Adds all joysticks to the list of polled joysticks. This will
// disconnect every active joysticks, reconnect them and start polling.
@ -91,7 +131,7 @@ private:
std::unordered_map<SDL_JoystickID, std::unique_ptr<wxSDLJoyState>> joystick_states_;
// Set of requested SDL joystick indexes.
std::unordered_set<int> requested_sdl_indexes_;
std::set<wxJoystick> requested_joysticks_;
// Set to true when we are actively polling controllers.
bool is_polling_active_ = false;
@ -101,15 +141,15 @@ private:
};
// Note: this means sdljoy can't be part of a library w/o extra work
DECLARE_LOCAL_EVENT_TYPE(wxEVT_SDLJOY, -1)
typedef void (wxEvtHandler::*wxSDLJoyEventFunction)(wxSDLJoyEvent&);
DECLARE_LOCAL_EVENT_TYPE(wxEVT_JOY, -1)
typedef void (wxEvtHandler::*wxJoyEventFunction)(wxJoyEvent&);
#define EVT_SDLJOY(fn) \
DECLARE_EVENT_TABLE_ENTRY(wxEVT_SDLJOY, \
DECLARE_EVENT_TABLE_ENTRY(wxEVT_JOY, \
wxID_ANY, \
wxID_ANY, \
(wxObjectEventFunction)(wxEventFunction)(wxCommandEventFunction) \
wxStaticCastEvent(wxSDLJoyEventFunction, &fn), \
wxStaticCastEvent(wxJoyEventFunction, &fn), \
(wxObject*)NULL) \
,
#endif /* JOYEVT_H */
#endif /* _WX_SDLJOY_H */

View File

@ -877,13 +877,13 @@ int MainFrame::FilterEvent(wxEvent& event)
return wxEventFilter::Event_Processed;
}
}
else if (event.GetEventType() == wxEVT_SDLJOY && !menus_opened && !dialog_opened)
else if (event.GetEventType() == wxEVT_JOY && !menus_opened && !dialog_opened)
{
wxSDLJoyEvent& je = (wxSDLJoyEvent&)event;
wxJoyEvent& je = (wxJoyEvent&)event;
if (je.control_value() == 0) return -1; // joystick button UP
uint8_t key = je.control_index();
int mod = wxJoyKeyTextCtrl::DigitalButton(je);
int joy = je.player_index();
int joy = je.joystick().player_index();
wxString label = wxJoyKeyTextCtrl::ToString(mod, key, joy);
wxAcceleratorEntry_v accels = wxGetApp().GetAccels();
for (size_t i = 0; i < accels.size(); ++i)
@ -934,14 +934,15 @@ void MainFrame::SetJoystick()
if (!emulating)
return;
std::unordered_set<unsigned> needed_joysticks;
std::set<wxJoystick> needed_joysticks;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < NUM_KEYS; j++) {
wxJoyKeyBinding_v b = gopts.joykey_bindings[i][j];
for (size_t k = 0; k < b.size(); k++) {
int jn = b[k].joy;
if (jn) {
needed_joysticks.insert(jn);
needed_joysticks.insert(
wxJoystick::FromLegacyPlayerIndex(jn));
}
}
}

View File

@ -360,7 +360,7 @@ private:
wxMenu* recent;
wxAcceleratorEntryUnicode recent_accel[10];
// joystick reader
wxSDLJoy joy;
wxJoyPoller joy;
JoystickPoller* jpoll = nullptr;
// helper function for adding menu to accel editor
@ -647,7 +647,7 @@ protected:
void OnIdle(wxIdleEvent&);
void OnKeyDown(wxKeyEvent& ev);
void OnKeyUp(wxKeyEvent& ev);
void OnSDLJoy(wxSDLJoyEvent& ev);
void OnSDLJoy(wxJoyEvent& ev);
void PaintEv(wxPaintEvent& ev);
void EraseBackground(wxEraseEvent& ev);
void OnSize(wxSizeEvent& ev);