diff --git a/src/citra/emu_window/emu_window_sdl2.cpp b/src/citra/emu_window/emu_window_sdl2.cpp index 1bf901e92..7d5372277 100644 --- a/src/citra/emu_window/emu_window_sdl2.cpp +++ b/src/citra/emu_window/emu_window_sdl2.cpp @@ -42,7 +42,7 @@ void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) { } void EmuWindow_SDL2::OnKeyEvent(SDL_Keysym key, u8 state) { - auto& keyboard = InputCore::main_keyboard; + auto& keyboard = InputCore::GetKeyboard(); KeyboardKey param = KeyboardKey(key.sym, key.scancode, SDL_GetKeyName(key.scancode)); if (state == SDL_PRESSED) { diff --git a/src/citra_qt/bootmanager.cpp b/src/citra_qt/bootmanager.cpp index 35a359cf1..15d595564 100644 --- a/src/citra_qt/bootmanager.cpp +++ b/src/citra_qt/bootmanager.cpp @@ -237,14 +237,14 @@ void GRenderWindow::closeEvent(QCloseEvent* event) { void GRenderWindow::keyPressEvent(QKeyEvent* event) { - auto& keyboard = InputCore::main_keyboard; + auto& keyboard = InputCore::GetKeyboard(); KeyboardKey param = KeyboardKey(event->key(), event->nativeScanCode(), QKeySequence(event->key()).toString().toStdString()); keyboard->KeyPressed(param); } void GRenderWindow::keyReleaseEvent(QKeyEvent* event) { - auto& keyboard = InputCore::main_keyboard; + auto& keyboard = InputCore::GetKeyboard(); KeyboardKey param = KeyboardKey(event->key(), event->nativeScanCode(), QKeySequence(event->key()).toString().toStdString()); keyboard->KeyReleased(param); } diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index d0b940b38..c46633f90 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -76,10 +76,10 @@ void Update() { return; } - PadState state = InputCore::pad_state; + PadState state = InputCore::GetPadState(); // Get current circle pad position and update circle pad direction s16 circle_pad_x, circle_pad_y; - std::tie(circle_pad_x, circle_pad_y) = InputCore::circle_pad; + std::tie(circle_pad_x, circle_pad_y) = InputCore::GetCirclePad(); state.hex |= GetCirclePadDirectionState(circle_pad_x, circle_pad_y).hex; mem->pad.current_state.hex = state.hex; diff --git a/src/core/settings.h b/src/core/settings.h index ffcd522ab..cf74faa23 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -56,37 +56,32 @@ namespace Settings { int number = 0; Device device = Device::Keyboard; std::string key; - InputDeviceMapping() { } - InputDeviceMapping(std::string input) { + + InputDeviceMapping() = default; + InputDeviceMapping(const std::string& input) { std::vector parts; Common::SplitString(input, '/', parts); - if (parts.size() == 4) { - if (parts[0] == "Qt") - framework = DeviceFramework::Qt; - else if (parts[0] == "SDL") - framework = DeviceFramework::SDL; + if (parts.size() != 4) + return; - number = std::stoi(parts[1]); - - if (parts[2] == "Keyboard") - device = Device::Keyboard; - else if (parts[2] == "Gamepad") - device = Device::Gamepad; - key = parts[3]; - } - else { - //default if can't read properly + if (parts[0] == "Qt") framework = DeviceFramework::Qt; - number = 0; + else if (parts[0] == "SDL") + framework = DeviceFramework::SDL; + + number = std::stoi(parts[1]); + + if (parts[2] == "Keyboard") device = Device::Keyboard; - key = ""; - } + else if (parts[2] == "Gamepad") + device = Device::Gamepad; + key = parts[3]; } bool operator==(const InputDeviceMapping& rhs) const { return (this->device == rhs.device) && (this->framework == rhs.framework) && (this->number == rhs.number); } - std::string ToString() const{ + std::string ToString() const { std::string result; if (framework == DeviceFramework::Qt) result = "Qt"; @@ -101,6 +96,7 @@ namespace Settings { result += "Keyboard"; else if (device == Device::Gamepad) result += "Gamepad"; + result += "/"; result += key; return result; diff --git a/src/input_core/devices/IDevice.h b/src/input_core/devices/IDevice.h index 4df588772..e262d8879 100644 --- a/src/input_core/devices/IDevice.h +++ b/src/input_core/devices/IDevice.h @@ -12,9 +12,11 @@ class IDevice { public: virtual ~IDevice() = default; - std::map> keyMapping; /// Maps the string in the settings file to the HID Padstate object - virtual bool InitDevice(int number, std::map> keyMap) = 0; + virtual bool InitDevice(int number, const std::map>& keyMap) = 0; virtual void ProcessInput() = 0; virtual bool CloseDevice() = 0; +protected: + std::map> keyMapping; ///< Maps the string in the settings file to the HID Padstate object + }; diff --git a/src/input_core/devices/Keyboard.cpp b/src/input_core/devices/Keyboard.cpp index afa1cfe59..c3e1c95e3 100644 --- a/src/input_core/devices/Keyboard.cpp +++ b/src/input_core/devices/Keyboard.cpp @@ -12,7 +12,7 @@ Keyboard::Keyboard() { Keyboard::~Keyboard() { } -bool Keyboard::InitDevice(int number, std::map> keyMap) { +bool Keyboard::InitDevice(int number, const std::map>& keyMap) { keyMapping = keyMap; return true; } @@ -21,17 +21,17 @@ void Keyboard::ProcessInput() { std::lock_guard lock(m); auto keysPressedCopy = keysPressed; lock.~lock_guard(); - for (auto const &ent1 : keyMapping) { + for (const auto &ent1 : keyMapping) { int scancode = std::stoul(ent1.first, nullptr, 16); KeyboardKey proxy = KeyboardKey(0, scancode, ""); if (keysPressedCopy[proxy] == true && keysPressedLast[scancode] == false) { - for (auto& key : ent1.second) { + for (const auto& key : ent1.second) { KeyMap::PressKey(key, 1.0); } keysPressedLast[scancode] = true; } else if (keysPressedCopy[proxy] == false && keysPressedLast[scancode] == true) { - for (auto& key : ent1.second) { + for (const auto& key : ent1.second) { KeyMap::ReleaseKey(key); } keysPressedLast[scancode] = false; @@ -51,4 +51,4 @@ void Keyboard::KeyPressed(KeyboardKey key) { void Keyboard::KeyReleased(KeyboardKey key) { std::lock_guard lock(m); keysPressed[key] = false; -} \ No newline at end of file +} diff --git a/src/input_core/devices/Keyboard.h b/src/input_core/devices/Keyboard.h index 5b2c00942..d8271abc7 100644 --- a/src/input_core/devices/Keyboard.h +++ b/src/input_core/devices/Keyboard.h @@ -20,7 +20,7 @@ private: public: Keyboard(); ~Keyboard(); - bool InitDevice(int number, std::map> keyMap) override; + bool InitDevice(int number, const std::map>& keyMap) override; void ProcessInput() override; bool CloseDevice() override; void KeyPressed(KeyboardKey key); @@ -31,18 +31,16 @@ struct KeyboardKey { uint32_t key; uint32_t scancode; std::string character; - KeyboardKey(uint32_t Key, uint32_t Scancode, std::string Character) { - key = Key; - scancode = Scancode; - character = Character; + + KeyboardKey(uint32_t key_, uint32_t scancode_, std::string character_) : key(key_), scancode(scancode_), character(std::move(character_)) { } bool operator==(const KeyboardKey& other) const { - return (this->scancode == other.scancode); + return scancode == other.scancode; } bool operator==(uint32_t other) const { - return (this->scancode == other); + return scancode == other; } - bool operator<(const KeyboardKey &o) const { - return (this->scancode < o.scancode); + bool operator<(const KeyboardKey& other) const { + return scancode < other.scancode; } -}; \ No newline at end of file +}; diff --git a/src/input_core/devices/SDLGamepad.cpp b/src/input_core/devices/SDLGamepad.cpp index 37f499dd4..0ac5652fe 100644 --- a/src/input_core/devices/SDLGamepad.cpp +++ b/src/input_core/devices/SDLGamepad.cpp @@ -20,7 +20,7 @@ SDLGamepad::~SDLGamepad() { CloseDevice(); } -bool SDLGamepad::InitDevice(int number, std::map> keyMap) { +bool SDLGamepad::InitDevice(int number, const std::map>& keyMap) { if (!SDLGamepad::SDLInitialized && SDL_Init(SDL_INIT_GAMECONTROLLER) < 0) { LOG_CRITICAL(Input, "SDL_Init(SDL_INIT_GAMECONTROLLER) failed"); return false; @@ -36,7 +36,7 @@ bool SDLGamepad::InitDevice(int number, std::map> keyMap) override; + bool InitDevice(int number, const std::map>& keyMap) override; void ProcessInput() override; bool CloseDevice() override; private: @@ -45,5 +45,5 @@ private: }; static bool SDLInitialized; std::map keysPressed; - SDL_GameController* gamepad; + SDL_GameController* gamepad = nullptr; }; diff --git a/src/input_core/input_core.cpp b/src/input_core/input_core.cpp index f43ae8434..788326cd7 100644 --- a/src/input_core/input_core.cpp +++ b/src/input_core/input_core.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include #include #include "core/core_timing.h" @@ -11,7 +12,6 @@ #include "input_core/devices/SDLGamepad.h" namespace InputCore { - constexpr u64 frame_ticks = 268123480ull / 60; static int tick_event; Service::HID::PadState pad_state; @@ -30,7 +30,7 @@ static void InputTickCallback(u64, int cycles_late) { } void Init() { - devices = ParseSettings(); + ParseSettings(); tick_event = CoreTiming::RegisterEvent("InputCore::tick_event", InputTickCallback); CoreTiming::ScheduleEvent(frame_ticks, tick_event); } @@ -39,18 +39,52 @@ void Shutdown() { devices.clear(); } -std::vector> ParseSettings() { - std::vector> devices; - std::vector uniqueMappings; //unique mappings from settings file, used to init devices. +Service::HID::PadState GetPadState() { + return pad_state; +} + +void SetPadState(Service::HID::PadState& state) { + pad_state.hex = state.hex; +} + +std::tuple GetCirclePad() { + return circle_pad; +} + +void SetCirclePad(std::tuple& pad) { + circle_pad = pad; +} + +std::shared_ptr GetKeyboard() { + return main_keyboard; +} + +///Get Unique input mappings from settings +std::vector GatherUniqueMappings() { + std::vector uniqueMappings; - //Get Unique input mappings from settings for (auto& mapping : Settings::values.input_mappings) { if (!CheckIfMappingExists(uniqueMappings, mapping)) { uniqueMappings.push_back(mapping); } } + return uniqueMappings; +} - //Generate a device for each unique mapping +std::map> BuildKeyMapping(Settings::InputDeviceMapping mapping) { + std::map> keyMapping; + for (int i = 0; i < Settings::values.input_mappings.size(); i++) { + KeyMap::KeyTarget val = KeyMap::mapping_targets[i]; + std::string key = Settings::values.input_mappings[i].key; + if (Settings::values.input_mappings[i] == mapping) { + keyMapping[key].push_back(val); + } + } + return keyMapping; +} + +///Generate a device for each unique mapping +void GenerateUniqueDevices(std::vector uniqueMappings) { std::shared_ptr input; for (auto& mapping : uniqueMappings) { switch (mapping.framework) { @@ -76,25 +110,23 @@ std::vector> ParseSettings() { devices.push_back(input); //Build map of inputs to listen for, for this device - std::map> keyMapping; - for (int i = 0; i < Settings::values.input_mappings.size(); i++) { - KeyMap::KeyTarget val = KeyMap::mapping_targets[i]; - std::string key = Settings::values.input_mappings[i].key; - if (Settings::values.input_mappings[i] == mapping) { - keyMapping[key].push_back(val); - } - } + auto keyMapping = BuildKeyMapping(mapping); input->InitDevice(mapping.number, keyMapping); } +} +void ParseSettings() { + std::vector> devices; + + auto uniqueMappings = GatherUniqueMappings(); + GenerateUniqueDevices(uniqueMappings); + //init keyboard, if it hasn't already if (main_keyboard == nullptr) main_keyboard = std::make_shared(); - - return devices; } -bool CheckIfMappingExists(const std::vector uniqueMapping, Settings::InputDeviceMapping mappingToCheck) { +bool CheckIfMappingExists(const std::vector& uniqueMapping, Settings::InputDeviceMapping mappingToCheck) { return std::any_of(uniqueMapping.begin(), uniqueMapping.end(), [mappingToCheck](const auto& mapping) { return mapping == mappingToCheck; }); diff --git a/src/input_core/input_core.h b/src/input_core/input_core.h index a09139d78..ddd856867 100644 --- a/src/input_core/input_core.h +++ b/src/input_core/input_core.h @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #pragma once + #include #include @@ -13,17 +14,16 @@ class Keyboard; namespace InputCore { - extern Service::HID::PadState pad_state; - extern std::tuple circle_pad; - - extern std::shared_ptr main_keyboard; ///< Instance of main keyboard device. Always initialized regardless of settings. - void Init(); void Shutdown(); + Service::HID::PadState GetPadState(); + void SetPadState(Service::HID::PadState& state); + std::tuple GetCirclePad(); + void SetCirclePad(std::tuple& circle ); + std::shared_ptr GetKeyboard(); + /// Read settings to initialize devices + void ParseSettings(); - ///Read settings to initialize devices - std::vector> ParseSettings(); - - ///Helper method to check if device was already initialized - bool CheckIfMappingExists(std::vector uniqueMapping, Settings::InputDeviceMapping mappingToCheck); + /// Helper method to check if device was already initialized + bool CheckIfMappingExists(const std::vector& uniqueMapping, Settings::InputDeviceMapping mappingToCheck); } diff --git a/src/input_core/key_map.cpp b/src/input_core/key_map.cpp index bb0362400..4f271df28 100644 --- a/src/input_core/key_map.cpp +++ b/src/input_core/key_map.cpp @@ -34,30 +34,40 @@ namespace KeyMap { }; void PressKey(KeyTarget target, const float strength) { - if (std::find(std::begin(analog_inputs), std::end(analog_inputs), target) == std::end(analog_inputs)) { // If is digital keytarget - InputCore::pad_state.hex |= target.target.direct_target_hex; + auto pad_state = InputCore::GetPadState(); + // If is digital keytarget + if (std::find(std::begin(analog_inputs), std::end(analog_inputs), target) == std::end(analog_inputs)) { + pad_state.hex |= target.target.direct_target_hex; + InputCore::SetPadState(pad_state); } else { // it is analog input + auto circle_pad = InputCore::GetCirclePad(); if (target == Service::HID::PAD_CIRCLE_UP || target == Service::HID::PAD_CIRCLE_DOWN) { - std::get<1>(InputCore::circle_pad) = MAX_CIRCLEPAD_POS * strength * -1; + std::get<1>(circle_pad) = MAX_CIRCLEPAD_POS * strength * -1; } else if (target == Service::HID::PAD_CIRCLE_LEFT || target == Service::HID::PAD_CIRCLE_RIGHT) { - std::get<0>(InputCore::circle_pad) = MAX_CIRCLEPAD_POS * strength; + std::get<0>(circle_pad) = MAX_CIRCLEPAD_POS * strength; } + InputCore::SetCirclePad(circle_pad); } } void ReleaseKey(KeyTarget target) { - if (std::find(std::begin(analog_inputs), std::end(analog_inputs), target) == std::end(analog_inputs)) { // If is digital keytarget - InputCore::pad_state.hex &= ~target.target.direct_target_hex; + auto pad_state = InputCore::GetPadState(); + // If is digital keytarget + if (std::find(std::begin(analog_inputs), std::end(analog_inputs), target) == std::end(analog_inputs)) { + pad_state.hex &= ~target.target.direct_target_hex; + InputCore::SetPadState(pad_state); } else { // it is analog input + auto circle_pad = InputCore::GetCirclePad(); if (target == Service::HID::PAD_CIRCLE_UP || target == Service::HID::PAD_CIRCLE_DOWN) { - std::get<1>(InputCore::circle_pad) = 0; + std::get<1>(circle_pad) = 0; } else if (target == Service::HID::PAD_CIRCLE_LEFT || target == Service::HID::PAD_CIRCLE_RIGHT) { - std::get<0>(InputCore::circle_pad) = 0; + std::get<0>(circle_pad) = 0; } + InputCore::SetCirclePad(circle_pad); } } }