diff options
| author | 2016-12-23 13:37:40 +0000 | |
|---|---|---|
| committer | 2016-12-23 13:42:39 +0000 | |
| commit | 64f98f4d0f33b5c626d86a05ab9dd8060e160cc5 (patch) | |
| tree | 8874f16f9f840add798f58981d5c2fcdf4da3c84 /src/common | |
| parent | Merge pull request #2364 from mailwl/nwm-services (diff) | |
| download | yuzu-64f98f4d0f33b5c626d86a05ab9dd8060e160cc5.tar.gz yuzu-64f98f4d0f33b5c626d86a05ab9dd8060e160cc5.tar.xz yuzu-64f98f4d0f33b5c626d86a05ab9dd8060e160cc5.zip | |
core: Move emu_window and key_map into core
* Removes circular dependences (common should not depend on core)
Diffstat (limited to 'src/common')
| -rw-r--r-- | src/common/CMakeLists.txt | 4 | ||||
| -rw-r--r-- | src/common/emu_window.cpp | 107 | ||||
| -rw-r--r-- | src/common/emu_window.h | 290 | ||||
| -rw-r--r-- | src/common/key_map.cpp | 152 | ||||
| -rw-r--r-- | src/common/key_map.h | 93 |
5 files changed, 0 insertions, 646 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index e6c2ce335..5aecf6e6e 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt | |||
| @@ -3,11 +3,9 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/scm_rev.cpp.in" "${CMAKE_CURRENT_SOU | |||
| 3 | 3 | ||
| 4 | set(SRCS | 4 | set(SRCS |
| 5 | break_points.cpp | 5 | break_points.cpp |
| 6 | emu_window.cpp | ||
| 7 | file_util.cpp | 6 | file_util.cpp |
| 8 | framebuffer_layout.cpp | 7 | framebuffer_layout.cpp |
| 9 | hash.cpp | 8 | hash.cpp |
| 10 | key_map.cpp | ||
| 11 | logging/filter.cpp | 9 | logging/filter.cpp |
| 12 | logging/text_formatter.cpp | 10 | logging/text_formatter.cpp |
| 13 | logging/backend.cpp | 11 | logging/backend.cpp |
| @@ -34,11 +32,9 @@ set(HEADERS | |||
| 34 | common_funcs.h | 32 | common_funcs.h |
| 35 | common_paths.h | 33 | common_paths.h |
| 36 | common_types.h | 34 | common_types.h |
| 37 | emu_window.h | ||
| 38 | file_util.h | 35 | file_util.h |
| 39 | framebuffer_layout.h | 36 | framebuffer_layout.h |
| 40 | hash.h | 37 | hash.h |
| 41 | key_map.h | ||
| 42 | linear_disk_cache.h | 38 | linear_disk_cache.h |
| 43 | logging/text_formatter.h | 39 | logging/text_formatter.h |
| 44 | logging/filter.h | 40 | logging/filter.h |
diff --git a/src/common/emu_window.cpp b/src/common/emu_window.cpp deleted file mode 100644 index e3a9e08e6..000000000 --- a/src/common/emu_window.cpp +++ /dev/null | |||
| @@ -1,107 +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 <algorithm> | ||
| 6 | #include <cmath> | ||
| 7 | #include "common/assert.h" | ||
| 8 | #include "common/key_map.h" | ||
| 9 | #include "emu_window.h" | ||
| 10 | #include "video_core/video_core.h" | ||
| 11 | |||
| 12 | void EmuWindow::ButtonPressed(Service::HID::PadState pad) { | ||
| 13 | pad_state.hex |= pad.hex; | ||
| 14 | } | ||
| 15 | |||
| 16 | void EmuWindow::ButtonReleased(Service::HID::PadState pad) { | ||
| 17 | pad_state.hex &= ~pad.hex; | ||
| 18 | } | ||
| 19 | |||
| 20 | void EmuWindow::CirclePadUpdated(float x, float y) { | ||
| 21 | constexpr int MAX_CIRCLEPAD_POS = 0x9C; // Max value for a circle pad position | ||
| 22 | |||
| 23 | // Make sure the coordinates are in the unit circle, | ||
| 24 | // otherwise normalize it. | ||
| 25 | float r = x * x + y * y; | ||
| 26 | if (r > 1) { | ||
| 27 | r = std::sqrt(r); | ||
| 28 | x /= r; | ||
| 29 | y /= r; | ||
| 30 | } | ||
| 31 | |||
| 32 | circle_pad_x = static_cast<s16>(x * MAX_CIRCLEPAD_POS); | ||
| 33 | circle_pad_y = static_cast<s16>(y * MAX_CIRCLEPAD_POS); | ||
| 34 | } | ||
| 35 | |||
| 36 | /** | ||
| 37 | * Check if the given x/y coordinates are within the touchpad specified by the framebuffer layout | ||
| 38 | * @param layout FramebufferLayout object describing the framebuffer size and screen positions | ||
| 39 | * @param framebuffer_x Framebuffer x-coordinate to check | ||
| 40 | * @param framebuffer_y Framebuffer y-coordinate to check | ||
| 41 | * @return True if the coordinates are within the touchpad, otherwise false | ||
| 42 | */ | ||
| 43 | static bool IsWithinTouchscreen(const Layout::FramebufferLayout& layout, unsigned framebuffer_x, | ||
| 44 | unsigned framebuffer_y) { | ||
| 45 | return ( | ||
| 46 | framebuffer_y >= layout.bottom_screen.top && framebuffer_y < layout.bottom_screen.bottom && | ||
| 47 | framebuffer_x >= layout.bottom_screen.left && framebuffer_x < layout.bottom_screen.right); | ||
| 48 | } | ||
| 49 | |||
| 50 | std::tuple<unsigned, unsigned> EmuWindow::ClipToTouchScreen(unsigned new_x, unsigned new_y) { | ||
| 51 | new_x = std::max(new_x, framebuffer_layout.bottom_screen.left); | ||
| 52 | new_x = std::min(new_x, framebuffer_layout.bottom_screen.right - 1); | ||
| 53 | |||
| 54 | new_y = std::max(new_y, framebuffer_layout.bottom_screen.top); | ||
| 55 | new_y = std::min(new_y, framebuffer_layout.bottom_screen.bottom - 1); | ||
| 56 | |||
| 57 | return std::make_tuple(new_x, new_y); | ||
| 58 | } | ||
| 59 | |||
| 60 | void EmuWindow::TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y) { | ||
| 61 | if (!IsWithinTouchscreen(framebuffer_layout, framebuffer_x, framebuffer_y)) | ||
| 62 | return; | ||
| 63 | |||
| 64 | touch_x = VideoCore::kScreenBottomWidth * | ||
| 65 | (framebuffer_x - framebuffer_layout.bottom_screen.left) / | ||
| 66 | (framebuffer_layout.bottom_screen.right - framebuffer_layout.bottom_screen.left); | ||
| 67 | touch_y = VideoCore::kScreenBottomHeight * | ||
| 68 | (framebuffer_y - framebuffer_layout.bottom_screen.top) / | ||
| 69 | (framebuffer_layout.bottom_screen.bottom - framebuffer_layout.bottom_screen.top); | ||
| 70 | |||
| 71 | touch_pressed = true; | ||
| 72 | pad_state.touch.Assign(1); | ||
| 73 | } | ||
| 74 | |||
| 75 | void EmuWindow::TouchReleased() { | ||
| 76 | touch_pressed = false; | ||
| 77 | touch_x = 0; | ||
| 78 | touch_y = 0; | ||
| 79 | pad_state.touch.Assign(0); | ||
| 80 | } | ||
| 81 | |||
| 82 | void EmuWindow::TouchMoved(unsigned framebuffer_x, unsigned framebuffer_y) { | ||
| 83 | if (!touch_pressed) | ||
| 84 | return; | ||
| 85 | |||
| 86 | if (!IsWithinTouchscreen(framebuffer_layout, framebuffer_x, framebuffer_y)) | ||
| 87 | std::tie(framebuffer_x, framebuffer_y) = ClipToTouchScreen(framebuffer_x, framebuffer_y); | ||
| 88 | |||
| 89 | TouchPressed(framebuffer_x, framebuffer_y); | ||
| 90 | } | ||
| 91 | |||
| 92 | void EmuWindow::UpdateCurrentFramebufferLayout(unsigned width, unsigned height) { | ||
| 93 | Layout::FramebufferLayout layout; | ||
| 94 | switch (Settings::values.layout_option) { | ||
| 95 | case Settings::LayoutOption::SingleScreen: | ||
| 96 | layout = Layout::SingleFrameLayout(width, height, Settings::values.swap_screen); | ||
| 97 | break; | ||
| 98 | case Settings::LayoutOption::LargeScreen: | ||
| 99 | layout = Layout::LargeFrameLayout(width, height, Settings::values.swap_screen); | ||
| 100 | break; | ||
| 101 | case Settings::LayoutOption::Default: | ||
| 102 | default: | ||
| 103 | layout = Layout::DefaultFrameLayout(width, height, Settings::values.swap_screen); | ||
| 104 | break; | ||
| 105 | } | ||
| 106 | NotifyFramebufferLayoutChanged(layout); | ||
| 107 | } | ||
diff --git a/src/common/emu_window.h b/src/common/emu_window.h deleted file mode 100644 index 835c4d500..000000000 --- a/src/common/emu_window.h +++ /dev/null | |||
| @@ -1,290 +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 <tuple> | ||
| 8 | #include <utility> | ||
| 9 | #include "common/common_types.h" | ||
| 10 | #include "common/framebuffer_layout.h" | ||
| 11 | #include "common/math_util.h" | ||
| 12 | #include "core/hle/service/hid/hid.h" | ||
| 13 | |||
| 14 | /** | ||
| 15 | * Abstraction class used to provide an interface between emulation code and the frontend | ||
| 16 | * (e.g. SDL, QGLWidget, GLFW, etc...). | ||
| 17 | * | ||
| 18 | * Design notes on the interaction between EmuWindow and the emulation core: | ||
| 19 | * - Generally, decisions on anything visible to the user should be left up to the GUI. | ||
| 20 | * For example, the emulation core should not try to dictate some window title or size. | ||
| 21 | * This stuff is not the core's business and only causes problems with regards to thread-safety | ||
| 22 | * anyway. | ||
| 23 | * - Under certain circumstances, it may be desirable for the core to politely request the GUI | ||
| 24 | * to set e.g. a minimum window size. However, the GUI should always be free to ignore any | ||
| 25 | * such hints. | ||
| 26 | * - EmuWindow may expose some of its state as read-only to the emulation core, however care | ||
| 27 | * should be taken to make sure the provided information is self-consistent. This requires | ||
| 28 | * some sort of synchronization (most of this is still a TODO). | ||
| 29 | * - DO NOT TREAT THIS CLASS AS A GUI TOOLKIT ABSTRACTION LAYER. That's not what it is. Please | ||
| 30 | * re-read the upper points again and think about it if you don't see this. | ||
| 31 | */ | ||
| 32 | class EmuWindow { | ||
| 33 | public: | ||
| 34 | /// Data structure to store emuwindow configuration | ||
| 35 | struct WindowConfig { | ||
| 36 | bool fullscreen; | ||
| 37 | int res_width; | ||
| 38 | int res_height; | ||
| 39 | std::pair<unsigned, unsigned> min_client_area_size; | ||
| 40 | }; | ||
| 41 | |||
| 42 | /// Swap buffers to display the next frame | ||
| 43 | virtual void SwapBuffers() = 0; | ||
| 44 | |||
| 45 | /// Polls window events | ||
| 46 | virtual void PollEvents() = 0; | ||
| 47 | |||
| 48 | /// Makes the graphics context current for the caller thread | ||
| 49 | virtual void MakeCurrent() = 0; | ||
| 50 | |||
| 51 | /// Releases (dunno if this is the "right" word) the GLFW context from the caller thread | ||
| 52 | virtual void DoneCurrent() = 0; | ||
| 53 | |||
| 54 | virtual void ReloadSetKeymaps() = 0; | ||
| 55 | |||
| 56 | /** | ||
| 57 | * Signals a button press action to the HID module. | ||
| 58 | * @param pad_state indicates which button to press | ||
| 59 | * @note only handles real buttons (A/B/X/Y/...), excluding analog inputs like the circle pad. | ||
| 60 | */ | ||
| 61 | void ButtonPressed(Service::HID::PadState pad_state); | ||
| 62 | |||
| 63 | /** | ||
| 64 | * Signals a button release action to the HID module. | ||
| 65 | * @param pad_state indicates which button to press | ||
| 66 | * @note only handles real buttons (A/B/X/Y/...), excluding analog inputs like the circle pad. | ||
| 67 | */ | ||
| 68 | void ButtonReleased(Service::HID::PadState pad_state); | ||
| 69 | |||
| 70 | /** | ||
| 71 | * Signals a circle pad change action to the HID module. | ||
| 72 | * @param x new x-coordinate of the circle pad, in the range [-1.0, 1.0] | ||
| 73 | * @param y new y-coordinate of the circle pad, in the range [-1.0, 1.0] | ||
| 74 | * @note the coordinates will be normalized if the radius is larger than 1 | ||
| 75 | */ | ||
| 76 | void CirclePadUpdated(float x, float y); | ||
| 77 | |||
| 78 | /** | ||
| 79 | * Signal that a touch pressed event has occurred (e.g. mouse click pressed) | ||
| 80 | * @param framebuffer_x Framebuffer x-coordinate that was pressed | ||
| 81 | * @param framebuffer_y Framebuffer y-coordinate that was pressed | ||
| 82 | */ | ||
| 83 | void TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y); | ||
| 84 | |||
| 85 | /// Signal that a touch released event has occurred (e.g. mouse click released) | ||
| 86 | void TouchReleased(); | ||
| 87 | |||
| 88 | /** | ||
| 89 | * Signal that a touch movement event has occurred (e.g. mouse was moved over the emu window) | ||
| 90 | * @param framebuffer_x Framebuffer x-coordinate | ||
| 91 | * @param framebuffer_y Framebuffer y-coordinate | ||
| 92 | */ | ||
| 93 | void TouchMoved(unsigned framebuffer_x, unsigned framebuffer_y); | ||
| 94 | |||
| 95 | /** | ||
| 96 | * Gets the current pad state (which buttons are pressed). | ||
| 97 | * @note This should be called by the core emu thread to get a state set by the window thread. | ||
| 98 | * @note This doesn't include analog input like circle pad direction | ||
| 99 | * @todo Fix this function to be thread-safe. | ||
| 100 | * @return PadState object indicating the current pad state | ||
| 101 | */ | ||
| 102 | Service::HID::PadState GetPadState() const { | ||
| 103 | return pad_state; | ||
| 104 | } | ||
| 105 | |||
| 106 | /** | ||
| 107 | * Gets the current circle pad state. | ||
| 108 | * @note This should be called by the core emu thread to get a state set by the window thread. | ||
| 109 | * @todo Fix this function to be thread-safe. | ||
| 110 | * @return std::tuple of (x, y), where `x` and `y` are the circle pad coordinates | ||
| 111 | */ | ||
| 112 | std::tuple<s16, s16> GetCirclePadState() const { | ||
| 113 | return std::make_tuple(circle_pad_x, circle_pad_y); | ||
| 114 | } | ||
| 115 | |||
| 116 | /** | ||
| 117 | * Gets the current touch screen state (touch X/Y coordinates and whether or not it is pressed). | ||
| 118 | * @note This should be called by the core emu thread to get a state set by the window thread. | ||
| 119 | * @todo Fix this function to be thread-safe. | ||
| 120 | * @return std::tuple of (x, y, pressed) where `x` and `y` are the touch coordinates and | ||
| 121 | * `pressed` is true if the touch screen is currently being pressed | ||
| 122 | */ | ||
| 123 | std::tuple<u16, u16, bool> GetTouchState() const { | ||
| 124 | return std::make_tuple(touch_x, touch_y, touch_pressed); | ||
| 125 | } | ||
| 126 | |||
| 127 | /** | ||
| 128 | * Gets the current accelerometer state (acceleration along each three axis). | ||
| 129 | * Axis explained: | ||
| 130 | * +x is the same direction as LEFT on D-pad. | ||
| 131 | * +y is normal to the touch screen, pointing outward. | ||
| 132 | * +z is the same direction as UP on D-pad. | ||
| 133 | * Units: | ||
| 134 | * 1 unit of return value = 1/512 g (measured by hw test), | ||
| 135 | * where g is the gravitational acceleration (9.8 m/sec2). | ||
| 136 | * @note This should be called by the core emu thread to get a state set by the window thread. | ||
| 137 | * @todo Implement accelerometer input in front-end. | ||
| 138 | * @return std::tuple of (x, y, z) | ||
| 139 | */ | ||
| 140 | std::tuple<s16, s16, s16> GetAccelerometerState() const { | ||
| 141 | // stubbed | ||
| 142 | return std::make_tuple(0, -512, 0); | ||
| 143 | } | ||
| 144 | |||
| 145 | /** | ||
| 146 | * Gets the current gyroscope state (angular rates about each three axis). | ||
| 147 | * Axis explained: | ||
| 148 | * +x is the same direction as LEFT on D-pad. | ||
| 149 | * +y is normal to the touch screen, pointing outward. | ||
| 150 | * +z is the same direction as UP on D-pad. | ||
| 151 | * Orientation is determined by right-hand rule. | ||
| 152 | * Units: | ||
| 153 | * 1 unit of return value = (1/coef) deg/sec, | ||
| 154 | * where coef is the return value of GetGyroscopeRawToDpsCoefficient(). | ||
| 155 | * @note This should be called by the core emu thread to get a state set by the window thread. | ||
| 156 | * @todo Implement gyroscope input in front-end. | ||
| 157 | * @return std::tuple of (x, y, z) | ||
| 158 | */ | ||
| 159 | std::tuple<s16, s16, s16> GetGyroscopeState() const { | ||
| 160 | // stubbed | ||
| 161 | return std::make_tuple(0, 0, 0); | ||
| 162 | } | ||
| 163 | |||
| 164 | /** | ||
| 165 | * Gets the coefficient for units conversion of gyroscope state. | ||
| 166 | * The conversion formula is r = coefficient * v, | ||
| 167 | * where v is angular rate in deg/sec, | ||
| 168 | * and r is the gyroscope state. | ||
| 169 | * @return float-type coefficient | ||
| 170 | */ | ||
| 171 | f32 GetGyroscopeRawToDpsCoefficient() const { | ||
| 172 | return 14.375f; // taken from hw test, and gyroscope's document | ||
| 173 | } | ||
| 174 | |||
| 175 | /** | ||
| 176 | * Returns currently active configuration. | ||
| 177 | * @note Accesses to the returned object need not be consistent because it may be modified in | ||
| 178 | * another thread | ||
| 179 | */ | ||
| 180 | const WindowConfig& GetActiveConfig() const { | ||
| 181 | return active_config; | ||
| 182 | } | ||
| 183 | |||
| 184 | /** | ||
| 185 | * Requests the internal configuration to be replaced by the specified argument at some point in | ||
| 186 | * the future. | ||
| 187 | * @note This method is thread-safe, because it delays configuration changes to the GUI event | ||
| 188 | * loop. Hence there is no guarantee on when the requested configuration will be active. | ||
| 189 | */ | ||
| 190 | void SetConfig(const WindowConfig& val) { | ||
| 191 | config = val; | ||
| 192 | } | ||
| 193 | |||
| 194 | /** | ||
| 195 | * Gets the framebuffer layout (width, height, and screen regions) | ||
| 196 | * @note This method is thread-safe | ||
| 197 | */ | ||
| 198 | const Layout::FramebufferLayout& GetFramebufferLayout() const { | ||
| 199 | return framebuffer_layout; | ||
| 200 | } | ||
| 201 | |||
| 202 | /** | ||
| 203 | * Convenience method to update the current frame layout | ||
| 204 | * Read from the current settings to determine which layout to use. | ||
| 205 | */ | ||
| 206 | void UpdateCurrentFramebufferLayout(unsigned width, unsigned height); | ||
| 207 | |||
| 208 | protected: | ||
| 209 | EmuWindow() { | ||
| 210 | // TODO: Find a better place to set this. | ||
| 211 | config.min_client_area_size = std::make_pair(400u, 480u); | ||
| 212 | active_config = config; | ||
| 213 | pad_state.hex = 0; | ||
| 214 | touch_x = 0; | ||
| 215 | touch_y = 0; | ||
| 216 | circle_pad_x = 0; | ||
| 217 | circle_pad_y = 0; | ||
| 218 | touch_pressed = false; | ||
| 219 | } | ||
| 220 | virtual ~EmuWindow() {} | ||
| 221 | |||
| 222 | /** | ||
| 223 | * Processes any pending configuration changes from the last SetConfig call. | ||
| 224 | * This method invokes OnMinimalClientAreaChangeRequest if the corresponding configuration | ||
| 225 | * field changed. | ||
| 226 | * @note Implementations will usually want to call this from the GUI thread. | ||
| 227 | * @todo Actually call this in existing implementations. | ||
| 228 | */ | ||
| 229 | void ProcessConfigurationChanges() { | ||
| 230 | // TODO: For proper thread safety, we should eventually implement a proper | ||
| 231 | // multiple-writer/single-reader queue... | ||
| 232 | |||
| 233 | if (config.min_client_area_size != active_config.min_client_area_size) { | ||
| 234 | OnMinimalClientAreaChangeRequest(config.min_client_area_size); | ||
| 235 | config.min_client_area_size = active_config.min_client_area_size; | ||
| 236 | } | ||
| 237 | } | ||
| 238 | |||
| 239 | /** | ||
| 240 | * Update framebuffer layout with the given parameter. | ||
| 241 | * @note EmuWindow implementations will usually use this in window resize event handlers. | ||
| 242 | */ | ||
| 243 | void NotifyFramebufferLayoutChanged(const Layout::FramebufferLayout& layout) { | ||
| 244 | framebuffer_layout = layout; | ||
| 245 | } | ||
| 246 | |||
| 247 | /** | ||
| 248 | * Update internal client area size with the given parameter. | ||
| 249 | * @note EmuWindow implementations will usually use this in window resize event handlers. | ||
| 250 | */ | ||
| 251 | void NotifyClientAreaSizeChanged(const std::pair<unsigned, unsigned>& size) { | ||
| 252 | client_area_width = size.first; | ||
| 253 | client_area_height = size.second; | ||
| 254 | } | ||
| 255 | |||
| 256 | private: | ||
| 257 | /** | ||
| 258 | * Handler called when the minimal client area was requested to be changed via SetConfig. | ||
| 259 | * For the request to be honored, EmuWindow implementations will usually reimplement this | ||
| 260 | * function. | ||
| 261 | */ | ||
| 262 | virtual void OnMinimalClientAreaChangeRequest( | ||
| 263 | const std::pair<unsigned, unsigned>& minimal_size) { | ||
| 264 | // By default, ignore this request and do nothing. | ||
| 265 | } | ||
| 266 | |||
| 267 | Layout::FramebufferLayout framebuffer_layout; ///< Current framebuffer layout | ||
| 268 | |||
| 269 | unsigned client_area_width; ///< Current client width, should be set by window impl. | ||
| 270 | unsigned client_area_height; ///< Current client height, should be set by window impl. | ||
| 271 | |||
| 272 | WindowConfig config; ///< Internal configuration (changes pending for being applied in | ||
| 273 | /// ProcessConfigurationChanges) | ||
| 274 | WindowConfig active_config; ///< Internal active configuration | ||
| 275 | |||
| 276 | bool touch_pressed; ///< True if touchpad area is currently pressed, otherwise false | ||
| 277 | |||
| 278 | u16 touch_x; ///< Touchpad X-position in native 3DS pixel coordinates (0-320) | ||
| 279 | u16 touch_y; ///< Touchpad Y-position in native 3DS pixel coordinates (0-240) | ||
| 280 | |||
| 281 | s16 circle_pad_x; ///< Circle pad X-position in native 3DS pixel coordinates (-156 - 156) | ||
| 282 | s16 circle_pad_y; ///< Circle pad Y-position in native 3DS pixel coordinates (-156 - 156) | ||
| 283 | |||
| 284 | /** | ||
| 285 | * Clip the provided coordinates to be inside the touchscreen area. | ||
| 286 | */ | ||
| 287 | std::tuple<unsigned, unsigned> ClipToTouchScreen(unsigned new_x, unsigned new_y); | ||
| 288 | |||
| 289 | Service::HID::PadState pad_state; | ||
| 290 | }; | ||
diff --git a/src/common/key_map.cpp b/src/common/key_map.cpp deleted file mode 100644 index 97cafe9c9..000000000 --- a/src/common/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 "common/emu_window.h" | ||
| 7 | #include "common/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/common/key_map.h b/src/common/key_map.h deleted file mode 100644 index 040794578..000000000 --- a/src/common/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 | } | ||