diff options
Diffstat (limited to 'src/core/frontend')
| -rw-r--r-- | src/core/frontend/emu_window.cpp | 26 | ||||
| -rw-r--r-- | src/core/frontend/emu_window.h | 54 | ||||
| -rw-r--r-- | src/core/frontend/input.h | 110 | ||||
| -rw-r--r-- | src/core/frontend/key_map.cpp | 152 | ||||
| -rw-r--r-- | src/core/frontend/key_map.h | 93 |
5 files changed, 111 insertions, 324 deletions
diff --git a/src/core/frontend/emu_window.cpp b/src/core/frontend/emu_window.cpp index a155b657d..73a44bfe7 100644 --- a/src/core/frontend/emu_window.cpp +++ b/src/core/frontend/emu_window.cpp | |||
| @@ -7,33 +7,9 @@ | |||
| 7 | #include "common/assert.h" | 7 | #include "common/assert.h" |
| 8 | #include "core/core.h" | 8 | #include "core/core.h" |
| 9 | #include "core/frontend/emu_window.h" | 9 | #include "core/frontend/emu_window.h" |
| 10 | #include "core/frontend/key_map.h" | 10 | #include "core/settings.h" |
| 11 | #include "video_core/video_core.h" | 11 | #include "video_core/video_core.h" |
| 12 | 12 | ||
| 13 | void EmuWindow::ButtonPressed(Service::HID::PadState pad) { | ||
| 14 | pad_state.hex |= pad.hex; | ||
| 15 | } | ||
| 16 | |||
| 17 | void EmuWindow::ButtonReleased(Service::HID::PadState pad) { | ||
| 18 | pad_state.hex &= ~pad.hex; | ||
| 19 | } | ||
| 20 | |||
| 21 | void EmuWindow::CirclePadUpdated(float x, float y) { | ||
| 22 | constexpr int MAX_CIRCLEPAD_POS = 0x9C; // Max value for a circle pad position | ||
| 23 | |||
| 24 | // Make sure the coordinates are in the unit circle, | ||
| 25 | // otherwise normalize it. | ||
| 26 | float r = x * x + y * y; | ||
| 27 | if (r > 1) { | ||
| 28 | r = std::sqrt(r); | ||
| 29 | x /= r; | ||
| 30 | y /= r; | ||
| 31 | } | ||
| 32 | |||
| 33 | circle_pad_x = static_cast<s16>(x * MAX_CIRCLEPAD_POS); | ||
| 34 | circle_pad_y = static_cast<s16>(y * MAX_CIRCLEPAD_POS); | ||
| 35 | } | ||
| 36 | |||
| 37 | /** | 13 | /** |
| 38 | * Check if the given x/y coordinates are within the touchpad specified by the framebuffer layout | 14 | * Check if the given x/y coordinates are within the touchpad specified by the framebuffer layout |
| 39 | * @param layout FramebufferLayout object describing the framebuffer size and screen positions | 15 | * @param layout FramebufferLayout object describing the framebuffer size and screen positions |
diff --git a/src/core/frontend/emu_window.h b/src/core/frontend/emu_window.h index 1ba64c92b..36f2667fa 100644 --- a/src/core/frontend/emu_window.h +++ b/src/core/frontend/emu_window.h | |||
| @@ -10,7 +10,6 @@ | |||
| 10 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | #include "common/framebuffer_layout.h" | 11 | #include "common/framebuffer_layout.h" |
| 12 | #include "common/math_util.h" | 12 | #include "common/math_util.h" |
| 13 | #include "core/hle/service/hid/hid.h" | ||
| 14 | 13 | ||
| 15 | /** | 14 | /** |
| 16 | * Abstraction class used to provide an interface between emulation code and the frontend | 15 | * Abstraction class used to provide an interface between emulation code and the frontend |
| @@ -52,30 +51,6 @@ public: | |||
| 52 | /// Releases (dunno if this is the "right" word) the GLFW context from the caller thread | 51 | /// Releases (dunno if this is the "right" word) the GLFW context from the caller thread |
| 53 | virtual void DoneCurrent() = 0; | 52 | virtual void DoneCurrent() = 0; |
| 54 | 53 | ||
| 55 | virtual void ReloadSetKeymaps() = 0; | ||
| 56 | |||
| 57 | /** | ||
| 58 | * Signals a button press action to the HID module. | ||
| 59 | * @param pad_state indicates which button to press | ||
| 60 | * @note only handles real buttons (A/B/X/Y/...), excluding analog inputs like the circle pad. | ||
| 61 | */ | ||
| 62 | void ButtonPressed(Service::HID::PadState pad_state); | ||
| 63 | |||
| 64 | /** | ||
| 65 | * Signals a button release action to the HID module. | ||
| 66 | * @param pad_state indicates which button to press | ||
| 67 | * @note only handles real buttons (A/B/X/Y/...), excluding analog inputs like the circle pad. | ||
| 68 | */ | ||
| 69 | void ButtonReleased(Service::HID::PadState pad_state); | ||
| 70 | |||
| 71 | /** | ||
| 72 | * Signals a circle pad change action to the HID module. | ||
| 73 | * @param x new x-coordinate of the circle pad, in the range [-1.0, 1.0] | ||
| 74 | * @param y new y-coordinate of the circle pad, in the range [-1.0, 1.0] | ||
| 75 | * @note the coordinates will be normalized if the radius is larger than 1 | ||
| 76 | */ | ||
| 77 | void CirclePadUpdated(float x, float y); | ||
| 78 | |||
| 79 | /** | 54 | /** |
| 80 | * Signal that a touch pressed event has occurred (e.g. mouse click pressed) | 55 | * Signal that a touch pressed event has occurred (e.g. mouse click pressed) |
| 81 | * @param framebuffer_x Framebuffer x-coordinate that was pressed | 56 | * @param framebuffer_x Framebuffer x-coordinate that was pressed |
| @@ -115,27 +90,6 @@ public: | |||
| 115 | void GyroscopeChanged(float x, float y, float z); | 90 | void GyroscopeChanged(float x, float y, float z); |
| 116 | 91 | ||
| 117 | /** | 92 | /** |
| 118 | * Gets the current pad state (which buttons are pressed). | ||
| 119 | * @note This should be called by the core emu thread to get a state set by the window thread. | ||
| 120 | * @note This doesn't include analog input like circle pad direction | ||
| 121 | * @todo Fix this function to be thread-safe. | ||
| 122 | * @return PadState object indicating the current pad state | ||
| 123 | */ | ||
| 124 | Service::HID::PadState GetPadState() const { | ||
| 125 | return pad_state; | ||
| 126 | } | ||
| 127 | |||
| 128 | /** | ||
| 129 | * Gets the current circle pad state. | ||
| 130 | * @note This should be called by the core emu thread to get a state set by the window thread. | ||
| 131 | * @todo Fix this function to be thread-safe. | ||
| 132 | * @return std::tuple of (x, y), where `x` and `y` are the circle pad coordinates | ||
| 133 | */ | ||
| 134 | std::tuple<s16, s16> GetCirclePadState() const { | ||
| 135 | return std::make_tuple(circle_pad_x, circle_pad_y); | ||
| 136 | } | ||
| 137 | |||
| 138 | /** | ||
| 139 | * Gets the current touch screen state (touch X/Y coordinates and whether or not it is pressed). | 93 | * Gets the current touch screen state (touch X/Y coordinates and whether or not it is pressed). |
| 140 | * @note This should be called by the core emu thread to get a state set by the window thread. | 94 | * @note This should be called by the core emu thread to get a state set by the window thread. |
| 141 | * @todo Fix this function to be thread-safe. | 95 | * @todo Fix this function to be thread-safe. |
| @@ -230,11 +184,8 @@ protected: | |||
| 230 | // TODO: Find a better place to set this. | 184 | // TODO: Find a better place to set this. |
| 231 | config.min_client_area_size = std::make_pair(400u, 480u); | 185 | config.min_client_area_size = std::make_pair(400u, 480u); |
| 232 | active_config = config; | 186 | active_config = config; |
| 233 | pad_state.hex = 0; | ||
| 234 | touch_x = 0; | 187 | touch_x = 0; |
| 235 | touch_y = 0; | 188 | touch_y = 0; |
| 236 | circle_pad_x = 0; | ||
| 237 | circle_pad_y = 0; | ||
| 238 | touch_pressed = false; | 189 | touch_pressed = false; |
| 239 | accel_x = 0; | 190 | accel_x = 0; |
| 240 | accel_y = -512; | 191 | accel_y = -512; |
| @@ -304,9 +255,6 @@ private: | |||
| 304 | u16 touch_x; ///< Touchpad X-position in native 3DS pixel coordinates (0-320) | 255 | u16 touch_x; ///< Touchpad X-position in native 3DS pixel coordinates (0-320) |
| 305 | u16 touch_y; ///< Touchpad Y-position in native 3DS pixel coordinates (0-240) | 256 | u16 touch_y; ///< Touchpad Y-position in native 3DS pixel coordinates (0-240) |
| 306 | 257 | ||
| 307 | s16 circle_pad_x; ///< Circle pad X-position in native 3DS pixel coordinates (-156 - 156) | ||
| 308 | s16 circle_pad_y; ///< Circle pad Y-position in native 3DS pixel coordinates (-156 - 156) | ||
| 309 | |||
| 310 | std::mutex accel_mutex; | 258 | std::mutex accel_mutex; |
| 311 | s16 accel_x; ///< Accelerometer X-axis value in native 3DS units | 259 | s16 accel_x; ///< Accelerometer X-axis value in native 3DS units |
| 312 | s16 accel_y; ///< Accelerometer Y-axis value in native 3DS units | 260 | s16 accel_y; ///< Accelerometer Y-axis value in native 3DS units |
| @@ -321,6 +269,4 @@ private: | |||
| 321 | * Clip the provided coordinates to be inside the touchscreen area. | 269 | * Clip the provided coordinates to be inside the touchscreen area. |
| 322 | */ | 270 | */ |
| 323 | std::tuple<unsigned, unsigned> ClipToTouchScreen(unsigned new_x, unsigned new_y); | 271 | std::tuple<unsigned, unsigned> ClipToTouchScreen(unsigned new_x, unsigned new_y); |
| 324 | |||
| 325 | Service::HID::PadState pad_state; | ||
| 326 | }; | 272 | }; |
diff --git a/src/core/frontend/input.h b/src/core/frontend/input.h new file mode 100644 index 000000000..0a5713dc0 --- /dev/null +++ b/src/core/frontend/input.h | |||
| @@ -0,0 +1,110 @@ | |||
| 1 | // Copyright 2017 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <memory> | ||
| 8 | #include <string> | ||
| 9 | #include <tuple> | ||
| 10 | #include <unordered_map> | ||
| 11 | #include <utility> | ||
| 12 | #include "common/logging/log.h" | ||
| 13 | #include "common/param_package.h" | ||
| 14 | |||
| 15 | namespace Input { | ||
| 16 | |||
| 17 | /// An abstract class template for an input device (a button, an analog input, etc.). | ||
| 18 | template <typename StatusType> | ||
| 19 | class InputDevice { | ||
| 20 | public: | ||
| 21 | virtual ~InputDevice() = default; | ||
| 22 | virtual StatusType GetStatus() const { | ||
| 23 | return {}; | ||
| 24 | } | ||
| 25 | }; | ||
| 26 | |||
| 27 | /// An abstract class template for a factory that can create input devices. | ||
| 28 | template <typename InputDeviceType> | ||
| 29 | class Factory { | ||
| 30 | public: | ||
| 31 | virtual ~Factory() = default; | ||
| 32 | virtual std::unique_ptr<InputDeviceType> Create(const Common::ParamPackage&) = 0; | ||
| 33 | }; | ||
| 34 | |||
| 35 | namespace Impl { | ||
| 36 | |||
| 37 | template <typename InputDeviceType> | ||
| 38 | using FactoryListType = std::unordered_map<std::string, std::shared_ptr<Factory<InputDeviceType>>>; | ||
| 39 | |||
| 40 | template <typename InputDeviceType> | ||
| 41 | struct FactoryList { | ||
| 42 | static FactoryListType<InputDeviceType> list; | ||
| 43 | }; | ||
| 44 | |||
| 45 | template <typename InputDeviceType> | ||
| 46 | FactoryListType<InputDeviceType> FactoryList<InputDeviceType>::list; | ||
| 47 | |||
| 48 | } // namespace Impl | ||
| 49 | |||
| 50 | /** | ||
| 51 | * Registers an input device factory. | ||
| 52 | * @tparam InputDeviceType the type of input devices the factory can create | ||
| 53 | * @param name the name of the factory. Will be used to match the "engine" parameter when creating | ||
| 54 | * a device | ||
| 55 | * @param factory the factory object to register | ||
| 56 | */ | ||
| 57 | template <typename InputDeviceType> | ||
| 58 | void RegisterFactory(const std::string& name, std::shared_ptr<Factory<InputDeviceType>> factory) { | ||
| 59 | auto pair = std::make_pair(name, std::move(factory)); | ||
| 60 | if (!Impl::FactoryList<InputDeviceType>::list.insert(std::move(pair)).second) { | ||
| 61 | LOG_ERROR(Input, "Factory %s already registered", name.c_str()); | ||
| 62 | } | ||
| 63 | } | ||
| 64 | |||
| 65 | /** | ||
| 66 | * Unregisters an input device factory. | ||
| 67 | * @tparam InputDeviceType the type of input devices the factory can create | ||
| 68 | * @param name the name of the factory to unregister | ||
| 69 | */ | ||
| 70 | template <typename InputDeviceType> | ||
| 71 | void UnregisterFactory(const std::string& name) { | ||
| 72 | if (Impl::FactoryList<InputDeviceType>::list.erase(name) == 0) { | ||
| 73 | LOG_ERROR(Input, "Factory %s not registered", name.c_str()); | ||
| 74 | } | ||
| 75 | } | ||
| 76 | |||
| 77 | /** | ||
| 78 | * Create an input device from given paramters. | ||
| 79 | * @tparam InputDeviceType the type of input devices to create | ||
| 80 | * @param params a serialized ParamPackage string contains all parameters for creating the device | ||
| 81 | */ | ||
| 82 | template <typename InputDeviceType> | ||
| 83 | std::unique_ptr<InputDeviceType> CreateDevice(const std::string& params) { | ||
| 84 | const Common::ParamPackage package(params); | ||
| 85 | const std::string engine = package.Get("engine", "null"); | ||
| 86 | const auto& factory_list = Impl::FactoryList<InputDeviceType>::list; | ||
| 87 | const auto pair = factory_list.find(engine); | ||
| 88 | if (pair == factory_list.end()) { | ||
| 89 | if (engine != "null") { | ||
| 90 | LOG_ERROR(Input, "Unknown engine name: %s", engine.c_str()); | ||
| 91 | } | ||
| 92 | return std::make_unique<InputDeviceType>(); | ||
| 93 | } | ||
| 94 | return pair->second->Create(package); | ||
| 95 | } | ||
| 96 | |||
| 97 | /** | ||
| 98 | * A button device is an input device that returns bool as status. | ||
| 99 | * true for pressed; false for released. | ||
| 100 | */ | ||
| 101 | using ButtonDevice = InputDevice<bool>; | ||
| 102 | |||
| 103 | /** | ||
| 104 | * An analog device is an input device that returns a tuple of x and y coordinates as status. The | ||
| 105 | * coordinates are within the unit circle. x+ is defined as right direction, and y+ is defined as up | ||
| 106 | * direction | ||
| 107 | */ | ||
| 108 | using AnalogDevice = InputDevice<std::tuple<float, float>>; | ||
| 109 | |||
| 110 | } // namespace Input | ||
diff --git a/src/core/frontend/key_map.cpp b/src/core/frontend/key_map.cpp deleted file mode 100644 index 15f0e079c..000000000 --- a/src/core/frontend/key_map.cpp +++ /dev/null | |||
| @@ -1,152 +0,0 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <map> | ||
| 6 | #include "core/frontend/emu_window.h" | ||
| 7 | #include "core/frontend/key_map.h" | ||
| 8 | |||
| 9 | namespace KeyMap { | ||
| 10 | |||
| 11 | // TODO (wwylele): currently we treat c-stick as four direction buttons | ||
| 12 | // and map it directly to EmuWindow::ButtonPressed. | ||
| 13 | // It should go the analog input way like circle pad does. | ||
| 14 | const std::array<KeyTarget, Settings::NativeInput::NUM_INPUTS> mapping_targets = {{ | ||
| 15 | Service::HID::PAD_A, | ||
| 16 | Service::HID::PAD_B, | ||
| 17 | Service::HID::PAD_X, | ||
| 18 | Service::HID::PAD_Y, | ||
| 19 | Service::HID::PAD_L, | ||
| 20 | Service::HID::PAD_R, | ||
| 21 | Service::HID::PAD_ZL, | ||
| 22 | Service::HID::PAD_ZR, | ||
| 23 | Service::HID::PAD_START, | ||
| 24 | Service::HID::PAD_SELECT, | ||
| 25 | Service::HID::PAD_NONE, | ||
| 26 | Service::HID::PAD_UP, | ||
| 27 | Service::HID::PAD_DOWN, | ||
| 28 | Service::HID::PAD_LEFT, | ||
| 29 | Service::HID::PAD_RIGHT, | ||
| 30 | Service::HID::PAD_C_UP, | ||
| 31 | Service::HID::PAD_C_DOWN, | ||
| 32 | Service::HID::PAD_C_LEFT, | ||
| 33 | Service::HID::PAD_C_RIGHT, | ||
| 34 | |||
| 35 | IndirectTarget::CirclePadUp, | ||
| 36 | IndirectTarget::CirclePadDown, | ||
| 37 | IndirectTarget::CirclePadLeft, | ||
| 38 | IndirectTarget::CirclePadRight, | ||
| 39 | IndirectTarget::CirclePadModifier, | ||
| 40 | }}; | ||
| 41 | |||
| 42 | static std::map<HostDeviceKey, KeyTarget> key_map; | ||
| 43 | static int next_device_id = 0; | ||
| 44 | |||
| 45 | static bool circle_pad_up = false; | ||
| 46 | static bool circle_pad_down = false; | ||
| 47 | static bool circle_pad_left = false; | ||
| 48 | static bool circle_pad_right = false; | ||
| 49 | static bool circle_pad_modifier = false; | ||
| 50 | |||
| 51 | static void UpdateCirclePad(EmuWindow& emu_window) { | ||
| 52 | constexpr float SQRT_HALF = 0.707106781f; | ||
| 53 | int x = 0, y = 0; | ||
| 54 | |||
| 55 | if (circle_pad_right) | ||
| 56 | ++x; | ||
| 57 | if (circle_pad_left) | ||
| 58 | --x; | ||
| 59 | if (circle_pad_up) | ||
| 60 | ++y; | ||
| 61 | if (circle_pad_down) | ||
| 62 | --y; | ||
| 63 | |||
| 64 | float modifier = circle_pad_modifier ? Settings::values.pad_circle_modifier_scale : 1.0f; | ||
| 65 | emu_window.CirclePadUpdated(x * modifier * (y == 0 ? 1.0f : SQRT_HALF), | ||
| 66 | y * modifier * (x == 0 ? 1.0f : SQRT_HALF)); | ||
| 67 | } | ||
| 68 | |||
| 69 | int NewDeviceId() { | ||
| 70 | return next_device_id++; | ||
| 71 | } | ||
| 72 | |||
| 73 | void SetKeyMapping(HostDeviceKey key, KeyTarget target) { | ||
| 74 | key_map[key] = target; | ||
| 75 | } | ||
| 76 | |||
| 77 | void ClearKeyMapping(int device_id) { | ||
| 78 | auto iter = key_map.begin(); | ||
| 79 | while (iter != key_map.end()) { | ||
| 80 | if (iter->first.device_id == device_id) | ||
| 81 | key_map.erase(iter++); | ||
| 82 | else | ||
| 83 | ++iter; | ||
| 84 | } | ||
| 85 | } | ||
| 86 | |||
| 87 | void PressKey(EmuWindow& emu_window, HostDeviceKey key) { | ||
| 88 | auto target = key_map.find(key); | ||
| 89 | if (target == key_map.end()) | ||
| 90 | return; | ||
| 91 | |||
| 92 | if (target->second.direct) { | ||
| 93 | emu_window.ButtonPressed({{target->second.target.direct_target_hex}}); | ||
| 94 | } else { | ||
| 95 | switch (target->second.target.indirect_target) { | ||
| 96 | case IndirectTarget::CirclePadUp: | ||
| 97 | circle_pad_up = true; | ||
| 98 | UpdateCirclePad(emu_window); | ||
| 99 | break; | ||
| 100 | case IndirectTarget::CirclePadDown: | ||
| 101 | circle_pad_down = true; | ||
| 102 | UpdateCirclePad(emu_window); | ||
| 103 | break; | ||
| 104 | case IndirectTarget::CirclePadLeft: | ||
| 105 | circle_pad_left = true; | ||
| 106 | UpdateCirclePad(emu_window); | ||
| 107 | break; | ||
| 108 | case IndirectTarget::CirclePadRight: | ||
| 109 | circle_pad_right = true; | ||
| 110 | UpdateCirclePad(emu_window); | ||
| 111 | break; | ||
| 112 | case IndirectTarget::CirclePadModifier: | ||
| 113 | circle_pad_modifier = true; | ||
| 114 | UpdateCirclePad(emu_window); | ||
| 115 | break; | ||
| 116 | } | ||
| 117 | } | ||
| 118 | } | ||
| 119 | |||
| 120 | void ReleaseKey(EmuWindow& emu_window, HostDeviceKey key) { | ||
| 121 | auto target = key_map.find(key); | ||
| 122 | if (target == key_map.end()) | ||
| 123 | return; | ||
| 124 | |||
| 125 | if (target->second.direct) { | ||
| 126 | emu_window.ButtonReleased({{target->second.target.direct_target_hex}}); | ||
| 127 | } else { | ||
| 128 | switch (target->second.target.indirect_target) { | ||
| 129 | case IndirectTarget::CirclePadUp: | ||
| 130 | circle_pad_up = false; | ||
| 131 | UpdateCirclePad(emu_window); | ||
| 132 | break; | ||
| 133 | case IndirectTarget::CirclePadDown: | ||
| 134 | circle_pad_down = false; | ||
| 135 | UpdateCirclePad(emu_window); | ||
| 136 | break; | ||
| 137 | case IndirectTarget::CirclePadLeft: | ||
| 138 | circle_pad_left = false; | ||
| 139 | UpdateCirclePad(emu_window); | ||
| 140 | break; | ||
| 141 | case IndirectTarget::CirclePadRight: | ||
| 142 | circle_pad_right = false; | ||
| 143 | UpdateCirclePad(emu_window); | ||
| 144 | break; | ||
| 145 | case IndirectTarget::CirclePadModifier: | ||
| 146 | circle_pad_modifier = false; | ||
| 147 | UpdateCirclePad(emu_window); | ||
| 148 | break; | ||
| 149 | } | ||
| 150 | } | ||
| 151 | } | ||
| 152 | } | ||
diff --git a/src/core/frontend/key_map.h b/src/core/frontend/key_map.h deleted file mode 100644 index 040794578..000000000 --- a/src/core/frontend/key_map.h +++ /dev/null | |||
| @@ -1,93 +0,0 @@ | |||
| 1 | // Copyright 2014 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <array> | ||
| 8 | #include <tuple> | ||
| 9 | #include "core/hle/service/hid/hid.h" | ||
| 10 | |||
| 11 | class EmuWindow; | ||
| 12 | |||
| 13 | namespace KeyMap { | ||
| 14 | |||
| 15 | /** | ||
| 16 | * Represents key mapping targets that are not real 3DS buttons. | ||
| 17 | * They will be handled by KeyMap and translated to 3DS input. | ||
| 18 | */ | ||
| 19 | enum class IndirectTarget { | ||
| 20 | CirclePadUp, | ||
| 21 | CirclePadDown, | ||
| 22 | CirclePadLeft, | ||
| 23 | CirclePadRight, | ||
| 24 | CirclePadModifier, | ||
| 25 | }; | ||
| 26 | |||
| 27 | /** | ||
| 28 | * Represents a key mapping target. It can be a PadState that represents real 3DS buttons, | ||
| 29 | * or an IndirectTarget. | ||
| 30 | */ | ||
| 31 | struct KeyTarget { | ||
| 32 | bool direct; | ||
| 33 | union { | ||
| 34 | u32 direct_target_hex; | ||
| 35 | IndirectTarget indirect_target; | ||
| 36 | } target; | ||
| 37 | |||
| 38 | KeyTarget() : direct(true) { | ||
| 39 | target.direct_target_hex = 0; | ||
| 40 | } | ||
| 41 | |||
| 42 | KeyTarget(Service::HID::PadState pad) : direct(true) { | ||
| 43 | target.direct_target_hex = pad.hex; | ||
| 44 | } | ||
| 45 | |||
| 46 | KeyTarget(IndirectTarget i) : direct(false) { | ||
| 47 | target.indirect_target = i; | ||
| 48 | } | ||
| 49 | }; | ||
| 50 | |||
| 51 | /** | ||
| 52 | * Represents a key for a specific host device. | ||
| 53 | */ | ||
| 54 | struct HostDeviceKey { | ||
| 55 | int key_code; | ||
| 56 | int device_id; ///< Uniquely identifies a host device | ||
| 57 | |||
| 58 | bool operator<(const HostDeviceKey& other) const { | ||
| 59 | return std::tie(key_code, device_id) < std::tie(other.key_code, other.device_id); | ||
| 60 | } | ||
| 61 | |||
| 62 | bool operator==(const HostDeviceKey& other) const { | ||
| 63 | return std::tie(key_code, device_id) == std::tie(other.key_code, other.device_id); | ||
| 64 | } | ||
| 65 | }; | ||
| 66 | |||
| 67 | extern const std::array<KeyTarget, Settings::NativeInput::NUM_INPUTS> mapping_targets; | ||
| 68 | |||
| 69 | /** | ||
| 70 | * Generates a new device id, which uniquely identifies a host device within KeyMap. | ||
| 71 | */ | ||
| 72 | int NewDeviceId(); | ||
| 73 | |||
| 74 | /** | ||
| 75 | * Maps a device-specific key to a target (a PadState or an IndirectTarget). | ||
| 76 | */ | ||
| 77 | void SetKeyMapping(HostDeviceKey key, KeyTarget target); | ||
| 78 | |||
| 79 | /** | ||
| 80 | * Clears all key mappings belonging to one device. | ||
| 81 | */ | ||
| 82 | void ClearKeyMapping(int device_id); | ||
| 83 | |||
| 84 | /** | ||
| 85 | * Maps a key press action and call the corresponding function in EmuWindow | ||
| 86 | */ | ||
| 87 | void PressKey(EmuWindow& emu_window, HostDeviceKey key); | ||
| 88 | |||
| 89 | /** | ||
| 90 | * Maps a key release action and call the corresponding function in EmuWindow | ||
| 91 | */ | ||
| 92 | void ReleaseKey(EmuWindow& emu_window, HostDeviceKey key); | ||
| 93 | } | ||