From cfdbdc4ec2692187e834cd6cc8ea2b05c4b3cb9d Mon Sep 17 00:00:00 2001 From: Fabrice de Gans Date: Tue, 23 Apr 2024 14:46:45 -0700 Subject: [PATCH] [Input] Move input configuration objects to app Previously, some input-related configuration objects were either owned by `gopts` or global values. This moves these objects to be owned by the app object instead. Rather than directly accessing the app object, other objects (like dialogs) that need to access the input-related configuration objects are passed a `ConfigurationObjectProvider` function. This will make it easier to test these objects independently down the line. Bug: #745 --- src/wx/config/game-control.cpp | 12 ++----- src/wx/config/game-control.h | 28 +++++++++------- src/wx/config/internal/option-internal.cpp | 1 + src/wx/config/shortcuts.cpp | 13 ++++---- src/wx/config/shortcuts.h | 38 ++++++++++++---------- src/wx/dialogs/accel-config.cpp | 18 ++++++---- src/wx/dialogs/accel-config.h | 12 +++++-- src/wx/guiinit.cpp | 3 +- src/wx/opts.cpp | 25 +++++++------- src/wx/opts.h | 12 ++----- src/wx/panel.cpp | 8 ++--- src/wx/sys.cpp | 5 ++- src/wx/widgets/user-input-ctrl.cpp | 6 ++-- src/wx/wxvbam.cpp | 11 ++++--- src/wx/wxvbam.h | 11 +++++++ 15 files changed, 115 insertions(+), 88 deletions(-) diff --git a/src/wx/config/game-control.cpp b/src/wx/config/game-control.cpp index efd1e022..ff524593 100644 --- a/src/wx/config/game-control.cpp +++ b/src/wx/config/game-control.cpp @@ -1,6 +1,5 @@ #include "wx/config/game-control.h" -#include "wx/opts.h" #include "wx/strutils.h" #include "wx/wxlogdebug.h" @@ -195,13 +194,8 @@ bool GameControl::operator>=(const GameControl& other) const { return !(*this < other); } -GameControlState& GameControlState::Instance() { - static GameControlState g_game_control_state; - return g_game_control_state; -} - -GameControlState::GameControlState() : joypads_({0, 0, 0, 0}) {} -GameControlState::~GameControlState() = default; +GameControlState::GameControlState(const GameControlBindingsProvider bindings_provider) + : joypads_({0, 0, 0, 0}), bindings_provider_(bindings_provider) {} bool GameControlState::OnInputPressed(const config::UserInput& user_input) { assert(user_input); @@ -282,7 +276,7 @@ void GameControlState::OnGameBindingsChanged() { Reset(); input_bindings_.clear(); - for (const auto& iter : gopts.game_control_bindings) { + for (const auto& iter : *bindings_provider_()) { for (const auto& user_input : iter.second) { input_bindings_[user_input].emplace(iter.first); } diff --git a/src/wx/config/game-control.h b/src/wx/config/game-control.h index 5508f924..32350b3a 100644 --- a/src/wx/config/game-control.h +++ b/src/wx/config/game-control.h @@ -5,6 +5,7 @@ #include #include #include +#include #include @@ -107,12 +108,16 @@ private: friend class GameControlState; }; +using GameControlBindings = std::map>; +using GameControlBindingsProvider = std::function; + // Tracks in-game input and computes the joypad value used to send control input -// data to the emulator. -class GameControlState { +// data to the emulator. This class should be kept as a singleton owned by the +// application. +class GameControlState final { public: - // This is a global singleton. - static GameControlState& Instance(); + explicit GameControlState(const GameControlBindingsProvider bindings_provider); + ~GameControlState() = default; // Disable copy constructor and assignment operator. GameControlState(const GameControlState&) = delete; @@ -120,8 +125,8 @@ public: // Processes `user_input` and updates the internal tracking state. // Returns true if `user_input` corresponds to a game input. - bool OnInputPressed(const config::UserInput& user_input); - bool OnInputReleased(const config::UserInput& user_input); + bool OnInputPressed(const UserInput& user_input); + bool OnInputReleased(const UserInput& user_input); // Clears all input. void Reset(); @@ -133,15 +138,16 @@ public: uint32_t GetJoypad(int joypad) const; private: - GameControlState(); - ~GameControlState(); - std::map> input_bindings_; - std::map> active_controls_; - std::set keys_pressed_; + std::map> active_controls_; + std::unordered_set keys_pressed_; std::array joypads_; + + const GameControlBindingsProvider bindings_provider_; }; +using GameControlStateProvider = std::function; + } // namespace config #endif // VBAM_WX_CONFIG_GAME_CONTROL_H_ diff --git a/src/wx/config/internal/option-internal.cpp b/src/wx/config/internal/option-internal.cpp index 8181b470..8011ac9b 100644 --- a/src/wx/config/internal/option-internal.cpp +++ b/src/wx/config/internal/option-internal.cpp @@ -6,6 +6,7 @@ #include #include +#include #include #include diff --git a/src/wx/config/shortcuts.cpp b/src/wx/config/shortcuts.cpp index bebe5adf..a73bb843 100644 --- a/src/wx/config/shortcuts.cpp +++ b/src/wx/config/shortcuts.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "wx/config/user-input.h" @@ -28,14 +29,14 @@ Shortcuts::Shortcuts() { } } -Shortcuts::Shortcuts(const std::unordered_map>& command_to_inputs, - const std::map& input_to_command, - const std::map& disabled_defaults) +Shortcuts::Shortcuts(const std::unordered_map>& command_to_inputs, + const std::unordered_map& input_to_command, + const std::unordered_map& disabled_defaults) : command_to_inputs_(command_to_inputs.begin(), command_to_inputs.end()), input_to_command_(input_to_command.begin(), input_to_command.end()), disabled_defaults_(disabled_defaults.begin(), disabled_defaults.end()) {} -std::vector> Shortcuts::GetConfiguration() const { +std::vector> Shortcuts::GetKeyboardConfiguration() const { std::vector> config; config.reserve(command_to_inputs_.size() + 1); @@ -63,9 +64,9 @@ std::vector> Shortcuts::GetConfiguration() const { return config; } -std::set Shortcuts::InputsForCommand(int command) const { +std::unordered_set Shortcuts::InputsForCommand(int command) const { if (command == NoopCommand()) { - std::set noop_inputs; + std::unordered_set noop_inputs; for (const auto& iter : disabled_defaults_) { noop_inputs.insert(iter.first); } diff --git a/src/wx/config/shortcuts.h b/src/wx/config/shortcuts.h index 5ce61c14..994045b7 100644 --- a/src/wx/config/shortcuts.h +++ b/src/wx/config/shortcuts.h @@ -1,11 +1,10 @@ #ifndef VBAM_WX_CONFIG_SHORTCUTS_H_ #define VBAM_WX_CONFIG_SHORTCUTS_H_ -#include -#include -#include #include +#include #include +#include #include "wx/config/user-input.h" @@ -27,20 +26,23 @@ public: // Disable copy and copy assignment operator. // Clone() is provided only for the configuration window, this class - // should otherwise be treated as move-only. + // should otherwise be treated as move-only. If you wish to access the + // Shortcuts configuration, do it from wxGetApp()->GameControlState(). Shortcuts(const Shortcuts&) = delete; Shortcuts& operator=(const Shortcuts&) = delete; - // Returns the configuration for the INI file. + // Returns the shortcuts configuration for the INI file. // Internally, there are global default system inputs that are immediately // available on first run. For the configuration saved in the [Keyboard] // section of the vbam.ini file, we only keep track of the following: // - Disabled default input. These appear under [Keyboard/NOOP]. // - User-added custom bindings. These appear under [Keyboard/CommandName]. - std::vector> GetConfiguration() const; + // Essentially, this is a diff between the default shortcuts and the user + // configuration. + std::vector> GetKeyboardConfiguration() const; // Returns the list of input currently configured for `command`. - std::set InputsForCommand(int command) const; + std::unordered_set InputsForCommand(int command) const; // Returns the command currently assigned to `input` or nullptr if none. int CommandForInput(const UserInput& input) const; @@ -52,17 +54,17 @@ public: // Assigns `input` to `command`. Silently unassigns `input` if it is already // assigned to another command. - void AssignInputToCommand(const UserInput& input, int command); + void AssignInputToCommand(const UserInput& input, const int command); // Removes `input` assignment. No-op if `input` is not assigned. `input` - // must be a valid UserInput. + // must be a valid UserInput. Call will assert otherwise. void UnassignInput(const UserInput& input); private: - // Faster constructor for explitit copy. - Shortcuts(const std::unordered_map>& command_to_inputs, - const std::map& input_to_command, - const std::map& disabled_defaults); + // Faster constructor for explicit copy. + Shortcuts(const std::unordered_map>& command_to_inputs, + const std::unordered_map& input_to_command, + const std::unordered_map& disabled_defaults); // Helper method to unassign a binding used by the default configuration. // This requires special handling since the INI configuration is a diff @@ -70,14 +72,16 @@ private: void UnassignDefaultBinding(const UserInput& input); // Map of command to their associated input set. - std::unordered_map> command_to_inputs_; + std::unordered_map> command_to_inputs_; // Reverse map of the above. An input can only map to a single command. - std::map input_to_command_; - // Disabled default inputs. This is used to easily retrieve the + std::unordered_map input_to_command_; + // Disabled default shortcuts. This is used to easily retrieve the // configuration to save in the INI file. - std::map disabled_defaults_; + std::unordered_map disabled_defaults_; }; +using ShortcutsProvider = std::function; + } // namespace config #endif // VBAM_WX_CONFIG_SHORTCUTS_H_ diff --git a/src/wx/dialogs/accel-config.cpp b/src/wx/dialogs/accel-config.cpp index 104501cf..eedffccc 100644 --- a/src/wx/dialogs/accel-config.cpp +++ b/src/wx/dialogs/accel-config.cpp @@ -122,15 +122,21 @@ void PopulateTreeWithMenu(std::unordered_map* command_to_item } // namespace // static -AccelConfig* AccelConfig::NewInstance(wxWindow* parent, wxMenuBar* menu, wxMenu* recents) { +AccelConfig* AccelConfig::NewInstance(wxWindow* parent, + wxMenuBar* menu, + wxMenu* recents, + const config::ShortcutsProvider shortcuts_provider) { assert(parent); assert(menu); assert(recents); - return new AccelConfig(parent, menu, recents); + return new AccelConfig(parent, menu, recents, shortcuts_provider); } -AccelConfig::AccelConfig(wxWindow* parent, wxMenuBar* menu, wxMenu* recents) - : BaseDialog(parent, "AccelConfig") { +AccelConfig::AccelConfig(wxWindow* parent, + wxMenuBar* menu, + wxMenu* recents, + const config::ShortcutsProvider shortcuts_provider) + : BaseDialog(parent, "AccelConfig"), shortcuts_provider_(shortcuts_provider) { assert(menu); // Loads the various dialog elements. @@ -213,11 +219,11 @@ void AccelConfig::OnDialogShown(wxShowEvent& ev) { remove_button_->Enable(false); currently_assigned_label_->SetLabel(""); - config_shortcuts_ = gopts.shortcuts.Clone(); + config_shortcuts_ = shortcuts_provider_()->Clone(); } void AccelConfig::OnValidate(wxCommandEvent& ev) { - gopts.shortcuts = std::move(config_shortcuts_); + *shortcuts_provider_() = std::move(config_shortcuts_); ev.Skip(); } diff --git a/src/wx/dialogs/accel-config.h b/src/wx/dialogs/accel-config.h index 11c9ce42..cf16658e 100644 --- a/src/wx/dialogs/accel-config.h +++ b/src/wx/dialogs/accel-config.h @@ -24,7 +24,10 @@ namespace dialogs { // Manages the shortcuts editor dialog. class AccelConfig : public BaseDialog { public: - static AccelConfig* NewInstance(wxWindow* parent, wxMenuBar* menu_bar, wxMenu* recents); + static AccelConfig* NewInstance(wxWindow* parent, + wxMenuBar* menu_bar, + wxMenu* recents, + const config::ShortcutsProvider shortcuts_provider); ~AccelConfig() override = default; @@ -32,7 +35,10 @@ private: // The constructor is private so initialization has to be done via the // static method. This is because this class is destroyed when its // owner, `parent` is destroyed. This prevents accidental deletion. - AccelConfig(wxWindow* parent, wxMenuBar* menu_bar, wxMenu* recents); + AccelConfig(wxWindow* parent, + wxMenuBar* menu_bar, + wxMenu* recents, + const config::ShortcutsProvider shortcuts_provider); // Re-initializes the configuration. void OnDialogShown(wxShowEvent& ev); @@ -73,6 +79,8 @@ private: config::Shortcuts config_shortcuts_; int selected_command_ = 0; + + const config::ShortcutsProvider shortcuts_provider_; }; } // namespace dialogs diff --git a/src/wx/guiinit.cpp b/src/wx/guiinit.cpp index 6e506c48..4d99258d 100644 --- a/src/wx/guiinit.cpp +++ b/src/wx/guiinit.cpp @@ -2480,7 +2480,8 @@ bool MainFrame::BindControls() d->Fit(); } #endif - dialogs::AccelConfig::NewInstance(this, menubar, recent); + dialogs::AccelConfig::NewInstance(this, menubar, recent, + std::bind(&wxvbamApp::shortcuts, &wxGetApp())); } catch (std::exception& e) { wxLogError(wxString::FromUTF8(e.what())); return false; diff --git a/src/wx/opts.cpp b/src/wx/opts.cpp index fefa1f43..c21b5611 100644 --- a/src/wx/opts.cpp +++ b/src/wx/opts.cpp @@ -13,6 +13,7 @@ #include "wx/config/option-observer.h" #include "wx/config/option-proxy.h" #include "wx/config/option.h" +#include "wx/config/shortcuts.h" #include "wx/config/user-input.h" #include "wx/strutils.h" #include "wx/wxvbam.h" @@ -107,7 +108,7 @@ uint32_t LoadUnsignedOption(wxConfigBase* cfg, opts_t gopts; -const std::map> kDefaultBindings = { +const config::GameControlBindings kDefaultBindings = { {config::GameControl(0, config::GameKey::Up), { config::KeyboardInput('W'), @@ -469,10 +470,10 @@ void load_opts(bool first_time_launch) { } // Initialize game control bindings to populate the configuration map. - gopts.game_control_bindings.insert(kDefaultBindings.begin(), kDefaultBindings.end()); + wxGetApp().game_control_bindings()->insert(kDefaultBindings.begin(), kDefaultBindings.end()); // joypad is special - for (auto& iter : gopts.game_control_bindings) { + for (auto& iter : *wxGetApp().game_control_bindings()) { const wxString optname = iter.first.ToString(); if (cfg->Read(optname, &s)) { iter.second = config::UserInput::FromConfigString(s); @@ -487,8 +488,9 @@ void load_opts(bool first_time_launch) { // keyboard is special // Keyboard does not get written with defaults - wxString kbopt(wxT("Keyboard/")); + wxString kbopt("Keyboard/"); int kboff = kbopt.size(); + config::Shortcuts* shortcuts = wxGetApp().shortcuts(); for (int i = 0; i < ncmds; i++) { kbopt.resize(kboff); @@ -500,7 +502,7 @@ void load_opts(bool first_time_launch) { wxLogWarning(_("Invalid key binding %s for %s"), s.c_str(), kbopt.c_str()); } else { for (const auto& input : inputs) { - gopts.shortcuts.AssignInputToCommand(input, cmdtab[i].cmd_id); + shortcuts->AssignInputToCommand(input, cmdtab[i].cmd_id); } } } @@ -564,7 +566,7 @@ void update_joypad_opts() { // For joypad, compare the UserInput sets. bool game_bindings_changed = false; - for (const auto &iter : gopts.game_control_bindings) { + for (const auto& iter : *wxvbamApp().game_control_bindings()) { wxString option_name = iter.first.ToString(); std::unordered_set saved_config = config::UserInput::FromConfigString(cfg->Read(option_name, "")); @@ -575,7 +577,7 @@ void update_joypad_opts() { } if (game_bindings_changed) { - config::GameControlState::Instance().OnGameBindingsChanged(); + wxvbamApp().game_control_state()->OnGameBindingsChanged(); } cfg->SetPath("/"); @@ -588,7 +590,7 @@ void update_shortcut_opts() { // For shortcuts, it's easier to delete everything and start over. cfg->DeleteGroup("/Keyboard"); cfg->SetPath("/Keyboard"); - for (const auto& iter : gopts.shortcuts.GetConfiguration()) { + for (const auto& iter : wxGetApp().shortcuts()->GetKeyboardConfiguration()) { int cmd = 0; for (cmd = 0; cmd < ncmds; cmd++) if (cmdtab[cmd].cmd_id == iter.first) @@ -685,7 +687,7 @@ void opt_set(const wxString& name, const wxString& val) { wxLogWarning(_("Invalid key binding %s for %s"), val.c_str(), name.c_str()); } for (const auto& input : inputs) { - gopts.shortcuts.AssignInputToCommand(input, cmd->cmd_id); + wxGetApp().shortcuts()->AssignInputToCommand(input, cmd->cmd_id); } } @@ -694,11 +696,12 @@ void opt_set(const wxString& name, const wxString& val) { const nonstd::optional game_control = config::GameControl::FromString(name); + auto game_control_bindings = wxGetApp().game_control_bindings(); if (game_control) { if (val.empty()) { - gopts.game_control_bindings[game_control.value()].clear(); + (*game_control_bindings)[game_control.value()].clear(); } else { - gopts.game_control_bindings[game_control.value()] = + (*game_control_bindings)[game_control.value()] = config::UserInput::FromConfigString(val); } return; diff --git a/src/wx/opts.h b/src/wx/opts.h index a538c0c0..0905b9d5 100644 --- a/src/wx/opts.h +++ b/src/wx/opts.h @@ -1,21 +1,18 @@ #ifndef VBAM_WX_OPTS_H_ #define VBAM_WX_OPTS_H_ -#include +#include #include #include #include "wx/config/game-control.h" -#include "wx/config/shortcuts.h" -#include "wx/config/user-input.h" // Forward declaration. class wxFileHistory; // Default joystick bindings. -extern const std::map> - kDefaultBindings; +extern const config::GameControlBindings kDefaultBindings; extern struct opts_t { opts_t(); @@ -36,13 +33,8 @@ extern struct opts_t { int rewind_interval = 0; /// Joypad - std::map> - game_control_bindings; int autofire_rate = 1; - /// Keyboard - config::Shortcuts shortcuts; - /// Core int gdb_port = 55555; int link_num_players = 2; diff --git a/src/wx/panel.cpp b/src/wx/panel.cpp index 13c54763..69f3cd0b 100644 --- a/src/wx/panel.cpp +++ b/src/wx/panel.cpp @@ -1058,7 +1058,7 @@ GameArea::~GameArea() void GameArea::OnKillFocus(wxFocusEvent& ev) { - config::GameControlState::Instance().Reset(); + wxGetApp().game_control_state()->Reset(); ev.Skip(); } @@ -1079,7 +1079,7 @@ void GameArea::Pause() // when the game is paused like this, we should not allow any // input to remain pressed, because they could be released // outside of the game zone and we would not know about it. - config::GameControlState::Instance().Reset(); + wxGetApp().game_control_state()->Reset(); if (loaded != IMAGE_UNKNOWN) soundPause(); @@ -1330,13 +1330,13 @@ static Display* GetX11Display() { #endif // __WXGTK__ void GameArea::OnUserInputDown(widgets::UserInputEvent& event) { - if (config::GameControlState::Instance().OnInputPressed(event.input())) { + if (wxGetApp().game_control_state()->OnInputPressed(event.input())) { wxWakeUpIdle(); } } void GameArea::OnUserInputUp(widgets::UserInputEvent& event) { - if (config::GameControlState::Instance().OnInputReleased(event.input())) { + if (wxGetApp().game_control_state()->OnInputReleased(event.input())) { wxWakeUpIdle(); } diff --git a/src/wx/sys.cpp b/src/wx/sys.cpp index b435bc32..b70db8fc 100644 --- a/src/wx/sys.cpp +++ b/src/wx/sys.cpp @@ -340,7 +340,7 @@ uint32_t systemReadJoypad(int joy) if (joy < 0 || joy > 3) joy = OPTION(kJoyDefault) - 1; - uint32_t ret = config::GameControlState::Instance().GetJoypad(joy); + uint32_t ret = wxGetApp().game_control_state()->GetJoypad(joy); if (turbo) ret |= KEYM_SPEED; @@ -662,8 +662,7 @@ void systemUpdateSolarSensor() void systemUpdateMotionSensor() { for (int i = 0; i < 4; i++) { - const uint32_t joy_value = - config::GameControlState::Instance().GetJoypad(i); + const uint32_t joy_value = wxGetApp().game_control_state()->GetJoypad(i); if (!sensorx[i]) sensorx[i] = 2047; diff --git a/src/wx/widgets/user-input-ctrl.cpp b/src/wx/widgets/user-input-ctrl.cpp index e4007e1e..47963de0 100644 --- a/src/wx/widgets/user-input-ctrl.cpp +++ b/src/wx/widgets/user-input-ctrl.cpp @@ -3,8 +3,8 @@ #include #include "wx/config/user-input.h" -#include "wx/opts.h" #include "wx/widgets/user-input-event.h" +#include "wx/wxvbam.h" namespace widgets { @@ -119,7 +119,7 @@ bool UserInputCtrlValidator::TransferToWindow() { UserInputCtrl* control = wxDynamicCast(GetWindow(), UserInputCtrl); assert(control); - control->SetInputs(gopts.game_control_bindings[game_control_]); + control->SetInputs((*wxGetApp().game_control_bindings())[game_control_]); return true; } @@ -127,7 +127,7 @@ bool UserInputCtrlValidator::TransferFromWindow() { UserInputCtrl* control = wxDynamicCast(GetWindow(), UserInputCtrl); assert(control); - gopts.game_control_bindings.insert({game_control_, control->inputs()}); + wxGetApp().game_control_bindings()->insert({game_control_, control->inputs()}); return true; } diff --git a/src/wx/wxvbam.cpp b/src/wx/wxvbam.cpp index 461715c9..3aa8d930 100644 --- a/src/wx/wxvbam.cpp +++ b/src/wx/wxvbam.cpp @@ -58,8 +58,8 @@ void ResetMenuItemAccelerator(wxMenuItem* menu_item) { if (tab_index != wxString::npos) { new_label.resize(tab_index); } - std::set user_inputs = - gopts.shortcuts.InputsForCommand(menu_item->GetId()); + std::unordered_set user_inputs = + wxGetApp().shortcuts()->InputsForCommand(menu_item->GetId()); for (const config::UserInput& user_input : user_inputs) { if (user_input.device() != config::UserInput::Device::Keyboard) { // Cannot use joystick keybinding as text without wx assertion error. @@ -256,7 +256,8 @@ wxvbamApp::wxvbamApp() pending_fullscreen(false), frame(nullptr), using_wayland(false), - sdl_poller_(widgets::SdlPoller(std::bind(&wxvbamApp::GetJoyEventHandler, this))) {} + game_control_state_(std::bind(&wxvbamApp::game_control_bindings, this)), + sdl_poller_(std::bind(&wxvbamApp::GetJoyEventHandler, this)) {} const wxString wxvbamApp::GetPluginsDir() { @@ -541,7 +542,7 @@ bool wxvbamApp::OnInit() { // Initialize game bindings here, after defaults bindings, vbam.ini bindings // and command line overrides have been applied. - config::GameControlState::Instance().OnGameBindingsChanged(); + game_control_state()->OnGameBindingsChanged(); // We need to gather this information before crating the MainFrame as the // OnSize / OnMove event handlers can fire during construction. @@ -1008,7 +1009,7 @@ int MainFrame::FilterEvent(wxEvent& event) { } const widgets::UserInputEvent& user_input_event = static_cast(event); - const int command = gopts.shortcuts.CommandForInput(user_input_event.input()); + const int command = wxGetApp().shortcuts()->CommandForInput(user_input_event.input()); if (command == 0) { // No associated command found. return wxEventFilter::Event_Skip; diff --git a/src/wx/wxvbam.h b/src/wx/wxvbam.h index db1197ba..133faac0 100644 --- a/src/wx/wxvbam.h +++ b/src/wx/wxvbam.h @@ -12,8 +12,10 @@ #include #include "core/base/system.h" +#include "wx/config/game-control.h" #include "wx/config/option-observer.h" #include "wx/config/option.h" +#include "wx/config/shortcuts.h" #include "wx/dialogs/base-dialog.h" #include "wx/widgets/dpi-support.h" #include "wx/widgets/keep-on-top-styler.h" @@ -118,6 +120,11 @@ public: } } + // Accessors for configuration data. + config::Shortcuts* shortcuts() { return &shortcuts_; } + config::GameControlState* game_control_state() { return &game_control_state_; } + config::GameControlBindings* game_control_bindings() { return &game_control_bindings_; } + virtual ~wxvbamApp(); protected: @@ -129,6 +136,10 @@ private: // Returns the currently active event handler to use for user input events. wxEvtHandler* GetJoyEventHandler(); + config::Shortcuts shortcuts_; + config::GameControlState game_control_state_; + config::GameControlBindings game_control_bindings_; + wxPathList config_path; char* home = nullptr;