diff --git a/Source/Core/DolphinQt/Config/Mapping/MappingButton.cpp b/Source/Core/DolphinQt/Config/Mapping/MappingButton.cpp index 3af4c2e00e..d0e1ce4bbe 100644 --- a/Source/Core/DolphinQt/Config/Mapping/MappingButton.cpp +++ b/Source/Core/DolphinQt/Config/Mapping/MappingButton.cpp @@ -11,8 +11,6 @@ #include "DolphinQt/Config/Mapping/IOWindow.h" #include "DolphinQt/Config/Mapping/MappingWidget.h" #include "DolphinQt/Config/Mapping/MappingWindow.h" -#include "DolphinQt/QtUtils/BlockUserInputFilter.h" -#include "DolphinQt/QtUtils/SetWindowDecorations.h" #include "InputCommon/ControlReference/ControlReference.h" #include "InputCommon/ControllerEmu/ControllerEmu.h" @@ -67,15 +65,10 @@ static QString RefToDisplayString(ControlReference* ref) return expression; } -bool MappingButton::IsInput() const -{ - return m_reference->IsInput(); -} - MappingButton::MappingButton(MappingWidget* parent, ControlReference* ref) : ElidedButton(RefToDisplayString(ref)), m_mapping_window(parent->GetParent()), m_reference(ref) { - if (IsInput()) + if (m_reference->IsInput()) { setToolTip( tr("Left-click to detect input.\nMiddle-click to clear.\nRight-click for more options.")); @@ -88,10 +81,8 @@ MappingButton::MappingButton(MappingWidget* parent, ControlReference* ref) connect(this, &MappingButton::clicked, this, &MappingButton::Clicked); connect(parent, &MappingWidget::ConfigChanged, this, &MappingButton::ConfigChanged); - connect(this, &MappingButton::ConfigChanged, [this] { - setText(RefToDisplayString(m_reference)); - m_is_mapping = false; - }); + connect(this, &MappingButton::ConfigChanged, + [this] { setText(RefToDisplayString(m_reference)); }); } void MappingButton::AdvancedPressed() @@ -114,7 +105,6 @@ void MappingButton::Clicked() return; } - m_is_mapping = true; m_mapping_window->QueueInputDetection(this); } @@ -131,14 +121,6 @@ void MappingButton::Clear() m_mapping_window->UnQueueInputDetection(this); } -void MappingButton::StartMapping() -{ - // Focus just makes it more clear which button is currently being mapped. - setFocus(); - setText(tr("[ Press Now ]")); - QtUtils::InstallKeyboardBlocker(this, this, &MappingButton::ConfigChanged); -} - void MappingButton::mouseReleaseEvent(QMouseEvent* event) { switch (event->button()) diff --git a/Source/Core/DolphinQt/Config/Mapping/MappingButton.h b/Source/Core/DolphinQt/Config/Mapping/MappingButton.h index 76bb412079..733bdf3e9e 100644 --- a/Source/Core/DolphinQt/Config/Mapping/MappingButton.h +++ b/Source/Core/DolphinQt/Config/Mapping/MappingButton.h @@ -17,12 +17,11 @@ class MappingButton : public ElidedButton public: MappingButton(MappingWidget* widget, ControlReference* ref); - bool IsInput() const; ControlReference* GetControlReference(); - void StartMapping(); signals: void ConfigChanged(); + void QueueNextButtonMapping(); private: void Clear(); @@ -33,5 +32,4 @@ private: MappingWindow* const m_mapping_window; ControlReference* const m_reference; - bool m_is_mapping = false; }; diff --git a/Source/Core/DolphinQt/Config/Mapping/MappingCommon.cpp b/Source/Core/DolphinQt/Config/Mapping/MappingCommon.cpp index 37407f2298..54a0db59ef 100644 --- a/Source/Core/DolphinQt/Config/Mapping/MappingCommon.cpp +++ b/Source/Core/DolphinQt/Config/Mapping/MappingCommon.cpp @@ -10,6 +10,7 @@ #include "DolphinQt/Config/Mapping/MappingButton.h" #include "DolphinQt/Config/Mapping/MappingWindow.h" +#include "DolphinQt/QtUtils/BlockUserInputFilter.h" #include "InputCommon/ControlReference/ControlReference.h" #include "InputCommon/ControllerEmu/ControllerEmu.h" @@ -49,7 +50,10 @@ public: const auto& default_device = m_parent->GetController()->GetDefaultDevice(); auto& button = m_clicked_mapping_buttons.front(); - button->StartMapping(); + // Focus just makes it more clear which button is currently being mapped. + button->setFocus(); + button->setText(tr("[ Press Now ]")); + QtUtils::InstallKeyboardBlocker(button, button, &MappingButton::ConfigChanged); std::vector device_strings{default_device.ToString()}; if (m_parent->IsCreateOtherDeviceMappingsEnabled()) @@ -73,9 +77,17 @@ public: if (m_input_detector->IsComplete()) { - // No inputs detected. Cancel this and any other queued mappings. + auto* const button = m_clicked_mapping_buttons.back(); + if (!FinalizeMapping(m_input_detector->TakeResults())) + { + // No inputs detected. Cancel this and any other queued mappings. CancelMapping(); + } + else if (m_parent->IsIterativeMappingEnabled() && m_clicked_mapping_buttons.empty()) + { + button->QueueNextButtonMapping(); + } } } @@ -110,22 +122,20 @@ public: m_input_detection_start_timer->start(INPUT_DETECT_INITIAL_DELAY); } - void UnQueueInputDetection(MappingButton* button) + bool UnQueueInputDetection(MappingButton* button) { - std::erase(m_clicked_mapping_buttons, button); + if (!std::erase(m_clicked_mapping_buttons, button)) + return false; button->ConfigChanged(); UpdateInputDetectionStartTimer(); + return true; } void QueueInputDetection(MappingButton* button) { - // UnQueue if already queued. - if (std::erase(m_clicked_mapping_buttons, button)) - { - button->ConfigChanged(); - UpdateInputDetectionStartTimer(); + // Just UnQueue if already queued. + if (UnQueueInputDetection(button)) return; - } button->setText(QStringLiteral("[ ... ]")); m_clicked_mapping_buttons.push_back(button); diff --git a/Source/Core/DolphinQt/Config/Mapping/MappingWidget.cpp b/Source/Core/DolphinQt/Config/Mapping/MappingWidget.cpp index 82fe042f9a..442fff464f 100644 --- a/Source/Core/DolphinQt/Config/Mapping/MappingWidget.cpp +++ b/Source/Core/DolphinQt/Config/Mapping/MappingWidget.cpp @@ -314,6 +314,17 @@ void MappingWidget::CreateControl(const ControllerEmu::Control* control, QFormLa bool indicator) { auto* const button = new MappingButton(this, control->control_ref.get()); + + if (control->control_ref->IsInput()) + { + if (m_previous_mapping_button) + { + connect(m_previous_mapping_button, &MappingButton::QueueNextButtonMapping, + [this, button]() { m_parent->QueueInputDetection(button); }); + } + m_previous_mapping_button = button; + } + button->setMinimumWidth(100); button->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); diff --git a/Source/Core/DolphinQt/Config/Mapping/MappingWidget.h b/Source/Core/DolphinQt/Config/Mapping/MappingWidget.h index 31cf964fc3..f993968590 100644 --- a/Source/Core/DolphinQt/Config/Mapping/MappingWidget.h +++ b/Source/Core/DolphinQt/Config/Mapping/MappingWidget.h @@ -7,6 +7,7 @@ #include class InputConfig; +class MappingButton; class MappingNumeric; class MappingWindow; class QFormLayout; @@ -55,4 +56,5 @@ protected: private: MappingWindow* m_parent; + MappingButton* m_previous_mapping_button = nullptr; }; diff --git a/Source/Core/DolphinQt/Config/Mapping/MappingWindow.cpp b/Source/Core/DolphinQt/Config/Mapping/MappingWindow.cpp index 665d5e9659..d8eb6ec408 100644 --- a/Source/Core/DolphinQt/Config/Mapping/MappingWindow.cpp +++ b/Source/Core/DolphinQt/Config/Mapping/MappingWindow.cpp @@ -117,9 +117,13 @@ void MappingWindow::CreateDevicesLayout() m_wait_for_alternate_mappings = new QAction(tr("Wait for Alternate Input Mappings"), options); m_wait_for_alternate_mappings->setCheckable(true); + m_iterative_mapping = new QAction(tr("Enable Iterative Input Mapping"), options); + m_iterative_mapping->setCheckable(true); + options->addAction(refresh_action); options->addAction(m_other_device_mappings); options->addAction(m_wait_for_alternate_mappings); + options->addAction(m_iterative_mapping); options->setDefaultAction(refresh_action); m_devices_combo->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); @@ -368,6 +372,11 @@ bool MappingWindow::IsWaitForAlternateMappingsEnabled() const return m_wait_for_alternate_mappings->isChecked(); } +bool MappingWindow::IsIterativeMappingEnabled() const +{ + return m_iterative_mapping->isChecked(); +} + void MappingWindow::RefreshDevices() { g_controller_interface.RefreshDevices(); diff --git a/Source/Core/DolphinQt/Config/Mapping/MappingWindow.h b/Source/Core/DolphinQt/Config/Mapping/MappingWindow.h index 10bf590f35..f07aac7fd4 100644 --- a/Source/Core/DolphinQt/Config/Mapping/MappingWindow.h +++ b/Source/Core/DolphinQt/Config/Mapping/MappingWindow.h @@ -53,6 +53,7 @@ public: ControllerEmu::EmulatedController* GetController() const; bool IsCreateOtherDeviceMappingsEnabled() const; bool IsWaitForAlternateMappingsEnabled() const; + bool IsIterativeMappingEnabled() const; void ShowExtensionMotionTabs(bool show); void ActivateExtensionTab(); @@ -106,6 +107,7 @@ private: QComboBox* m_devices_combo; QAction* m_other_device_mappings; QAction* m_wait_for_alternate_mappings; + QAction* m_iterative_mapping; // Profiles QGroupBox* m_profiles_box;