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:
parent
37dc95b930
commit
f132e15511
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue