summaryrefslogtreecommitdiff
path: root/src/yuzu/configuration
diff options
context:
space:
mode:
Diffstat (limited to 'src/yuzu/configuration')
-rw-r--r--src/yuzu/configuration/config.cpp36
-rw-r--r--src/yuzu/configuration/config.h3
-rw-r--r--src/yuzu/configuration/configure_audio.cpp5
-rw-r--r--src/yuzu/configuration/configure_audio.h5
-rw-r--r--src/yuzu/configuration/configure_cpu.cpp5
-rw-r--r--src/yuzu/configuration/configure_cpu.h5
-rw-r--r--src/yuzu/configuration/configure_cpu.ui5
-rw-r--r--src/yuzu/configuration/configure_cpu_debug.cpp5
-rw-r--r--src/yuzu/configuration/configure_cpu_debug.h5
-rw-r--r--src/yuzu/configuration/configure_debug.cpp8
-rw-r--r--src/yuzu/configuration/configure_debug.ui93
-rw-r--r--src/yuzu/configuration/configure_debug_controller.cpp5
-rw-r--r--src/yuzu/configuration/configure_debug_controller.h5
-rw-r--r--src/yuzu/configuration/configure_debug_tab.cpp5
-rw-r--r--src/yuzu/configuration/configure_debug_tab.h5
-rw-r--r--src/yuzu/configuration/configure_dialog.cpp3
-rw-r--r--src/yuzu/configuration/configure_filesystem.cpp5
-rw-r--r--src/yuzu/configuration/configure_filesystem.h5
-rw-r--r--src/yuzu/configuration/configure_graphics_advanced.cpp5
-rw-r--r--src/yuzu/configuration/configure_graphics_advanced.h5
-rw-r--r--src/yuzu/configuration/configure_hotkeys.cpp7
-rw-r--r--src/yuzu/configuration/configure_input.cpp5
-rw-r--r--src/yuzu/configuration/configure_input_advanced.cpp14
-rw-r--r--src/yuzu/configuration/configure_input_advanced.h6
-rw-r--r--src/yuzu/configuration/configure_input_advanced.ui14
-rw-r--r--src/yuzu/configuration/configure_input_player.cpp41
-rw-r--r--src/yuzu/configuration/configure_input_player_widget.cpp5
-rw-r--r--src/yuzu/configuration/configure_input_player_widget.h5
-rw-r--r--src/yuzu/configuration/configure_input_profile_dialog.cpp5
-rw-r--r--src/yuzu/configuration/configure_input_profile_dialog.h5
-rw-r--r--src/yuzu/configuration/configure_network.cpp5
-rw-r--r--src/yuzu/configuration/configure_network.h5
-rw-r--r--src/yuzu/configuration/configure_per_game.cpp5
-rw-r--r--src/yuzu/configuration/configure_per_game.h5
-rw-r--r--src/yuzu/configuration/configure_per_game_addons.cpp6
-rw-r--r--src/yuzu/configuration/configure_ringcon.cpp423
-rw-r--r--src/yuzu/configuration/configure_ringcon.h84
-rw-r--r--src/yuzu/configuration/configure_ringcon.ui278
-rw-r--r--src/yuzu/configuration/configure_tas.cpp5
-rw-r--r--src/yuzu/configuration/configure_tas.h5
-rw-r--r--src/yuzu/configuration/configure_vibration.cpp5
-rw-r--r--src/yuzu/configuration/configure_vibration.h5
-rw-r--r--src/yuzu/configuration/input_profiles.cpp5
-rw-r--r--src/yuzu/configuration/input_profiles.h5
44 files changed, 1026 insertions, 140 deletions
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index 4b943c6ba..ac26b885b 100644
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -60,6 +60,11 @@ const std::array<int, 2> Config::default_stick_mod = {
0,
};
+const std::array<int, 2> Config::default_ringcon_analogs{{
+ Qt::Key_A,
+ Qt::Key_D,
+}};
+
// This shouldn't have anything except static initializers (no functions). So
// QKeySequence(...).toString() is NOT ALLOWED HERE.
// This must be in alphabetical order according to action name as it must have the same order as
@@ -346,6 +351,23 @@ void Config::ReadTouchscreenValues() {
ReadSetting(QStringLiteral("touchscreen_diameter_y"), 15).toUInt();
}
+void Config::ReadHidbusValues() {
+ Settings::values.enable_ring_controller =
+ ReadSetting(QStringLiteral("enable_ring_controller"), true).toBool();
+
+ const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
+ 0, 0, default_ringcon_analogs[0], default_ringcon_analogs[1], 0, 0.05f);
+ auto& ringcon_analogs = Settings::values.ringcon_analogs;
+
+ ringcon_analogs =
+ qt_config->value(QStringLiteral("ring_controller"), QString::fromStdString(default_param))
+ .toString()
+ .toStdString();
+ if (ringcon_analogs.empty()) {
+ ringcon_analogs = default_param;
+ }
+}
+
void Config::ReadAudioValues() {
qt_config->beginGroup(QStringLiteral("Audio"));
@@ -369,6 +391,7 @@ void Config::ReadControlValues() {
ReadMouseValues();
ReadTouchscreenValues();
ReadMotionTouchValues();
+ ReadHidbusValues();
#ifdef _WIN32
ReadBasicSetting(Settings::values.enable_raw_input);
@@ -775,6 +798,7 @@ void Config::ReadUIValues() {
ReadBasicSetting(UISettings::values.pause_when_in_background);
ReadBasicSetting(UISettings::values.mute_when_in_background);
ReadBasicSetting(UISettings::values.hide_mouse);
+ ReadBasicSetting(UISettings::values.disable_web_applet);
qt_config->endGroup();
}
@@ -961,6 +985,16 @@ void Config::SaveMotionTouchValues() {
qt_config->endArray();
}
+void Config::SaveHidbusValues() {
+ WriteBasicSetting(Settings::values.enable_ring_controller);
+
+ const std::string default_param = InputCommon::GenerateAnalogParamFromKeys(
+ 0, 0, default_ringcon_analogs[0], default_ringcon_analogs[1], 0, 0.05f);
+ WriteSetting(QStringLiteral("ring_controller"),
+ QString::fromStdString(Settings::values.ringcon_analogs),
+ QString::fromStdString(default_param));
+}
+
void Config::SaveValues() {
if (global) {
SaveControlValues();
@@ -1001,6 +1035,7 @@ void Config::SaveControlValues() {
SaveMouseValues();
SaveTouchscreenValues();
SaveMotionTouchValues();
+ SaveHidbusValues();
WriteGlobalSetting(Settings::values.use_docked_mode);
WriteGlobalSetting(Settings::values.vibration_enabled);
@@ -1308,6 +1343,7 @@ void Config::SaveUIValues() {
WriteBasicSetting(UISettings::values.pause_when_in_background);
WriteBasicSetting(UISettings::values.mute_when_in_background);
WriteBasicSetting(UISettings::values.hide_mouse);
+ WriteBasicSetting(UISettings::values.disable_web_applet);
qt_config->endGroup();
}
diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h
index ae3e36a11..f0ab6bdaa 100644
--- a/src/yuzu/configuration/config.h
+++ b/src/yuzu/configuration/config.h
@@ -42,6 +42,7 @@ public:
static const std::array<int, Settings::NativeMotion::NumMotions> default_motions;
static const std::array<std::array<int, 4>, Settings::NativeAnalog::NumAnalogs> default_analogs;
static const std::array<int, 2> default_stick_mod;
+ static const std::array<int, 2> default_ringcon_analogs;
static const std::array<int, Settings::NativeMouseButton::NumMouseButtons>
default_mouse_buttons;
static const std::array<int, Settings::NativeKeyboard::NumKeyboardKeys> default_keyboard_keys;
@@ -66,6 +67,7 @@ private:
void ReadMouseValues();
void ReadTouchscreenValues();
void ReadMotionTouchValues();
+ void ReadHidbusValues();
// Read functions bases off the respective config section names.
void ReadAudioValues();
@@ -93,6 +95,7 @@ private:
void SaveMouseValues();
void SaveTouchscreenValues();
void SaveMotionTouchValues();
+ void SaveHidbusValues();
// Save functions based off the respective config section names.
void SaveAudioValues();
diff --git a/src/yuzu/configuration/configure_audio.cpp b/src/yuzu/configuration/configure_audio.cpp
index 2f9285e77..512bdfc22 100644
--- a/src/yuzu/configuration/configure_audio.cpp
+++ b/src/yuzu/configuration/configure_audio.cpp
@@ -1,6 +1,5 @@
-// Copyright 2018 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
+// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
#include <memory>
diff --git a/src/yuzu/configuration/configure_audio.h b/src/yuzu/configuration/configure_audio.h
index 5d2d05e47..08c278eeb 100644
--- a/src/yuzu/configuration/configure_audio.h
+++ b/src/yuzu/configuration/configure_audio.h
@@ -1,6 +1,5 @@
-// Copyright 2018 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
+// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
diff --git a/src/yuzu/configuration/configure_cpu.cpp b/src/yuzu/configuration/configure_cpu.cpp
index 0de7fbfed..3d69fb03f 100644
--- a/src/yuzu/configuration/configure_cpu.cpp
+++ b/src/yuzu/configuration/configure_cpu.cpp
@@ -1,6 +1,5 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
+// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/common_types.h"
#include "common/settings.h"
diff --git a/src/yuzu/configuration/configure_cpu.h b/src/yuzu/configuration/configure_cpu.h
index 3209c11d5..86d928ca3 100644
--- a/src/yuzu/configuration/configure_cpu.h
+++ b/src/yuzu/configuration/configure_cpu.h
@@ -1,6 +1,5 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
+// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
diff --git a/src/yuzu/configuration/configure_cpu.ui b/src/yuzu/configuration/configure_cpu.ui
index 5d80a8c91..8ae569ee6 100644
--- a/src/yuzu/configuration/configure_cpu.ui
+++ b/src/yuzu/configuration/configure_cpu.ui
@@ -52,6 +52,11 @@
<string>Unsafe</string>
</property>
</item>
+ <item>
+ <property name="text">
+ <string>Paranoid (disables most optimizations)</string>
+ </property>
+ </item>
</widget>
</item>
</layout>
diff --git a/src/yuzu/configuration/configure_cpu_debug.cpp b/src/yuzu/configuration/configure_cpu_debug.cpp
index 087d9496c..3c302ec16 100644
--- a/src/yuzu/configuration/configure_cpu_debug.cpp
+++ b/src/yuzu/configuration/configure_cpu_debug.cpp
@@ -1,6 +1,5 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
+// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/settings.h"
#include "core/core.h"
diff --git a/src/yuzu/configuration/configure_cpu_debug.h b/src/yuzu/configuration/configure_cpu_debug.h
index d06c4c63f..566ae7ecc 100644
--- a/src/yuzu/configuration/configure_cpu_debug.h
+++ b/src/yuzu/configuration/configure_cpu_debug.h
@@ -1,6 +1,5 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
+// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp
index c1cf4050c..bd50f7a68 100644
--- a/src/yuzu/configuration/configure_debug.cpp
+++ b/src/yuzu/configuration/configure_debug.cpp
@@ -59,6 +59,13 @@ void ConfigureDebug::SetConfiguration() {
ui->disable_loop_safety_checks->setChecked(
Settings::values.disable_shader_loop_safety_checks.GetValue());
ui->extended_logging->setChecked(Settings::values.extended_logging.GetValue());
+
+#ifdef YUZU_USE_QT_WEB_ENGINE
+ ui->disable_web_applet->setChecked(UISettings::values.disable_web_applet.GetValue());
+#else
+ ui->disable_web_applet->setEnabled(false);
+ ui->disable_web_applet->setText(QString::fromUtf8("Web applet not compiled"));
+#endif
}
void ConfigureDebug::ApplyConfiguration() {
@@ -80,6 +87,7 @@ void ConfigureDebug::ApplyConfiguration() {
ui->disable_loop_safety_checks->isChecked();
Settings::values.disable_macro_jit = ui->disable_macro_jit->isChecked();
Settings::values.extended_logging = ui->extended_logging->isChecked();
+ UISettings::values.disable_web_applet = ui->disable_web_applet->isChecked();
Debugger::ToggleConsole();
Common::Log::Filter filter;
filter.ParseFilterString(Settings::values.log_filter.GetValue());
diff --git a/src/yuzu/configuration/configure_debug.ui b/src/yuzu/configuration/configure_debug.ui
index 4dd870855..c1d90d588 100644
--- a/src/yuzu/configuration/configure_debug.ui
+++ b/src/yuzu/configuration/configure_debug.ui
@@ -8,49 +8,49 @@
<property name="title">
<string>Logging</string>
</property>
- <layout class="QGridLayout" name="gridLayout_1">
- <item row="0" column="0" colspan="2">
- <layout class="QHBoxLayout" name="horizontalLayout_1">
- <item>
- <widget class="QLabel" name="label_1">
- <property name="text">
- <string>Global Log Filter</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLineEdit" name="log_filter_edit"/>
- </item>
- </layout>
- </item>
- <item row="1" column="0">
- <widget class="QCheckBox" name="toggle_console">
- <property name="text">
- <string>Show Log in Console</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QPushButton" name="open_log_button">
- <property name="text">
- <string>Open Log Location</string>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QCheckBox" name="extended_logging">
- <property name="enabled">
- <bool>true</bool>
- </property>
- <property name="toolTip">
- <string>When checked, the max size of the log increases from 100 MB to 1 GB</string>
- </property>
+ <layout class="QGridLayout" name="gridLayout_1">
+ <item row="0" column="0" colspan="2">
+ <layout class="QHBoxLayout" name="horizontalLayout_1">
+ <item>
+ <widget class="QLabel" name="label_1">
<property name="text">
- <string>Enable Extended Logging**</string>
+ <string>Global Log Filter</string>
</property>
- </widget>
- </item>
- </layout>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLineEdit" name="log_filter_edit"/>
+ </item>
+ </layout>
+ </item>
+ <item row="1" column="0">
+ <widget class="QCheckBox" name="toggle_console">
+ <property name="text">
+ <string>Show Log in Console</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QPushButton" name="open_log_button">
+ <property name="text">
+ <string>Open Log Location</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QCheckBox" name="extended_logging">
+ <property name="enabled">
+ <bool>true</bool>
+ </property>
+ <property name="toolTip">
+ <string>When checked, the max size of the log increases from 100 MB to 1 GB</string>
+ </property>
+ <property name="text">
+ <string>Enable Extended Logging**</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
</widget>
</item>
<item>
@@ -183,7 +183,7 @@
<string>Advanced</string>
</property>
<layout class="QGridLayout" name="gridLayout_4">
- <item> row="0" column="0">
+ <item row="0" column="0">
<widget class="QCheckBox" name="quest_flag">
<property name="text">
<string>Kiosk (Quest) Mode</string>
@@ -214,7 +214,14 @@
<item row="1" column="1">
<widget class="QCheckBox" name="enable_all_controllers">
<property name="text">
- <string>Enable all Controller Types</string>
+ <string>Enable All Controller Types</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QCheckBox" name="disable_web_applet">
+ <property name="text">
+ <string>Disable Web Applet</string>
</property>
</widget>
</item>
diff --git a/src/yuzu/configuration/configure_debug_controller.cpp b/src/yuzu/configuration/configure_debug_controller.cpp
index 9a8de92a1..42abe9119 100644
--- a/src/yuzu/configuration/configure_debug_controller.cpp
+++ b/src/yuzu/configuration/configure_debug_controller.cpp
@@ -1,6 +1,5 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
+// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hid/hid_core.h"
#include "ui_configure_debug_controller.h"
diff --git a/src/yuzu/configuration/configure_debug_controller.h b/src/yuzu/configuration/configure_debug_controller.h
index d716edbc2..aaed717e2 100644
--- a/src/yuzu/configuration/configure_debug_controller.h
+++ b/src/yuzu/configuration/configure_debug_controller.h
@@ -1,6 +1,5 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
+// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
diff --git a/src/yuzu/configuration/configure_debug_tab.cpp b/src/yuzu/configuration/configure_debug_tab.cpp
index e69cca1ef..d1ca4752a 100644
--- a/src/yuzu/configuration/configure_debug_tab.cpp
+++ b/src/yuzu/configuration/configure_debug_tab.cpp
@@ -1,6 +1,5 @@
-// Copyright 2021 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
+// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
#include <memory>
#include "ui_configure_debug_tab.h"
diff --git a/src/yuzu/configuration/configure_debug_tab.h b/src/yuzu/configuration/configure_debug_tab.h
index 4f68260aa..c0fd9f73f 100644
--- a/src/yuzu/configuration/configure_debug_tab.h
+++ b/src/yuzu/configuration/configure_debug_tab.h
@@ -1,6 +1,5 @@
-// Copyright 2021 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
+// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp
index 69458a3ff..b415a1cc4 100644
--- a/src/yuzu/configuration/configure_dialog.cpp
+++ b/src/yuzu/configuration/configure_dialog.cpp
@@ -25,6 +25,7 @@
#include "yuzu/configuration/configure_ui.h"
#include "yuzu/configuration/configure_web.h"
#include "yuzu/hotkeys.h"
+#include "yuzu/uisettings.h"
ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry,
InputCommon::InputSubsystem* input_subsystem,
@@ -169,6 +170,8 @@ void ConfigureDialog::PopulateSelectionList() {
void ConfigureDialog::OnLanguageChanged(const QString& locale) {
emit LanguageChanged(locale);
+ // Reloading the game list is needed to force retranslation.
+ UISettings::values.is_game_list_reload_pending = true;
// first apply the configuration, and then restore the display
ApplyConfiguration();
RetranslateUI();
diff --git a/src/yuzu/configuration/configure_filesystem.cpp b/src/yuzu/configuration/configure_filesystem.cpp
index d6fb43f8b..ad1951754 100644
--- a/src/yuzu/configuration/configure_filesystem.cpp
+++ b/src/yuzu/configuration/configure_filesystem.cpp
@@ -1,6 +1,5 @@
-// Copyright 2019 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
+// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
#include <QFileDialog>
#include <QMessageBox>
diff --git a/src/yuzu/configuration/configure_filesystem.h b/src/yuzu/configuration/configure_filesystem.h
index b4f9355eb..31d2f1d56 100644
--- a/src/yuzu/configuration/configure_filesystem.h
+++ b/src/yuzu/configuration/configure_filesystem.h
@@ -1,6 +1,5 @@
-// Copyright 2019 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
+// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
diff --git a/src/yuzu/configuration/configure_graphics_advanced.cpp b/src/yuzu/configuration/configure_graphics_advanced.cpp
index 30c5a3595..7c3196c83 100644
--- a/src/yuzu/configuration/configure_graphics_advanced.cpp
+++ b/src/yuzu/configuration/configure_graphics_advanced.cpp
@@ -1,6 +1,5 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
+// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/settings.h"
#include "core/core.h"
diff --git a/src/yuzu/configuration/configure_graphics_advanced.h b/src/yuzu/configuration/configure_graphics_advanced.h
index 0a1724ce4..1ef7bd916 100644
--- a/src/yuzu/configuration/configure_graphics_advanced.h
+++ b/src/yuzu/configuration/configure_graphics_advanced.h
@@ -1,6 +1,5 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
+// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
diff --git a/src/yuzu/configuration/configure_hotkeys.cpp b/src/yuzu/configuration/configure_hotkeys.cpp
index 53e629a5e..6679e9c53 100644
--- a/src/yuzu/configuration/configure_hotkeys.cpp
+++ b/src/yuzu/configuration/configure_hotkeys.cpp
@@ -35,8 +35,9 @@ ConfigureHotkeys::ConfigureHotkeys(Core::HID::HIDCore& hid_core, QWidget* parent
ui->hotkey_list->setContextMenuPolicy(Qt::CustomContextMenu);
ui->hotkey_list->setModel(model);
- ui->hotkey_list->setColumnWidth(name_column, 200);
- ui->hotkey_list->resizeColumnToContents(hotkey_column);
+ ui->hotkey_list->header()->setStretchLastSection(false);
+ ui->hotkey_list->header()->setSectionResizeMode(name_column, QHeaderView::ResizeMode::Stretch);
+ ui->hotkey_list->header()->setMinimumSectionSize(150);
connect(ui->button_restore_defaults, &QPushButton::clicked, this,
&ConfigureHotkeys::RestoreDefaults);
@@ -76,8 +77,8 @@ void ConfigureHotkeys::Populate(const HotkeyRegistry& registry) {
}
ui->hotkey_list->expandAll();
- ui->hotkey_list->resizeColumnToContents(name_column);
ui->hotkey_list->resizeColumnToContents(hotkey_column);
+ ui->hotkey_list->resizeColumnToContents(controller_column);
}
void ConfigureHotkeys::changeEvent(QEvent* event) {
diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp
index 4ca74a5f7..73d7ba24b 100644
--- a/src/yuzu/configuration/configure_input.cpp
+++ b/src/yuzu/configuration/configure_input.cpp
@@ -20,6 +20,7 @@
#include "yuzu/configuration/configure_input_advanced.h"
#include "yuzu/configuration/configure_input_player.h"
#include "yuzu/configuration/configure_motion_touch.h"
+#include "yuzu/configuration/configure_ringcon.h"
#include "yuzu/configuration/configure_touchscreen_advanced.h"
#include "yuzu/configuration/configure_vibration.h"
#include "yuzu/configuration/input_profiles.h"
@@ -158,6 +159,10 @@ void ConfigureInput::Initialize(InputCommon::InputSubsystem* input_subsystem,
[this, input_subsystem] {
CallConfigureDialog<ConfigureMotionTouch>(*this, input_subsystem);
});
+ connect(advanced, &ConfigureInputAdvanced::CallRingControllerDialog,
+ [this, input_subsystem, &hid_core] {
+ CallConfigureDialog<ConfigureRingController>(*this, input_subsystem, hid_core);
+ });
connect(ui->vibrationButton, &QPushButton::clicked,
[this, &hid_core] { CallConfigureDialog<ConfigureVibration>(*this, hid_core); });
diff --git a/src/yuzu/configuration/configure_input_advanced.cpp b/src/yuzu/configuration/configure_input_advanced.cpp
index 20fc2599d..f14bdc831 100644
--- a/src/yuzu/configuration/configure_input_advanced.cpp
+++ b/src/yuzu/configuration/configure_input_advanced.cpp
@@ -1,6 +1,5 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
+// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
#include <QColorDialog>
#include "common/settings.h"
@@ -79,13 +78,17 @@ ConfigureInputAdvanced::ConfigureInputAdvanced(QWidget* parent)
&ConfigureInputAdvanced::UpdateUIEnabled);
connect(ui->touchscreen_enabled, &QCheckBox::stateChanged, this,
&ConfigureInputAdvanced::UpdateUIEnabled);
+ connect(ui->enable_ring_controller, &QCheckBox::stateChanged, this,
+ &ConfigureInputAdvanced::UpdateUIEnabled);
connect(ui->debug_configure, &QPushButton::clicked, this,
[this] { CallDebugControllerDialog(); });
connect(ui->touchscreen_advanced, &QPushButton::clicked, this,
[this] { CallTouchscreenConfigDialog(); });
connect(ui->buttonMotionTouch, &QPushButton::clicked, this,
- &ConfigureInputAdvanced::CallMotionTouchConfigDialog);
+ [this] { CallMotionTouchConfigDialog(); });
+ connect(ui->ring_controller_configure, &QPushButton::clicked, this,
+ [this] { CallRingControllerDialog(); });
#ifndef _WIN32
ui->enable_raw_input->setVisible(false);
@@ -132,6 +135,7 @@ void ConfigureInputAdvanced::ApplyConfiguration() {
Settings::values.enable_raw_input = ui->enable_raw_input->isChecked();
Settings::values.enable_udp_controller = ui->enable_udp_controller->isChecked();
Settings::values.controller_navigation = ui->controller_navigation->isChecked();
+ Settings::values.enable_ring_controller = ui->enable_ring_controller->isChecked();
}
void ConfigureInputAdvanced::LoadConfiguration() {
@@ -164,6 +168,7 @@ void ConfigureInputAdvanced::LoadConfiguration() {
ui->enable_raw_input->setChecked(Settings::values.enable_raw_input.GetValue());
ui->enable_udp_controller->setChecked(Settings::values.enable_udp_controller.GetValue());
ui->controller_navigation->setChecked(Settings::values.controller_navigation.GetValue());
+ ui->enable_ring_controller->setChecked(Settings::values.enable_ring_controller.GetValue());
UpdateUIEnabled();
}
@@ -185,4 +190,5 @@ void ConfigureInputAdvanced::UpdateUIEnabled() {
ui->touchscreen_advanced->setEnabled(ui->touchscreen_enabled->isChecked());
ui->mouse_panning->setEnabled(!ui->mouse_enabled->isChecked());
ui->mouse_panning_sensitivity->setEnabled(!ui->mouse_enabled->isChecked());
+ ui->ring_controller_configure->setEnabled(ui->enable_ring_controller->isChecked());
}
diff --git a/src/yuzu/configuration/configure_input_advanced.h b/src/yuzu/configuration/configure_input_advanced.h
index 3083d55c1..644e56dd8 100644
--- a/src/yuzu/configuration/configure_input_advanced.h
+++ b/src/yuzu/configuration/configure_input_advanced.h
@@ -1,6 +1,5 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
+// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
@@ -29,6 +28,7 @@ signals:
void CallMouseConfigDialog();
void CallTouchscreenConfigDialog();
void CallMotionTouchConfigDialog();
+ void CallRingControllerDialog();
private:
void changeEvent(QEvent* event) override;
diff --git a/src/yuzu/configuration/configure_input_advanced.ui b/src/yuzu/configuration/configure_input_advanced.ui
index 66f2075f2..14403cb10 100644
--- a/src/yuzu/configuration/configure_input_advanced.ui
+++ b/src/yuzu/configuration/configure_input_advanced.ui
@@ -2603,6 +2603,20 @@
</property>
</widget>
</item>
+ <item row="4" column="0">
+ <widget class="QCheckBox" name="enable_ring_controller">
+ <property name="text">
+ <string>Ring Controller</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="2">
+ <widget class="QPushButton" name="ring_controller_configure">
+ <property name="text">
+ <string>Configure</string>
+ </property>
+ </widget>
+ </item>
</layout>
</widget>
</item>
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index 8ef3596dd..b4f5d172a 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -10,6 +10,7 @@
#include <QMenu>
#include <QMessageBox>
#include <QTimer>
+#include "common/assert.h"
#include "common/param_package.h"
#include "core/hid/emulated_controller.h"
#include "core/hid/hid_core.h"
@@ -119,6 +120,23 @@ QString GetButtonName(Common::Input::ButtonNames button_name) {
}
}
+QString GetDirectionName(const std::string& direction) {
+ if (direction == "left") {
+ return QObject::tr("Left");
+ }
+ if (direction == "right") {
+ return QObject::tr("Right");
+ }
+ if (direction == "up") {
+ return QObject::tr("Up");
+ }
+ if (direction == "down") {
+ return QObject::tr("Down");
+ }
+ UNIMPLEMENTED_MSG("Unimplemented direction name={}", direction);
+ return QString::fromStdString(direction);
+}
+
void SetAnalogParam(const Common::ParamPackage& input_param, Common::ParamPackage& analog_param,
const std::string& button_name) {
// The poller returned a complete axis, so set all the buttons
@@ -162,7 +180,7 @@ QString ConfigureInputPlayer::ButtonToText(const Common::ParamPackage& param) {
if (common_button_name == Common::Input::ButtonNames::Value) {
if (param.Has("hat")) {
- const QString hat = QString::fromStdString(param.Get("direction", ""));
+ const QString hat = GetDirectionName(param.Get("direction", ""));
return QObject::tr("%1%2Hat %3").arg(toggle, inverted, hat);
}
if (param.Has("axis")) {
@@ -471,6 +489,25 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
[=, this](const Common::ParamPackage& params) {
Common::ParamPackage param = emulated_controller->GetStickParam(analog_id);
SetAnalogParam(params, param, analog_sub_buttons[sub_button_id]);
+ // Correct axis direction for inverted sticks
+ if (input_subsystem->IsStickInverted(param)) {
+ switch (analog_id) {
+ case Settings::NativeAnalog::LStick: {
+ const bool invert_value = param.Get("invert_x", "+") == "-";
+ const std::string invert_str = invert_value ? "+" : "-";
+ param.Set("invert_x", invert_str);
+ break;
+ }
+ case Settings::NativeAnalog::RStick: {
+ const bool invert_value = param.Get("invert_y", "+") == "-";
+ const std::string invert_str = invert_value ? "+" : "-";
+ param.Set("invert_y", invert_str);
+ break;
+ }
+ default:
+ break;
+ }
+ }
emulated_controller->SetStickParam(analog_id, param);
},
InputCommon::Polling::InputType::Stick);
@@ -1407,10 +1444,10 @@ void ConfigureInputPlayer::mousePressEvent(QMouseEvent* event) {
}
void ConfigureInputPlayer::keyPressEvent(QKeyEvent* event) {
- event->ignore();
if (!input_setter || !event) {
return;
}
+ event->ignore();
if (event->key() != Qt::Key_Escape) {
input_subsystem->GetKeyboard()->PressKey(event->key());
}
diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp
index fb168b2ca..11390fec0 100644
--- a/src/yuzu/configuration/configure_input_player_widget.cpp
+++ b/src/yuzu/configuration/configure_input_player_widget.cpp
@@ -1,6 +1,5 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
+// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
#include <algorithm>
#include <QMenu>
diff --git a/src/yuzu/configuration/configure_input_player_widget.h b/src/yuzu/configuration/configure_input_player_widget.h
index 3582ef77a..b258c6d77 100644
--- a/src/yuzu/configuration/configure_input_player_widget.h
+++ b/src/yuzu/configuration/configure_input_player_widget.h
@@ -1,6 +1,5 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
+// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
diff --git a/src/yuzu/configuration/configure_input_profile_dialog.cpp b/src/yuzu/configuration/configure_input_profile_dialog.cpp
index 17bbe6b61..58dffda51 100644
--- a/src/yuzu/configuration/configure_input_profile_dialog.cpp
+++ b/src/yuzu/configuration/configure_input_profile_dialog.cpp
@@ -1,6 +1,5 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
+// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/core.h"
#include "ui_configure_input_profile_dialog.h"
diff --git a/src/yuzu/configuration/configure_input_profile_dialog.h b/src/yuzu/configuration/configure_input_profile_dialog.h
index 84b1f6d1a..956cdf954 100644
--- a/src/yuzu/configuration/configure_input_profile_dialog.h
+++ b/src/yuzu/configuration/configure_input_profile_dialog.h
@@ -1,6 +1,5 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
+// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
diff --git a/src/yuzu/configuration/configure_network.cpp b/src/yuzu/configuration/configure_network.cpp
index 1f5799546..f87d3d53a 100644
--- a/src/yuzu/configuration/configure_network.cpp
+++ b/src/yuzu/configuration/configure_network.cpp
@@ -1,6 +1,5 @@
-// Copyright 2019 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
+// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
#include <QtConcurrent/QtConcurrent>
#include "common/settings.h"
diff --git a/src/yuzu/configuration/configure_network.h b/src/yuzu/configuration/configure_network.h
index 1d07d0b53..e8245cfdc 100644
--- a/src/yuzu/configuration/configure_network.h
+++ b/src/yuzu/configuration/configure_network.h
@@ -1,6 +1,5 @@
-// Copyright 2019 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
+// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
diff --git a/src/yuzu/configuration/configure_per_game.cpp b/src/yuzu/configuration/configure_per_game.cpp
index 55b2aa74f..54b3fe150 100644
--- a/src/yuzu/configuration/configure_per_game.cpp
+++ b/src/yuzu/configuration/configure_per_game.cpp
@@ -1,6 +1,5 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
+// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
#include <algorithm>
#include <filesystem>
diff --git a/src/yuzu/configuration/configure_per_game.h b/src/yuzu/configuration/configure_per_game.h
index b34b28577..e6dc05546 100644
--- a/src/yuzu/configuration/configure_per_game.h
+++ b/src/yuzu/configuration/configure_per_game.h
@@ -1,6 +1,5 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
+// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
diff --git a/src/yuzu/configuration/configure_per_game_addons.cpp b/src/yuzu/configuration/configure_per_game_addons.cpp
index 21e51d749..7893a85bb 100644
--- a/src/yuzu/configuration/configure_per_game_addons.cpp
+++ b/src/yuzu/configuration/configure_per_game_addons.cpp
@@ -47,6 +47,10 @@ ConfigurePerGameAddons::ConfigurePerGameAddons(Core::System& system_, QWidget* p
item_model->setHeaderData(0, Qt::Horizontal, tr("Patch Name"));
item_model->setHeaderData(1, Qt::Horizontal, tr("Version"));
+ tree_view->header()->setStretchLastSection(false);
+ tree_view->header()->setSectionResizeMode(0, QHeaderView::ResizeMode::Stretch);
+ tree_view->header()->setMinimumSectionSize(150);
+
// We must register all custom types with the Qt Automoc system so that we are able to use it
// with signals/slots. In this case, QList falls under the umbrella of custom types.
qRegisterMetaType<QList<QStandardItem*>>("QList<QStandardItem*>");
@@ -138,5 +142,5 @@ void ConfigurePerGameAddons::LoadConfiguration() {
item_model->appendRow(list_items.back());
}
- tree_view->setColumnWidth(0, 5 * tree_view->width() / 16);
+ tree_view->resizeColumnToContents(1);
}
diff --git a/src/yuzu/configuration/configure_ringcon.cpp b/src/yuzu/configuration/configure_ringcon.cpp
new file mode 100644
index 000000000..4fcc22b7a
--- /dev/null
+++ b/src/yuzu/configuration/configure_ringcon.cpp
@@ -0,0 +1,423 @@
+// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <memory>
+#include <QKeyEvent>
+#include <QMenu>
+#include <QTimer>
+
+#include "core/hid/emulated_devices.h"
+#include "core/hid/hid_core.h"
+#include "input_common/drivers/keyboard.h"
+#include "input_common/drivers/mouse.h"
+#include "input_common/main.h"
+#include "ui_configure_ringcon.h"
+#include "yuzu/bootmanager.h"
+#include "yuzu/configuration/config.h"
+#include "yuzu/configuration/configure_ringcon.h"
+
+const std::array<std::string, ConfigureRingController::ANALOG_SUB_BUTTONS_NUM>
+ ConfigureRingController::analog_sub_buttons{{
+ "left",
+ "right",
+ }};
+
+namespace {
+
+QString GetKeyName(int key_code) {
+ switch (key_code) {
+ case Qt::Key_Shift:
+ return QObject::tr("Shift");
+ case Qt::Key_Control:
+ return QObject::tr("Ctrl");
+ case Qt::Key_Alt:
+ return QObject::tr("Alt");
+ case Qt::Key_Meta:
+ return {};
+ default:
+ return QKeySequence(key_code).toString();
+ }
+}
+
+QString GetButtonName(Common::Input::ButtonNames button_name) {
+ switch (button_name) {
+ case Common::Input::ButtonNames::ButtonLeft:
+ return QObject::tr("Left");
+ case Common::Input::ButtonNames::ButtonRight:
+ return QObject::tr("Right");
+ case Common::Input::ButtonNames::ButtonDown:
+ return QObject::tr("Down");
+ case Common::Input::ButtonNames::ButtonUp:
+ return QObject::tr("Up");
+ case Common::Input::ButtonNames::TriggerZ:
+ return QObject::tr("Z");
+ case Common::Input::ButtonNames::TriggerR:
+ return QObject::tr("R");
+ case Common::Input::ButtonNames::TriggerL:
+ return QObject::tr("L");
+ case Common::Input::ButtonNames::ButtonA:
+ return QObject::tr("A");
+ case Common::Input::ButtonNames::ButtonB:
+ return QObject::tr("B");
+ case Common::Input::ButtonNames::ButtonX:
+ return QObject::tr("X");
+ case Common::Input::ButtonNames::ButtonY:
+ return QObject::tr("Y");
+ case Common::Input::ButtonNames::ButtonStart:
+ return QObject::tr("Start");
+ case Common::Input::ButtonNames::L1:
+ return QObject::tr("L1");
+ case Common::Input::ButtonNames::L2:
+ return QObject::tr("L2");
+ case Common::Input::ButtonNames::L3:
+ return QObject::tr("L3");
+ case Common::Input::ButtonNames::R1:
+ return QObject::tr("R1");
+ case Common::Input::ButtonNames::R2:
+ return QObject::tr("R2");
+ case Common::Input::ButtonNames::R3:
+ return QObject::tr("R3");
+ case Common::Input::ButtonNames::Circle:
+ return QObject::tr("Circle");
+ case Common::Input::ButtonNames::Cross:
+ return QObject::tr("Cross");
+ case Common::Input::ButtonNames::Square:
+ return QObject::tr("Square");
+ case Common::Input::ButtonNames::Triangle:
+ return QObject::tr("Triangle");
+ case Common::Input::ButtonNames::Share:
+ return QObject::tr("Share");
+ case Common::Input::ButtonNames::Options:
+ return QObject::tr("Options");
+ default:
+ return QObject::tr("[undefined]");
+ }
+}
+
+void SetAnalogParam(const Common::ParamPackage& input_param, Common::ParamPackage& analog_param,
+ const std::string& button_name) {
+ // The poller returned a complete axis, so set all the buttons
+ if (input_param.Has("axis_x") && input_param.Has("axis_y")) {
+ analog_param = input_param;
+ return;
+ }
+ // Check if the current configuration has either no engine or an axis binding.
+ // Clears out the old binding and adds one with analog_from_button.
+ if (!analog_param.Has("engine") || analog_param.Has("axis_x") || analog_param.Has("axis_y")) {
+ analog_param = {
+ {"engine", "analog_from_button"},
+ };
+ }
+ analog_param.Set(button_name, input_param.Serialize());
+}
+} // namespace
+
+ConfigureRingController::ConfigureRingController(QWidget* parent,
+ InputCommon::InputSubsystem* input_subsystem_,
+ Core::HID::HIDCore& hid_core_)
+ : QDialog(parent), timeout_timer(std::make_unique<QTimer>()),
+ poll_timer(std::make_unique<QTimer>()), input_subsystem{input_subsystem_},
+
+ ui(std::make_unique<Ui::ConfigureRingController>()) {
+ ui->setupUi(this);
+
+ analog_map_buttons = {
+ ui->buttonRingAnalogPull,
+ ui->buttonRingAnalogPush,
+ };
+
+ emulated_device = hid_core_.GetEmulatedDevices();
+ emulated_device->SaveCurrentConfig();
+ emulated_device->EnableConfiguration();
+
+ LoadConfiguration();
+
+ for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) {
+ auto* const analog_button = analog_map_buttons[sub_button_id];
+
+ if (analog_button == nullptr) {
+ continue;
+ }
+
+ connect(analog_button, &QPushButton::clicked, [=, this] {
+ HandleClick(
+ analog_map_buttons[sub_button_id],
+ [=, this](const Common::ParamPackage& params) {
+ Common::ParamPackage param = emulated_device->GetRingParam();
+ SetAnalogParam(params, param, analog_sub_buttons[sub_button_id]);
+ emulated_device->SetRingParam(param);
+ },
+ InputCommon::Polling::InputType::Stick);
+ });
+
+ analog_button->setContextMenuPolicy(Qt::CustomContextMenu);
+
+ connect(analog_button, &QPushButton::customContextMenuRequested,
+ [=, this](const QPoint& menu_location) {
+ QMenu context_menu;
+ Common::ParamPackage param = emulated_device->GetRingParam();
+ context_menu.addAction(tr("Clear"), [&] {
+ emulated_device->SetRingParam({});
+ analog_map_buttons[sub_button_id]->setText(tr("[not set]"));
+ });
+ context_menu.addAction(tr("Invert axis"), [&] {
+ const bool invert_value = param.Get("invert_x", "+") == "-";
+ const std::string invert_str = invert_value ? "+" : "-";
+ param.Set("invert_x", invert_str);
+ emulated_device->SetRingParam(param);
+ for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM;
+ ++sub_button_id) {
+ analog_map_buttons[sub_button_id]->setText(
+ AnalogToText(param, analog_sub_buttons[sub_button_id]));
+ }
+ });
+ context_menu.exec(
+ analog_map_buttons[sub_button_id]->mapToGlobal(menu_location));
+ });
+ }
+
+ connect(ui->sliderRingAnalogDeadzone, &QSlider::valueChanged, [=, this] {
+ Common::ParamPackage param = emulated_device->GetRingParam();
+ const auto slider_value = ui->sliderRingAnalogDeadzone->value();
+ ui->labelRingAnalogDeadzone->setText(tr("Deadzone: %1%").arg(slider_value));
+ param.Set("deadzone", slider_value / 100.0f);
+ emulated_device->SetRingParam(param);
+ });
+
+ connect(ui->restore_defaults_button, &QPushButton::clicked, this,
+ &ConfigureRingController::RestoreDefaults);
+
+ timeout_timer->setSingleShot(true);
+ connect(timeout_timer.get(), &QTimer::timeout, [this] { SetPollingResult({}, true); });
+
+ connect(poll_timer.get(), &QTimer::timeout, [this] {
+ const auto& params = input_subsystem->GetNextInput();
+ if (params.Has("engine") && IsInputAcceptable(params)) {
+ SetPollingResult(params, false);
+ return;
+ }
+ });
+
+ resize(0, 0);
+}
+
+ConfigureRingController::~ConfigureRingController() {
+ emulated_device->DisableConfiguration();
+};
+
+void ConfigureRingController::changeEvent(QEvent* event) {
+ if (event->type() == QEvent::LanguageChange) {
+ RetranslateUI();
+ }
+
+ QDialog::changeEvent(event);
+}
+
+void ConfigureRingController::RetranslateUI() {
+ ui->retranslateUi(this);
+}
+
+void ConfigureRingController::UpdateUI() {
+ RetranslateUI();
+ const Common::ParamPackage param = emulated_device->GetRingParam();
+
+ for (int sub_button_id = 0; sub_button_id < ANALOG_SUB_BUTTONS_NUM; ++sub_button_id) {
+ auto* const analog_button = analog_map_buttons[sub_button_id];
+
+ if (analog_button == nullptr) {
+ continue;
+ }
+
+ analog_button->setText(AnalogToText(param, analog_sub_buttons[sub_button_id]));
+ }
+
+ const auto deadzone_label = ui->labelRingAnalogDeadzone;
+ const auto deadzone_slider = ui->sliderRingAnalogDeadzone;
+
+ int slider_value = static_cast<int>(param.Get("deadzone", 0.15f) * 100);
+ deadzone_label->setText(tr("Deadzone: %1%").arg(slider_value));
+ deadzone_slider->setValue(slider_value);
+}
+
+void ConfigureRingController::ApplyConfiguration() {
+ emulated_device->DisableConfiguration();
+ emulated_device->SaveCurrentConfig();
+ emulated_device->EnableConfiguration();
+}
+
+void ConfigureRingController::LoadConfiguration() {
+ UpdateUI();
+}
+
+void ConfigureRingController::RestoreDefaults() {
+ const std::string default_ring_string = InputCommon::GenerateAnalogParamFromKeys(
+ 0, 0, Config::default_ringcon_analogs[0], Config::default_ringcon_analogs[1], 0, 0.05f);
+ emulated_device->SetRingParam(Common::ParamPackage(default_ring_string));
+ UpdateUI();
+}
+
+void ConfigureRingController::HandleClick(
+ QPushButton* button, std::function<void(const Common::ParamPackage&)> new_input_setter,
+ InputCommon::Polling::InputType type) {
+ button->setText(tr("[waiting]"));
+ button->setFocus();
+
+ input_setter = new_input_setter;
+
+ input_subsystem->BeginMapping(type);
+
+ QWidget::grabMouse();
+ QWidget::grabKeyboard();
+
+ timeout_timer->start(2500); // Cancel after 2.5 seconds
+ poll_timer->start(25); // Check for new inputs every 25ms
+}
+
+void ConfigureRingController::SetPollingResult(const Common::ParamPackage& params, bool abort) {
+ timeout_timer->stop();
+ poll_timer->stop();
+ input_subsystem->StopMapping();
+
+ QWidget::releaseMouse();
+ QWidget::releaseKeyboard();
+
+ if (!abort) {
+ (*input_setter)(params);
+ }
+
+ UpdateUI();
+
+ input_setter = std::nullopt;
+}
+
+bool ConfigureRingController::IsInputAcceptable(const Common::ParamPackage& params) const {
+ return true;
+}
+
+void ConfigureRingController::mousePressEvent(QMouseEvent* event) {
+ if (!input_setter || !event) {
+ return;
+ }
+
+ const auto button = GRenderWindow::QtButtonToMouseButton(event->button());
+ input_subsystem->GetMouse()->PressButton(0, 0, 0, 0, button);
+}
+
+void ConfigureRingController::keyPressEvent(QKeyEvent* event) {
+ if (!input_setter || !event) {
+ return;
+ }
+ event->ignore();
+ if (event->key() != Qt::Key_Escape) {
+ input_subsystem->GetKeyboard()->PressKey(event->key());
+ }
+}
+
+QString ConfigureRingController::ButtonToText(const Common::ParamPackage& param) {
+ if (!param.Has("engine")) {
+ return QObject::tr("[not set]");
+ }
+
+ const QString toggle = QString::fromStdString(param.Get("toggle", false) ? "~" : "");
+ const QString inverted = QString::fromStdString(param.Get("inverted", false) ? "!" : "");
+ const auto common_button_name = input_subsystem->GetButtonName(param);
+
+ // Retrieve the names from Qt
+ if (param.Get("engine", "") == "keyboard") {
+ const QString button_str = GetKeyName(param.Get("code", 0));
+ return QObject::tr("%1%2").arg(toggle, button_str);
+ }
+
+ if (common_button_name == Common::Input::ButtonNames::Invalid) {
+ return QObject::tr("[invalid]");
+ }
+
+ if (common_button_name == Common::Input::ButtonNames::Engine) {
+ return QString::fromStdString(param.Get("engine", ""));
+ }
+
+ if (common_button_name == Common::Input::ButtonNames::Value) {
+ if (param.Has("hat")) {
+ const QString hat = QString::fromStdString(param.Get("direction", ""));
+ return QObject::tr("%1%2Hat %3").arg(toggle, inverted, hat);
+ }
+ if (param.Has("axis")) {
+ const QString axis = QString::fromStdString(param.Get("axis", ""));
+ return QObject::tr("%1%2Axis %3").arg(toggle, inverted, axis);
+ }
+ if (param.Has("axis_x") && param.Has("axis_y") && param.Has("axis_z")) {
+ const QString axis_x = QString::fromStdString(param.Get("axis_x", ""));
+ const QString axis_y = QString::fromStdString(param.Get("axis_y", ""));
+ const QString axis_z = QString::fromStdString(param.Get("axis_z", ""));
+ return QObject::tr("%1%2Axis %3,%4,%5").arg(toggle, inverted, axis_x, axis_y, axis_z);
+ }
+ if (param.Has("motion")) {
+ const QString motion = QString::fromStdString(param.Get("motion", ""));
+ return QObject::tr("%1%2Motion %3").arg(toggle, inverted, motion);
+ }
+ if (param.Has("button")) {
+ const QString button = QString::fromStdString(param.Get("button", ""));
+ return QObject::tr("%1%2Button %3").arg(toggle, inverted, button);
+ }
+ }
+
+ QString button_name = GetButtonName(common_button_name);
+ if (param.Has("hat")) {
+ return QObject::tr("%1%2Hat %3").arg(toggle, inverted, button_name);
+ }
+ if (param.Has("axis")) {
+ return QObject::tr("%1%2Axis %3").arg(toggle, inverted, button_name);
+ }
+ if (param.Has("motion")) {
+ return QObject::tr("%1%2Axis %3").arg(toggle, inverted, button_name);
+ }
+ if (param.Has("button")) {
+ return QObject::tr("%1%2Button %3").arg(toggle, inverted, button_name);
+ }
+
+ return QObject::tr("[unknown]");
+}
+
+QString ConfigureRingController::AnalogToText(const Common::ParamPackage& param,
+ const std::string& dir) {
+ if (!param.Has("engine")) {
+ return QObject::tr("[not set]");
+ }
+
+ if (param.Get("engine", "") == "analog_from_button") {
+ return ButtonToText(Common::ParamPackage{param.Get(dir, "")});
+ }
+
+ if (!param.Has("axis_x") || !param.Has("axis_y")) {
+ return QObject::tr("[unknown]");
+ }
+
+ const auto engine_str = param.Get("engine", "");
+ const QString axis_x_str = QString::fromStdString(param.Get("axis_x", ""));
+ const QString axis_y_str = QString::fromStdString(param.Get("axis_y", ""));
+ const bool invert_x = param.Get("invert_x", "+") == "-";
+ const bool invert_y = param.Get("invert_y", "+") == "-";
+
+ if (dir == "modifier") {
+ return QObject::tr("[unused]");
+ }
+
+ if (dir == "left") {
+ const QString invert_x_str = QString::fromStdString(invert_x ? "+" : "-");
+ return QObject::tr("Axis %1%2").arg(axis_x_str, invert_x_str);
+ }
+ if (dir == "right") {
+ const QString invert_x_str = QString::fromStdString(invert_x ? "-" : "+");
+ return QObject::tr("Axis %1%2").arg(axis_x_str, invert_x_str);
+ }
+ if (dir == "up") {
+ const QString invert_y_str = QString::fromStdString(invert_y ? "-" : "+");
+ return QObject::tr("Axis %1%2").arg(axis_y_str, invert_y_str);
+ }
+ if (dir == "down") {
+ const QString invert_y_str = QString::fromStdString(invert_y ? "+" : "-");
+ return QObject::tr("Axis %1%2").arg(axis_y_str, invert_y_str);
+ }
+
+ return QObject::tr("[unknown]");
+} \ No newline at end of file
diff --git a/src/yuzu/configuration/configure_ringcon.h b/src/yuzu/configuration/configure_ringcon.h
new file mode 100644
index 000000000..38a9cb716
--- /dev/null
+++ b/src/yuzu/configuration/configure_ringcon.h
@@ -0,0 +1,84 @@
+// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#pragma once
+
+#include <functional>
+#include <memory>
+#include <QDialog>
+
+namespace InputCommon {
+class InputSubsystem;
+} // namespace InputCommon
+
+namespace Core::HID {
+class HIDCore;
+class EmulatedDevices;
+} // namespace Core::HID
+
+namespace Ui {
+class ConfigureRingController;
+} // namespace Ui
+
+class ConfigureRingController : public QDialog {
+ Q_OBJECT
+
+public:
+ explicit ConfigureRingController(QWidget* parent, InputCommon::InputSubsystem* input_subsystem_,
+ Core::HID::HIDCore& hid_core_);
+ ~ConfigureRingController() override;
+
+ void ApplyConfiguration();
+
+private:
+ void changeEvent(QEvent* event) override;
+ void RetranslateUI();
+
+ void UpdateUI();
+
+ /// Load configuration settings.
+ void LoadConfiguration();
+
+ /// Restore all buttons to their default values.
+ void RestoreDefaults();
+
+ /// Called when the button was pressed.
+ void HandleClick(QPushButton* button,
+ std::function<void(const Common::ParamPackage&)> new_input_setter,
+ InputCommon::Polling::InputType type);
+
+ /// Finish polling and configure input using the input_setter.
+ void SetPollingResult(const Common::ParamPackage& params, bool abort);
+
+ /// Checks whether a given input can be accepted.
+ bool IsInputAcceptable(const Common::ParamPackage& params) const;
+
+ /// Handle mouse button press events.
+ void mousePressEvent(QMouseEvent* event) override;
+
+ /// Handle key press events.
+ void keyPressEvent(QKeyEvent* event) override;
+
+ QString ButtonToText(const Common::ParamPackage& param);
+
+ QString AnalogToText(const Common::ParamPackage& param, const std::string& dir);
+
+ static constexpr int ANALOG_SUB_BUTTONS_NUM = 2;
+
+ // A group of four QPushButtons represent one analog input. The buttons each represent left,
+ // right, respectively.
+ std::array<QPushButton*, ANALOG_SUB_BUTTONS_NUM> analog_map_buttons;
+
+ static const std::array<std::string, ANALOG_SUB_BUTTONS_NUM> analog_sub_buttons;
+
+ std::unique_ptr<QTimer> timeout_timer;
+ std::unique_ptr<QTimer> poll_timer;
+
+ /// This will be the the setting function when an input is awaiting configuration.
+ std::optional<std::function<void(const Common::ParamPackage&)>> input_setter;
+
+ InputCommon::InputSubsystem* input_subsystem;
+ Core::HID::EmulatedDevices* emulated_device;
+
+ std::unique_ptr<Ui::ConfigureRingController> ui;
+};
diff --git a/src/yuzu/configuration/configure_ringcon.ui b/src/yuzu/configuration/configure_ringcon.ui
new file mode 100644
index 000000000..9ec634dd4
--- /dev/null
+++ b/src/yuzu/configuration/configure_ringcon.ui
@@ -0,0 +1,278 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>ConfigureRingController</class>
+ <widget class="QDialog" name="ConfigureRingController">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>298</width>
+ <height>339</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Configure Ring Controller</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="minimumSize">
+ <size>
+ <width>280</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="text">
+ <string>If you want to use this controller configure player 1 as right controller and player 2 as dual joycon before starting the game to allow this controller to be detected properly.</string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Fixed</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>10</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="RingAnalog">
+ <property name="title">
+ <string>Ring Sensor Parameters</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <property name="spacing">
+ <number>0</number>
+ </property>
+ <property name="sizeConstraint">
+ <enum>QLayout::SetDefaultConstraint</enum>
+ </property>
+ <property name="leftMargin">
+ <number>3</number>
+ </property>
+ <property name="topMargin">
+ <number>6</number>
+ </property>
+ <property name="rightMargin">
+ <number>3</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <layout class="QHBoxLayout" name="buttonRingAnalogPullHorizontaLayout">
+ <property name="spacing">
+ <number>3</number>
+ </property>
+ <item alignment="Qt::AlignHCenter">
+ <widget class="QGroupBox" name="buttonRingAnalogPullGroup">
+ <property name="title">
+ <string>Pull</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ <layout class="QVBoxLayout" name="buttonRingAnalogPullVerticalLayout">
+ <property name="spacing">
+ <number>3</number>
+ </property>
+ <property name="leftMargin">
+ <number>3</number>
+ </property>
+ <property name="topMargin">
+ <number>3</number>
+ </property>
+ <property name="rightMargin">
+ <number>3</number>
+ </property>
+ <property name="bottomMargin">
+ <number>3</number>
+ </property>
+ <item>
+ <widget class="QPushButton" name="buttonRingAnalogPull">
+ <property name="minimumSize">
+ <size>
+ <width>68</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>68</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">min-width: 68px;</string>
+ </property>
+ <property name="text">
+ <string>Pull</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item alignment="Qt::AlignHCenter">
+ <widget class="QGroupBox" name="buttonRingAnalogPushGroup">
+ <property name="title">
+ <string>Push</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignCenter</set>
+ </property>
+ <layout class="QVBoxLayout" name="buttonRingAnalogPushVerticalLayout">
+ <property name="spacing">
+ <number>3</number>
+ </property>
+ <property name="leftMargin">
+ <number>3</number>
+ </property>
+ <property name="topMargin">
+ <number>3</number>
+ </property>
+ <property name="rightMargin">
+ <number>3</number>
+ </property>
+ <property name="bottomMargin">
+ <number>3</number>
+ </property>
+ <item>
+ <widget class="QPushButton" name="buttonRingAnalogPush">
+ <property name="minimumSize">
+ <size>
+ <width>68</width>
+ <height>0</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>68</width>
+ <height>16777215</height>
+ </size>
+ </property>
+ <property name="styleSheet">
+ <string notr="true">min-width: 68px;</string>
+ </property>
+ <property name="text">
+ <string>Push</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="sliderRingAnalogDeadzoneVerticalLayout">
+ <property name="spacing">
+ <number>3</number>
+ </property>
+ <property name="sizeConstraint">
+ <enum>QLayout::SetDefaultConstraint</enum>
+ </property>
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>10</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>3</number>
+ </property>
+ <item>
+ <layout class="QHBoxLayout" name="sliderRingAnalogDeadzoneHorizontalLayout">
+ <item>
+ <widget class="QLabel" name="labelRingAnalogDeadzone">
+ <property name="text">
+ <string>Deadzone: 0%</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignHCenter</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QSlider" name="sliderRingAnalogDeadzone">
+ <property name="maximum">
+ <number>100</number>
+ </property>
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QPushButton" name="restore_defaults_button">
+ <property name="text">
+ <string>Restore Defaults</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="buttonBox">
+ <property name="standardButtons">
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>ConfigureRingController</receiver>
+ <slot>accept()</slot>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>ConfigureRingController</receiver>
+ <slot>reject()</slot>
+ </connection>
+ </connections>
+</ui>
diff --git a/src/yuzu/configuration/configure_tas.cpp b/src/yuzu/configuration/configure_tas.cpp
index 979a8db61..1edc5f1f3 100644
--- a/src/yuzu/configuration/configure_tas.cpp
+++ b/src/yuzu/configuration/configure_tas.cpp
@@ -1,6 +1,5 @@
-// Copyright 2021 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
+// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
#include <QFileDialog>
#include <QMessageBox>
diff --git a/src/yuzu/configuration/configure_tas.h b/src/yuzu/configuration/configure_tas.h
index 23a3673a7..4a6b0ba4e 100644
--- a/src/yuzu/configuration/configure_tas.h
+++ b/src/yuzu/configuration/configure_tas.h
@@ -1,6 +1,5 @@
-// Copyright 2021 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
+// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
diff --git a/src/yuzu/configuration/configure_vibration.cpp b/src/yuzu/configuration/configure_vibration.cpp
index d134ed02f..d765e808a 100644
--- a/src/yuzu/configuration/configure_vibration.cpp
+++ b/src/yuzu/configuration/configure_vibration.cpp
@@ -1,6 +1,5 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
+// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/settings.h"
#include "core/hid/emulated_controller.h"
diff --git a/src/yuzu/configuration/configure_vibration.h b/src/yuzu/configuration/configure_vibration.h
index 50b8195fa..e9d05df51 100644
--- a/src/yuzu/configuration/configure_vibration.h
+++ b/src/yuzu/configuration/configure_vibration.h
@@ -1,6 +1,5 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
+// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
diff --git a/src/yuzu/configuration/input_profiles.cpp b/src/yuzu/configuration/input_profiles.cpp
index 38ea6c772..20b22e7de 100644
--- a/src/yuzu/configuration/input_profiles.cpp
+++ b/src/yuzu/configuration/input_profiles.cpp
@@ -1,6 +1,5 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
+// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
#include <fmt/format.h>
diff --git a/src/yuzu/configuration/input_profiles.h b/src/yuzu/configuration/input_profiles.h
index 7353aa77b..65fc9e62c 100644
--- a/src/yuzu/configuration/input_profiles.h
+++ b/src/yuzu/configuration/input_profiles.h
@@ -1,6 +1,5 @@
-// Copyright 2020 yuzu Emulator Project
-// Licensed under GPLv2 or any later version
-// Refer to the license.txt file included.
+// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
+// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once