summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Baptiste Marie2023-05-29 14:51:56 +0200
committerGravatar Baptiste Marie2023-06-12 00:47:52 +0200
commit8e3d4e33961ef7276247ee03ac5c342d4055ac3a (patch)
tree85de5ce092b27c1457471c7ce3c72ec62090cb99 /src
parentMerge pull request #10668 from Kelebek1/reduce_vertex_bindings (diff)
downloadyuzu-8e3d4e33961ef7276247ee03ac5c342d4055ac3a.tar.gz
yuzu-8e3d4e33961ef7276247ee03ac5c342d4055ac3a.tar.xz
yuzu-8e3d4e33961ef7276247ee03ac5c342d4055ac3a.zip
input_common: Redesign mouse panning
Diffstat (limited to 'src')
-rw-r--r--src/common/settings.h11
-rw-r--r--src/input_common/drivers/mouse.cpp99
-rw-r--r--src/input_common/drivers/mouse.h2
-rw-r--r--src/yuzu/CMakeLists.txt3
-rw-r--r--src/yuzu/configuration/config.cpp33
-rw-r--r--src/yuzu/configuration/config.h2
-rw-r--r--src/yuzu/configuration/configure_input_advanced.cpp7
-rw-r--r--src/yuzu/configuration/configure_input_advanced.ui37
-rw-r--r--src/yuzu/configuration/configure_input_player.cpp16
-rw-r--r--src/yuzu/configuration/configure_input_player.ui96
-rw-r--r--src/yuzu/configuration/configure_mouse_panning.cpp79
-rw-r--r--src/yuzu/configuration/configure_mouse_panning.h35
-rw-r--r--src/yuzu/configuration/configure_mouse_panning.ui238
-rw-r--r--src/yuzu_cmd/default_ini.h26
14 files changed, 581 insertions, 103 deletions
diff --git a/src/common/settings.h b/src/common/settings.h
index 9682281b0..3c775d3d2 100644
--- a/src/common/settings.h
+++ b/src/common/settings.h
@@ -524,9 +524,16 @@ struct Values {
524 Setting<bool> tas_loop{false, "tas_loop"}; 524 Setting<bool> tas_loop{false, "tas_loop"};
525 525
526 Setting<bool> mouse_panning{false, "mouse_panning"}; 526 Setting<bool> mouse_panning{false, "mouse_panning"};
527 Setting<u8, true> mouse_panning_sensitivity{50, 1, 100, "mouse_panning_sensitivity"}; 527 Setting<u8, true> mouse_panning_x_sensitivity{50, 1, 100, "mouse_panning_x_sensitivity"};
528 Setting<bool> mouse_enabled{false, "mouse_enabled"}; 528 Setting<u8, true> mouse_panning_y_sensitivity{50, 1, 100, "mouse_panning_y_sensitivity"};
529 Setting<u8, true> mouse_panning_deadzone_x_counterweight{
530 0, 0, 100, "mouse_panning_deadzone_x_counterweight"};
531 Setting<u8, true> mouse_panning_deadzone_y_counterweight{
532 0, 0, 100, "mouse_panning_deadzone_y_counterweight"};
533 Setting<u8, true> mouse_panning_decay_strength{22, 0, 100, "mouse_panning_decay_strength"};
534 Setting<u8, true> mouse_panning_min_decay{5, 0, 100, "mouse_panning_min_decay"};
529 535
536 Setting<bool> mouse_enabled{false, "mouse_enabled"};
530 Setting<bool> emulate_analog_keyboard{false, "emulate_analog_keyboard"}; 537 Setting<bool> emulate_analog_keyboard{false, "emulate_analog_keyboard"};
531 Setting<bool> keyboard_enabled{false, "keyboard_enabled"}; 538 Setting<bool> keyboard_enabled{false, "keyboard_enabled"};
532 539
diff --git a/src/input_common/drivers/mouse.cpp b/src/input_common/drivers/mouse.cpp
index 0c9f642bb..f07cf8a0e 100644
--- a/src/input_common/drivers/mouse.cpp
+++ b/src/input_common/drivers/mouse.cpp
@@ -76,9 +76,6 @@ void Mouse::UpdateThread(std::stop_token stop_token) {
76 UpdateStickInput(); 76 UpdateStickInput();
77 UpdateMotionInput(); 77 UpdateMotionInput();
78 78
79 if (mouse_panning_timeout++ > 20) {
80 StopPanning();
81 }
82 std::this_thread::sleep_for(std::chrono::milliseconds(update_time)); 79 std::this_thread::sleep_for(std::chrono::milliseconds(update_time));
83 } 80 }
84} 81}
@@ -88,18 +85,45 @@ void Mouse::UpdateStickInput() {
88 return; 85 return;
89 } 86 }
90 87
91 const float sensitivity = 88 const float length = last_mouse_change.Length();
92 Settings::values.mouse_panning_sensitivity.GetValue() * default_stick_sensitivity;
93 89
94 // Slow movement by 4% 90 // Prevent input from exceeding the max range (1.0f) too much,
95 last_mouse_change *= 0.96f; 91 // but allow some room to make it easier to sustain
96 SetAxis(identifier, mouse_axis_x, last_mouse_change.x * sensitivity); 92 if (length > 1.2f) {
97 SetAxis(identifier, mouse_axis_y, -last_mouse_change.y * sensitivity); 93 last_mouse_change /= length;
94 last_mouse_change *= 1.2f;
95 }
96
97 auto mouse_change = last_mouse_change;
98
99 // Bind the mouse change to [0 <= deadzone_counterweight <= 1,1]
100 if (length < 1.0f) {
101 const float deadzone_h_counterweight =
102 Settings::values.mouse_panning_deadzone_x_counterweight.GetValue();
103 const float deadzone_v_counterweight =
104 Settings::values.mouse_panning_deadzone_y_counterweight.GetValue();
105 mouse_change /= length;
106 mouse_change.x *= length + (1 - length) * deadzone_h_counterweight * 0.01f;
107 mouse_change.y *= length + (1 - length) * deadzone_v_counterweight * 0.01f;
108 }
109
110 SetAxis(identifier, mouse_axis_x, mouse_change.x);
111 SetAxis(identifier, mouse_axis_y, -mouse_change.y);
112
113 // Decay input over time
114 const float clamped_length = std::min(1.0f, length);
115 const float decay_strength = Settings::values.mouse_panning_decay_strength.GetValue();
116 const float decay = 1 - clamped_length * clamped_length * decay_strength * 0.01f;
117 const float min_decay = Settings::values.mouse_panning_min_decay.GetValue();
118 const float clamped_decay = std::min(1 - min_decay / 100.0f, decay);
119 last_mouse_change *= clamped_decay;
98} 120}
99 121
100void Mouse::UpdateMotionInput() { 122void Mouse::UpdateMotionInput() {
101 const float sensitivity = 123 // This may need its own sensitivity instead of using the average
102 Settings::values.mouse_panning_sensitivity.GetValue() * default_motion_sensitivity; 124 const float sensitivity = (Settings::values.mouse_panning_x_sensitivity.GetValue() +
125 Settings::values.mouse_panning_y_sensitivity.GetValue()) /
126 2.0f * default_motion_sensitivity;
103 127
104 const float rotation_velocity = std::sqrt(last_motion_change.x * last_motion_change.x + 128 const float rotation_velocity = std::sqrt(last_motion_change.x * last_motion_change.x +
105 last_motion_change.y * last_motion_change.y); 129 last_motion_change.y * last_motion_change.y);
@@ -131,49 +155,28 @@ void Mouse::UpdateMotionInput() {
131 155
132void Mouse::Move(int x, int y, int center_x, int center_y) { 156void Mouse::Move(int x, int y, int center_x, int center_y) {
133 if (Settings::values.mouse_panning) { 157 if (Settings::values.mouse_panning) {
134 mouse_panning_timeout = 0; 158 const auto mouse_change =
135
136 auto mouse_change =
137 (Common::MakeVec(x, y) - Common::MakeVec(center_x, center_y)).Cast<float>(); 159 (Common::MakeVec(x, y) - Common::MakeVec(center_x, center_y)).Cast<float>();
138 last_motion_change += {-mouse_change.y, -mouse_change.x, 0}; 160 const float x_sensitivity =
139 161 Settings::values.mouse_panning_x_sensitivity.GetValue() * default_stick_sensitivity;
140 const auto move_distance = mouse_change.Length(); 162 const float y_sensitivity =
141 if (move_distance == 0) { 163 Settings::values.mouse_panning_y_sensitivity.GetValue() * default_stick_sensitivity;
142 return;
143 }
144 164
145 // Make slow movements at least 3 units on length 165 last_motion_change += {-mouse_change.y, -mouse_change.x, 0};
146 if (move_distance < 3.0f) { 166 last_mouse_change.x += mouse_change.x * x_sensitivity * 0.09f;
147 // Normalize value 167 last_mouse_change.y += mouse_change.y * y_sensitivity * 0.09f;
148 mouse_change /= move_distance;
149 mouse_change *= 3.0f;
150 }
151
152 // Average mouse movements
153 last_mouse_change = (last_mouse_change * 0.91f) + (mouse_change * 0.09f);
154
155 const auto last_move_distance = last_mouse_change.Length();
156
157 // Make fast movements clamp to 8 units on length
158 if (last_move_distance > 8.0f) {
159 // Normalize value
160 last_mouse_change /= last_move_distance;
161 last_mouse_change *= 8.0f;
162 }
163
164 // Ignore average if it's less than 1 unit and use current movement value
165 if (last_move_distance < 1.0f) {
166 last_mouse_change = mouse_change / mouse_change.Length();
167 }
168 168
169 return; 169 return;
170 } 170 }
171 171
172 if (button_pressed) { 172 if (button_pressed) {
173 const auto mouse_move = Common::MakeVec<int>(x, y) - mouse_origin; 173 const auto mouse_move = Common::MakeVec<int>(x, y) - mouse_origin;
174 const float sensitivity = Settings::values.mouse_panning_sensitivity.GetValue() * 0.0012f; 174 const float x_sensitivity = Settings::values.mouse_panning_x_sensitivity.GetValue();
175 SetAxis(identifier, mouse_axis_x, static_cast<float>(mouse_move.x) * sensitivity); 175 const float y_sensitivity = Settings::values.mouse_panning_y_sensitivity.GetValue();
176 SetAxis(identifier, mouse_axis_y, static_cast<float>(-mouse_move.y) * sensitivity); 176 SetAxis(identifier, mouse_axis_x,
177 static_cast<float>(mouse_move.x) * x_sensitivity * 0.0012f);
178 SetAxis(identifier, mouse_axis_y,
179 static_cast<float>(-mouse_move.y) * y_sensitivity * 0.0012f);
177 180
178 last_motion_change = { 181 last_motion_change = {
179 static_cast<float>(-mouse_move.y) / 50.0f, 182 static_cast<float>(-mouse_move.y) / 50.0f,
@@ -241,10 +244,6 @@ void Mouse::ReleaseAllButtons() {
241 button_pressed = false; 244 button_pressed = false;
242} 245}
243 246
244void Mouse::StopPanning() {
245 last_mouse_change = {};
246}
247
248std::vector<Common::ParamPackage> Mouse::GetInputDevices() const { 247std::vector<Common::ParamPackage> Mouse::GetInputDevices() const {
249 std::vector<Common::ParamPackage> devices; 248 std::vector<Common::ParamPackage> devices;
250 devices.emplace_back(Common::ParamPackage{ 249 devices.emplace_back(Common::ParamPackage{
diff --git a/src/input_common/drivers/mouse.h b/src/input_common/drivers/mouse.h
index b872c7a0f..0e8edcce1 100644
--- a/src/input_common/drivers/mouse.h
+++ b/src/input_common/drivers/mouse.h
@@ -98,7 +98,6 @@ private:
98 void UpdateThread(std::stop_token stop_token); 98 void UpdateThread(std::stop_token stop_token);
99 void UpdateStickInput(); 99 void UpdateStickInput();
100 void UpdateMotionInput(); 100 void UpdateMotionInput();
101 void StopPanning();
102 101
103 Common::Input::ButtonNames GetUIButtonName(const Common::ParamPackage& params) const; 102 Common::Input::ButtonNames GetUIButtonName(const Common::ParamPackage& params) const;
104 103
@@ -108,7 +107,6 @@ private:
108 Common::Vec3<float> last_motion_change; 107 Common::Vec3<float> last_motion_change;
109 Common::Vec2<int> wheel_position; 108 Common::Vec2<int> wheel_position;
110 bool button_pressed; 109 bool button_pressed;
111 int mouse_panning_timeout{};
112 std::jthread update_thread; 110 std::jthread update_thread;
113}; 111};
114 112
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt
index 84d9ca796..8676bfd8a 100644
--- a/src/yuzu/CMakeLists.txt
+++ b/src/yuzu/CMakeLists.txt
@@ -98,6 +98,9 @@ add_executable(yuzu
98 configuration/configure_input_profile_dialog.cpp 98 configuration/configure_input_profile_dialog.cpp
99 configuration/configure_input_profile_dialog.h 99 configuration/configure_input_profile_dialog.h
100 configuration/configure_input_profile_dialog.ui 100 configuration/configure_input_profile_dialog.ui
101 configuration/configure_mouse_panning.cpp
102 configuration/configure_mouse_panning.h
103 configuration/configure_mouse_panning.ui
101 configuration/configure_motion_touch.cpp 104 configuration/configure_motion_touch.cpp
102 configuration/configure_motion_touch.h 105 configuration/configure_motion_touch.h
103 configuration/configure_motion_touch.ui 106 configuration/configure_motion_touch.ui
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index bac9dff90..b58a1e9d1 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -351,6 +351,10 @@ void Config::ReadPlayerValue(std::size_t player_index) {
351 player_motions = default_param; 351 player_motions = default_param;
352 } 352 }
353 } 353 }
354
355 if (player_index == 0) {
356 ReadMousePanningValues();
357 }
354} 358}
355 359
356void Config::ReadDebugValues() { 360void Config::ReadDebugValues() {
@@ -471,6 +475,7 @@ void Config::ReadControlValues() {
471 ReadKeyboardValues(); 475 ReadKeyboardValues();
472 ReadMouseValues(); 476 ReadMouseValues();
473 ReadTouchscreenValues(); 477 ReadTouchscreenValues();
478 ReadMousePanningValues();
474 ReadMotionTouchValues(); 479 ReadMotionTouchValues();
475 ReadHidbusValues(); 480 ReadHidbusValues();
476 ReadIrCameraValues(); 481 ReadIrCameraValues();
@@ -481,8 +486,6 @@ void Config::ReadControlValues() {
481 Settings::values.enable_raw_input = false; 486 Settings::values.enable_raw_input = false;
482#endif 487#endif
483 ReadBasicSetting(Settings::values.emulate_analog_keyboard); 488 ReadBasicSetting(Settings::values.emulate_analog_keyboard);
484 Settings::values.mouse_panning = false;
485 ReadBasicSetting(Settings::values.mouse_panning_sensitivity);
486 ReadBasicSetting(Settings::values.enable_joycon_driver); 489 ReadBasicSetting(Settings::values.enable_joycon_driver);
487 ReadBasicSetting(Settings::values.enable_procon_driver); 490 ReadBasicSetting(Settings::values.enable_procon_driver);
488 ReadBasicSetting(Settings::values.random_amiibo_id); 491 ReadBasicSetting(Settings::values.random_amiibo_id);
@@ -496,6 +499,16 @@ void Config::ReadControlValues() {
496 qt_config->endGroup(); 499 qt_config->endGroup();
497} 500}
498 501
502void Config::ReadMousePanningValues() {
503 ReadBasicSetting(Settings::values.mouse_panning);
504 ReadBasicSetting(Settings::values.mouse_panning_x_sensitivity);
505 ReadBasicSetting(Settings::values.mouse_panning_y_sensitivity);
506 ReadBasicSetting(Settings::values.mouse_panning_deadzone_x_counterweight);
507 ReadBasicSetting(Settings::values.mouse_panning_deadzone_y_counterweight);
508 ReadBasicSetting(Settings::values.mouse_panning_decay_strength);
509 ReadBasicSetting(Settings::values.mouse_panning_min_decay);
510}
511
499void Config::ReadMotionTouchValues() { 512void Config::ReadMotionTouchValues() {
500 int num_touch_from_button_maps = 513 int num_touch_from_button_maps =
501 qt_config->beginReadArray(QStringLiteral("touch_from_button_maps")); 514 qt_config->beginReadArray(QStringLiteral("touch_from_button_maps"));
@@ -1063,6 +1076,10 @@ void Config::SavePlayerValue(std::size_t player_index) {
1063 QString::fromStdString(player.motions[i]), 1076 QString::fromStdString(player.motions[i]),
1064 QString::fromStdString(default_param)); 1077 QString::fromStdString(default_param));
1065 } 1078 }
1079
1080 if (player_index == 0) {
1081 SaveMousePanningValues();
1082 }
1066} 1083}
1067 1084
1068void Config::SaveDebugValues() { 1085void Config::SaveDebugValues() {
@@ -1099,6 +1116,16 @@ void Config::SaveTouchscreenValues() {
1099 WriteSetting(QStringLiteral("touchscreen_diameter_y"), touchscreen.diameter_y, 15); 1116 WriteSetting(QStringLiteral("touchscreen_diameter_y"), touchscreen.diameter_y, 15);
1100} 1117}
1101 1118
1119void Config::SaveMousePanningValues() {
1120 // Don't overwrite values.mouse_panning
1121 WriteBasicSetting(Settings::values.mouse_panning_x_sensitivity);
1122 WriteBasicSetting(Settings::values.mouse_panning_y_sensitivity);
1123 WriteBasicSetting(Settings::values.mouse_panning_deadzone_x_counterweight);
1124 WriteBasicSetting(Settings::values.mouse_panning_deadzone_y_counterweight);
1125 WriteBasicSetting(Settings::values.mouse_panning_decay_strength);
1126 WriteBasicSetting(Settings::values.mouse_panning_min_decay);
1127}
1128
1102void Config::SaveMotionTouchValues() { 1129void Config::SaveMotionTouchValues() {
1103 WriteBasicSetting(Settings::values.touch_device); 1130 WriteBasicSetting(Settings::values.touch_device);
1104 WriteBasicSetting(Settings::values.touch_from_button_map_index); 1131 WriteBasicSetting(Settings::values.touch_from_button_map_index);
@@ -1185,6 +1212,7 @@ void Config::SaveControlValues() {
1185 SaveDebugValues(); 1212 SaveDebugValues();
1186 SaveMouseValues(); 1213 SaveMouseValues();
1187 SaveTouchscreenValues(); 1214 SaveTouchscreenValues();
1215 SaveMousePanningValues();
1188 SaveMotionTouchValues(); 1216 SaveMotionTouchValues();
1189 SaveHidbusValues(); 1217 SaveHidbusValues();
1190 SaveIrCameraValues(); 1218 SaveIrCameraValues();
@@ -1199,7 +1227,6 @@ void Config::SaveControlValues() {
1199 WriteBasicSetting(Settings::values.random_amiibo_id); 1227 WriteBasicSetting(Settings::values.random_amiibo_id);
1200 WriteBasicSetting(Settings::values.keyboard_enabled); 1228 WriteBasicSetting(Settings::values.keyboard_enabled);
1201 WriteBasicSetting(Settings::values.emulate_analog_keyboard); 1229 WriteBasicSetting(Settings::values.emulate_analog_keyboard);
1202 WriteBasicSetting(Settings::values.mouse_panning_sensitivity);
1203 WriteBasicSetting(Settings::values.controller_navigation); 1230 WriteBasicSetting(Settings::values.controller_navigation);
1204 1231
1205 WriteBasicSetting(Settings::values.tas_enable); 1232 WriteBasicSetting(Settings::values.tas_enable);
diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h
index 0fd4baf6b..1211389d2 100644
--- a/src/yuzu/configuration/config.h
+++ b/src/yuzu/configuration/config.h
@@ -74,6 +74,7 @@ private:
74 void ReadKeyboardValues(); 74 void ReadKeyboardValues();
75 void ReadMouseValues(); 75 void ReadMouseValues();
76 void ReadTouchscreenValues(); 76 void ReadTouchscreenValues();
77 void ReadMousePanningValues();
77 void ReadMotionTouchValues(); 78 void ReadMotionTouchValues();
78 void ReadHidbusValues(); 79 void ReadHidbusValues();
79 void ReadIrCameraValues(); 80 void ReadIrCameraValues();
@@ -104,6 +105,7 @@ private:
104 void SaveDebugValues(); 105 void SaveDebugValues();
105 void SaveMouseValues(); 106 void SaveMouseValues();
106 void SaveTouchscreenValues(); 107 void SaveTouchscreenValues();
108 void SaveMousePanningValues();
107 void SaveMotionTouchValues(); 109 void SaveMotionTouchValues();
108 void SaveHidbusValues(); 110 void SaveHidbusValues();
109 void SaveIrCameraValues(); 111 void SaveIrCameraValues();
diff --git a/src/yuzu/configuration/configure_input_advanced.cpp b/src/yuzu/configuration/configure_input_advanced.cpp
index f13156434..3cfd5d439 100644
--- a/src/yuzu/configuration/configure_input_advanced.cpp
+++ b/src/yuzu/configuration/configure_input_advanced.cpp
@@ -129,9 +129,6 @@ void ConfigureInputAdvanced::ApplyConfiguration() {
129 Settings::values.mouse_enabled = ui->mouse_enabled->isChecked(); 129 Settings::values.mouse_enabled = ui->mouse_enabled->isChecked();
130 Settings::values.keyboard_enabled = ui->keyboard_enabled->isChecked(); 130 Settings::values.keyboard_enabled = ui->keyboard_enabled->isChecked();
131 Settings::values.emulate_analog_keyboard = ui->emulate_analog_keyboard->isChecked(); 131 Settings::values.emulate_analog_keyboard = ui->emulate_analog_keyboard->isChecked();
132 Settings::values.mouse_panning = ui->mouse_panning->isChecked();
133 Settings::values.mouse_panning_sensitivity =
134 static_cast<float>(ui->mouse_panning_sensitivity->value());
135 Settings::values.touchscreen.enabled = ui->touchscreen_enabled->isChecked(); 132 Settings::values.touchscreen.enabled = ui->touchscreen_enabled->isChecked();
136 Settings::values.enable_raw_input = ui->enable_raw_input->isChecked(); 133 Settings::values.enable_raw_input = ui->enable_raw_input->isChecked();
137 Settings::values.enable_udp_controller = ui->enable_udp_controller->isChecked(); 134 Settings::values.enable_udp_controller = ui->enable_udp_controller->isChecked();
@@ -167,8 +164,6 @@ void ConfigureInputAdvanced::LoadConfiguration() {
167 ui->mouse_enabled->setChecked(Settings::values.mouse_enabled.GetValue()); 164 ui->mouse_enabled->setChecked(Settings::values.mouse_enabled.GetValue());
168 ui->keyboard_enabled->setChecked(Settings::values.keyboard_enabled.GetValue()); 165 ui->keyboard_enabled->setChecked(Settings::values.keyboard_enabled.GetValue());
169 ui->emulate_analog_keyboard->setChecked(Settings::values.emulate_analog_keyboard.GetValue()); 166 ui->emulate_analog_keyboard->setChecked(Settings::values.emulate_analog_keyboard.GetValue());
170 ui->mouse_panning->setChecked(Settings::values.mouse_panning.GetValue());
171 ui->mouse_panning_sensitivity->setValue(Settings::values.mouse_panning_sensitivity.GetValue());
172 ui->touchscreen_enabled->setChecked(Settings::values.touchscreen.enabled); 167 ui->touchscreen_enabled->setChecked(Settings::values.touchscreen.enabled);
173 ui->enable_raw_input->setChecked(Settings::values.enable_raw_input.GetValue()); 168 ui->enable_raw_input->setChecked(Settings::values.enable_raw_input.GetValue());
174 ui->enable_udp_controller->setChecked(Settings::values.enable_udp_controller.GetValue()); 169 ui->enable_udp_controller->setChecked(Settings::values.enable_udp_controller.GetValue());
@@ -197,8 +192,6 @@ void ConfigureInputAdvanced::RetranslateUI() {
197void ConfigureInputAdvanced::UpdateUIEnabled() { 192void ConfigureInputAdvanced::UpdateUIEnabled() {
198 ui->debug_configure->setEnabled(ui->debug_enabled->isChecked()); 193 ui->debug_configure->setEnabled(ui->debug_enabled->isChecked());
199 ui->touchscreen_advanced->setEnabled(ui->touchscreen_enabled->isChecked()); 194 ui->touchscreen_advanced->setEnabled(ui->touchscreen_enabled->isChecked());
200 ui->mouse_panning->setEnabled(!ui->mouse_enabled->isChecked());
201 ui->mouse_panning_sensitivity->setEnabled(!ui->mouse_enabled->isChecked());
202 ui->ring_controller_configure->setEnabled(ui->enable_ring_controller->isChecked()); 195 ui->ring_controller_configure->setEnabled(ui->enable_ring_controller->isChecked());
203#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0) || !defined(YUZU_USE_QT_MULTIMEDIA) 196#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0) || !defined(YUZU_USE_QT_MULTIMEDIA)
204 ui->enable_ir_sensor->setEnabled(false); 197 ui->enable_ir_sensor->setEnabled(false);
diff --git a/src/yuzu/configuration/configure_input_advanced.ui b/src/yuzu/configuration/configure_input_advanced.ui
index 2e8b13660..2994d0ab4 100644
--- a/src/yuzu/configuration/configure_input_advanced.ui
+++ b/src/yuzu/configuration/configure_input_advanced.ui
@@ -2744,48 +2744,13 @@
2744 </widget> 2744 </widget>
2745 </item> 2745 </item>
2746 <item row="8" column="0"> 2746 <item row="8" column="0">
2747 <widget class="QCheckBox" name="mouse_panning">
2748 <property name="minimumSize">
2749 <size>
2750 <width>0</width>
2751 <height>23</height>
2752 </size>
2753 </property>
2754 <property name="text">
2755 <string>Enable mouse panning</string>
2756 </property>
2757 </widget>
2758 </item>
2759 <item row="8" column="2">
2760 <widget class="QSpinBox" name="mouse_panning_sensitivity">
2761 <property name="toolTip">
2762 <string>Mouse sensitivity</string>
2763 </property>
2764 <property name="alignment">
2765 <set>Qt::AlignCenter</set>
2766 </property>
2767 <property name="suffix">
2768 <string>%</string>
2769 </property>
2770 <property name="minimum">
2771 <number>1</number>
2772 </property>
2773 <property name="maximum">
2774 <number>100</number>
2775 </property>
2776 <property name="value">
2777 <number>100</number>
2778 </property>
2779 </widget>
2780 </item>
2781 <item row="9" column="0">
2782 <widget class="QLabel" name="motion_touch"> 2747 <widget class="QLabel" name="motion_touch">
2783 <property name="text"> 2748 <property name="text">
2784 <string>Motion / Touch</string> 2749 <string>Motion / Touch</string>
2785 </property> 2750 </property>
2786 </widget> 2751 </widget>
2787 </item> 2752 </item>
2788 <item row="9" column="2"> 2753 <item row="8" column="2">
2789 <widget class="QPushButton" name="buttonMotionTouch"> 2754 <widget class="QPushButton" name="buttonMotionTouch">
2790 <property name="text"> 2755 <property name="text">
2791 <string>Configure</string> 2756 <string>Configure</string>
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index 2c2e7e47b..576f5b571 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -23,6 +23,7 @@
23#include "yuzu/configuration/config.h" 23#include "yuzu/configuration/config.h"
24#include "yuzu/configuration/configure_input_player.h" 24#include "yuzu/configuration/configure_input_player.h"
25#include "yuzu/configuration/configure_input_player_widget.h" 25#include "yuzu/configuration/configure_input_player_widget.h"
26#include "yuzu/configuration/configure_mouse_panning.h"
26#include "yuzu/configuration/input_profiles.h" 27#include "yuzu/configuration/input_profiles.h"
27#include "yuzu/util/limitable_input_dialog.h" 28#include "yuzu/util/limitable_input_dialog.h"
28 29
@@ -711,6 +712,21 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
711 }); 712 });
712 } 713 }
713 714
715 if (player_index_ == 0) {
716 connect(ui->mousePanningButton, &QPushButton::clicked, [this, input_subsystem_] {
717 const auto right_stick_param =
718 emulated_controller->GetStickParam(Settings::NativeAnalog::RStick);
719 ConfigureMousePanning dialog(this, input_subsystem_,
720 right_stick_param.Get("deadzone", 0.0f),
721 right_stick_param.Get("range", 1.0f));
722 if (dialog.exec() == QDialog::Accepted) {
723 dialog.ApplyConfiguration();
724 }
725 });
726 } else {
727 ui->mousePanningWidget->hide();
728 }
729
714 // Player Connected checkbox 730 // Player Connected checkbox
715 connect(ui->groupConnectedController, &QGroupBox::toggled, 731 connect(ui->groupConnectedController, &QGroupBox::toggled,
716 [this](bool checked) { emit Connected(checked); }); 732 [this](bool checked) { emit Connected(checked); });
diff --git a/src/yuzu/configuration/configure_input_player.ui b/src/yuzu/configuration/configure_input_player.ui
index a9567c6ee..43f6c7b50 100644
--- a/src/yuzu/configuration/configure_input_player.ui
+++ b/src/yuzu/configuration/configure_input_player.ui
@@ -3048,6 +3048,102 @@
3048 </item> 3048 </item>
3049 </layout> 3049 </layout>
3050 </item> 3050 </item>
3051 <item>
3052 <widget class="QWidget" name="mousePanningWidget" native="true">
3053 <layout class="QHBoxLayout" name="mousePanningHorizontalLayout">
3054 <property name="spacing">
3055 <number>0</number>
3056 </property>
3057 <property name="leftMargin">
3058 <number>0</number>
3059 </property>
3060 <property name="topMargin">
3061 <number>0</number>
3062 </property>
3063 <property name="rightMargin">
3064 <number>0</number>
3065 </property>
3066 <property name="bottomMargin">
3067 <number>3</number>
3068 </property>
3069 <item>
3070 <spacer name="mousePanningHorizontalSpacerLeft">
3071 <property name="orientation">
3072 <enum>Qt::Horizontal</enum>
3073 </property>
3074 <property name="sizeHint" stdset="0">
3075 <size>
3076 <width>20</width>
3077 <height>20</height>
3078 </size>
3079 </property>
3080 </spacer>
3081 </item>
3082 <item>
3083 <widget class="QGroupBox" name="mousePanningGroup">
3084 <property name="title">
3085 <string>Mouse panning</string>
3086 </property>
3087 <property name="alignment">
3088 <set>Qt::AlignCenter</set>
3089 </property>
3090 <layout class="QVBoxLayout" name="mousePanningVerticalLayout">
3091 <property name="spacing">
3092 <number>3</number>
3093 </property>
3094 <property name="leftMargin">
3095 <number>3</number>
3096 </property>
3097 <property name="topMargin">
3098 <number>3</number>
3099 </property>
3100 <property name="rightMargin">
3101 <number>3</number>
3102 </property>
3103 <property name="bottomMargin">
3104 <number>3</number>
3105 </property>
3106 <item>
3107 <widget class="QPushButton" name="mousePanningButton">
3108 <property name="minimumSize">
3109 <size>
3110 <width>68</width>
3111 <height>0</height>
3112 </size>
3113 </property>
3114 <property name="maximumSize">
3115 <size>
3116 <width>68</width>
3117 <height>16777215</height>
3118 </size>
3119 </property>
3120 <property name="styleSheet">
3121 <string notr="true">min-width: 68px;</string>
3122 </property>
3123 <property name="text">
3124 <string>Configure</string>
3125 </property>
3126 </widget>
3127 </item>
3128 </layout>
3129 </widget>
3130 </item>
3131 <item>
3132 <spacer name="mousePanningHorizontalSpacerRight">
3133 <property name="orientation">
3134 <enum>Qt::Horizontal</enum>
3135 </property>
3136 <property name="sizeHint" stdset="0">
3137 <size>
3138 <width>20</width>
3139 <height>20</height>
3140 </size>
3141 </property>
3142 </spacer>
3143 </item>
3144 </layout>
3145 </widget>
3146 </item>
3051 </layout> 3147 </layout>
3052 </widget> 3148 </widget>
3053 </item> 3149 </item>
diff --git a/src/yuzu/configuration/configure_mouse_panning.cpp b/src/yuzu/configuration/configure_mouse_panning.cpp
new file mode 100644
index 000000000..f183d2740
--- /dev/null
+++ b/src/yuzu/configuration/configure_mouse_panning.cpp
@@ -0,0 +1,79 @@
1// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include <QCloseEvent>
5
6#include "common/settings.h"
7#include "ui_configure_mouse_panning.h"
8#include "yuzu/configuration/configure_mouse_panning.h"
9
10ConfigureMousePanning::ConfigureMousePanning(QWidget* parent,
11 InputCommon::InputSubsystem* input_subsystem_,
12 float right_stick_deadzone, float right_stick_range)
13 : QDialog(parent), input_subsystem{input_subsystem_},
14 ui(std::make_unique<Ui::ConfigureMousePanning>()) {
15 ui->setupUi(this);
16 SetConfiguration(right_stick_deadzone, right_stick_range);
17 ConnectEvents();
18}
19
20ConfigureMousePanning::~ConfigureMousePanning() = default;
21
22void ConfigureMousePanning::closeEvent(QCloseEvent* event) {
23 event->accept();
24}
25
26void ConfigureMousePanning::SetConfiguration(float right_stick_deadzone, float right_stick_range) {
27 ui->enable->setChecked(Settings::values.mouse_panning.GetValue());
28 ui->x_sensitivity->setValue(Settings::values.mouse_panning_x_sensitivity.GetValue());
29 ui->y_sensitivity->setValue(Settings::values.mouse_panning_y_sensitivity.GetValue());
30 ui->deadzone_x_counterweight->setValue(
31 Settings::values.mouse_panning_deadzone_x_counterweight.GetValue());
32 ui->deadzone_y_counterweight->setValue(
33 Settings::values.mouse_panning_deadzone_y_counterweight.GetValue());
34 ui->decay_strength->setValue(Settings::values.mouse_panning_decay_strength.GetValue());
35 ui->min_decay->setValue(Settings::values.mouse_panning_min_decay.GetValue());
36
37 if (right_stick_deadzone > 0.0f || right_stick_range != 1.0f) {
38 ui->warning_label->setText(QString::fromStdString(
39 "Mouse panning works better with a deadzone of 0% and a range of 100%.\n"
40 "Current values are " +
41 std::to_string(static_cast<int>(right_stick_deadzone * 100.0f)) + "% and " +
42 std::to_string(static_cast<int>(right_stick_range * 100.0f)) + "% respectively."));
43 } else {
44 ui->warning_label->hide();
45 }
46}
47
48void ConfigureMousePanning::SetDefaultConfiguration() {
49 ui->x_sensitivity->setValue(Settings::values.mouse_panning_x_sensitivity.GetDefault());
50 ui->y_sensitivity->setValue(Settings::values.mouse_panning_y_sensitivity.GetDefault());
51 ui->deadzone_x_counterweight->setValue(
52 Settings::values.mouse_panning_deadzone_x_counterweight.GetDefault());
53 ui->deadzone_y_counterweight->setValue(
54 Settings::values.mouse_panning_deadzone_y_counterweight.GetDefault());
55 ui->decay_strength->setValue(Settings::values.mouse_panning_decay_strength.GetDefault());
56 ui->min_decay->setValue(Settings::values.mouse_panning_min_decay.GetDefault());
57}
58
59void ConfigureMousePanning::ConnectEvents() {
60 connect(ui->default_button, &QPushButton::clicked, this,
61 &ConfigureMousePanning::SetDefaultConfiguration);
62 connect(ui->button_box, &QDialogButtonBox::accepted, this,
63 &ConfigureMousePanning::ApplyConfiguration);
64 connect(ui->button_box, &QDialogButtonBox::rejected, this, [this] { reject(); });
65}
66
67void ConfigureMousePanning::ApplyConfiguration() {
68 Settings::values.mouse_panning = ui->enable->isChecked();
69 Settings::values.mouse_panning_x_sensitivity = static_cast<float>(ui->x_sensitivity->value());
70 Settings::values.mouse_panning_y_sensitivity = static_cast<float>(ui->y_sensitivity->value());
71 Settings::values.mouse_panning_deadzone_x_counterweight =
72 static_cast<float>(ui->deadzone_x_counterweight->value());
73 Settings::values.mouse_panning_deadzone_y_counterweight =
74 static_cast<float>(ui->deadzone_y_counterweight->value());
75 Settings::values.mouse_panning_decay_strength = static_cast<float>(ui->decay_strength->value());
76 Settings::values.mouse_panning_min_decay = static_cast<float>(ui->min_decay->value());
77
78 accept();
79}
diff --git a/src/yuzu/configuration/configure_mouse_panning.h b/src/yuzu/configuration/configure_mouse_panning.h
new file mode 100644
index 000000000..08c6e1f62
--- /dev/null
+++ b/src/yuzu/configuration/configure_mouse_panning.h
@@ -0,0 +1,35 @@
1// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <memory>
7#include <QDialog>
8
9namespace InputCommon {
10class InputSubsystem;
11}
12
13namespace Ui {
14class ConfigureMousePanning;
15}
16
17class ConfigureMousePanning : public QDialog {
18 Q_OBJECT
19public:
20 explicit ConfigureMousePanning(QWidget* parent, InputCommon::InputSubsystem* input_subsystem_,
21 float right_stick_deadzone, float right_stick_range);
22 ~ConfigureMousePanning() override;
23
24public slots:
25 void ApplyConfiguration();
26
27private:
28 void closeEvent(QCloseEvent* event) override;
29 void SetConfiguration(float right_stick_deadzone, float right_stick_range);
30 void SetDefaultConfiguration();
31 void ConnectEvents();
32
33 InputCommon::InputSubsystem* input_subsystem;
34 std::unique_ptr<Ui::ConfigureMousePanning> ui;
35};
diff --git a/src/yuzu/configuration/configure_mouse_panning.ui b/src/yuzu/configuration/configure_mouse_panning.ui
new file mode 100644
index 000000000..75795b727
--- /dev/null
+++ b/src/yuzu/configuration/configure_mouse_panning.ui
@@ -0,0 +1,238 @@
1<?xml version="1.0" encoding="UTF-8"?>
2<ui version="4.0">
3 <class>ConfigureMousePanning</class>
4 <widget class="QDialog" name="configure_mouse_panning">
5 <property name="windowTitle">
6 <string>Configure mouse panning</string>
7 </property>
8 <layout class="QVBoxLayout">
9 <item>
10 <widget class="QCheckBox" name="enable">
11 <property name="text">
12 <string>Enable</string>
13 </property>
14 <property name="toolTip">
15 <string>Can be toggled via a hotkey</string>
16 </property>
17 </widget>
18 </item>
19 <item>
20 <layout class="QHBoxLayout">
21 <item>
22 <widget class="QGroupBox" name="sensitivity_box">
23 <property name="title">
24 <string>Sensitivity</string>
25 </property>
26 <layout class="QGridLayout">
27 <item row="0" column="0">
28 <widget class="QLabel" name="x_sensitivity_label">
29 <property name="text">
30 <string>Horizontal</string>
31 </property>
32 </widget>
33 </item>
34 <item row="0" column="1">
35 <widget class="QSpinBox" name="x_sensitivity">
36 <property name="alignment">
37 <set>Qt::AlignCenter</set>
38 </property>
39 <property name="suffix">
40 <string>%</string>
41 </property>
42 <property name="minimum">
43 <number>1</number>
44 </property>
45 <property name="maximum">
46 <number>100</number>
47 </property>
48 <property name="value">
49 <number>50</number>
50 </property>
51 </widget>
52 </item>
53 <item row="1" column="0">
54 <widget class="QLabel" name="y_sensitivity_label">
55 <property name="text">
56 <string>Vertical</string>
57 </property>
58 </widget>
59 </item>
60 <item row="1" column="1">
61 <widget class="QSpinBox" name="y_sensitivity">
62 <property name="alignment">
63 <set>Qt::AlignCenter</set>
64 </property>
65 <property name="suffix">
66 <string>%</string>
67 </property>
68 <property name="minimum">
69 <number>1</number>
70 </property>
71 <property name="maximum">
72 <number>100</number>
73 </property>
74 <property name="value">
75 <number>50</number>
76 </property>
77 </widget>
78 </item>
79 </layout>
80 </widget>
81 </item>
82 <item>
83 <widget class="QGroupBox" name="deadzone_counterweight_box">
84 <property name="title">
85 <string>Deadzone counterweight</string>
86 </property>
87 <property name="toolTip">
88 <string>Counteracts a game's built-in deadzone</string>
89 </property>
90 <layout class="QGridLayout">
91 <item row="0" column="0">
92 <widget class="QLabel" name="deadzone_x_counterweight_label">
93 <property name="text">
94 <string>Horizontal</string>
95 </property>
96 </widget>
97 </item>
98 <item row="0" column="1">
99 <widget class="QSpinBox" name="deadzone_x_counterweight">
100 <property name="alignment">
101 <set>Qt::AlignCenter</set>
102 </property>
103 <property name="suffix">
104 <string>%</string>
105 </property>
106 <property name="minimum">
107 <number>0</number>
108 </property>
109 <property name="maximum">
110 <number>100</number>
111 </property>
112 <property name="value">
113 <number>0</number>
114 </property>
115 </widget>
116 </item>
117 <item row="1" column="0">
118 <widget class="QLabel" name="deadzone_y_counterweight_label">
119 <property name="text">
120 <string>Vertical</string>
121 </property>
122 </widget>
123 </item>
124 <item row="1" column="1">
125 <widget class="QSpinBox" name="deadzone_y_counterweight">
126 <property name="alignment">
127 <set>Qt::AlignCenter</set>
128 </property>
129 <property name="suffix">
130 <string>%</string>
131 </property>
132 <property name="minimum">
133 <number>0</number>
134 </property>
135 <property name="maximum">
136 <number>100</number>
137 </property>
138 <property name="value">
139 <number>0</number>
140 </property>
141 </widget>
142 </item>
143 </layout>
144 </widget>
145 </item>
146 <item>
147 <widget class="QGroupBox" name="decay_box">
148 <property name="title">
149 <string>Stick decay</string>
150 </property>
151 <layout class="QGridLayout">
152 <item row="0" column="0">
153 <widget class="QLabel" name="decay_strength_label">
154 <property name="text">
155 <string>Strength</string>
156 </property>
157 </widget>
158 </item>
159 <item row="0" column="1">
160 <widget class="QSpinBox" name="decay_strength">
161 <property name="alignment">
162 <set>Qt::AlignCenter</set>
163 </property>
164 <property name="suffix">
165 <string>%</string>
166 </property>
167 <property name="minimum">
168 <number>0</number>
169 </property>
170 <property name="maximum">
171 <number>100</number>
172 </property>
173 <property name="value">
174 <number>22</number>
175 </property>
176 </widget>
177 </item>
178 <item row="1" column="0">
179 <widget class="QLabel" name="min_decay_label">
180 <property name="text">
181 <string>Minimum</string>
182 </property>
183 </widget>
184 </item>
185 <item row="1" column="1">
186 <widget class="QSpinBox" name="min_decay">
187 <property name="alignment">
188 <set>Qt::AlignCenter</set>
189 </property>
190 <property name="suffix">
191 <string>%</string>
192 </property>
193 <property name="minimum">
194 <number>0</number>
195 </property>
196 <property name="maximum">
197 <number>100</number>
198 </property>
199 <property name="value">
200 <number>5</number>
201 </property>
202 </widget>
203 </item>
204 </layout>
205 </widget>
206 </item>
207 </layout>
208 </item>
209 <item>
210 <widget class="QLabel" name="warning_label">
211 <property name="text">
212 <string/>
213 </property>
214 </widget>
215 </item>
216 <item>
217 <layout class="QHBoxLayout">
218 <item>
219 <widget class="QPushButton" name="default_button">
220 <property name="text">
221 <string>Default</string>
222 </property>
223 </widget>
224 </item>
225 <item>
226 <widget class="QDialogButtonBox" name="button_box">
227 <property name="standardButtons">
228 <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
229 </property>
230 </widget>
231 </item>
232 </layout>
233 </item>
234 </layout>
235 </widget>
236 <resources/>
237 <connections/>
238</ui>
diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h
index 911d461e4..119e22183 100644
--- a/src/yuzu_cmd/default_ini.h
+++ b/src/yuzu_cmd/default_ini.h
@@ -140,9 +140,29 @@ udp_input_servers =
140# 0 (default): Off, 1: On 140# 0 (default): Off, 1: On
141mouse_panning = 141mouse_panning =
142 142
143# Set mouse sensitivity. 143# Set mouse panning horizontal sensitivity.
144# Default: 1.0 144# Default: 50.0
145mouse_panning_sensitivity = 145mouse_panning_x_sensitivity =
146
147# Set mouse panning vertical sensitivity.
148# Default: 50.0
149mouse_panning_y_sensitivity =
150
151# Set mouse panning deadzone horizontal counterweight.
152# Default: 0.0
153mouse_panning_deadzone_x_counterweight =
154
155# Set mouse panning deadzone vertical counterweight.
156# Default: 0.0
157mouse_panning_deadzone_y_counterweight =
158
159# Set mouse panning stick decay strength.
160# Default: 22.0
161mouse_panning_decay_strength =
162
163# Set mouse panning stick minimum decay.
164# Default: 5.0
165mouse_panning_minimum_decay =
146 166
147# Emulate an analog control stick from keyboard inputs. 167# Emulate an analog control stick from keyboard inputs.
148# 0 (default): Disabled, 1: Enabled 168# 0 (default): Disabled, 1: Enabled