From 0300b44d23b149a0b93dd0aa2e77d20a02882ddf Mon Sep 17 00:00:00 2001 From: JosJuice Date: Tue, 7 Mar 2023 19:22:09 +0100 Subject: [PATCH] DolphinQt: Rework TAS input threading, part 2 (analog inputs) --- Source/Core/DolphinQt/CMakeLists.txt | 2 + Source/Core/DolphinQt/DolphinQt.vcxproj | 2 + Source/Core/DolphinQt/TAS/TASInputWindow.cpp | 61 ++++++------------- Source/Core/DolphinQt/TAS/TASInputWindow.h | 24 ++++---- Source/Core/DolphinQt/TAS/TASSpinBox.cpp | 33 ++++++++++ Source/Core/DolphinQt/TAS/TASSpinBox.h | 29 +++++++++ .../Core/DolphinQt/TAS/WiiTASInputWindow.cpp | 1 + Source/Core/DolphinQt/TAS/WiiTASInputWindow.h | 5 +- 8 files changed, 101 insertions(+), 56 deletions(-) create mode 100644 Source/Core/DolphinQt/TAS/TASSpinBox.cpp create mode 100644 Source/Core/DolphinQt/TAS/TASSpinBox.h diff --git a/Source/Core/DolphinQt/CMakeLists.txt b/Source/Core/DolphinQt/CMakeLists.txt index 78a842f2bc..e9d24bc4d1 100644 --- a/Source/Core/DolphinQt/CMakeLists.txt +++ b/Source/Core/DolphinQt/CMakeLists.txt @@ -343,6 +343,8 @@ add_executable(dolphin-emu TAS/TASInputWindow.h TAS/TASSlider.cpp TAS/TASSlider.h + TAS/TASSpinBox.cpp + TAS/TASSpinBox.h TAS/WiiTASInputWindow.cpp TAS/WiiTASInputWindow.h ToolBar.cpp diff --git a/Source/Core/DolphinQt/DolphinQt.vcxproj b/Source/Core/DolphinQt/DolphinQt.vcxproj index 76b01c95d7..838e33d7a1 100644 --- a/Source/Core/DolphinQt/DolphinQt.vcxproj +++ b/Source/Core/DolphinQt/DolphinQt.vcxproj @@ -209,6 +209,7 @@ + @@ -389,6 +390,7 @@ + diff --git a/Source/Core/DolphinQt/TAS/TASInputWindow.cpp b/Source/Core/DolphinQt/TAS/TASInputWindow.cpp index 047b554b38..d74a84997f 100644 --- a/Source/Core/DolphinQt/TAS/TASInputWindow.cpp +++ b/Source/Core/DolphinQt/TAS/TASInputWindow.cpp @@ -23,6 +23,7 @@ #include "DolphinQt/TAS/StickWidget.h" #include "DolphinQt/TAS/TASCheckBox.h" #include "DolphinQt/TAS/TASSlider.h" +#include "DolphinQt/TAS/TASSpinBox.h" #include "InputCommon/ControllerEmu/ControllerEmu.h" #include "InputCommon/ControllerEmu/StickGate.h" @@ -109,11 +110,11 @@ QGroupBox* TASInputWindow::CreateStickInputs(const QString& text, std::string_vi const int y_default = static_cast(std::round(max_y / 2.)); auto* x_layout = new QHBoxLayout; - QSpinBox* x_value = CreateSliderValuePair(x_layout, x_default, max_x, x_shortcut_key_sequence, - Qt::Horizontal, box); + TASSpinBox* x_value = CreateSliderValuePair(x_layout, x_default, max_x, x_shortcut_key_sequence, + Qt::Horizontal, box); auto* y_layout = new QVBoxLayout; - QSpinBox* y_value = + TASSpinBox* y_value = CreateSliderValuePair(y_layout, y_default, max_y, y_shortcut_key_sequence, Qt::Vertical, box); y_value->setMaximumWidth(60); @@ -169,14 +170,14 @@ QBoxLayout* TASInputWindow::CreateSliderValuePairLayout( return layout; } -QSpinBox* TASInputWindow::CreateSliderValuePair( +TASSpinBox* TASInputWindow::CreateSliderValuePair( std::string_view group_name, std::string_view control_name, InputOverrider* overrider, QBoxLayout* layout, u16 zero, int default_, u16 min, u16 max, QKeySequence shortcut_key_sequence, Qt::Orientation orientation, QWidget* shortcut_widget, std::optional scale) { - QSpinBox* value = CreateSliderValuePair(layout, default_, max, shortcut_key_sequence, orientation, - shortcut_widget); + TASSpinBox* value = CreateSliderValuePair(layout, default_, max, shortcut_key_sequence, + orientation, shortcut_widget); InputOverrider::OverrideFunction func; if (scale) @@ -199,12 +200,12 @@ QSpinBox* TASInputWindow::CreateSliderValuePair( // The shortcut_widget argument needs to specify the container widget that will be hidden/shown. // This is done to avoid ambigous shortcuts -QSpinBox* TASInputWindow::CreateSliderValuePair(QBoxLayout* layout, int default_, u16 max, - QKeySequence shortcut_key_sequence, - Qt::Orientation orientation, - QWidget* shortcut_widget) +TASSpinBox* TASInputWindow::CreateSliderValuePair(QBoxLayout* layout, int default_, u16 max, + QKeySequence shortcut_key_sequence, + Qt::Orientation orientation, + QWidget* shortcut_widget) { - auto* value = new QSpinBox(); + auto* value = new TASSpinBox(); value->setRange(0, 99999); value->setValue(default_); connect(value, qOverload(&QSpinBox::valueChanged), [value, max](int i) { @@ -243,51 +244,27 @@ std::optional TASInputWindow::GetButton(TASCheckBox* checkbox, return checkbox->GetValue() ? 1.0 : 0.0; } -std::optional TASInputWindow::GetSpinBox(QSpinBox* spin, u16 zero, u16 min, u16 max, +std::optional TASInputWindow::GetSpinBox(TASSpinBox* spin, u16 zero, u16 min, u16 max, ControlState controller_state) { const u16 controller_value = ControllerEmu::EmulatedController::MapFloat(controller_state, zero, 0, max); if (m_use_controller->isChecked()) - { - if (!m_spinbox_most_recent_values.count(spin) || - m_spinbox_most_recent_values[spin] != controller_value) - { - QueueOnObjectBlocking(spin, [spin, controller_value] { spin->setValue(controller_value); }); - } + spin->OnControllerValueChanged(controller_value); - m_spinbox_most_recent_values[spin] = controller_value; - } - else - { - m_spinbox_most_recent_values.clear(); - } - - return ControllerEmu::EmulatedController::MapToFloat(spin->value(), zero, min, - max); + return ControllerEmu::EmulatedController::MapToFloat(spin->GetValue(), zero, + min, max); } -std::optional TASInputWindow::GetSpinBox(QSpinBox* spin, u16 zero, +std::optional TASInputWindow::GetSpinBox(TASSpinBox* spin, u16 zero, ControlState controller_state, ControlState scale) { const u16 controller_value = static_cast(std::llround(controller_state * scale + zero)); if (m_use_controller->isChecked()) - { - if (!m_spinbox_most_recent_values.count(spin) || - m_spinbox_most_recent_values[spin] != controller_value) - { - QueueOnObjectBlocking(spin, [spin, controller_value] { spin->setValue(controller_value); }); - } + spin->OnControllerValueChanged(controller_value); - m_spinbox_most_recent_values[spin] = controller_value; - } - else - { - m_spinbox_most_recent_values.clear(); - } - - return (spin->value() - zero) / scale; + return (spin->GetValue() - zero) / scale; } diff --git a/Source/Core/DolphinQt/TAS/TASInputWindow.h b/Source/Core/DolphinQt/TAS/TASInputWindow.h index 15aea29443..45d84ba014 100644 --- a/Source/Core/DolphinQt/TAS/TASInputWindow.h +++ b/Source/Core/DolphinQt/TAS/TASInputWindow.h @@ -22,6 +22,7 @@ class QGroupBox; class QSpinBox; class QString; class TASCheckBox; +class TASSpinBox; class InputOverrider final { @@ -57,14 +58,15 @@ protected: u16 zero, int default_, u16 min, u16 max, Qt::Key shortcut_key, QWidget* shortcut_widget, std::optional scale = {}); - QSpinBox* CreateSliderValuePair(std::string_view group_name, std::string_view control_name, - InputOverrider* overrider, QBoxLayout* layout, u16 zero, - int default_, u16 min, u16 max, - QKeySequence shortcut_key_sequence, Qt::Orientation orientation, - QWidget* shortcut_widget, std::optional scale = {}); - QSpinBox* CreateSliderValuePair(QBoxLayout* layout, int default_, u16 max, - QKeySequence shortcut_key_sequence, Qt::Orientation orientation, - QWidget* shortcut_widget); + TASSpinBox* CreateSliderValuePair(std::string_view group_name, std::string_view control_name, + InputOverrider* overrider, QBoxLayout* layout, u16 zero, + int default_, u16 min, u16 max, + QKeySequence shortcut_key_sequence, Qt::Orientation orientation, + QWidget* shortcut_widget, + std::optional scale = {}); + TASSpinBox* CreateSliderValuePair(QBoxLayout* layout, int default_, u16 max, + QKeySequence shortcut_key_sequence, Qt::Orientation orientation, + QWidget* shortcut_widget); QGroupBox* m_settings_box; QCheckBox* m_use_controller; @@ -73,10 +75,8 @@ protected: private: std::optional GetButton(TASCheckBox* checkbox, ControlState controller_state); - std::optional GetSpinBox(QSpinBox* spin, u16 zero, u16 min, u16 max, + std::optional GetSpinBox(TASSpinBox* spin, u16 zero, u16 min, u16 max, ControlState controller_state); - std::optional GetSpinBox(QSpinBox* spin, u16 zero, ControlState controller_state, + std::optional GetSpinBox(TASSpinBox* spin, u16 zero, ControlState controller_state, ControlState scale); - - std::map m_spinbox_most_recent_values; }; diff --git a/Source/Core/DolphinQt/TAS/TASSpinBox.cpp b/Source/Core/DolphinQt/TAS/TASSpinBox.cpp new file mode 100644 index 0000000000..30c3618b26 --- /dev/null +++ b/Source/Core/DolphinQt/TAS/TASSpinBox.cpp @@ -0,0 +1,33 @@ +// Copyright 2019 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "DolphinQt/TAS/TASSpinBox.h" + +#include "DolphinQt/QtUtils/QueueOnObject.h" + +TASSpinBox::TASSpinBox(QWidget* parent) : QSpinBox(parent) +{ + connect(this, QOverload::of(&TASSpinBox::valueChanged), this, &TASSpinBox::OnUIValueChanged); +} + +int TASSpinBox::GetValue() const +{ + return m_state.GetValue(); +} + +void TASSpinBox::OnControllerValueChanged(int new_value) +{ + if (m_state.OnControllerValueChanged(static_cast(new_value))) + QueueOnObject(this, &TASSpinBox::ApplyControllerValueChange); +} + +void TASSpinBox::OnUIValueChanged(int new_value) +{ + m_state.OnUIValueChanged(static_cast(new_value)); +} + +void TASSpinBox::ApplyControllerValueChange() +{ + const QSignalBlocker blocker(this); + setValue(m_state.ApplyControllerValueChange()); +} diff --git a/Source/Core/DolphinQt/TAS/TASSpinBox.h b/Source/Core/DolphinQt/TAS/TASSpinBox.h new file mode 100644 index 0000000000..55908911d7 --- /dev/null +++ b/Source/Core/DolphinQt/TAS/TASSpinBox.h @@ -0,0 +1,29 @@ +// Copyright 2023 Dolphin Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include + +#include "DolphinQt/TAS/TASControlState.h" + +class TASInputWindow; + +class TASSpinBox : public QSpinBox +{ + Q_OBJECT +public: + explicit TASSpinBox(QWidget* parent = nullptr); + + // Can be called from the CPU thread + int GetValue() const; + // Must be called from the CPU thread + void OnControllerValueChanged(int new_value); + +private slots: + void OnUIValueChanged(int new_value); + void ApplyControllerValueChange(); + +private: + TASControlState m_state; +}; diff --git a/Source/Core/DolphinQt/TAS/WiiTASInputWindow.cpp b/Source/Core/DolphinQt/TAS/WiiTASInputWindow.cpp index c38e340912..b6e54fb6da 100644 --- a/Source/Core/DolphinQt/TAS/WiiTASInputWindow.cpp +++ b/Source/Core/DolphinQt/TAS/WiiTASInputWindow.cpp @@ -29,6 +29,7 @@ #include "DolphinQt/QtUtils/QueueOnObject.h" #include "DolphinQt/TAS/IRWidget.h" #include "DolphinQt/TAS/TASCheckBox.h" +#include "DolphinQt/TAS/TASSpinBox.h" #include "InputCommon/ControllerEmu/ControlGroup/Attachments.h" #include "InputCommon/ControllerEmu/ControllerEmu.h" diff --git a/Source/Core/DolphinQt/TAS/WiiTASInputWindow.h b/Source/Core/DolphinQt/TAS/WiiTASInputWindow.h index ef01906741..63ce0fb4df 100644 --- a/Source/Core/DolphinQt/TAS/WiiTASInputWindow.h +++ b/Source/Core/DolphinQt/TAS/WiiTASInputWindow.h @@ -12,6 +12,7 @@ class QHideEvent; class QShowEvent; class QSpinBox; class TASCheckBox; +class TASSpinBox; namespace WiimoteEmu { @@ -75,8 +76,8 @@ private: TASCheckBox* m_classic_up_button; TASCheckBox* m_classic_down_button; TASCheckBox* m_classic_right_button; - QSpinBox* m_ir_x_value; - QSpinBox* m_ir_y_value; + TASSpinBox* m_ir_x_value; + TASSpinBox* m_ir_y_value; QGroupBox* m_remote_orientation_box; QGroupBox* m_nunchuk_orientation_box; QGroupBox* m_ir_box;