diff options
-rw-r--r-- | src/core/settings.h | 5 | ||||
-rw-r--r-- | src/input_common/mouse/mouse_input.cpp | 32 | ||||
-rw-r--r-- | src/input_common/mouse/mouse_input.h | 7 | ||||
-rw-r--r-- | src/input_common/mouse/mouse_poller.cpp | 3 | ||||
-rw-r--r-- | src/yuzu/bootmanager.cpp | 14 | ||||
-rw-r--r-- | src/yuzu/configuration/config.cpp | 10 | ||||
-rw-r--r-- | src/yuzu/configuration/config.h | 2 | ||||
-rw-r--r-- | src/yuzu/configuration/configure_input_advanced.cpp | 5 | ||||
-rw-r--r-- | src/yuzu/configuration/configure_input_advanced.ui | 82 | ||||
-rw-r--r-- | src/yuzu/main.cpp | 24 | ||||
-rw-r--r-- | src/yuzu_cmd/emu_window/emu_window_sdl2.cpp | 3 |
11 files changed, 149 insertions, 38 deletions
diff --git a/src/core/settings.h b/src/core/settings.h index a324530bd..d849dded3 100644 --- a/src/core/settings.h +++ b/src/core/settings.h @@ -181,12 +181,13 @@ struct Values { std::string motion_device; std::string udp_input_servers; - bool emulate_analog_keyboard; - + bool mouse_panning; + float mouse_panning_sensitivity; bool mouse_enabled; std::string mouse_device; MouseButtonsRaw mouse_buttons; + bool emulate_analog_keyboard; bool keyboard_enabled; KeyboardKeysRaw keyboard_keys; KeyboardModsRaw keyboard_mods; diff --git a/src/input_common/mouse/mouse_input.cpp b/src/input_common/mouse/mouse_input.cpp index 10786a541..67a584d53 100644 --- a/src/input_common/mouse/mouse_input.cpp +++ b/src/input_common/mouse/mouse_input.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2+ // Refer to the license.txt file included. +#include "core/settings.h" #include "input_common/mouse/mouse_input.h" namespace MouseInput { @@ -36,6 +37,9 @@ void Mouse::UpdateThread() { if (configuring) { UpdateYuzuSettings(); } + if (mouse_panning_timout++ > 8) { + StopPanning(); + } std::this_thread::sleep_for(std::chrono::milliseconds(update_time)); } } @@ -65,8 +69,34 @@ void Mouse::PressButton(int x, int y, int button_) { mouse_info[button_index].data.pressed = true; } -void Mouse::MouseMove(int x, int y) { +void Mouse::StopPanning() { + for (MouseInfo& info : mouse_info) { + if (Settings::values.mouse_panning) { + info.data.axis = {}; + info.tilt_speed = 0; + info.last_mouse_change = {}; + } + } +} + +void Mouse::MouseMove(int x, int y, int center_x, int center_y) { for (MouseInfo& info : mouse_info) { + if (Settings::values.mouse_panning) { + const auto mouse_change = Common::MakeVec(x, y) - Common::MakeVec(center_x, center_y); + mouse_panning_timout = 0; + + if (mouse_change.y == 0 && mouse_change.x == 0) { + continue; + } + + info.last_mouse_change = (info.last_mouse_change * 0.8f) + (mouse_change * 0.2f); + info.data.axis = {static_cast<int>(16 * info.last_mouse_change.x), + static_cast<int>(16 * -info.last_mouse_change.y)}; + info.tilt_direction = info.last_mouse_change; + info.tilt_speed = info.tilt_direction.Normalize() * info.sensitivity; + continue; + } + if (info.data.pressed) { const auto mouse_move = Common::MakeVec(x, y) - info.mouse_origin; const auto mouse_change = Common::MakeVec(x, y) - info.last_mouse_position; diff --git a/src/input_common/mouse/mouse_input.h b/src/input_common/mouse/mouse_input.h index 58803c1bf..46aa676c1 100644 --- a/src/input_common/mouse/mouse_input.h +++ b/src/input_common/mouse/mouse_input.h @@ -57,8 +57,10 @@ public: * Signals that mouse has moved. * @param x the x-coordinate of the cursor * @param y the y-coordinate of the cursor + * @param center_x the x-coordinate of the middle of the screen + * @param center_y the y-coordinate of the middle of the screen */ - void MouseMove(int x, int y); + void MouseMove(int x, int y, int center_x, int center_y); /** * Signals that a motion sensor tilt has ended. @@ -74,11 +76,13 @@ public: private: void UpdateThread(); void UpdateYuzuSettings(); + void StopPanning(); struct MouseInfo { InputCommon::MotionInput motion{0.0f, 0.0f, 0.0f}; Common::Vec2<int> mouse_origin; Common::Vec2<int> last_mouse_position; + Common::Vec2<float> last_mouse_change; bool is_tilting = false; float sensitivity{0.120f}; @@ -94,5 +98,6 @@ private: Common::SPSCQueue<MouseStatus> mouse_queue; bool configuring{false}; bool update_thread_running{true}; + int mouse_panning_timout{}; }; } // namespace MouseInput diff --git a/src/input_common/mouse/mouse_poller.cpp b/src/input_common/mouse/mouse_poller.cpp index 3d799b293..bb56787ee 100644 --- a/src/input_common/mouse/mouse_poller.cpp +++ b/src/input_common/mouse/mouse_poller.cpp @@ -6,6 +6,7 @@ #include <utility> #include "common/threadsafe_queue.h" +#include "core/settings.h" #include "input_common/mouse/mouse_input.h" #include "input_common/mouse/mouse_poller.h" @@ -71,7 +72,7 @@ public: std::lock_guard lock{mutex}; const auto axis_value = static_cast<float>(mouse_input->GetMouseState(button).axis.at(axis)); - return axis_value / (100.0f * range); + return axis_value * Settings::values.mouse_panning_sensitivity / (100.0f * range); } std::pair<float, float> GetAnalog(u32 analog_axis_x, u32 analog_axis_y) const { diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index ffdf34a4a..d9a3035cb 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -405,12 +405,17 @@ void GRenderWindow::mouseMoveEvent(QMouseEvent* event) { if (event->source() == Qt::MouseEventSynthesizedBySystem) { return; } - auto pos = event->pos(); const auto [x, y] = ScaleTouch(pos); - input_subsystem->GetMouse()->MouseMove(x, y); + const int center_x = width() / 2; + const int center_y = height() / 2; + input_subsystem->GetMouse()->MouseMove(x, y, center_x, center_y); this->TouchMoved(x, y, 0); + if (Settings::values.mouse_panning) { + QCursor::setPos(mapToGlobal({center_x, center_y})); + } + emit MouseActivity(); } @@ -714,6 +719,11 @@ void GRenderWindow::showEvent(QShowEvent* event) { bool GRenderWindow::eventFilter(QObject* object, QEvent* event) { if (event->type() == QEvent::HoverMove) { + if (Settings::values.mouse_panning) { + auto* hover_event = static_cast<QMouseEvent*>(event); + mouseMoveEvent(hover_event); + return false; + } emit MouseActivity(); } return false; diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 8d85a1986..8f7458119 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -220,7 +220,7 @@ const std::array<int, Settings::NativeKeyboard::NumKeyboardMods> Config::default // This must be in alphabetical order according to action name as it must have the same order as // UISetting::values.shortcuts, which is alphabetically ordered. // clang-format off -const std::array<UISettings::Shortcut, 16> Config::default_hotkeys{{ +const std::array<UISettings::Shortcut, 17> Config::default_hotkeys{{ {QStringLiteral("Capture Screenshot"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+P"), Qt::WidgetWithChildrenShortcut}}, {QStringLiteral("Change Docked Mode"), QStringLiteral("Main Window"), {QStringLiteral("F10"), Qt::ApplicationShortcut}}, {QStringLiteral("Continue/Pause Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F4"), Qt::WindowShortcut}}, @@ -235,6 +235,7 @@ const std::array<UISettings::Shortcut, 16> Config::default_hotkeys{{ {QStringLiteral("Restart Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F6"), Qt::WindowShortcut}}, {QStringLiteral("Stop Emulation"), QStringLiteral("Main Window"), {QStringLiteral("F5"), Qt::WindowShortcut}}, {QStringLiteral("Toggle Filter Bar"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+F"), Qt::WindowShortcut}}, + {QStringLiteral("Toggle Mouse Panning"), QStringLiteral("Main Window"), {QStringLiteral("F9"), Qt::ApplicationShortcut}}, {QStringLiteral("Toggle Speed Limit"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+Z"), Qt::ApplicationShortcut}}, {QStringLiteral("Toggle Status Bar"), QStringLiteral("Main Window"), {QStringLiteral("Ctrl+S"), Qt::WindowShortcut}}, }}; @@ -507,6 +508,9 @@ void Config::ReadControlValues() { Settings::values.emulate_analog_keyboard = ReadSetting(QStringLiteral("emulate_analog_keyboard"), false).toBool(); + Settings::values.mouse_panning = ReadSetting(QStringLiteral("mouse_panning"), false).toBool(); + Settings::values.mouse_panning_sensitivity = + ReadSetting(QStringLiteral("mouse_panning_sensitivity"), 1).toFloat(); ReadSettingGlobal(Settings::values.use_docked_mode, QStringLiteral("use_docked_mode"), true); ReadSettingGlobal(Settings::values.vibration_enabled, QStringLiteral("vibration_enabled"), @@ -1184,7 +1188,9 @@ void Config::SaveControlValues() { WriteSetting(QStringLiteral("keyboard_enabled"), Settings::values.keyboard_enabled, false); WriteSetting(QStringLiteral("emulate_analog_keyboard"), Settings::values.emulate_analog_keyboard, false); - + WriteSetting(QStringLiteral("mouse_panning"), Settings::values.mouse_panning, false); + WriteSetting(QStringLiteral("mouse_panning_sensitivity"), + Settings::values.mouse_panning_sensitivity, 1.0f); qt_config->endGroup(); } diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h index 8a600e19d..949c4eb13 100644 --- a/src/yuzu/configuration/config.h +++ b/src/yuzu/configuration/config.h @@ -42,7 +42,7 @@ public: default_mouse_buttons; static const std::array<int, Settings::NativeKeyboard::NumKeyboardKeys> default_keyboard_keys; static const std::array<int, Settings::NativeKeyboard::NumKeyboardMods> default_keyboard_mods; - static const std::array<UISettings::Shortcut, 16> default_hotkeys; + static const std::array<UISettings::Shortcut, 17> default_hotkeys; private: void Initialize(const std::string& config_name); diff --git a/src/yuzu/configuration/configure_input_advanced.cpp b/src/yuzu/configuration/configure_input_advanced.cpp index 4e557bc6f..a1a0eb676 100644 --- a/src/yuzu/configuration/configure_input_advanced.cpp +++ b/src/yuzu/configuration/configure_input_advanced.cpp @@ -122,6 +122,9 @@ void ConfigureInputAdvanced::ApplyConfiguration() { Settings::values.mouse_enabled = ui->mouse_enabled->isChecked(); Settings::values.keyboard_enabled = ui->keyboard_enabled->isChecked(); Settings::values.emulate_analog_keyboard = ui->emulate_analog_keyboard->isChecked(); + Settings::values.mouse_panning = ui->mouse_panning->isChecked(); + Settings::values.mouse_panning_sensitivity = + static_cast<float>(ui->mouse_panning_sensitivity->value()); Settings::values.touchscreen.enabled = ui->touchscreen_enabled->isChecked(); } @@ -149,6 +152,8 @@ void ConfigureInputAdvanced::LoadConfiguration() { ui->mouse_enabled->setChecked(Settings::values.mouse_enabled); ui->keyboard_enabled->setChecked(Settings::values.keyboard_enabled); ui->emulate_analog_keyboard->setChecked(Settings::values.emulate_analog_keyboard); + ui->mouse_panning->setChecked(Settings::values.mouse_panning); + ui->mouse_panning_sensitivity->setValue(Settings::values.mouse_panning_sensitivity); ui->touchscreen_enabled->setChecked(Settings::values.touchscreen.enabled); UpdateUIEnabled(); diff --git a/src/yuzu/configuration/configure_input_advanced.ui b/src/yuzu/configuration/configure_input_advanced.ui index f207e5d3b..173130d8d 100644 --- a/src/yuzu/configuration/configure_input_advanced.ui +++ b/src/yuzu/configuration/configure_input_advanced.ui @@ -2546,27 +2546,65 @@ </property> </widget> </item> - <item row="1" column="0"> - <widget class="QCheckBox" name="emulate_analog_keyboard"> - <property name="minimumSize"> - <size> - <width>0</width> - <height>23</height> - </size> - </property> - <property name="text"> - <string>Emulate Analog with Keyboard Input</string> - </property> - </widget> - </item> - <item row="5" column="2"> + <item row="1" column="0"> + <widget class="QCheckBox" name="emulate_analog_keyboard"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>23</height> + </size> + </property> + <property name="text"> + <string>Emulate Analog with Keyboard Input</string> + </property> + </widget> + </item> + <item row="2" column="0"> + <widget class="QCheckBox" name="mouse_panning"> + <property name="minimumSize"> + <size> + <width>0</width> + <height>23</height> + </size> + </property> + <property name="text"> + <string>Enable mouse panning</string> + </property> + </widget> + </item> + <item row="2" column="2"> + <widget class="QDoubleSpinBox" name="mouse_panning_sensitivity"> + <property name="toolTip"> + <string>Mouse sensitivity</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + <property name="decimals"> + <number>2</number> + </property> + <property name="minimum"> + <double>0.100000000000000</double> + </property> + <property name="maximum"> + <double>16.000000000000000</double> + </property> + <property name="singleStep"> + <double>0.010000000000000</double> + </property> + <property name="value"> + <double>1.000000000000000</double> + </property> + </widget> + </item> + <item row="6" column="2"> <widget class="QPushButton" name="touchscreen_advanced"> <property name="text"> <string>Advanced</string> </property> </widget> </item> - <item row="2" column="1"> + <item row="3" column="1"> <spacer name="horizontalSpacer_8"> <property name="orientation"> <enum>Qt::Horizontal</enum> @@ -2582,21 +2620,21 @@ </property> </spacer> </item> - <item row="2" column="2"> + <item row="3" column="2"> <widget class="QPushButton" name="mouse_advanced"> <property name="text"> <string>Advanced</string> </property> </widget> </item> - <item row="5" column="0"> + <item row="6" column="0"> <widget class="QCheckBox" name="touchscreen_enabled"> <property name="text"> <string>Touchscreen</string> </property> </widget> </item> - <item row="2" column="0"> + <item row="3" column="0"> <widget class="QCheckBox" name="mouse_enabled"> <property name="minimumSize"> <size> @@ -2609,28 +2647,28 @@ </property> </widget> </item> - <item row="7" column="0"> + <item row="8" column="0"> <widget class="QLabel" name="motion_touch"> <property name="text"> <string>Motion / Touch</string> </property> </widget> </item> - <item row="7" column="2"> + <item row="8" column="2"> <widget class="QPushButton" name="buttonMotionTouch"> <property name="text"> <string>Configure</string> </property> </widget> </item> - <item row="6" column="0"> + <item row="7" column="0"> <widget class="QCheckBox" name="debug_enabled"> <property name="text"> <string>Debug Controller</string> </property> </widget> </item> - <item row="6" column="2"> + <item row="7" column="2"> <widget class="QPushButton" name="debug_configure"> <property name="text"> <string>Configure</string> diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index ef92c25bc..52218eb70 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -850,6 +850,16 @@ void GMainWindow::InitializeHotkeys() { connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Mute Audio"), this), &QShortcut::activated, this, [] { Settings::values.audio_muted = !Settings::values.audio_muted; }); + + connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Toggle Mouse Panning"), this), + &QShortcut::activated, this, [&] { + Settings::values.mouse_panning = !Settings::values.mouse_panning; + if (UISettings::values.hide_mouse || Settings::values.mouse_panning) { + mouse_hide_timer.start(); + render_window->installEventFilter(render_window); + render_window->setAttribute(Qt::WA_Hover, true); + } + }); } void GMainWindow::SetDefaultUIGeometry() { @@ -1197,7 +1207,7 @@ void GMainWindow::BootGame(const QString& filename, std::size_t program_index) { multicore_status_button->setDisabled(true); renderer_status_button->setDisabled(true); - if (UISettings::values.hide_mouse) { + if (UISettings::values.hide_mouse || Settings::values.mouse_panning) { mouse_hide_timer.start(); render_window->installEventFilter(render_window); render_window->setAttribute(Qt::WA_Hover, true); @@ -2359,7 +2369,7 @@ void GMainWindow::OnConfigure() { config->Save(); - if (UISettings::values.hide_mouse && emulation_running) { + if ((UISettings::values.hide_mouse || Settings::values.mouse_panning) && emulation_running) { render_window->installEventFilter(render_window); render_window->setAttribute(Qt::WA_Hover, true); mouse_hide_timer.start(); @@ -2600,7 +2610,8 @@ void GMainWindow::UpdateUISettings() { } void GMainWindow::HideMouseCursor() { - if (emu_thread == nullptr || UISettings::values.hide_mouse == false) { + if (emu_thread == nullptr || + (!UISettings::values.hide_mouse && !Settings::values.mouse_panning)) { mouse_hide_timer.stop(); ShowMouseCursor(); return; @@ -2610,13 +2621,16 @@ void GMainWindow::HideMouseCursor() { void GMainWindow::ShowMouseCursor() { render_window->unsetCursor(); - if (emu_thread != nullptr && UISettings::values.hide_mouse) { + if (emu_thread != nullptr && + (UISettings::values.hide_mouse || Settings::values.mouse_panning)) { mouse_hide_timer.start(); } } void GMainWindow::OnMouseActivity() { - ShowMouseCursor(); + if (!Settings::values.mouse_panning) { + ShowMouseCursor(); + } } void GMainWindow::OnCoreError(Core::System::ResultStatus result, std::string details) { diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp index 7843d5167..39841aa28 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp @@ -30,7 +30,8 @@ EmuWindow_SDL2::~EmuWindow_SDL2() { void EmuWindow_SDL2::OnMouseMotion(s32 x, s32 y) { TouchMoved((unsigned)std::max(x, 0), (unsigned)std::max(y, 0), 0); - input_subsystem->GetMouse()->MouseMove(x, y); + + input_subsystem->GetMouse()->MouseMove(x, y, 0, 0); } void EmuWindow_SDL2::OnMouseButton(u32 button, u8 state, s32 x, s32 y) { |