diff options
Diffstat (limited to 'src')
26 files changed, 417 insertions, 295 deletions
diff --git a/src/core/frontend/emu_window.cpp b/src/core/frontend/emu_window.cpp index 8c1193894..ee7a58b1c 100644 --- a/src/core/frontend/emu_window.cpp +++ b/src/core/frontend/emu_window.cpp | |||
| @@ -21,21 +21,18 @@ public: | |||
| 21 | 21 | ||
| 22 | std::mutex mutex; | 22 | std::mutex mutex; |
| 23 | 23 | ||
| 24 | bool touch_pressed = false; ///< True if touchpad area is currently pressed, otherwise false | 24 | Input::TouchStatus status; |
| 25 | |||
| 26 | float touch_x = 0.0f; ///< Touchpad X-position | ||
| 27 | float touch_y = 0.0f; ///< Touchpad Y-position | ||
| 28 | 25 | ||
| 29 | private: | 26 | private: |
| 30 | class Device : public Input::TouchDevice { | 27 | class Device : public Input::TouchDevice { |
| 31 | public: | 28 | public: |
| 32 | explicit Device(std::weak_ptr<TouchState>&& touch_state) : touch_state(touch_state) {} | 29 | explicit Device(std::weak_ptr<TouchState>&& touch_state) : touch_state(touch_state) {} |
| 33 | std::tuple<float, float, bool> GetStatus() const override { | 30 | Input::TouchStatus GetStatus() const override { |
| 34 | if (auto state = touch_state.lock()) { | 31 | if (auto state = touch_state.lock()) { |
| 35 | std::lock_guard guard{state->mutex}; | 32 | std::lock_guard guard{state->mutex}; |
| 36 | return std::make_tuple(state->touch_x, state->touch_y, state->touch_pressed); | 33 | return state->status; |
| 37 | } | 34 | } |
| 38 | return std::make_tuple(0.0f, 0.0f, false); | 35 | return {}; |
| 39 | } | 36 | } |
| 40 | 37 | ||
| 41 | private: | 38 | private: |
| @@ -79,36 +76,44 @@ std::tuple<unsigned, unsigned> EmuWindow::ClipToTouchScreen(unsigned new_x, unsi | |||
| 79 | return std::make_tuple(new_x, new_y); | 76 | return std::make_tuple(new_x, new_y); |
| 80 | } | 77 | } |
| 81 | 78 | ||
| 82 | void EmuWindow::TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y) { | 79 | void EmuWindow::TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y, std::size_t id) { |
| 83 | if (!IsWithinTouchscreen(framebuffer_layout, framebuffer_x, framebuffer_y)) | 80 | if (!IsWithinTouchscreen(framebuffer_layout, framebuffer_x, framebuffer_y)) { |
| 84 | return; | 81 | return; |
| 82 | } | ||
| 83 | if (id >= touch_state->status.size()) { | ||
| 84 | return; | ||
| 85 | } | ||
| 85 | 86 | ||
| 86 | std::lock_guard guard{touch_state->mutex}; | 87 | std::lock_guard guard{touch_state->mutex}; |
| 87 | touch_state->touch_x = | 88 | const float x = |
| 88 | static_cast<float>(framebuffer_x - framebuffer_layout.screen.left) / | 89 | static_cast<float>(framebuffer_x - framebuffer_layout.screen.left) / |
| 89 | static_cast<float>(framebuffer_layout.screen.right - framebuffer_layout.screen.left); | 90 | static_cast<float>(framebuffer_layout.screen.right - framebuffer_layout.screen.left); |
| 90 | touch_state->touch_y = | 91 | const float y = |
| 91 | static_cast<float>(framebuffer_y - framebuffer_layout.screen.top) / | 92 | static_cast<float>(framebuffer_y - framebuffer_layout.screen.top) / |
| 92 | static_cast<float>(framebuffer_layout.screen.bottom - framebuffer_layout.screen.top); | 93 | static_cast<float>(framebuffer_layout.screen.bottom - framebuffer_layout.screen.top); |
| 93 | 94 | ||
| 94 | touch_state->touch_pressed = true; | 95 | touch_state->status[id] = std::make_tuple(x, y, true); |
| 95 | } | 96 | } |
| 96 | 97 | ||
| 97 | void EmuWindow::TouchReleased() { | 98 | void EmuWindow::TouchReleased(std::size_t id) { |
| 99 | if (id >= touch_state->status.size()) { | ||
| 100 | return; | ||
| 101 | } | ||
| 98 | std::lock_guard guard{touch_state->mutex}; | 102 | std::lock_guard guard{touch_state->mutex}; |
| 99 | touch_state->touch_pressed = false; | 103 | touch_state->status[id] = std::make_tuple(0.0f, 0.0f, false); |
| 100 | touch_state->touch_x = 0; | ||
| 101 | touch_state->touch_y = 0; | ||
| 102 | } | 104 | } |
| 103 | 105 | ||
| 104 | void EmuWindow::TouchMoved(unsigned framebuffer_x, unsigned framebuffer_y) { | 106 | void EmuWindow::TouchMoved(unsigned framebuffer_x, unsigned framebuffer_y, std::size_t id) { |
| 105 | if (!touch_state->touch_pressed) | 107 | if (id >= touch_state->status.size()) { |
| 108 | return; | ||
| 109 | } | ||
| 110 | if (!std::get<2>(touch_state->status[id])) | ||
| 106 | return; | 111 | return; |
| 107 | 112 | ||
| 108 | if (!IsWithinTouchscreen(framebuffer_layout, framebuffer_x, framebuffer_y)) | 113 | if (!IsWithinTouchscreen(framebuffer_layout, framebuffer_x, framebuffer_y)) |
| 109 | std::tie(framebuffer_x, framebuffer_y) = ClipToTouchScreen(framebuffer_x, framebuffer_y); | 114 | std::tie(framebuffer_x, framebuffer_y) = ClipToTouchScreen(framebuffer_x, framebuffer_y); |
| 110 | 115 | ||
| 111 | TouchPressed(framebuffer_x, framebuffer_y); | 116 | TouchPressed(framebuffer_x, framebuffer_y, id); |
| 112 | } | 117 | } |
| 113 | 118 | ||
| 114 | void EmuWindow::UpdateCurrentFramebufferLayout(unsigned width, unsigned height) { | 119 | void EmuWindow::UpdateCurrentFramebufferLayout(unsigned width, unsigned height) { |
diff --git a/src/core/frontend/emu_window.h b/src/core/frontend/emu_window.h index 276d2b906..2436c6580 100644 --- a/src/core/frontend/emu_window.h +++ b/src/core/frontend/emu_window.h | |||
| @@ -117,18 +117,23 @@ public: | |||
| 117 | * Signal that a touch pressed event has occurred (e.g. mouse click pressed) | 117 | * Signal that a touch pressed event has occurred (e.g. mouse click pressed) |
| 118 | * @param framebuffer_x Framebuffer x-coordinate that was pressed | 118 | * @param framebuffer_x Framebuffer x-coordinate that was pressed |
| 119 | * @param framebuffer_y Framebuffer y-coordinate that was pressed | 119 | * @param framebuffer_y Framebuffer y-coordinate that was pressed |
| 120 | * @param id Touch event ID | ||
| 120 | */ | 121 | */ |
| 121 | void TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y); | 122 | void TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y, std::size_t id); |
| 122 | 123 | ||
| 123 | /// Signal that a touch released event has occurred (e.g. mouse click released) | 124 | /** |
| 124 | void TouchReleased(); | 125 | * Signal that a touch released event has occurred (e.g. mouse click released) |
| 126 | * @param id Touch event ID | ||
| 127 | */ | ||
| 128 | void TouchReleased(std::size_t id); | ||
| 125 | 129 | ||
| 126 | /** | 130 | /** |
| 127 | * Signal that a touch movement event has occurred (e.g. mouse was moved over the emu window) | 131 | * Signal that a touch movement event has occurred (e.g. mouse was moved over the emu window) |
| 128 | * @param framebuffer_x Framebuffer x-coordinate | 132 | * @param framebuffer_x Framebuffer x-coordinate |
| 129 | * @param framebuffer_y Framebuffer y-coordinate | 133 | * @param framebuffer_y Framebuffer y-coordinate |
| 134 | * @param id Touch event ID | ||
| 130 | */ | 135 | */ |
| 131 | void TouchMoved(unsigned framebuffer_x, unsigned framebuffer_y); | 136 | void TouchMoved(unsigned framebuffer_x, unsigned framebuffer_y, std::size_t id); |
| 132 | 137 | ||
| 133 | /** | 138 | /** |
| 134 | * Returns currently active configuration. | 139 | * Returns currently active configuration. |
diff --git a/src/core/frontend/input.h b/src/core/frontend/input.h index de51a754e..f014dfea3 100644 --- a/src/core/frontend/input.h +++ b/src/core/frontend/input.h | |||
| @@ -163,10 +163,11 @@ using MotionStatus = std::tuple<Common::Vec3<float>, Common::Vec3<float>, Common | |||
| 163 | using MotionDevice = InputDevice<MotionStatus>; | 163 | using MotionDevice = InputDevice<MotionStatus>; |
| 164 | 164 | ||
| 165 | /** | 165 | /** |
| 166 | * A touch status is an object that returns a tuple of two floats and a bool. The floats are | 166 | * A touch status is an object that returns an array of 16 tuple elements of two floats and a bool. |
| 167 | * x and y coordinates in the range 0.0 - 1.0, and the bool indicates whether it is pressed. | 167 | * The floats are x and y coordinates in the range 0.0 - 1.0, and the bool indicates whether it is |
| 168 | * pressed. | ||
| 168 | */ | 169 | */ |
| 169 | using TouchStatus = std::tuple<float, float, bool>; | 170 | using TouchStatus = std::array<std::tuple<float, float, bool>, 16>; |
| 170 | 171 | ||
| 171 | /** | 172 | /** |
| 172 | * A touch device is an input device that returns a touch status object | 173 | * A touch device is an input device that returns a touch status object |
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp index 1082be489..ff783b3cc 100644 --- a/src/core/hle/service/hid/controllers/npad.cpp +++ b/src/core/hle/service/hid/controllers/npad.cpp | |||
| @@ -892,7 +892,7 @@ void Controller_NPad::UpdateControllerAt(NPadControllerType controller, std::siz | |||
| 892 | return; | 892 | return; |
| 893 | } | 893 | } |
| 894 | 894 | ||
| 895 | if (controller == NPadControllerType::Handheld) { | 895 | if (controller == NPadControllerType::Handheld && npad_index == HANDHELD_INDEX) { |
| 896 | Settings::values.players.GetValue()[HANDHELD_INDEX].controller_type = | 896 | Settings::values.players.GetValue()[HANDHELD_INDEX].controller_type = |
| 897 | MapNPadToSettingsType(controller); | 897 | MapNPadToSettingsType(controller); |
| 898 | Settings::values.players.GetValue()[HANDHELD_INDEX].connected = true; | 898 | Settings::values.players.GetValue()[HANDHELD_INDEX].connected = true; |
diff --git a/src/core/hle/service/hid/controllers/touchscreen.cpp b/src/core/hle/service/hid/controllers/touchscreen.cpp index 0df395e85..5219f2dad 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.cpp +++ b/src/core/hle/service/hid/controllers/touchscreen.cpp | |||
| @@ -2,6 +2,7 @@ | |||
| 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 <algorithm> | ||
| 5 | #include <cstring> | 6 | #include <cstring> |
| 6 | #include "common/common_types.h" | 7 | #include "common/common_types.h" |
| 7 | #include "core/core_timing.h" | 8 | #include "core/core_timing.h" |
| @@ -16,7 +17,13 @@ constexpr std::size_t SHARED_MEMORY_OFFSET = 0x400; | |||
| 16 | Controller_Touchscreen::Controller_Touchscreen(Core::System& system) : ControllerBase(system) {} | 17 | Controller_Touchscreen::Controller_Touchscreen(Core::System& system) : ControllerBase(system) {} |
| 17 | Controller_Touchscreen::~Controller_Touchscreen() = default; | 18 | Controller_Touchscreen::~Controller_Touchscreen() = default; |
| 18 | 19 | ||
| 19 | void Controller_Touchscreen::OnInit() {} | 20 | void Controller_Touchscreen::OnInit() { |
| 21 | for (std::size_t id = 0; id < MAX_FINGERS; ++id) { | ||
| 22 | mouse_finger_id[id] = MAX_FINGERS; | ||
| 23 | keyboard_finger_id[id] = MAX_FINGERS; | ||
| 24 | udp_finger_id[id] = MAX_FINGERS; | ||
| 25 | } | ||
| 26 | } | ||
| 20 | 27 | ||
| 21 | void Controller_Touchscreen::OnRelease() {} | 28 | void Controller_Touchscreen::OnRelease() {} |
| 22 | 29 | ||
| @@ -40,38 +47,106 @@ void Controller_Touchscreen::OnUpdate(const Core::Timing::CoreTiming& core_timin | |||
| 40 | cur_entry.sampling_number = last_entry.sampling_number + 1; | 47 | cur_entry.sampling_number = last_entry.sampling_number + 1; |
| 41 | cur_entry.sampling_number2 = cur_entry.sampling_number; | 48 | cur_entry.sampling_number2 = cur_entry.sampling_number; |
| 42 | 49 | ||
| 43 | bool pressed = false; | 50 | const Input::TouchStatus& mouse_status = touch_mouse_device->GetStatus(); |
| 44 | float x, y; | 51 | const Input::TouchStatus& udp_status = touch_udp_device->GetStatus(); |
| 45 | std::tie(x, y, pressed) = touch_device->GetStatus(); | 52 | for (std::size_t id = 0; id < mouse_status.size(); ++id) { |
| 46 | auto& touch_entry = cur_entry.states[0]; | 53 | mouse_finger_id[id] = UpdateTouchInputEvent(mouse_status[id], mouse_finger_id[id]); |
| 47 | touch_entry.attribute.raw = 0; | 54 | udp_finger_id[id] = UpdateTouchInputEvent(udp_status[id], udp_finger_id[id]); |
| 48 | if (!pressed && touch_btn_device) { | ||
| 49 | std::tie(x, y, pressed) = touch_btn_device->GetStatus(); | ||
| 50 | } | 55 | } |
| 51 | if (pressed && Settings::values.touchscreen.enabled) { | 56 | |
| 52 | touch_entry.x = static_cast<u16>(x * Layout::ScreenUndocked::Width); | 57 | if (Settings::values.use_touch_from_button) { |
| 53 | touch_entry.y = static_cast<u16>(y * Layout::ScreenUndocked::Height); | 58 | const Input::TouchStatus& keyboard_status = touch_btn_device->GetStatus(); |
| 54 | touch_entry.diameter_x = Settings::values.touchscreen.diameter_x; | 59 | for (std::size_t id = 0; id < mouse_status.size(); ++id) { |
| 55 | touch_entry.diameter_y = Settings::values.touchscreen.diameter_y; | 60 | keyboard_finger_id[id] = |
| 56 | touch_entry.rotation_angle = Settings::values.touchscreen.rotation_angle; | 61 | UpdateTouchInputEvent(keyboard_status[id], keyboard_finger_id[id]); |
| 57 | const u64 tick = core_timing.GetCPUTicks(); | 62 | } |
| 58 | touch_entry.delta_time = tick - last_touch; | ||
| 59 | last_touch = tick; | ||
| 60 | touch_entry.finger = Settings::values.touchscreen.finger; | ||
| 61 | cur_entry.entry_count = 1; | ||
| 62 | } else { | ||
| 63 | cur_entry.entry_count = 0; | ||
| 64 | } | 63 | } |
| 65 | 64 | ||
| 65 | std::array<Finger, 16> active_fingers; | ||
| 66 | const auto end_iter = std::copy_if(fingers.begin(), fingers.end(), active_fingers.begin(), | ||
| 67 | [](const auto& finger) { return finger.pressed; }); | ||
| 68 | const auto active_fingers_count = | ||
| 69 | static_cast<std::size_t>(std::distance(active_fingers.begin(), end_iter)); | ||
| 70 | |||
| 71 | const u64 tick = core_timing.GetCPUTicks(); | ||
| 72 | cur_entry.entry_count = static_cast<s32_le>(active_fingers_count); | ||
| 73 | for (std::size_t id = 0; id < MAX_FINGERS; ++id) { | ||
| 74 | auto& touch_entry = cur_entry.states[id]; | ||
| 75 | if (id < active_fingers_count) { | ||
| 76 | touch_entry.x = static_cast<u16>(active_fingers[id].x * Layout::ScreenUndocked::Width); | ||
| 77 | touch_entry.y = static_cast<u16>(active_fingers[id].y * Layout::ScreenUndocked::Height); | ||
| 78 | touch_entry.diameter_x = Settings::values.touchscreen.diameter_x; | ||
| 79 | touch_entry.diameter_y = Settings::values.touchscreen.diameter_y; | ||
| 80 | touch_entry.rotation_angle = Settings::values.touchscreen.rotation_angle; | ||
| 81 | touch_entry.delta_time = tick - active_fingers[id].last_touch; | ||
| 82 | fingers[active_fingers[id].id].last_touch = tick; | ||
| 83 | touch_entry.finger = active_fingers[id].id; | ||
| 84 | touch_entry.attribute.raw = active_fingers[id].attribute.raw; | ||
| 85 | } else { | ||
| 86 | // Clear touch entry | ||
| 87 | touch_entry.attribute.raw = 0; | ||
| 88 | touch_entry.x = 0; | ||
| 89 | touch_entry.y = 0; | ||
| 90 | touch_entry.diameter_x = 0; | ||
| 91 | touch_entry.diameter_y = 0; | ||
| 92 | touch_entry.rotation_angle = 0; | ||
| 93 | touch_entry.delta_time = 0; | ||
| 94 | touch_entry.finger = 0; | ||
| 95 | } | ||
| 96 | } | ||
| 66 | std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(TouchScreenSharedMemory)); | 97 | std::memcpy(data + SHARED_MEMORY_OFFSET, &shared_memory, sizeof(TouchScreenSharedMemory)); |
| 67 | } | 98 | } |
| 68 | 99 | ||
| 69 | void Controller_Touchscreen::OnLoadInputDevices() { | 100 | void Controller_Touchscreen::OnLoadInputDevices() { |
| 70 | touch_device = Input::CreateDevice<Input::TouchDevice>(Settings::values.touchscreen.device); | 101 | touch_mouse_device = Input::CreateDevice<Input::TouchDevice>("engine:emu_window"); |
| 71 | if (Settings::values.use_touch_from_button) { | 102 | touch_udp_device = Input::CreateDevice<Input::TouchDevice>("engine:cemuhookudp"); |
| 72 | touch_btn_device = Input::CreateDevice<Input::TouchDevice>("engine:touch_from_button"); | 103 | touch_btn_device = Input::CreateDevice<Input::TouchDevice>("engine:touch_from_button"); |
| 73 | } else { | 104 | } |
| 74 | touch_btn_device.reset(); | 105 | |
| 106 | std::optional<std::size_t> Controller_Touchscreen::GetUnusedFingerID() const { | ||
| 107 | std::size_t first_free_id = 0; | ||
| 108 | while (first_free_id < MAX_FINGERS) { | ||
| 109 | if (!fingers[first_free_id].pressed) { | ||
| 110 | return first_free_id; | ||
| 111 | } else { | ||
| 112 | first_free_id++; | ||
| 113 | } | ||
| 114 | } | ||
| 115 | return std::nullopt; | ||
| 116 | } | ||
| 117 | |||
| 118 | std::size_t Controller_Touchscreen::UpdateTouchInputEvent( | ||
| 119 | const std::tuple<float, float, bool>& touch_input, std::size_t finger_id) { | ||
| 120 | const auto& [x, y, pressed] = touch_input; | ||
| 121 | if (pressed) { | ||
| 122 | Attributes attribute{}; | ||
| 123 | if (finger_id == MAX_FINGERS) { | ||
| 124 | const auto first_free_id = GetUnusedFingerID(); | ||
| 125 | if (!first_free_id) { | ||
| 126 | // Invalid finger id do nothing | ||
| 127 | return MAX_FINGERS; | ||
| 128 | } | ||
| 129 | finger_id = first_free_id.value(); | ||
| 130 | fingers[finger_id].pressed = true; | ||
| 131 | fingers[finger_id].id = static_cast<u32_le>(finger_id); | ||
| 132 | attribute.start_touch.Assign(1); | ||
| 133 | } | ||
| 134 | fingers[finger_id].x = x; | ||
| 135 | fingers[finger_id].y = y; | ||
| 136 | fingers[finger_id].attribute = attribute; | ||
| 137 | return finger_id; | ||
| 75 | } | 138 | } |
| 139 | |||
| 140 | if (finger_id != MAX_FINGERS) { | ||
| 141 | if (!fingers[finger_id].attribute.end_touch) { | ||
| 142 | fingers[finger_id].attribute.end_touch.Assign(1); | ||
| 143 | fingers[finger_id].attribute.start_touch.Assign(0); | ||
| 144 | return finger_id; | ||
| 145 | } | ||
| 146 | fingers[finger_id].pressed = false; | ||
| 147 | } | ||
| 148 | |||
| 149 | return MAX_FINGERS; | ||
| 76 | } | 150 | } |
| 151 | |||
| 77 | } // namespace Service::HID | 152 | } // namespace Service::HID |
diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h index 4d9042adc..784124e25 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.h +++ b/src/core/hle/service/hid/controllers/touchscreen.h | |||
| @@ -30,6 +30,18 @@ public: | |||
| 30 | void OnLoadInputDevices() override; | 30 | void OnLoadInputDevices() override; |
| 31 | 31 | ||
| 32 | private: | 32 | private: |
| 33 | static constexpr std::size_t MAX_FINGERS = 16; | ||
| 34 | |||
| 35 | // Returns an unused finger id, if there is no fingers available std::nullopt will be returned | ||
| 36 | std::optional<std::size_t> GetUnusedFingerID() const; | ||
| 37 | |||
| 38 | // If the touch is new it tries to assing a new finger id, if there is no fingers avaliable no | ||
| 39 | // changes will be made. Updates the coordinates if the finger id it's already set. If the touch | ||
| 40 | // ends delays the output by one frame to set the end_touch flag before finally freeing the | ||
| 41 | // finger id | ||
| 42 | std::size_t UpdateTouchInputEvent(const std::tuple<float, float, bool>& touch_input, | ||
| 43 | std::size_t finger_id); | ||
| 44 | |||
| 33 | struct Attributes { | 45 | struct Attributes { |
| 34 | union { | 46 | union { |
| 35 | u32 raw{}; | 47 | u32 raw{}; |
| @@ -55,7 +67,7 @@ private: | |||
| 55 | s64_le sampling_number; | 67 | s64_le sampling_number; |
| 56 | s64_le sampling_number2; | 68 | s64_le sampling_number2; |
| 57 | s32_le entry_count; | 69 | s32_le entry_count; |
| 58 | std::array<TouchState, 16> states; | 70 | std::array<TouchState, MAX_FINGERS> states; |
| 59 | }; | 71 | }; |
| 60 | static_assert(sizeof(TouchScreenEntry) == 0x298, "TouchScreenEntry is an invalid size"); | 72 | static_assert(sizeof(TouchScreenEntry) == 0x298, "TouchScreenEntry is an invalid size"); |
| 61 | 73 | ||
| @@ -66,9 +78,23 @@ private: | |||
| 66 | }; | 78 | }; |
| 67 | static_assert(sizeof(TouchScreenSharedMemory) == 0x3000, | 79 | static_assert(sizeof(TouchScreenSharedMemory) == 0x3000, |
| 68 | "TouchScreenSharedMemory is an invalid size"); | 80 | "TouchScreenSharedMemory is an invalid size"); |
| 81 | |||
| 82 | struct Finger { | ||
| 83 | u64_le last_touch{}; | ||
| 84 | float x{}; | ||
| 85 | float y{}; | ||
| 86 | u32_le id{}; | ||
| 87 | bool pressed{}; | ||
| 88 | Attributes attribute; | ||
| 89 | }; | ||
| 90 | |||
| 69 | TouchScreenSharedMemory shared_memory{}; | 91 | TouchScreenSharedMemory shared_memory{}; |
| 70 | std::unique_ptr<Input::TouchDevice> touch_device; | 92 | std::unique_ptr<Input::TouchDevice> touch_mouse_device; |
| 93 | std::unique_ptr<Input::TouchDevice> touch_udp_device; | ||
| 71 | std::unique_ptr<Input::TouchDevice> touch_btn_device; | 94 | std::unique_ptr<Input::TouchDevice> touch_btn_device; |
| 72 | s64_le last_touch{}; | 95 | std::array<std::size_t, MAX_FINGERS> mouse_finger_id; |
| 96 | std::array<std::size_t, MAX_FINGERS> keyboard_finger_id; | ||
| 97 | std::array<std::size_t, MAX_FINGERS> udp_finger_id; | ||
| 98 | std::array<Finger, MAX_FINGERS> fingers; | ||
| 73 | }; | 99 | }; |
| 74 | } // namespace Service::HID | 100 | } // namespace Service::HID |
diff --git a/src/input_common/touch_from_button.cpp b/src/input_common/touch_from_button.cpp index a07124a86..ffbe4f2ed 100644 --- a/src/input_common/touch_from_button.cpp +++ b/src/input_common/touch_from_button.cpp | |||
| @@ -25,18 +25,19 @@ public: | |||
| 25 | } | 25 | } |
| 26 | } | 26 | } |
| 27 | 27 | ||
| 28 | std::tuple<float, float, bool> GetStatus() const override { | 28 | Input::TouchStatus GetStatus() const override { |
| 29 | for (const auto& m : map) { | 29 | Input::TouchStatus touch_status{}; |
| 30 | const bool state = std::get<0>(m)->GetStatus(); | 30 | for (std::size_t id = 0; id < map.size() && id < touch_status.size(); ++id) { |
| 31 | const bool state = std::get<0>(map[id])->GetStatus(); | ||
| 31 | if (state) { | 32 | if (state) { |
| 32 | const float x = static_cast<float>(std::get<1>(m)) / | 33 | const float x = static_cast<float>(std::get<1>(map[id])) / |
| 33 | static_cast<int>(Layout::ScreenUndocked::Width); | 34 | static_cast<int>(Layout::ScreenUndocked::Width); |
| 34 | const float y = static_cast<float>(std::get<2>(m)) / | 35 | const float y = static_cast<float>(std::get<2>(map[id])) / |
| 35 | static_cast<int>(Layout::ScreenUndocked::Height); | 36 | static_cast<int>(Layout::ScreenUndocked::Height); |
| 36 | return {x, y, true}; | 37 | touch_status[id] = {x, y, true}; |
| 37 | } | 38 | } |
| 38 | } | 39 | } |
| 39 | return {}; | 40 | return touch_status; |
| 40 | } | 41 | } |
| 41 | 42 | ||
| 42 | private: | 43 | private: |
diff --git a/src/input_common/udp/client.cpp b/src/input_common/udp/client.cpp index 412d57896..e7e50d789 100644 --- a/src/input_common/udp/client.cpp +++ b/src/input_common/udp/client.cpp | |||
| @@ -136,6 +136,7 @@ static void SocketLoop(Socket* socket) { | |||
| 136 | 136 | ||
| 137 | Client::Client() { | 137 | Client::Client() { |
| 138 | LOG_INFO(Input, "Udp Initialization started"); | 138 | LOG_INFO(Input, "Udp Initialization started"); |
| 139 | finger_id.fill(MAX_TOUCH_FINGERS); | ||
| 139 | ReloadSockets(); | 140 | ReloadSockets(); |
| 140 | } | 141 | } |
| 141 | 142 | ||
| @@ -176,7 +177,7 @@ void Client::ReloadSockets() { | |||
| 176 | std::string server_token; | 177 | std::string server_token; |
| 177 | std::size_t client = 0; | 178 | std::size_t client = 0; |
| 178 | while (std::getline(servers_ss, server_token, ',')) { | 179 | while (std::getline(servers_ss, server_token, ',')) { |
| 179 | if (client == max_udp_clients) { | 180 | if (client == MAX_UDP_CLIENTS) { |
| 180 | break; | 181 | break; |
| 181 | } | 182 | } |
| 182 | std::stringstream server_ss(server_token); | 183 | std::stringstream server_ss(server_token); |
| @@ -194,7 +195,7 @@ void Client::ReloadSockets() { | |||
| 194 | for (std::size_t pad = 0; pad < 4; ++pad) { | 195 | for (std::size_t pad = 0; pad < 4; ++pad) { |
| 195 | const std::size_t client_number = | 196 | const std::size_t client_number = |
| 196 | GetClientNumber(udp_input_address, udp_input_port, pad); | 197 | GetClientNumber(udp_input_address, udp_input_port, pad); |
| 197 | if (client_number != max_udp_clients) { | 198 | if (client_number != MAX_UDP_CLIENTS) { |
| 198 | LOG_ERROR(Input, "Duplicated UDP servers found"); | 199 | LOG_ERROR(Input, "Duplicated UDP servers found"); |
| 199 | continue; | 200 | continue; |
| 200 | } | 201 | } |
| @@ -213,7 +214,7 @@ std::size_t Client::GetClientNumber(std::string_view host, u16 port, std::size_t | |||
| 213 | return client; | 214 | return client; |
| 214 | } | 215 | } |
| 215 | } | 216 | } |
| 216 | return max_udp_clients; | 217 | return MAX_UDP_CLIENTS; |
| 217 | } | 218 | } |
| 218 | 219 | ||
| 219 | void Client::OnVersion([[maybe_unused]] Response::Version data) { | 220 | void Client::OnVersion([[maybe_unused]] Response::Version data) { |
| @@ -259,33 +260,14 @@ void Client::OnPadData(Response::PadData data, std::size_t client) { | |||
| 259 | std::lock_guard guard(clients[client].status.update_mutex); | 260 | std::lock_guard guard(clients[client].status.update_mutex); |
| 260 | clients[client].status.motion_status = clients[client].motion.GetMotion(); | 261 | clients[client].status.motion_status = clients[client].motion.GetMotion(); |
| 261 | 262 | ||
| 262 | // TODO: add a setting for "click" touch. Click touch refers to a device that differentiates | 263 | for (std::size_t id = 0; id < data.touch.size(); ++id) { |
| 263 | // between a simple "tap" and a hard press that causes the touch screen to click. | 264 | UpdateTouchInput(data.touch[id], client, id); |
| 264 | const bool is_active = data.touch_1.is_active != 0; | ||
| 265 | |||
| 266 | float x = 0; | ||
| 267 | float y = 0; | ||
| 268 | |||
| 269 | if (is_active && clients[client].status.touch_calibration) { | ||
| 270 | const u16 min_x = clients[client].status.touch_calibration->min_x; | ||
| 271 | const u16 max_x = clients[client].status.touch_calibration->max_x; | ||
| 272 | const u16 min_y = clients[client].status.touch_calibration->min_y; | ||
| 273 | const u16 max_y = clients[client].status.touch_calibration->max_y; | ||
| 274 | |||
| 275 | x = static_cast<float>(std::clamp(static_cast<u16>(data.touch_1.x), min_x, max_x) - | ||
| 276 | min_x) / | ||
| 277 | static_cast<float>(max_x - min_x); | ||
| 278 | y = static_cast<float>(std::clamp(static_cast<u16>(data.touch_1.y), min_y, max_y) - | ||
| 279 | min_y) / | ||
| 280 | static_cast<float>(max_y - min_y); | ||
| 281 | } | 265 | } |
| 282 | 266 | ||
| 283 | clients[client].status.touch_status = {x, y, is_active}; | ||
| 284 | |||
| 285 | if (configuring) { | 267 | if (configuring) { |
| 286 | const Common::Vec3f gyroscope = clients[client].motion.GetGyroscope(); | 268 | const Common::Vec3f gyroscope = clients[client].motion.GetGyroscope(); |
| 287 | const Common::Vec3f accelerometer = clients[client].motion.GetAcceleration(); | 269 | const Common::Vec3f accelerometer = clients[client].motion.GetAcceleration(); |
| 288 | UpdateYuzuSettings(client, accelerometer, gyroscope, is_active); | 270 | UpdateYuzuSettings(client, accelerometer, gyroscope); |
| 289 | } | 271 | } |
| 290 | } | 272 | } |
| 291 | } | 273 | } |
| @@ -320,21 +302,17 @@ void Client::Reset() { | |||
| 320 | } | 302 | } |
| 321 | 303 | ||
| 322 | void Client::UpdateYuzuSettings(std::size_t client, const Common::Vec3<float>& acc, | 304 | void Client::UpdateYuzuSettings(std::size_t client, const Common::Vec3<float>& acc, |
| 323 | const Common::Vec3<float>& gyro, bool touch) { | 305 | const Common::Vec3<float>& gyro) { |
| 324 | if (gyro.Length() > 0.2f) { | 306 | if (gyro.Length() > 0.2f) { |
| 325 | LOG_DEBUG(Input, "UDP Controller {}: gyro=({}, {}, {}), accel=({}, {}, {}), touch={}", | 307 | LOG_DEBUG(Input, "UDP Controller {}: gyro=({}, {}, {}), accel=({}, {}, {})", client, |
| 326 | client, gyro[0], gyro[1], gyro[2], acc[0], acc[1], acc[2], touch); | 308 | gyro[0], gyro[1], gyro[2], acc[0], acc[1], acc[2]); |
| 327 | } | 309 | } |
| 328 | UDPPadStatus pad{ | 310 | UDPPadStatus pad{ |
| 329 | .host = clients[client].host, | 311 | .host = clients[client].host, |
| 330 | .port = clients[client].port, | 312 | .port = clients[client].port, |
| 331 | .pad_index = clients[client].pad_index, | 313 | .pad_index = clients[client].pad_index, |
| 332 | }; | 314 | }; |
| 333 | if (touch) { | 315 | for (std::size_t i = 0; i < 3; ++i) { |
| 334 | pad.touch = PadTouch::Click; | ||
| 335 | pad_queue.Push(pad); | ||
| 336 | } | ||
| 337 | for (size_t i = 0; i < 3; ++i) { | ||
| 338 | if (gyro[i] > 5.0f || gyro[i] < -5.0f) { | 316 | if (gyro[i] > 5.0f || gyro[i] < -5.0f) { |
| 339 | pad.motion = static_cast<PadMotion>(i); | 317 | pad.motion = static_cast<PadMotion>(i); |
| 340 | pad.motion_value = gyro[i]; | 318 | pad.motion_value = gyro[i]; |
| @@ -348,6 +326,50 @@ void Client::UpdateYuzuSettings(std::size_t client, const Common::Vec3<float>& a | |||
| 348 | } | 326 | } |
| 349 | } | 327 | } |
| 350 | 328 | ||
| 329 | std::optional<std::size_t> Client::GetUnusedFingerID() const { | ||
| 330 | std::size_t first_free_id = 0; | ||
| 331 | while (first_free_id < MAX_TOUCH_FINGERS) { | ||
| 332 | if (!std::get<2>(touch_status[first_free_id])) { | ||
| 333 | return first_free_id; | ||
| 334 | } else { | ||
| 335 | first_free_id++; | ||
| 336 | } | ||
| 337 | } | ||
| 338 | return std::nullopt; | ||
| 339 | } | ||
| 340 | |||
| 341 | void Client::UpdateTouchInput(Response::TouchPad& touch_pad, std::size_t client, std::size_t id) { | ||
| 342 | // TODO: Use custom calibration per device | ||
| 343 | const Common::ParamPackage touch_param(Settings::values.touch_device); | ||
| 344 | const u16 min_x = static_cast<u16>(touch_param.Get("min_x", 100)); | ||
| 345 | const u16 min_y = static_cast<u16>(touch_param.Get("min_y", 50)); | ||
| 346 | const u16 max_x = static_cast<u16>(touch_param.Get("max_x", 1800)); | ||
| 347 | const u16 max_y = static_cast<u16>(touch_param.Get("max_y", 850)); | ||
| 348 | const std::size_t touch_id = client * 2 + id; | ||
| 349 | if (touch_pad.is_active) { | ||
| 350 | if (finger_id[touch_id] == MAX_TOUCH_FINGERS) { | ||
| 351 | const auto first_free_id = GetUnusedFingerID(); | ||
| 352 | if (!first_free_id) { | ||
| 353 | // Invalid finger id skip to next input | ||
| 354 | return; | ||
| 355 | } | ||
| 356 | finger_id[touch_id] = *first_free_id; | ||
| 357 | } | ||
| 358 | auto& [x, y, pressed] = touch_status[finger_id[touch_id]]; | ||
| 359 | x = static_cast<float>(std::clamp(static_cast<u16>(touch_pad.x), min_x, max_x) - min_x) / | ||
| 360 | static_cast<float>(max_x - min_x); | ||
| 361 | y = static_cast<float>(std::clamp(static_cast<u16>(touch_pad.y), min_y, max_y) - min_y) / | ||
| 362 | static_cast<float>(max_y - min_y); | ||
| 363 | pressed = true; | ||
| 364 | return; | ||
| 365 | } | ||
| 366 | |||
| 367 | if (finger_id[touch_id] != MAX_TOUCH_FINGERS) { | ||
| 368 | touch_status[finger_id[touch_id]] = {}; | ||
| 369 | finger_id[touch_id] = MAX_TOUCH_FINGERS; | ||
| 370 | } | ||
| 371 | } | ||
| 372 | |||
| 351 | void Client::BeginConfiguration() { | 373 | void Client::BeginConfiguration() { |
| 352 | pad_queue.Clear(); | 374 | pad_queue.Clear(); |
| 353 | configuring = true; | 375 | configuring = true; |
| @@ -360,7 +382,7 @@ void Client::EndConfiguration() { | |||
| 360 | 382 | ||
| 361 | DeviceStatus& Client::GetPadState(const std::string& host, u16 port, std::size_t pad) { | 383 | DeviceStatus& Client::GetPadState(const std::string& host, u16 port, std::size_t pad) { |
| 362 | const std::size_t client_number = GetClientNumber(host, port, pad); | 384 | const std::size_t client_number = GetClientNumber(host, port, pad); |
| 363 | if (client_number == max_udp_clients) { | 385 | if (client_number == MAX_UDP_CLIENTS) { |
| 364 | return clients[0].status; | 386 | return clients[0].status; |
| 365 | } | 387 | } |
| 366 | return clients[client_number].status; | 388 | return clients[client_number].status; |
| @@ -368,12 +390,20 @@ DeviceStatus& Client::GetPadState(const std::string& host, u16 port, std::size_t | |||
| 368 | 390 | ||
| 369 | const DeviceStatus& Client::GetPadState(const std::string& host, u16 port, std::size_t pad) const { | 391 | const DeviceStatus& Client::GetPadState(const std::string& host, u16 port, std::size_t pad) const { |
| 370 | const std::size_t client_number = GetClientNumber(host, port, pad); | 392 | const std::size_t client_number = GetClientNumber(host, port, pad); |
| 371 | if (client_number == max_udp_clients) { | 393 | if (client_number == MAX_UDP_CLIENTS) { |
| 372 | return clients[0].status; | 394 | return clients[0].status; |
| 373 | } | 395 | } |
| 374 | return clients[client_number].status; | 396 | return clients[client_number].status; |
| 375 | } | 397 | } |
| 376 | 398 | ||
| 399 | Input::TouchStatus& Client::GetTouchState() { | ||
| 400 | return touch_status; | ||
| 401 | } | ||
| 402 | |||
| 403 | const Input::TouchStatus& Client::GetTouchState() const { | ||
| 404 | return touch_status; | ||
| 405 | } | ||
| 406 | |||
| 377 | Common::SPSCQueue<UDPPadStatus>& Client::GetPadQueue() { | 407 | Common::SPSCQueue<UDPPadStatus>& Client::GetPadQueue() { |
| 378 | return pad_queue; | 408 | return pad_queue; |
| 379 | } | 409 | } |
| @@ -426,24 +456,24 @@ CalibrationConfigurationJob::CalibrationConfigurationJob( | |||
| 426 | current_status = Status::Ready; | 456 | current_status = Status::Ready; |
| 427 | status_callback(current_status); | 457 | status_callback(current_status); |
| 428 | } | 458 | } |
| 429 | if (data.touch_1.is_active == 0) { | 459 | if (data.touch[0].is_active == 0) { |
| 430 | return; | 460 | return; |
| 431 | } | 461 | } |
| 432 | LOG_DEBUG(Input, "Current touch: {} {}", data.touch_1.x, | 462 | LOG_DEBUG(Input, "Current touch: {} {}", data.touch[0].x, |
| 433 | data.touch_1.y); | 463 | data.touch[0].y); |
| 434 | min_x = std::min(min_x, static_cast<u16>(data.touch_1.x)); | 464 | min_x = std::min(min_x, static_cast<u16>(data.touch[0].x)); |
| 435 | min_y = std::min(min_y, static_cast<u16>(data.touch_1.y)); | 465 | min_y = std::min(min_y, static_cast<u16>(data.touch[0].y)); |
| 436 | if (current_status == Status::Ready) { | 466 | if (current_status == Status::Ready) { |
| 437 | // First touch - min data (min_x/min_y) | 467 | // First touch - min data (min_x/min_y) |
| 438 | current_status = Status::Stage1Completed; | 468 | current_status = Status::Stage1Completed; |
| 439 | status_callback(current_status); | 469 | status_callback(current_status); |
| 440 | } | 470 | } |
| 441 | if (data.touch_1.x - min_x > CALIBRATION_THRESHOLD && | 471 | if (data.touch[0].x - min_x > CALIBRATION_THRESHOLD && |
| 442 | data.touch_1.y - min_y > CALIBRATION_THRESHOLD) { | 472 | data.touch[0].y - min_y > CALIBRATION_THRESHOLD) { |
| 443 | // Set the current position as max value and finishes | 473 | // Set the current position as max value and finishes |
| 444 | // configuration | 474 | // configuration |
| 445 | max_x = data.touch_1.x; | 475 | max_x = data.touch[0].x; |
| 446 | max_y = data.touch_1.y; | 476 | max_y = data.touch[0].y; |
| 447 | current_status = Status::Completed; | 477 | current_status = Status::Completed; |
| 448 | data_callback(min_x, min_y, max_x, max_y); | 478 | data_callback(min_x, min_y, max_x, max_y); |
| 449 | status_callback(current_status); | 479 | status_callback(current_status); |
diff --git a/src/input_common/udp/client.h b/src/input_common/udp/client.h index 00c8b09f5..822f9c550 100644 --- a/src/input_common/udp/client.h +++ b/src/input_common/udp/client.h | |||
| @@ -28,6 +28,7 @@ class Socket; | |||
| 28 | namespace Response { | 28 | namespace Response { |
| 29 | struct PadData; | 29 | struct PadData; |
| 30 | struct PortInfo; | 30 | struct PortInfo; |
| 31 | struct TouchPad; | ||
| 31 | struct Version; | 32 | struct Version; |
| 32 | } // namespace Response | 33 | } // namespace Response |
| 33 | 34 | ||
| @@ -50,7 +51,6 @@ struct UDPPadStatus { | |||
| 50 | std::string host{"127.0.0.1"}; | 51 | std::string host{"127.0.0.1"}; |
| 51 | u16 port{26760}; | 52 | u16 port{26760}; |
| 52 | std::size_t pad_index{}; | 53 | std::size_t pad_index{}; |
| 53 | PadTouch touch{PadTouch::Undefined}; | ||
| 54 | PadMotion motion{PadMotion::Undefined}; | 54 | PadMotion motion{PadMotion::Undefined}; |
| 55 | f32 motion_value{0.0f}; | 55 | f32 motion_value{0.0f}; |
| 56 | }; | 56 | }; |
| @@ -93,6 +93,9 @@ public: | |||
| 93 | DeviceStatus& GetPadState(const std::string& host, u16 port, std::size_t pad); | 93 | DeviceStatus& GetPadState(const std::string& host, u16 port, std::size_t pad); |
| 94 | const DeviceStatus& GetPadState(const std::string& host, u16 port, std::size_t pad) const; | 94 | const DeviceStatus& GetPadState(const std::string& host, u16 port, std::size_t pad) const; |
| 95 | 95 | ||
| 96 | Input::TouchStatus& GetTouchState(); | ||
| 97 | const Input::TouchStatus& GetTouchState() const; | ||
| 98 | |||
| 96 | private: | 99 | private: |
| 97 | struct ClientData { | 100 | struct ClientData { |
| 98 | std::string host{"127.0.0.1"}; | 101 | std::string host{"127.0.0.1"}; |
| @@ -122,14 +125,25 @@ private: | |||
| 122 | void StartCommunication(std::size_t client, const std::string& host, u16 port, | 125 | void StartCommunication(std::size_t client, const std::string& host, u16 port, |
| 123 | std::size_t pad_index, u32 client_id); | 126 | std::size_t pad_index, u32 client_id); |
| 124 | void UpdateYuzuSettings(std::size_t client, const Common::Vec3<float>& acc, | 127 | void UpdateYuzuSettings(std::size_t client, const Common::Vec3<float>& acc, |
| 125 | const Common::Vec3<float>& gyro, bool touch); | 128 | const Common::Vec3<float>& gyro); |
| 129 | |||
| 130 | // Returns an unused finger id, if there is no fingers available std::nullopt will be | ||
| 131 | // returned | ||
| 132 | std::optional<std::size_t> GetUnusedFingerID() const; | ||
| 133 | |||
| 134 | // Merges and updates all touch inputs into the touch_status array | ||
| 135 | void UpdateTouchInput(Response::TouchPad& touch_pad, std::size_t client, std::size_t id); | ||
| 126 | 136 | ||
| 127 | bool configuring = false; | 137 | bool configuring = false; |
| 128 | 138 | ||
| 129 | // Allocate clients for 8 udp servers | 139 | // Allocate clients for 8 udp servers |
| 130 | const std::size_t max_udp_clients = 32; | 140 | static constexpr std::size_t MAX_UDP_CLIENTS = 4 * 8; |
| 131 | std::array<ClientData, 4 * 8> clients; | 141 | // Each client can have up 2 touch inputs |
| 132 | Common::SPSCQueue<UDPPadStatus> pad_queue; | 142 | static constexpr std::size_t MAX_TOUCH_FINGERS = MAX_UDP_CLIENTS * 2; |
| 143 | std::array<ClientData, MAX_UDP_CLIENTS> clients{}; | ||
| 144 | Common::SPSCQueue<UDPPadStatus> pad_queue{}; | ||
| 145 | Input::TouchStatus touch_status{}; | ||
| 146 | std::array<std::size_t, MAX_TOUCH_FINGERS> finger_id{}; | ||
| 133 | }; | 147 | }; |
| 134 | 148 | ||
| 135 | /// An async job allowing configuration of the touchpad calibration. | 149 | /// An async job allowing configuration of the touchpad calibration. |
diff --git a/src/input_common/udp/protocol.h b/src/input_common/udp/protocol.h index fc1aea4b9..a3d276697 100644 --- a/src/input_common/udp/protocol.h +++ b/src/input_common/udp/protocol.h | |||
| @@ -140,6 +140,14 @@ static_assert(sizeof(PortInfo) == 12, "UDP Response PortInfo struct has wrong si | |||
| 140 | static_assert(std::is_trivially_copyable_v<PortInfo>, | 140 | static_assert(std::is_trivially_copyable_v<PortInfo>, |
| 141 | "UDP Response PortInfo is not trivially copyable"); | 141 | "UDP Response PortInfo is not trivially copyable"); |
| 142 | 142 | ||
| 143 | struct TouchPad { | ||
| 144 | u8 is_active{}; | ||
| 145 | u8 id{}; | ||
| 146 | u16_le x{}; | ||
| 147 | u16_le y{}; | ||
| 148 | }; | ||
| 149 | static_assert(sizeof(TouchPad) == 6, "UDP Response TouchPad struct has wrong size "); | ||
| 150 | |||
| 143 | #pragma pack(push, 1) | 151 | #pragma pack(push, 1) |
| 144 | struct PadData { | 152 | struct PadData { |
| 145 | PortInfo info{}; | 153 | PortInfo info{}; |
| @@ -190,12 +198,7 @@ struct PadData { | |||
| 190 | u8 button_13{}; | 198 | u8 button_13{}; |
| 191 | } analog_button; | 199 | } analog_button; |
| 192 | 200 | ||
| 193 | struct TouchPad { | 201 | std::array<TouchPad, 2> touch; |
| 194 | u8 is_active{}; | ||
| 195 | u8 id{}; | ||
| 196 | u16_le x{}; | ||
| 197 | u16_le y{}; | ||
| 198 | } touch_1, touch_2; | ||
| 199 | 202 | ||
| 200 | u64_le motion_timestamp; | 203 | u64_le motion_timestamp; |
| 201 | 204 | ||
| @@ -222,7 +225,6 @@ static_assert(sizeof(Message<PadData>) == MAX_PACKET_SIZE, | |||
| 222 | 225 | ||
| 223 | static_assert(sizeof(PadData::AnalogButton) == 12, | 226 | static_assert(sizeof(PadData::AnalogButton) == 12, |
| 224 | "UDP Response AnalogButton struct has wrong size "); | 227 | "UDP Response AnalogButton struct has wrong size "); |
| 225 | static_assert(sizeof(PadData::TouchPad) == 6, "UDP Response TouchPad struct has wrong size "); | ||
| 226 | static_assert(sizeof(PadData::Accelerometer) == 12, | 228 | static_assert(sizeof(PadData::Accelerometer) == 12, |
| 227 | "UDP Response Accelerometer struct has wrong size "); | 229 | "UDP Response Accelerometer struct has wrong size "); |
| 228 | static_assert(sizeof(PadData::Gyroscope) == 12, "UDP Response Gyroscope struct has wrong size "); | 230 | static_assert(sizeof(PadData::Gyroscope) == 12, "UDP Response Gyroscope struct has wrong size "); |
diff --git a/src/input_common/udp/udp.cpp b/src/input_common/udp/udp.cpp index c5da27a38..b630281a0 100644 --- a/src/input_common/udp/udp.cpp +++ b/src/input_common/udp/udp.cpp | |||
| @@ -78,8 +78,8 @@ public: | |||
| 78 | explicit UDPTouch(std::string ip_, u16 port_, u16 pad_, CemuhookUDP::Client* client_) | 78 | explicit UDPTouch(std::string ip_, u16 port_, u16 pad_, CemuhookUDP::Client* client_) |
| 79 | : ip(std::move(ip_)), port(port_), pad(pad_), client(client_) {} | 79 | : ip(std::move(ip_)), port(port_), pad(pad_), client(client_) {} |
| 80 | 80 | ||
| 81 | std::tuple<float, float, bool> GetStatus() const override { | 81 | Input::TouchStatus GetStatus() const override { |
| 82 | return client->GetPadState(ip, port, pad).touch_status; | 82 | return client->GetTouchState(); |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | private: | 85 | private: |
| @@ -107,32 +107,4 @@ std::unique_ptr<Input::TouchDevice> UDPTouchFactory::Create(const Common::ParamP | |||
| 107 | return std::make_unique<UDPTouch>(std::move(ip), port, pad, client.get()); | 107 | return std::make_unique<UDPTouch>(std::move(ip), port, pad, client.get()); |
| 108 | } | 108 | } |
| 109 | 109 | ||
| 110 | void UDPTouchFactory::BeginConfiguration() { | ||
| 111 | polling = true; | ||
| 112 | client->BeginConfiguration(); | ||
| 113 | } | ||
| 114 | |||
| 115 | void UDPTouchFactory::EndConfiguration() { | ||
| 116 | polling = false; | ||
| 117 | client->EndConfiguration(); | ||
| 118 | } | ||
| 119 | |||
| 120 | Common::ParamPackage UDPTouchFactory::GetNextInput() { | ||
| 121 | Common::ParamPackage params; | ||
| 122 | CemuhookUDP::UDPPadStatus pad; | ||
| 123 | auto& queue = client->GetPadQueue(); | ||
| 124 | while (queue.Pop(pad)) { | ||
| 125 | if (pad.touch == CemuhookUDP::PadTouch::Undefined) { | ||
| 126 | continue; | ||
| 127 | } | ||
| 128 | params.Set("engine", "cemuhookudp"); | ||
| 129 | params.Set("ip", pad.host); | ||
| 130 | params.Set("port", static_cast<u16>(pad.port)); | ||
| 131 | params.Set("pad_index", static_cast<u16>(pad.pad_index)); | ||
| 132 | params.Set("touch", static_cast<u16>(pad.touch)); | ||
| 133 | return params; | ||
| 134 | } | ||
| 135 | return params; | ||
| 136 | } | ||
| 137 | |||
| 138 | } // namespace InputCommon | 110 | } // namespace InputCommon |
diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp index 89cbe01ad..61d52b961 100644 --- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp +++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp | |||
| @@ -1334,7 +1334,10 @@ private: | |||
| 1334 | } | 1334 | } |
| 1335 | 1335 | ||
| 1336 | if (const auto comment = std::get_if<CommentNode>(&*node)) { | 1336 | if (const auto comment = std::get_if<CommentNode>(&*node)) { |
| 1337 | Name(OpUndef(t_void), comment->GetText()); | 1337 | if (device.HasDebuggingToolAttached()) { |
| 1338 | // We should insert comments with OpString instead of using named variables | ||
| 1339 | Name(OpUndef(t_int), comment->GetText()); | ||
| 1340 | } | ||
| 1338 | return {}; | 1341 | return {}; |
| 1339 | } | 1342 | } |
| 1340 | 1343 | ||
diff --git a/src/video_core/texture_cache/util.cpp b/src/video_core/texture_cache/util.cpp index ce8fcfe0a..b23424523 100644 --- a/src/video_core/texture_cache/util.cpp +++ b/src/video_core/texture_cache/util.cpp | |||
| @@ -679,7 +679,7 @@ u32 CalculateLayerSize(const ImageInfo& info) noexcept { | |||
| 679 | } | 679 | } |
| 680 | 680 | ||
| 681 | std::array<u32, MAX_MIP_LEVELS> CalculateMipLevelOffsets(const ImageInfo& info) noexcept { | 681 | std::array<u32, MAX_MIP_LEVELS> CalculateMipLevelOffsets(const ImageInfo& info) noexcept { |
| 682 | ASSERT(info.resources.levels <= MAX_MIP_LEVELS); | 682 | ASSERT(info.resources.levels <= static_cast<s32>(MAX_MIP_LEVELS)); |
| 683 | const LevelInfo level_info = MakeLevelInfo(info); | 683 | const LevelInfo level_info = MakeLevelInfo(info); |
| 684 | std::array<u32, MAX_MIP_LEVELS> offsets{}; | 684 | std::array<u32, MAX_MIP_LEVELS> offsets{}; |
| 685 | u32 offset = 0; | 685 | u32 offset = 0; |
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index e6c8f18af..4528eb196 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp | |||
| @@ -394,7 +394,7 @@ void GRenderWindow::mousePressEvent(QMouseEvent* event) { | |||
| 394 | input_subsystem->GetMouse()->PressButton(x, y, event->button()); | 394 | input_subsystem->GetMouse()->PressButton(x, y, event->button()); |
| 395 | 395 | ||
| 396 | if (event->button() == Qt::LeftButton) { | 396 | if (event->button() == Qt::LeftButton) { |
| 397 | this->TouchPressed(x, y); | 397 | this->TouchPressed(x, y, 0); |
| 398 | } | 398 | } |
| 399 | 399 | ||
| 400 | emit MouseActivity(); | 400 | emit MouseActivity(); |
| @@ -409,7 +409,7 @@ void GRenderWindow::mouseMoveEvent(QMouseEvent* event) { | |||
| 409 | auto pos = event->pos(); | 409 | auto pos = event->pos(); |
| 410 | const auto [x, y] = ScaleTouch(pos); | 410 | const auto [x, y] = ScaleTouch(pos); |
| 411 | input_subsystem->GetMouse()->MouseMove(x, y); | 411 | input_subsystem->GetMouse()->MouseMove(x, y); |
| 412 | this->TouchMoved(x, y); | 412 | this->TouchMoved(x, y, 0); |
| 413 | 413 | ||
| 414 | emit MouseActivity(); | 414 | emit MouseActivity(); |
| 415 | } | 415 | } |
| @@ -423,36 +423,72 @@ void GRenderWindow::mouseReleaseEvent(QMouseEvent* event) { | |||
| 423 | input_subsystem->GetMouse()->ReleaseButton(event->button()); | 423 | input_subsystem->GetMouse()->ReleaseButton(event->button()); |
| 424 | 424 | ||
| 425 | if (event->button() == Qt::LeftButton) { | 425 | if (event->button() == Qt::LeftButton) { |
| 426 | this->TouchReleased(); | 426 | this->TouchReleased(0); |
| 427 | } | 427 | } |
| 428 | } | 428 | } |
| 429 | 429 | ||
| 430 | void GRenderWindow::TouchBeginEvent(const QTouchEvent* event) { | 430 | void GRenderWindow::TouchBeginEvent(const QTouchEvent* event) { |
| 431 | // TouchBegin always has exactly one touch point, so take the .first() | 431 | QList<QTouchEvent::TouchPoint> touch_points = event->touchPoints(); |
| 432 | const auto [x, y] = ScaleTouch(event->touchPoints().first().pos()); | 432 | for (const auto& touch_point : touch_points) { |
| 433 | this->TouchPressed(x, y); | 433 | if (!TouchUpdate(touch_point)) { |
| 434 | TouchStart(touch_point); | ||
| 435 | } | ||
| 436 | } | ||
| 434 | } | 437 | } |
| 435 | 438 | ||
| 436 | void GRenderWindow::TouchUpdateEvent(const QTouchEvent* event) { | 439 | void GRenderWindow::TouchUpdateEvent(const QTouchEvent* event) { |
| 437 | QPointF pos; | 440 | QList<QTouchEvent::TouchPoint> touch_points = event->touchPoints(); |
| 438 | int active_points = 0; | 441 | for (const auto& touch_point : touch_points) { |
| 439 | 442 | if (!TouchUpdate(touch_point)) { | |
| 440 | // average all active touch points | 443 | TouchStart(touch_point); |
| 441 | for (const auto& tp : event->touchPoints()) { | ||
| 442 | if (tp.state() & (Qt::TouchPointPressed | Qt::TouchPointMoved | Qt::TouchPointStationary)) { | ||
| 443 | active_points++; | ||
| 444 | pos += tp.pos(); | ||
| 445 | } | 444 | } |
| 446 | } | 445 | } |
| 446 | // Release all inactive points | ||
| 447 | for (std::size_t id = 0; id < touch_ids.size(); ++id) { | ||
| 448 | if (!TouchExist(touch_ids[id], touch_points)) { | ||
| 449 | touch_ids[id] = 0; | ||
| 450 | this->TouchReleased(id + 1); | ||
| 451 | } | ||
| 452 | } | ||
| 453 | } | ||
| 447 | 454 | ||
| 448 | pos /= active_points; | 455 | void GRenderWindow::TouchEndEvent() { |
| 456 | for (std::size_t id = 0; id < touch_ids.size(); ++id) { | ||
| 457 | if (touch_ids[id] != 0) { | ||
| 458 | touch_ids[id] = 0; | ||
| 459 | this->TouchReleased(id + 1); | ||
| 460 | } | ||
| 461 | } | ||
| 462 | } | ||
| 449 | 463 | ||
| 450 | const auto [x, y] = ScaleTouch(pos); | 464 | bool GRenderWindow::TouchStart(const QTouchEvent::TouchPoint& touch_point) { |
| 451 | this->TouchMoved(x, y); | 465 | for (std::size_t id = 0; id < touch_ids.size(); ++id) { |
| 466 | if (touch_ids[id] == 0) { | ||
| 467 | touch_ids[id] = touch_point.id() + 1; | ||
| 468 | const auto [x, y] = ScaleTouch(touch_point.pos()); | ||
| 469 | this->TouchPressed(x, y, id + 1); | ||
| 470 | return true; | ||
| 471 | } | ||
| 472 | } | ||
| 473 | return false; | ||
| 452 | } | 474 | } |
| 453 | 475 | ||
| 454 | void GRenderWindow::TouchEndEvent() { | 476 | bool GRenderWindow::TouchUpdate(const QTouchEvent::TouchPoint& touch_point) { |
| 455 | this->TouchReleased(); | 477 | for (std::size_t id = 0; id < touch_ids.size(); ++id) { |
| 478 | if (touch_ids[id] == static_cast<std::size_t>(touch_point.id() + 1)) { | ||
| 479 | const auto [x, y] = ScaleTouch(touch_point.pos()); | ||
| 480 | this->TouchMoved(x, y, id + 1); | ||
| 481 | return true; | ||
| 482 | } | ||
| 483 | } | ||
| 484 | return false; | ||
| 485 | } | ||
| 486 | |||
| 487 | bool GRenderWindow::TouchExist(std::size_t id, | ||
| 488 | const QList<QTouchEvent::TouchPoint>& touch_points) const { | ||
| 489 | return std::any_of(touch_points.begin(), touch_points.end(), [id](const auto& point) { | ||
| 490 | return id == static_cast<std::size_t>(point.id() + 1); | ||
| 491 | }); | ||
| 456 | } | 492 | } |
| 457 | 493 | ||
| 458 | bool GRenderWindow::event(QEvent* event) { | 494 | bool GRenderWindow::event(QEvent* event) { |
diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h index 339095509..b5ec7de07 100644 --- a/src/yuzu/bootmanager.h +++ b/src/yuzu/bootmanager.h | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | 11 | ||
| 12 | #include <QImage> | 12 | #include <QImage> |
| 13 | #include <QThread> | 13 | #include <QThread> |
| 14 | #include <QTouchEvent> | ||
| 14 | #include <QWidget> | 15 | #include <QWidget> |
| 15 | #include <QWindow> | 16 | #include <QWindow> |
| 16 | 17 | ||
| @@ -21,7 +22,6 @@ | |||
| 21 | class GRenderWindow; | 22 | class GRenderWindow; |
| 22 | class GMainWindow; | 23 | class GMainWindow; |
| 23 | class QKeyEvent; | 24 | class QKeyEvent; |
| 24 | class QTouchEvent; | ||
| 25 | class QStringList; | 25 | class QStringList; |
| 26 | 26 | ||
| 27 | namespace InputCommon { | 27 | namespace InputCommon { |
| @@ -191,6 +191,10 @@ private: | |||
| 191 | void TouchUpdateEvent(const QTouchEvent* event); | 191 | void TouchUpdateEvent(const QTouchEvent* event); |
| 192 | void TouchEndEvent(); | 192 | void TouchEndEvent(); |
| 193 | 193 | ||
| 194 | bool TouchStart(const QTouchEvent::TouchPoint& touch_point); | ||
| 195 | bool TouchUpdate(const QTouchEvent::TouchPoint& touch_point); | ||
| 196 | bool TouchExist(std::size_t id, const QList<QTouchEvent::TouchPoint>& touch_points) const; | ||
| 197 | |||
| 194 | void OnMinimalClientAreaChangeRequest(std::pair<u32, u32> minimal_size) override; | 198 | void OnMinimalClientAreaChangeRequest(std::pair<u32, u32> minimal_size) override; |
| 195 | 199 | ||
| 196 | bool InitializeOpenGL(); | 200 | bool InitializeOpenGL(); |
| @@ -215,6 +219,8 @@ private: | |||
| 215 | 219 | ||
| 216 | bool first_frame = false; | 220 | bool first_frame = false; |
| 217 | 221 | ||
| 222 | std::array<std::size_t, 16> touch_ids{}; | ||
| 223 | |||
| 218 | protected: | 224 | protected: |
| 219 | void showEvent(QShowEvent* event) override; | 225 | void showEvent(QShowEvent* event) override; |
| 220 | bool eventFilter(QObject* object, QEvent* event) override; | 226 | bool eventFilter(QObject* object, QEvent* event) override; |
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index cda448718..8d85a1986 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp | |||
| @@ -464,13 +464,7 @@ void Config::ReadMouseValues() { | |||
| 464 | void Config::ReadTouchscreenValues() { | 464 | void Config::ReadTouchscreenValues() { |
| 465 | Settings::values.touchscreen.enabled = | 465 | Settings::values.touchscreen.enabled = |
| 466 | ReadSetting(QStringLiteral("touchscreen_enabled"), true).toBool(); | 466 | ReadSetting(QStringLiteral("touchscreen_enabled"), true).toBool(); |
| 467 | Settings::values.touchscreen.device = | ||
| 468 | ReadSetting(QStringLiteral("touchscreen_device"), QStringLiteral("engine:emu_window")) | ||
| 469 | .toString() | ||
| 470 | .toStdString(); | ||
| 471 | 467 | ||
| 472 | Settings::values.touchscreen.finger = | ||
| 473 | ReadSetting(QStringLiteral("touchscreen_finger"), 0).toUInt(); | ||
| 474 | Settings::values.touchscreen.rotation_angle = | 468 | Settings::values.touchscreen.rotation_angle = |
| 475 | ReadSetting(QStringLiteral("touchscreen_angle"), 0).toUInt(); | 469 | ReadSetting(QStringLiteral("touchscreen_angle"), 0).toUInt(); |
| 476 | Settings::values.touchscreen.diameter_x = | 470 | Settings::values.touchscreen.diameter_x = |
| @@ -563,7 +557,8 @@ void Config::ReadMotionTouchValues() { | |||
| 563 | .toString() | 557 | .toString() |
| 564 | .toStdString(); | 558 | .toStdString(); |
| 565 | Settings::values.touch_device = | 559 | Settings::values.touch_device = |
| 566 | ReadSetting(QStringLiteral("touch_device"), QStringLiteral("engine:emu_window")) | 560 | ReadSetting(QStringLiteral("touch_device"), |
| 561 | QStringLiteral("min_x:100,min_y:50,max_x:1800,max_y:850")) | ||
| 567 | .toString() | 562 | .toString() |
| 568 | .toStdString(); | 563 | .toStdString(); |
| 569 | Settings::values.use_touch_from_button = | 564 | Settings::values.use_touch_from_button = |
| @@ -1005,7 +1000,8 @@ void Config::SavePlayerValue(std::size_t player_index) { | |||
| 1005 | static_cast<u8>(Settings::ControllerType::ProController)); | 1000 | static_cast<u8>(Settings::ControllerType::ProController)); |
| 1006 | 1001 | ||
| 1007 | if (!player_prefix.isEmpty()) { | 1002 | if (!player_prefix.isEmpty()) { |
| 1008 | WriteSetting(QStringLiteral("%1connected").arg(player_prefix), player.connected, false); | 1003 | WriteSetting(QStringLiteral("%1connected").arg(player_prefix), player.connected, |
| 1004 | player_index == 0); | ||
| 1009 | WriteSetting(QStringLiteral("%1vibration_enabled").arg(player_prefix), | 1005 | WriteSetting(QStringLiteral("%1vibration_enabled").arg(player_prefix), |
| 1010 | player.vibration_enabled, true); | 1006 | player.vibration_enabled, true); |
| 1011 | WriteSetting(QStringLiteral("%1vibration_strength").arg(player_prefix), | 1007 | WriteSetting(QStringLiteral("%1vibration_strength").arg(player_prefix), |
| @@ -1087,10 +1083,7 @@ void Config::SaveTouchscreenValues() { | |||
| 1087 | const auto& touchscreen = Settings::values.touchscreen; | 1083 | const auto& touchscreen = Settings::values.touchscreen; |
| 1088 | 1084 | ||
| 1089 | WriteSetting(QStringLiteral("touchscreen_enabled"), touchscreen.enabled, true); | 1085 | WriteSetting(QStringLiteral("touchscreen_enabled"), touchscreen.enabled, true); |
| 1090 | WriteSetting(QStringLiteral("touchscreen_device"), QString::fromStdString(touchscreen.device), | ||
| 1091 | QStringLiteral("engine:emu_window")); | ||
| 1092 | 1086 | ||
| 1093 | WriteSetting(QStringLiteral("touchscreen_finger"), touchscreen.finger, 0); | ||
| 1094 | WriteSetting(QStringLiteral("touchscreen_angle"), touchscreen.rotation_angle, 0); | 1087 | WriteSetting(QStringLiteral("touchscreen_angle"), touchscreen.rotation_angle, 0); |
| 1095 | WriteSetting(QStringLiteral("touchscreen_diameter_x"), touchscreen.diameter_x, 15); | 1088 | WriteSetting(QStringLiteral("touchscreen_diameter_x"), touchscreen.diameter_x, 15); |
| 1096 | WriteSetting(QStringLiteral("touchscreen_diameter_y"), touchscreen.diameter_y, 15); | 1089 | WriteSetting(QStringLiteral("touchscreen_diameter_y"), touchscreen.diameter_y, 15); |
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index 46ea026e4..13f0351d4 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp | |||
| @@ -575,6 +575,16 @@ void ConfigureInputPlayer::ApplyConfiguration() { | |||
| 575 | 575 | ||
| 576 | std::transform(motions_param.begin(), motions_param.end(), motions.begin(), | 576 | std::transform(motions_param.begin(), motions_param.end(), motions.begin(), |
| 577 | [](const Common::ParamPackage& param) { return param.Serialize(); }); | 577 | [](const Common::ParamPackage& param) { return param.Serialize(); }); |
| 578 | |||
| 579 | // Apply configuration for handheld | ||
| 580 | if (player_index == 0) { | ||
| 581 | auto& handheld = Settings::values.players.GetValue()[HANDHELD_INDEX]; | ||
| 582 | if (player.controller_type == Settings::ControllerType::Handheld) { | ||
| 583 | handheld = player; | ||
| 584 | } | ||
| 585 | handheld.connected = ui->groupConnectedController->isChecked() && | ||
| 586 | player.controller_type == Settings::ControllerType::Handheld; | ||
| 587 | } | ||
| 578 | } | 588 | } |
| 579 | 589 | ||
| 580 | void ConfigureInputPlayer::TryConnectSelectedController() { | 590 | void ConfigureInputPlayer::TryConnectSelectedController() { |
diff --git a/src/yuzu/configuration/configure_motion_touch.cpp b/src/yuzu/configuration/configure_motion_touch.cpp index caaa85930..1f2b792e4 100644 --- a/src/yuzu/configuration/configure_motion_touch.cpp +++ b/src/yuzu/configuration/configure_motion_touch.cpp | |||
| @@ -81,19 +81,11 @@ void CalibrationConfigurationDialog::UpdateButtonText(const QString& text) { | |||
| 81 | cancel_button->setText(text); | 81 | cancel_button->setText(text); |
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | constexpr std::array<std::pair<const char*, const char*>, 2> TouchProviders = {{ | ||
| 85 | {"emu_window", QT_TRANSLATE_NOOP("ConfigureMotionTouch", "Emulator Window")}, | ||
| 86 | {"cemuhookudp", QT_TRANSLATE_NOOP("ConfigureMotionTouch", "CemuhookUDP")}, | ||
| 87 | }}; | ||
| 88 | |||
| 89 | ConfigureMotionTouch::ConfigureMotionTouch(QWidget* parent, | 84 | ConfigureMotionTouch::ConfigureMotionTouch(QWidget* parent, |
| 90 | InputCommon::InputSubsystem* input_subsystem_) | 85 | InputCommon::InputSubsystem* input_subsystem_) |
| 91 | : QDialog(parent), input_subsystem{input_subsystem_}, | 86 | : QDialog(parent), input_subsystem{input_subsystem_}, |
| 92 | ui(std::make_unique<Ui::ConfigureMotionTouch>()) { | 87 | ui(std::make_unique<Ui::ConfigureMotionTouch>()) { |
| 93 | ui->setupUi(this); | 88 | ui->setupUi(this); |
| 94 | for (const auto& [provider, name] : TouchProviders) { | ||
| 95 | ui->touch_provider->addItem(tr(name), QString::fromUtf8(provider)); | ||
| 96 | } | ||
| 97 | 89 | ||
| 98 | ui->udp_learn_more->setOpenExternalLinks(true); | 90 | ui->udp_learn_more->setOpenExternalLinks(true); |
| 99 | ui->udp_learn_more->setText( | 91 | ui->udp_learn_more->setText( |
| @@ -112,10 +104,7 @@ ConfigureMotionTouch::~ConfigureMotionTouch() = default; | |||
| 112 | void ConfigureMotionTouch::SetConfiguration() { | 104 | void ConfigureMotionTouch::SetConfiguration() { |
| 113 | const Common::ParamPackage motion_param(Settings::values.motion_device); | 105 | const Common::ParamPackage motion_param(Settings::values.motion_device); |
| 114 | const Common::ParamPackage touch_param(Settings::values.touch_device); | 106 | const Common::ParamPackage touch_param(Settings::values.touch_device); |
| 115 | const std::string touch_engine = touch_param.Get("engine", "emu_window"); | ||
| 116 | 107 | ||
| 117 | ui->touch_provider->setCurrentIndex( | ||
| 118 | ui->touch_provider->findData(QString::fromStdString(touch_engine))); | ||
| 119 | ui->touch_from_button_checkbox->setChecked(Settings::values.use_touch_from_button); | 108 | ui->touch_from_button_checkbox->setChecked(Settings::values.use_touch_from_button); |
| 120 | touch_from_button_maps = Settings::values.touch_from_button_maps; | 109 | touch_from_button_maps = Settings::values.touch_from_button_maps; |
| 121 | for (const auto& touch_map : touch_from_button_maps) { | 110 | for (const auto& touch_map : touch_from_button_maps) { |
| @@ -148,30 +137,21 @@ void ConfigureMotionTouch::SetConfiguration() { | |||
| 148 | } | 137 | } |
| 149 | 138 | ||
| 150 | void ConfigureMotionTouch::UpdateUiDisplay() { | 139 | void ConfigureMotionTouch::UpdateUiDisplay() { |
| 151 | const QString touch_engine = ui->touch_provider->currentData().toString(); | ||
| 152 | const QString cemuhook_udp = QStringLiteral("cemuhookudp"); | 140 | const QString cemuhook_udp = QStringLiteral("cemuhookudp"); |
| 153 | 141 | ||
| 154 | ui->motion_sensitivity_label->setVisible(true); | 142 | ui->motion_sensitivity_label->setVisible(true); |
| 155 | ui->motion_sensitivity->setVisible(true); | 143 | ui->motion_sensitivity->setVisible(true); |
| 156 | 144 | ||
| 157 | if (touch_engine == cemuhook_udp) { | 145 | ui->touch_calibration->setVisible(true); |
| 158 | ui->touch_calibration->setVisible(true); | 146 | ui->touch_calibration_config->setVisible(true); |
| 159 | ui->touch_calibration_config->setVisible(true); | 147 | ui->touch_calibration_label->setVisible(true); |
| 160 | ui->touch_calibration_label->setVisible(true); | 148 | ui->touch_calibration->setText( |
| 161 | ui->touch_calibration->setText( | 149 | QStringLiteral("(%1, %2) - (%3, %4)").arg(min_x).arg(min_y).arg(max_x).arg(max_y)); |
| 162 | QStringLiteral("(%1, %2) - (%3, %4)").arg(min_x).arg(min_y).arg(max_x).arg(max_y)); | ||
| 163 | } else { | ||
| 164 | ui->touch_calibration->setVisible(false); | ||
| 165 | ui->touch_calibration_config->setVisible(false); | ||
| 166 | ui->touch_calibration_label->setVisible(false); | ||
| 167 | } | ||
| 168 | 150 | ||
| 169 | ui->udp_config_group_box->setVisible(true); | 151 | ui->udp_config_group_box->setVisible(true); |
| 170 | } | 152 | } |
| 171 | 153 | ||
| 172 | void ConfigureMotionTouch::ConnectEvents() { | 154 | void ConfigureMotionTouch::ConnectEvents() { |
| 173 | connect(ui->touch_provider, qOverload<int>(&QComboBox::currentIndexChanged), this, | ||
| 174 | [this](int index) { UpdateUiDisplay(); }); | ||
| 175 | connect(ui->udp_test, &QPushButton::clicked, this, &ConfigureMotionTouch::OnCemuhookUDPTest); | 155 | connect(ui->udp_test, &QPushButton::clicked, this, &ConfigureMotionTouch::OnCemuhookUDPTest); |
| 176 | connect(ui->udp_add, &QPushButton::clicked, this, &ConfigureMotionTouch::OnUDPAddServer); | 156 | connect(ui->udp_add, &QPushButton::clicked, this, &ConfigureMotionTouch::OnUDPAddServer); |
| 177 | connect(ui->udp_remove, &QPushButton::clicked, this, &ConfigureMotionTouch::OnUDPDeleteServer); | 157 | connect(ui->udp_remove, &QPushButton::clicked, this, &ConfigureMotionTouch::OnUDPDeleteServer); |
| @@ -327,16 +307,11 @@ void ConfigureMotionTouch::ApplyConfiguration() { | |||
| 327 | return; | 307 | return; |
| 328 | } | 308 | } |
| 329 | 309 | ||
| 330 | std::string touch_engine = ui->touch_provider->currentData().toString().toStdString(); | ||
| 331 | |||
| 332 | Common::ParamPackage touch_param{}; | 310 | Common::ParamPackage touch_param{}; |
| 333 | if (touch_engine == "cemuhookudp") { | 311 | touch_param.Set("min_x", min_x); |
| 334 | touch_param.Set("min_x", min_x); | 312 | touch_param.Set("min_y", min_y); |
| 335 | touch_param.Set("min_y", min_y); | 313 | touch_param.Set("max_x", max_x); |
| 336 | touch_param.Set("max_x", max_x); | 314 | touch_param.Set("max_y", max_y); |
| 337 | touch_param.Set("max_y", max_y); | ||
| 338 | } | ||
| 339 | touch_param.Set("engine", std::move(touch_engine)); | ||
| 340 | 315 | ||
| 341 | Settings::values.touch_device = touch_param.Serialize(); | 316 | Settings::values.touch_device = touch_param.Serialize(); |
| 342 | Settings::values.use_touch_from_button = ui->touch_from_button_checkbox->isChecked(); | 317 | Settings::values.use_touch_from_button = ui->touch_from_button_checkbox->isChecked(); |
diff --git a/src/yuzu/configuration/configure_motion_touch.ui b/src/yuzu/configuration/configure_motion_touch.ui index ebca835ac..1e35ea946 100644 --- a/src/yuzu/configuration/configure_motion_touch.ui +++ b/src/yuzu/configuration/configure_motion_touch.ui | |||
| @@ -68,23 +68,9 @@ | |||
| 68 | <item> | 68 | <item> |
| 69 | <layout class="QHBoxLayout"> | 69 | <layout class="QHBoxLayout"> |
| 70 | <item> | 70 | <item> |
| 71 | <widget class="QLabel" name="touch_provider_label"> | ||
| 72 | <property name="text"> | ||
| 73 | <string>Touch Provider:</string> | ||
| 74 | </property> | ||
| 75 | </widget> | ||
| 76 | </item> | ||
| 77 | <item> | ||
| 78 | <widget class="QComboBox" name="touch_provider"/> | ||
| 79 | </item> | ||
| 80 | </layout> | ||
| 81 | </item> | ||
| 82 | <item> | ||
| 83 | <layout class="QHBoxLayout"> | ||
| 84 | <item> | ||
| 85 | <widget class="QLabel" name="touch_calibration_label"> | 71 | <widget class="QLabel" name="touch_calibration_label"> |
| 86 | <property name="text"> | 72 | <property name="text"> |
| 87 | <string>Calibration:</string> | 73 | <string>UDP Calibration:</string> |
| 88 | </property> | 74 | </property> |
| 89 | </widget> | 75 | </widget> |
| 90 | </item> | 76 | </item> |
diff --git a/src/yuzu/configuration/configure_service.cpp b/src/yuzu/configuration/configure_service.cpp index 0de7a4f0b..b580cfff2 100644 --- a/src/yuzu/configuration/configure_service.cpp +++ b/src/yuzu/configuration/configure_service.cpp | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | #include "ui_configure_service.h" | 9 | #include "ui_configure_service.h" |
| 10 | #include "yuzu/configuration/configure_service.h" | 10 | #include "yuzu/configuration/configure_service.h" |
| 11 | 11 | ||
| 12 | #ifdef YUZU_ENABLE_BOXCAT | ||
| 12 | namespace { | 13 | namespace { |
| 13 | QString FormatEventStatusString(const Service::BCAT::EventStatus& status) { | 14 | QString FormatEventStatusString(const Service::BCAT::EventStatus& status) { |
| 14 | QString out; | 15 | QString out; |
| @@ -32,6 +33,7 @@ QString FormatEventStatusString(const Service::BCAT::EventStatus& status) { | |||
| 32 | return out; | 33 | return out; |
| 33 | } | 34 | } |
| 34 | } // Anonymous namespace | 35 | } // Anonymous namespace |
| 36 | #endif | ||
| 35 | 37 | ||
| 36 | ConfigureService::ConfigureService(QWidget* parent) | 38 | ConfigureService::ConfigureService(QWidget* parent) |
| 37 | : QWidget(parent), ui(std::make_unique<Ui::ConfigureService>()) { | 39 | : QWidget(parent), ui(std::make_unique<Ui::ConfigureService>()) { |
diff --git a/src/yuzu/configuration/configure_touchscreen_advanced.cpp b/src/yuzu/configuration/configure_touchscreen_advanced.cpp index 7d7cc00b7..29c86c7bc 100644 --- a/src/yuzu/configuration/configure_touchscreen_advanced.cpp +++ b/src/yuzu/configuration/configure_touchscreen_advanced.cpp | |||
| @@ -33,21 +33,18 @@ void ConfigureTouchscreenAdvanced::RetranslateUI() { | |||
| 33 | } | 33 | } |
| 34 | 34 | ||
| 35 | void ConfigureTouchscreenAdvanced::ApplyConfiguration() { | 35 | void ConfigureTouchscreenAdvanced::ApplyConfiguration() { |
| 36 | Settings::values.touchscreen.finger = ui->finger_box->value(); | ||
| 37 | Settings::values.touchscreen.diameter_x = ui->diameter_x_box->value(); | 36 | Settings::values.touchscreen.diameter_x = ui->diameter_x_box->value(); |
| 38 | Settings::values.touchscreen.diameter_y = ui->diameter_y_box->value(); | 37 | Settings::values.touchscreen.diameter_y = ui->diameter_y_box->value(); |
| 39 | Settings::values.touchscreen.rotation_angle = ui->angle_box->value(); | 38 | Settings::values.touchscreen.rotation_angle = ui->angle_box->value(); |
| 40 | } | 39 | } |
| 41 | 40 | ||
| 42 | void ConfigureTouchscreenAdvanced::LoadConfiguration() { | 41 | void ConfigureTouchscreenAdvanced::LoadConfiguration() { |
| 43 | ui->finger_box->setValue(Settings::values.touchscreen.finger); | ||
| 44 | ui->diameter_x_box->setValue(Settings::values.touchscreen.diameter_x); | 42 | ui->diameter_x_box->setValue(Settings::values.touchscreen.diameter_x); |
| 45 | ui->diameter_y_box->setValue(Settings::values.touchscreen.diameter_y); | 43 | ui->diameter_y_box->setValue(Settings::values.touchscreen.diameter_y); |
| 46 | ui->angle_box->setValue(Settings::values.touchscreen.rotation_angle); | 44 | ui->angle_box->setValue(Settings::values.touchscreen.rotation_angle); |
| 47 | } | 45 | } |
| 48 | 46 | ||
| 49 | void ConfigureTouchscreenAdvanced::RestoreDefaults() { | 47 | void ConfigureTouchscreenAdvanced::RestoreDefaults() { |
| 50 | ui->finger_box->setValue(0); | ||
| 51 | ui->diameter_x_box->setValue(15); | 48 | ui->diameter_x_box->setValue(15); |
| 52 | ui->diameter_y_box->setValue(15); | 49 | ui->diameter_y_box->setValue(15); |
| 53 | ui->angle_box->setValue(0); | 50 | ui->angle_box->setValue(0); |
diff --git a/src/yuzu/configuration/configure_touchscreen_advanced.ui b/src/yuzu/configuration/configure_touchscreen_advanced.ui index 30ceccddb..88e7cf050 100644 --- a/src/yuzu/configuration/configure_touchscreen_advanced.ui +++ b/src/yuzu/configuration/configure_touchscreen_advanced.ui | |||
| @@ -65,20 +65,13 @@ | |||
| 65 | </property> | 65 | </property> |
| 66 | </spacer> | 66 | </spacer> |
| 67 | </item> | 67 | </item> |
| 68 | <item row="2" column="1"> | 68 | <item row="1" column="1"> |
| 69 | <widget class="QLabel" name="label_4"> | 69 | <widget class="QLabel" name="label_4"> |
| 70 | <property name="text"> | 70 | <property name="text"> |
| 71 | <string>Touch Diameter Y</string> | 71 | <string>Touch Diameter Y</string> |
| 72 | </property> | 72 | </property> |
| 73 | </widget> | 73 | </widget> |
| 74 | </item> | 74 | </item> |
| 75 | <item row="0" column="1"> | ||
| 76 | <widget class="QLabel" name="label"> | ||
| 77 | <property name="text"> | ||
| 78 | <string>Finger</string> | ||
| 79 | </property> | ||
| 80 | </widget> | ||
| 81 | </item> | ||
| 82 | <item row="0" column="3"> | 75 | <item row="0" column="3"> |
| 83 | <spacer name="horizontalSpacer_2"> | 76 | <spacer name="horizontalSpacer_2"> |
| 84 | <property name="orientation"> | 77 | <property name="orientation"> |
| @@ -92,37 +85,27 @@ | |||
| 92 | </property> | 85 | </property> |
| 93 | </spacer> | 86 | </spacer> |
| 94 | </item> | 87 | </item> |
| 95 | <item row="1" column="1"> | 88 | <item row="0" column="1"> |
| 96 | <widget class="QLabel" name="label_3"> | 89 | <widget class="QLabel" name="label_3"> |
| 97 | <property name="text"> | 90 | <property name="text"> |
| 98 | <string>Touch Diameter X</string> | 91 | <string>Touch Diameter X</string> |
| 99 | </property> | 92 | </property> |
| 100 | </widget> | 93 | </widget> |
| 101 | </item> | 94 | </item> |
| 102 | <item row="0" column="2"> | 95 | <item row="2" column="1"> |
| 103 | <widget class="QSpinBox" name="finger_box"> | ||
| 104 | <property name="minimumSize"> | ||
| 105 | <size> | ||
| 106 | <width>80</width> | ||
| 107 | <height>0</height> | ||
| 108 | </size> | ||
| 109 | </property> | ||
| 110 | </widget> | ||
| 111 | </item> | ||
| 112 | <item row="3" column="1"> | ||
| 113 | <widget class="QLabel" name="label_5"> | 96 | <widget class="QLabel" name="label_5"> |
| 114 | <property name="text"> | 97 | <property name="text"> |
| 115 | <string>Rotational Angle</string> | 98 | <string>Rotational Angle</string> |
| 116 | </property> | 99 | </property> |
| 117 | </widget> | 100 | </widget> |
| 118 | </item> | 101 | </item> |
| 119 | <item row="1" column="2"> | 102 | <item row="0" column="2"> |
| 120 | <widget class="QSpinBox" name="diameter_x_box"/> | 103 | <widget class="QSpinBox" name="diameter_x_box"/> |
| 121 | </item> | 104 | </item> |
| 122 | <item row="2" column="2"> | 105 | <item row="1" column="2"> |
| 123 | <widget class="QSpinBox" name="diameter_y_box"/> | 106 | <widget class="QSpinBox" name="diameter_y_box"/> |
| 124 | </item> | 107 | </item> |
| 125 | <item row="3" column="2"> | 108 | <item row="2" column="2"> |
| 126 | <widget class="QSpinBox" name="angle_box"/> | 109 | <widget class="QSpinBox" name="angle_box"/> |
| 127 | </item> | 110 | </item> |
| 128 | </layout> | 111 | </layout> |
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp index 37b0d1a0e..9afd5b45f 100644 --- a/src/yuzu/game_list.cpp +++ b/src/yuzu/game_list.cpp | |||
| @@ -173,8 +173,8 @@ void GameList::OnItemExpanded(const QModelIndex& item) { | |||
| 173 | return; | 173 | return; |
| 174 | } | 174 | } |
| 175 | 175 | ||
| 176 | auto* game_dir = item.data(GameListDir::GameDirRole).value<UISettings::GameDir*>(); | 176 | UISettings::values.game_dirs[item.data(GameListDir::GameDirRole).toInt()].expanded = |
| 177 | game_dir->expanded = tree_view->isExpanded(item); | 177 | tree_view->isExpanded(item); |
| 178 | } | 178 | } |
| 179 | 179 | ||
| 180 | // Event in order to filter the gamelist after editing the searchfield | 180 | // Event in order to filter the gamelist after editing the searchfield |
| @@ -262,9 +262,9 @@ void GameList::OnUpdateThemedIcons() { | |||
| 262 | Qt::DecorationRole); | 262 | Qt::DecorationRole); |
| 263 | break; | 263 | break; |
| 264 | case GameListItemType::CustomDir: { | 264 | case GameListItemType::CustomDir: { |
| 265 | const UISettings::GameDir* game_dir = | 265 | const UISettings::GameDir& game_dir = |
| 266 | child->data(GameListDir::GameDirRole).value<UISettings::GameDir*>(); | 266 | UISettings::values.game_dirs[child->data(GameListDir::GameDirRole).toInt()]; |
| 267 | const QString icon_name = QFileInfo::exists(game_dir->path) | 267 | const QString icon_name = QFileInfo::exists(game_dir.path) |
| 268 | ? QStringLiteral("folder") | 268 | ? QStringLiteral("folder") |
| 269 | : QStringLiteral("bad_folder"); | 269 | : QStringLiteral("bad_folder"); |
| 270 | child->setData( | 270 | child->setData( |
| @@ -366,7 +366,7 @@ void GameList::AddDirEntry(GameListDir* entry_items) { | |||
| 366 | item_model->invisibleRootItem()->appendRow(entry_items); | 366 | item_model->invisibleRootItem()->appendRow(entry_items); |
| 367 | tree_view->setExpanded( | 367 | tree_view->setExpanded( |
| 368 | entry_items->index(), | 368 | entry_items->index(), |
| 369 | entry_items->data(GameListDir::GameDirRole).value<UISettings::GameDir*>()->expanded); | 369 | UISettings::values.game_dirs[entry_items->data(GameListDir::GameDirRole).toInt()].expanded); |
| 370 | } | 370 | } |
| 371 | 371 | ||
| 372 | void GameList::AddEntry(const QList<QStandardItem*>& entry_items, GameListDir* parent) { | 372 | void GameList::AddEntry(const QList<QStandardItem*>& entry_items, GameListDir* parent) { |
| @@ -549,7 +549,7 @@ void GameList::AddGamePopup(QMenu& context_menu, u64 program_id, const std::stri | |||
| 549 | 549 | ||
| 550 | void GameList::AddCustomDirPopup(QMenu& context_menu, QModelIndex selected) { | 550 | void GameList::AddCustomDirPopup(QMenu& context_menu, QModelIndex selected) { |
| 551 | UISettings::GameDir& game_dir = | 551 | UISettings::GameDir& game_dir = |
| 552 | *selected.data(GameListDir::GameDirRole).value<UISettings::GameDir*>(); | 552 | UISettings::values.game_dirs[selected.data(GameListDir::GameDirRole).toInt()]; |
| 553 | 553 | ||
| 554 | QAction* deep_scan = context_menu.addAction(tr("Scan Subfolders")); | 554 | QAction* deep_scan = context_menu.addAction(tr("Scan Subfolders")); |
| 555 | QAction* delete_dir = context_menu.addAction(tr("Remove Game Directory")); | 555 | QAction* delete_dir = context_menu.addAction(tr("Remove Game Directory")); |
| @@ -568,8 +568,7 @@ void GameList::AddCustomDirPopup(QMenu& context_menu, QModelIndex selected) { | |||
| 568 | } | 568 | } |
| 569 | 569 | ||
| 570 | void GameList::AddPermDirPopup(QMenu& context_menu, QModelIndex selected) { | 570 | void GameList::AddPermDirPopup(QMenu& context_menu, QModelIndex selected) { |
| 571 | UISettings::GameDir& game_dir = | 571 | const int game_dir_index = selected.data(GameListDir::GameDirRole).toInt(); |
| 572 | *selected.data(GameListDir::GameDirRole).value<UISettings::GameDir*>(); | ||
| 573 | 572 | ||
| 574 | QAction* move_up = context_menu.addAction(tr("\u25B2 Move Up")); | 573 | QAction* move_up = context_menu.addAction(tr("\u25B2 Move Up")); |
| 575 | QAction* move_down = context_menu.addAction(tr("\u25bc Move Down")); | 574 | QAction* move_down = context_menu.addAction(tr("\u25bc Move Down")); |
| @@ -580,34 +579,39 @@ void GameList::AddPermDirPopup(QMenu& context_menu, QModelIndex selected) { | |||
| 580 | move_up->setEnabled(row > 0); | 579 | move_up->setEnabled(row > 0); |
| 581 | move_down->setEnabled(row < item_model->rowCount() - 2); | 580 | move_down->setEnabled(row < item_model->rowCount() - 2); |
| 582 | 581 | ||
| 583 | connect(move_up, &QAction::triggered, [this, selected, row, &game_dir] { | 582 | connect(move_up, &QAction::triggered, [this, selected, row, game_dir_index] { |
| 584 | // find the indices of the items in settings and swap them | 583 | const int other_index = selected.sibling(row - 1, 0).data(GameListDir::GameDirRole).toInt(); |
| 585 | std::swap(UISettings::values.game_dirs[UISettings::values.game_dirs.indexOf(game_dir)], | 584 | // swap the items in the settings |
| 586 | UISettings::values.game_dirs[UISettings::values.game_dirs.indexOf( | 585 | std::swap(UISettings::values.game_dirs[game_dir_index], |
| 587 | *selected.sibling(row - 1, 0) | 586 | UISettings::values.game_dirs[other_index]); |
| 588 | .data(GameListDir::GameDirRole) | 587 | // swap the indexes held by the QVariants |
| 589 | .value<UISettings::GameDir*>())]); | 588 | item_model->setData(selected, QVariant(other_index), GameListDir::GameDirRole); |
| 589 | item_model->setData(selected.sibling(row - 1, 0), QVariant(game_dir_index), | ||
| 590 | GameListDir::GameDirRole); | ||
| 590 | // move the treeview items | 591 | // move the treeview items |
| 591 | QList<QStandardItem*> item = item_model->takeRow(row); | 592 | QList<QStandardItem*> item = item_model->takeRow(row); |
| 592 | item_model->invisibleRootItem()->insertRow(row - 1, item); | 593 | item_model->invisibleRootItem()->insertRow(row - 1, item); |
| 593 | tree_view->setExpanded(selected, game_dir.expanded); | 594 | tree_view->setExpanded(selected, UISettings::values.game_dirs[game_dir_index].expanded); |
| 594 | }); | 595 | }); |
| 595 | 596 | ||
| 596 | connect(move_down, &QAction::triggered, [this, selected, row, &game_dir] { | 597 | connect(move_down, &QAction::triggered, [this, selected, row, game_dir_index] { |
| 597 | // find the indices of the items in settings and swap them | 598 | const int other_index = selected.sibling(row + 1, 0).data(GameListDir::GameDirRole).toInt(); |
| 598 | std::swap(UISettings::values.game_dirs[UISettings::values.game_dirs.indexOf(game_dir)], | 599 | // swap the items in the settings |
| 599 | UISettings::values.game_dirs[UISettings::values.game_dirs.indexOf( | 600 | std::swap(UISettings::values.game_dirs[game_dir_index], |
| 600 | *selected.sibling(row + 1, 0) | 601 | UISettings::values.game_dirs[other_index]); |
| 601 | .data(GameListDir::GameDirRole) | 602 | // swap the indexes held by the QVariants |
| 602 | .value<UISettings::GameDir*>())]); | 603 | item_model->setData(selected, QVariant(other_index), GameListDir::GameDirRole); |
| 604 | item_model->setData(selected.sibling(row + 1, 0), QVariant(game_dir_index), | ||
| 605 | GameListDir::GameDirRole); | ||
| 603 | // move the treeview items | 606 | // move the treeview items |
| 604 | const QList<QStandardItem*> item = item_model->takeRow(row); | 607 | const QList<QStandardItem*> item = item_model->takeRow(row); |
| 605 | item_model->invisibleRootItem()->insertRow(row + 1, item); | 608 | item_model->invisibleRootItem()->insertRow(row + 1, item); |
| 606 | tree_view->setExpanded(selected, game_dir.expanded); | 609 | tree_view->setExpanded(selected, UISettings::values.game_dirs[game_dir_index].expanded); |
| 607 | }); | 610 | }); |
| 608 | 611 | ||
| 609 | connect(open_directory_location, &QAction::triggered, | 612 | connect(open_directory_location, &QAction::triggered, [this, game_dir_index] { |
| 610 | [this, game_dir] { emit OpenDirectory(game_dir.path); }); | 613 | emit OpenDirectory(UISettings::values.game_dirs[game_dir_index].path); |
| 614 | }); | ||
| 611 | } | 615 | } |
| 612 | 616 | ||
| 613 | void GameList::LoadCompatibilityList() { | 617 | void GameList::LoadCompatibilityList() { |
diff --git a/src/yuzu/game_list_p.h b/src/yuzu/game_list_p.h index df935022d..f25445f18 100644 --- a/src/yuzu/game_list_p.h +++ b/src/yuzu/game_list_p.h | |||
| @@ -230,7 +230,7 @@ public: | |||
| 230 | setData(type(), TypeRole); | 230 | setData(type(), TypeRole); |
| 231 | 231 | ||
| 232 | UISettings::GameDir* game_dir = &directory; | 232 | UISettings::GameDir* game_dir = &directory; |
| 233 | setData(QVariant::fromValue(game_dir), GameDirRole); | 233 | setData(QVariant(UISettings::values.game_dirs.indexOf(directory)), GameDirRole); |
| 234 | 234 | ||
| 235 | const int icon_size = std::min(static_cast<int>(UISettings::values.icon_size), 64); | 235 | const int icon_size = std::min(static_cast<int>(UISettings::values.icon_size), 64); |
| 236 | switch (dir_type) { | 236 | switch (dir_type) { |
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index 41ef6f6b8..f76102459 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp | |||
| @@ -296,10 +296,6 @@ void Config::ReadValues() { | |||
| 296 | sdl2_config->GetBoolean("ControlsGeneral", "motion_enabled", true)); | 296 | sdl2_config->GetBoolean("ControlsGeneral", "motion_enabled", true)); |
| 297 | Settings::values.touchscreen.enabled = | 297 | Settings::values.touchscreen.enabled = |
| 298 | sdl2_config->GetBoolean("ControlsGeneral", "touch_enabled", true); | 298 | sdl2_config->GetBoolean("ControlsGeneral", "touch_enabled", true); |
| 299 | Settings::values.touchscreen.device = | ||
| 300 | sdl2_config->Get("ControlsGeneral", "touch_device", "engine:emu_window"); | ||
| 301 | Settings::values.touchscreen.finger = | ||
| 302 | sdl2_config->GetInteger("ControlsGeneral", "touch_finger", 0); | ||
| 303 | Settings::values.touchscreen.rotation_angle = | 299 | Settings::values.touchscreen.rotation_angle = |
| 304 | sdl2_config->GetInteger("ControlsGeneral", "touch_angle", 0); | 300 | sdl2_config->GetInteger("ControlsGeneral", "touch_angle", 0); |
| 305 | Settings::values.touchscreen.diameter_x = | 301 | Settings::values.touchscreen.diameter_x = |
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp index e32bed5e6..7843d5167 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp | |||
| @@ -29,16 +29,16 @@ EmuWindow_SDL2::~EmuWindow_SDL2() { | |||
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) { | 31 | void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) { |
| 32 | TouchMoved((unsigned)std::max(x, 0), (unsigned)std::max(y, 0)); | 32 | TouchMoved((unsigned)std::max(x, 0), (unsigned)std::max(y, 0), 0); |
| 33 | input_subsystem->GetMouse()->MouseMove(x, y); | 33 | input_subsystem->GetMouse()->MouseMove(x, y); |
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) { | 36 | void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) { |
| 37 | if (button == SDL_BUTTON_LEFT) { | 37 | if (button == SDL_BUTTON_LEFT) { |
| 38 | if (state == SDL_PRESSED) { | 38 | if (state == SDL_PRESSED) { |
| 39 | TouchPressed((unsigned)std::max(x, 0), (unsigned)std::max(y, 0)); | 39 | TouchPressed((unsigned)std::max(x, 0), (unsigned)std::max(y, 0), 0); |
| 40 | } else { | 40 | } else { |
| 41 | TouchReleased(); | 41 | TouchReleased(0); |
| 42 | } | 42 | } |
| 43 | } else if (button == SDL_BUTTON_RIGHT) { | 43 | } else if (button == SDL_BUTTON_RIGHT) { |
| 44 | if (state == SDL_PRESSED) { | 44 | if (state == SDL_PRESSED) { |
| @@ -66,16 +66,16 @@ void EmuWindow_SDL2::OnFingerDown(float x, float y) { | |||
| 66 | // 3DS does | 66 | // 3DS does |
| 67 | 67 | ||
| 68 | const auto [px, py] = TouchToPixelPos(x, y); | 68 | const auto [px, py] = TouchToPixelPos(x, y); |
| 69 | TouchPressed(px, py); | 69 | TouchPressed(px, py, 0); |
| 70 | } | 70 | } |
| 71 | 71 | ||
| 72 | void EmuWindow_SDL2::OnFingerMotion(float x, float y) { | 72 | void EmuWindow_SDL2::OnFingerMotion(float x, float y) { |
| 73 | const auto [px, py] = TouchToPixelPos(x, y); | 73 | const auto [px, py] = TouchToPixelPos(x, y); |
| 74 | TouchMoved(px, py); | 74 | TouchMoved(px, py, 0); |
| 75 | } | 75 | } |
| 76 | 76 | ||
| 77 | void EmuWindow_SDL2::OnFingerUp() { | 77 | void EmuWindow_SDL2::OnFingerUp() { |
| 78 | TouchReleased(); | 78 | TouchReleased(0); |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | void EmuWindow_SDL2::OnKeyEvent(int key, u8 state) { | 81 | void EmuWindow_SDL2::OnKeyEvent(int key, u8 state) { |