diff options
Diffstat (limited to 'src/common/key_map.cpp')
| -rw-r--r-- | src/common/key_map.cpp | 112 |
1 files changed, 106 insertions, 6 deletions
diff --git a/src/common/key_map.cpp b/src/common/key_map.cpp index 844d5df68..c8f168aa1 100644 --- a/src/common/key_map.cpp +++ b/src/common/key_map.cpp | |||
| @@ -2,24 +2,124 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include "key_map.h" | ||
| 6 | #include <map> | 5 | #include <map> |
| 7 | 6 | ||
| 7 | #include "common/emu_window.h" | ||
| 8 | #include "common/key_map.h" | ||
| 9 | |||
| 8 | namespace KeyMap { | 10 | namespace KeyMap { |
| 9 | 11 | ||
| 10 | static std::map<HostDeviceKey, Service::HID::PadState> key_map; | 12 | // TODO (wwylele): currently we treat c-stick as four direction buttons |
| 13 | // and map it directly to EmuWindow::ButtonPressed. | ||
| 14 | // It should go the analog input way like circle pad does. | ||
| 15 | const std::array<KeyTarget, Settings::NativeInput::NUM_INPUTS> mapping_targets = {{ | ||
| 16 | Service::HID::PAD_A, Service::HID::PAD_B, Service::HID::PAD_X, Service::HID::PAD_Y, | ||
| 17 | Service::HID::PAD_L, Service::HID::PAD_R, Service::HID::PAD_ZL, Service::HID::PAD_ZR, | ||
| 18 | Service::HID::PAD_START, Service::HID::PAD_SELECT, Service::HID::PAD_NONE, | ||
| 19 | Service::HID::PAD_UP, Service::HID::PAD_DOWN, Service::HID::PAD_LEFT, Service::HID::PAD_RIGHT, | ||
| 20 | Service::HID::PAD_C_UP, Service::HID::PAD_C_DOWN, Service::HID::PAD_C_LEFT, Service::HID::PAD_C_RIGHT, | ||
| 21 | |||
| 22 | IndirectTarget::CIRCLE_PAD_UP, | ||
| 23 | IndirectTarget::CIRCLE_PAD_DOWN, | ||
| 24 | IndirectTarget::CIRCLE_PAD_LEFT, | ||
| 25 | IndirectTarget::CIRCLE_PAD_RIGHT, | ||
| 26 | }}; | ||
| 27 | |||
| 28 | static std::map<HostDeviceKey, KeyTarget> key_map; | ||
| 11 | static int next_device_id = 0; | 29 | static int next_device_id = 0; |
| 12 | 30 | ||
| 31 | static bool circle_pad_up = false, circle_pad_down = false, circle_pad_left = false, circle_pad_right = false; | ||
| 32 | |||
| 33 | static void UpdateCirclePad(EmuWindow& emu_window) { | ||
| 34 | constexpr float SQRT_HALF = 0.707106781; | ||
| 35 | int x = 0, y = 0; | ||
| 36 | |||
| 37 | if (circle_pad_right) | ||
| 38 | ++x; | ||
| 39 | if (circle_pad_left) | ||
| 40 | --x; | ||
| 41 | if (circle_pad_up) | ||
| 42 | ++y; | ||
| 43 | if (circle_pad_down) | ||
| 44 | --y; | ||
| 45 | // TODO: apply modifier here | ||
| 46 | emu_window.CirclePadUpdated(x * (y == 0 ? 1.0 : SQRT_HALF), y * (x == 0 ? 1.0 : SQRT_HALF)); | ||
| 47 | } | ||
| 48 | |||
| 13 | int NewDeviceId() { | 49 | int NewDeviceId() { |
| 14 | return next_device_id++; | 50 | return next_device_id++; |
| 15 | } | 51 | } |
| 16 | 52 | ||
| 17 | void SetKeyMapping(HostDeviceKey key, Service::HID::PadState padState) { | 53 | void SetKeyMapping(HostDeviceKey key, KeyTarget target) { |
| 18 | key_map[key].hex = padState.hex; | 54 | key_map[key] = target; |
| 19 | } | 55 | } |
| 20 | 56 | ||
| 21 | Service::HID::PadState GetPadKey(HostDeviceKey key) { | 57 | void ClearKeyMapping(int device_id) { |
| 22 | return key_map[key]; | 58 | auto iter = key_map.begin(); |
| 59 | while (iter != key_map.end()) { | ||
| 60 | if (iter->first.device_id == device_id) | ||
| 61 | key_map.erase(iter++); | ||
| 62 | else | ||
| 63 | ++iter; | ||
| 64 | } | ||
| 65 | } | ||
| 66 | |||
| 67 | void PressKey(EmuWindow& emu_window, HostDeviceKey key) { | ||
| 68 | auto target = key_map.find(key); | ||
| 69 | if (target == key_map.end()) | ||
| 70 | return; | ||
| 71 | |||
| 72 | if (target->second.direct) { | ||
| 73 | emu_window.ButtonPressed({{target->second.target.direct_target_hex}}); | ||
| 74 | } else { | ||
| 75 | switch (target->second.target.indirect_target) { | ||
| 76 | case IndirectTarget::CIRCLE_PAD_UP: | ||
| 77 | circle_pad_up = true; | ||
| 78 | UpdateCirclePad(emu_window); | ||
| 79 | break; | ||
| 80 | case IndirectTarget::CIRCLE_PAD_DOWN: | ||
| 81 | circle_pad_down = true; | ||
| 82 | UpdateCirclePad(emu_window); | ||
| 83 | break; | ||
| 84 | case IndirectTarget::CIRCLE_PAD_LEFT: | ||
| 85 | circle_pad_left = true; | ||
| 86 | UpdateCirclePad(emu_window); | ||
| 87 | break; | ||
| 88 | case IndirectTarget::CIRCLE_PAD_RIGHT: | ||
| 89 | circle_pad_right = true; | ||
| 90 | UpdateCirclePad(emu_window); | ||
| 91 | break; | ||
| 92 | } | ||
| 93 | } | ||
| 94 | } | ||
| 95 | |||
| 96 | void ReleaseKey(EmuWindow& emu_window,HostDeviceKey key) { | ||
| 97 | auto target = key_map.find(key); | ||
| 98 | if (target == key_map.end()) | ||
| 99 | return; | ||
| 100 | |||
| 101 | if (target->second.direct) { | ||
| 102 | emu_window.ButtonReleased({{target->second.target.direct_target_hex}}); | ||
| 103 | } else { | ||
| 104 | switch (target->second.target.indirect_target) { | ||
| 105 | case IndirectTarget::CIRCLE_PAD_UP: | ||
| 106 | circle_pad_up = false; | ||
| 107 | UpdateCirclePad(emu_window); | ||
| 108 | break; | ||
| 109 | case IndirectTarget::CIRCLE_PAD_DOWN: | ||
| 110 | circle_pad_down = false; | ||
| 111 | UpdateCirclePad(emu_window); | ||
| 112 | break; | ||
| 113 | case IndirectTarget::CIRCLE_PAD_LEFT: | ||
| 114 | circle_pad_left = false; | ||
| 115 | UpdateCirclePad(emu_window); | ||
| 116 | break; | ||
| 117 | case IndirectTarget::CIRCLE_PAD_RIGHT: | ||
| 118 | circle_pad_right = false; | ||
| 119 | UpdateCirclePad(emu_window); | ||
| 120 | break; | ||
| 121 | } | ||
| 122 | } | ||
| 23 | } | 123 | } |
| 24 | 124 | ||
| 25 | } | 125 | } |