summaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
authorGravatar wwylele2016-05-12 13:09:36 +0300
committerGravatar wwylele2016-05-15 13:24:22 +0300
commit03631f9b8fe75cf1c3a70a3094aeddcebffa4cf9 (patch)
tree95edc62b3b8520a533e534bf4991159875fef3e5 /src/common
parentAudioCore: Implement time stretcher (#1737) (diff)
downloadyuzu-03631f9b8fe75cf1c3a70a3094aeddcebffa4cf9.tar.gz
yuzu-03631f9b8fe75cf1c3a70a3094aeddcebffa4cf9.tar.xz
yuzu-03631f9b8fe75cf1c3a70a3094aeddcebffa4cf9.zip
Refactor input subsystem
Diffstat (limited to 'src/common')
-rw-r--r--src/common/emu_window.cpp24
-rw-r--r--src/common/emu_window.h46
-rw-r--r--src/common/key_map.cpp112
-rw-r--r--src/common/key_map.h51
4 files changed, 210 insertions, 23 deletions
diff --git a/src/common/emu_window.cpp b/src/common/emu_window.cpp
index b2807354a..08270dd88 100644
--- a/src/common/emu_window.cpp
+++ b/src/common/emu_window.cpp
@@ -11,12 +11,28 @@
11#include "emu_window.h" 11#include "emu_window.h"
12#include "video_core/video_core.h" 12#include "video_core/video_core.h"
13 13
14void EmuWindow::KeyPressed(KeyMap::HostDeviceKey key) { 14void EmuWindow::ButtonPressed(Service::HID::PadState pad) {
15 pad_state.hex |= KeyMap::GetPadKey(key).hex; 15 pad_state.hex |= pad.hex;
16} 16}
17 17
18void EmuWindow::KeyReleased(KeyMap::HostDeviceKey key) { 18void EmuWindow::ButtonReleased(Service::HID::PadState pad) {
19 pad_state.hex &= ~KeyMap::GetPadKey(key).hex; 19 pad_state.hex &= ~pad.hex;
20}
21
22void EmuWindow::CirclePadUpdated(float x, float y) {
23 constexpr int MAX_CIRCLEPAD_POS = 0x9C; // Max value for a circle pad position
24
25 // Make sure the coordinates are in the unit circle,
26 // otherwise normalize it.
27 float r = x * x + y * y;
28 if (r > 1) {
29 r = std::sqrt(r);
30 x /= r;
31 y /= r;
32 }
33
34 circle_pad_x = static_cast<s16>(x * MAX_CIRCLEPAD_POS);
35 circle_pad_y = static_cast<s16>(y * MAX_CIRCLEPAD_POS);
20} 36}
21 37
22/** 38/**
diff --git a/src/common/emu_window.h b/src/common/emu_window.h
index 7c3486dea..0ae3ea2af 100644
--- a/src/common/emu_window.h
+++ b/src/common/emu_window.h
@@ -12,10 +12,6 @@
12 12
13#include "core/hle/service/hid/hid.h" 13#include "core/hle/service/hid/hid.h"
14 14
15namespace KeyMap {
16struct HostDeviceKey;
17}
18
19/** 15/**
20 * Abstraction class used to provide an interface between emulation code and the frontend 16 * Abstraction class used to provide an interface between emulation code and the frontend
21 * (e.g. SDL, QGLWidget, GLFW, etc...). 17 * (e.g. SDL, QGLWidget, GLFW, etc...).
@@ -76,11 +72,27 @@ public:
76 72
77 virtual void ReloadSetKeymaps() = 0; 73 virtual void ReloadSetKeymaps() = 0;
78 74
79 /// Signals a key press action to the HID module 75 /**
80 void KeyPressed(KeyMap::HostDeviceKey key); 76 * Signals a button press action to the HID module.
77 * @param pad_state indicates which button to press
78 * @note only handle real buttons (A/B/X/Y/...), excluding analog input like circle pad.
79 */
80 void ButtonPressed(Service::HID::PadState pad_state);
81
82 /**
83 * Signals a button release action to the HID module.
84 * @param pad_state indicates which button to press
85 * @note only handle real buttons (A/B/X/Y/...), excluding analog input like circle pad.
86 */
87 void ButtonReleased(Service::HID::PadState pad_state);
81 88
82 /// Signals a key release action to the HID module 89 /**
83 void KeyReleased(KeyMap::HostDeviceKey key); 90 * Signals a circle pad change action to the HID module.
91 * @param x new x-coordinate of the circle pad, in the range [-1.0, 1.0]
92 * @param y new y-coordinate of the circle pad, in the range [-1.0, 1.0]
93 * @note the coordinates will be normalized if the radius is larger than 1
94 */
95 void CirclePadUpdated(float x, float y);
84 96
85 /** 97 /**
86 * Signal that a touch pressed event has occurred (e.g. mouse click pressed) 98 * Signal that a touch pressed event has occurred (e.g. mouse click pressed)
@@ -100,8 +112,9 @@ public:
100 void TouchMoved(unsigned framebuffer_x, unsigned framebuffer_y); 112 void TouchMoved(unsigned framebuffer_x, unsigned framebuffer_y);
101 113
102 /** 114 /**
103 * Gets the current pad state (which buttons are pressed and the circle pad direction). 115 * Gets the current pad state (which buttons are pressed).
104 * @note This should be called by the core emu thread to get a state set by the window thread. 116 * @note This should be called by the core emu thread to get a state set by the window thread.
117 * @note This doesn't include analog input like circle pad direction
105 * @todo Fix this function to be thread-safe. 118 * @todo Fix this function to be thread-safe.
106 * @return PadState object indicating the current pad state 119 * @return PadState object indicating the current pad state
107 */ 120 */
@@ -110,6 +123,16 @@ public:
110 } 123 }
111 124
112 /** 125 /**
126 * Gets the current cirle pad state.
127 * @note This should be called by the core emu thread to get a state set by the window thread.
128 * @todo Fix this function to be thread-safe.
129 * @return std::tuple of (x, y), where `x` and `y` are the circle pad coordinates
130 */
131 std::tuple<s16, s16> GetCirclePadState() const {
132 return std::make_tuple(circle_pad_x, circle_pad_y);
133 }
134
135 /**
113 * Gets the current touch screen state (touch X/Y coordinates and whether or not it is pressed). 136 * Gets the current touch screen state (touch X/Y coordinates and whether or not it is pressed).
114 * @note This should be called by the core emu thread to get a state set by the window thread. 137 * @note This should be called by the core emu thread to get a state set by the window thread.
115 * @todo Fix this function to be thread-safe. 138 * @todo Fix this function to be thread-safe.
@@ -200,6 +223,8 @@ protected:
200 pad_state.hex = 0; 223 pad_state.hex = 0;
201 touch_x = 0; 224 touch_x = 0;
202 touch_y = 0; 225 touch_y = 0;
226 circle_pad_x = 0;
227 circle_pad_y = 0;
203 touch_pressed = false; 228 touch_pressed = false;
204 } 229 }
205 virtual ~EmuWindow() {} 230 virtual ~EmuWindow() {}
@@ -260,6 +285,9 @@ private:
260 u16 touch_x; ///< Touchpad X-position in native 3DS pixel coordinates (0-320) 285 u16 touch_x; ///< Touchpad X-position in native 3DS pixel coordinates (0-320)
261 u16 touch_y; ///< Touchpad Y-position in native 3DS pixel coordinates (0-240) 286 u16 touch_y; ///< Touchpad Y-position in native 3DS pixel coordinates (0-240)
262 287
288 s16 circle_pad_x; ///< Circle pad X-position in native 3DS pixel coordinates (-156 - 156)
289 s16 circle_pad_y; ///< Circle pad Y-position in native 3DS pixel coordinates (-156 - 156)
290
263 /** 291 /**
264 * Clip the provided coordinates to be inside the touchscreen area. 292 * Clip the provided coordinates to be inside the touchscreen area.
265 */ 293 */
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
8namespace KeyMap { 10namespace KeyMap {
9 11
10static 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.
15const 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
28static std::map<HostDeviceKey, KeyTarget> key_map;
11static int next_device_id = 0; 29static int next_device_id = 0;
12 30
31static bool circle_pad_up = false, circle_pad_down = false, circle_pad_left = false, circle_pad_right = false;
32
33static 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
13int NewDeviceId() { 49int NewDeviceId() {
14 return next_device_id++; 50 return next_device_id++;
15} 51}
16 52
17void SetKeyMapping(HostDeviceKey key, Service::HID::PadState padState) { 53void SetKeyMapping(HostDeviceKey key, KeyTarget target) {
18 key_map[key].hex = padState.hex; 54 key_map[key] = target;
19} 55}
20 56
21Service::HID::PadState GetPadKey(HostDeviceKey key) { 57void 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
67void 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
96void 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}
diff --git a/src/common/key_map.h b/src/common/key_map.h
index 68f7e2f99..0438a14e0 100644
--- a/src/common/key_map.h
+++ b/src/common/key_map.h
@@ -4,11 +4,42 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <array>
7#include <tuple> 8#include <tuple>
8#include "core/hle/service/hid/hid.h" 9#include "core/hle/service/hid/hid.h"
9 10
11class EmuWindow;
12
10namespace KeyMap { 13namespace KeyMap {
11 14
15enum class IndirectTarget {
16 CIRCLE_PAD_UP, CIRCLE_PAD_DOWN, CIRCLE_PAD_LEFT, CIRCLE_PAD_RIGHT,
17};
18
19/**
20 * Represents a key mapping target. It can be a PadState that represents 3DS real buttons,
21 * or an IndirectTarget.
22 */
23struct KeyTarget {
24 bool direct;
25 union {
26 u32 direct_target_hex;
27 IndirectTarget indirect_target;
28 } target;
29
30 KeyTarget() : direct(true) {
31 target.direct_target_hex = 0;
32 }
33
34 KeyTarget(Service::HID::PadState pad) : direct(true) {
35 target.direct_target_hex = pad.hex;
36 }
37
38 KeyTarget(IndirectTarget i) : direct(false) {
39 target.indirect_target = i;
40 }
41};
42
12/** 43/**
13 * Represents a key for a specific host device. 44 * Represents a key for a specific host device.
14 */ 45 */
@@ -27,19 +58,31 @@ struct HostDeviceKey {
27 } 58 }
28}; 59};
29 60
61extern const std::array<KeyTarget, Settings::NativeInput::NUM_INPUTS> mapping_targets;
62
30/** 63/**
31 * Generates a new device id, which uniquely identifies a host device within KeyMap. 64 * Generates a new device id, which uniquely identifies a host device within KeyMap.
32 */ 65 */
33int NewDeviceId(); 66int NewDeviceId();
34 67
35/** 68/**
36 * Maps a device-specific key to a PadState. 69 * Maps a device-specific key to a target (a PadState or an IndirectTarget).
70 */
71void SetKeyMapping(HostDeviceKey key, KeyTarget target);
72
73/**
74 * Clears all key mappings belonging to one device.
75 */
76void ClearKeyMapping(int device_id);
77
78/**
79 * Maps a key press actions and call the corresponding function in EmuWindow
37 */ 80 */
38void SetKeyMapping(HostDeviceKey key, Service::HID::PadState padState); 81void PressKey(EmuWindow& emu_window, HostDeviceKey key);
39 82
40/** 83/**
41 * Gets the PadState that's mapped to the provided device-specific key. 84 * Maps a key release actions and call the corresponding function in EmuWindow
42 */ 85 */
43Service::HID::PadState GetPadKey(HostDeviceKey key); 86void ReleaseKey(EmuWindow& emu_window, HostDeviceKey key);
44 87
45} 88}