diff --git a/Source/Core/DolphinQt/CMakeLists.txt b/Source/Core/DolphinQt/CMakeLists.txt index 24a2ec9b35..7990a5d32b 100644 --- a/Source/Core/DolphinQt/CMakeLists.txt +++ b/Source/Core/DolphinQt/CMakeLists.txt @@ -192,6 +192,8 @@ add_executable(dolphin-emu Config/ToolTipControls/ToolTipWidget.h Config/VerifyWidget.cpp Config/VerifyWidget.h + Config/WiimoteControllersWidget.cpp + Config/WiimoteControllersWidget.h Debugger/BreakpointWidget.cpp Debugger/BreakpointWidget.h Debugger/CodeViewWidget.cpp diff --git a/Source/Core/DolphinQt/Config/ControllersWindow.cpp b/Source/Core/DolphinQt/Config/ControllersWindow.cpp index 42465f1a8c..f368ac9a72 100644 --- a/Source/Core/DolphinQt/Config/ControllersWindow.cpp +++ b/Source/Core/DolphinQt/Config/ControllersWindow.cpp @@ -26,15 +26,12 @@ #include "Core/Core.h" #include "Core/HW/SI/SI.h" #include "Core/HW/SI/SI_Device.h" -#include "Core/HW/Wiimote.h" -#include "Core/HW/WiimoteReal/WiimoteReal.h" #include "Core/IOS/IOS.h" -#include "Core/IOS/USB/Bluetooth/BTReal.h" #include "DolphinQt/Config/CommonControllersWidget.h" #include "DolphinQt/Config/Mapping/GCPadWiiUConfigDialog.h" #include "DolphinQt/Config/Mapping/MappingWindow.h" -#include "DolphinQt/QtUtils/ModalMessageBox.h" +#include "DolphinQt/Config/WiimoteControllersWidget.h" #include "DolphinQt/QtUtils/WrapInScrollArea.h" #include "DolphinQt/Settings.h" @@ -67,7 +64,7 @@ ControllersWindow::ControllersWindow(QWidget* parent) : QDialog(parent) setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint); CreateGamecubeLayout(); - CreateWiimoteLayout(); + m_wiimote_controllers = new WiimoteControllersWidget(this); m_common = new CommonControllersWidget(this); CreateMainLayout(); LoadSettings(); @@ -102,115 +99,13 @@ void ControllersWindow::CreateGamecubeLayout() m_gc_box->setLayout(m_gc_layout); } -static int GetRadioButtonIndicatorWidth() -{ - const QStyle* style = QApplication::style(); - QStyleOptionButton opt; - - // TODO: why does the macOS style act different? Is it because of the magic with - // Cocoa widgets it does behind the scenes? - if (style->objectName() == QStringLiteral("macintosh")) - return style->subElementRect(QStyle::SE_RadioButtonIndicator, &opt).width(); - - return style->subElementRect(QStyle::SE_RadioButtonContents, &opt).left(); -} - -static int GetLayoutHorizontalSpacing(const QGridLayout* layout) -{ - // TODO: shouldn't layout->horizontalSpacing() do all this? Why does it return -1? - int hspacing = layout->horizontalSpacing(); - if (hspacing >= 0) - return hspacing; - - // According to docs, this is the fallback if horizontalSpacing() isn't set. - auto style = layout->parentWidget()->style(); - hspacing = style->pixelMetric(QStyle::PM_LayoutHorizontalSpacing); - if (hspacing >= 0) - return hspacing; - - // Docs claim this is deprecated, but on macOS with Qt 5.8 this is the only one that actually - // works. - float pixel_ratio = QGuiApplication::primaryScreen()->devicePixelRatio(); -#ifdef __APPLE__ - // TODO is this still required? - hspacing = pixel_ratio * style->pixelMetric(QStyle::PM_DefaultLayoutSpacing); - if (hspacing >= 0) - return hspacing; -#endif - - // Ripped from qtbase/src/widgets/styles/qcommonstyle.cpp - return pixel_ratio * 6; -} - -void ControllersWindow::CreateWiimoteLayout() -{ - m_wiimote_layout = new QGridLayout(); - m_wiimote_box = new QGroupBox(tr("Wii Remotes")); - m_wiimote_box->setLayout(m_wiimote_layout); - - m_wiimote_passthrough = new QRadioButton(tr("Passthrough a Bluetooth adapter")); - m_wiimote_sync = new QPushButton(tr("Sync")); - m_wiimote_reset = new QPushButton(tr("Reset")); - m_wiimote_refresh = new QPushButton(tr("Refresh")); - m_wiimote_pt_labels[0] = new QLabel(tr("Sync real Wii Remotes and pair them")); - m_wiimote_pt_labels[1] = new QLabel(tr("Reset all saved Wii Remote pairings")); - m_wiimote_emu = new QRadioButton(tr("Emulate the Wii's Bluetooth adapter")); - m_wiimote_continuous_scanning = new QCheckBox(tr("Continuous Scanning")); - m_wiimote_real_balance_board = new QCheckBox(tr("Real Balance Board")); - m_wiimote_speaker_data = new QCheckBox(tr("Enable Speaker Data")); - m_wiimote_ciface = new QCheckBox(tr("Connect Wii Remotes for Emulated Controllers")); - - m_wiimote_layout->setVerticalSpacing(7); - m_wiimote_layout->setColumnMinimumWidth(0, GetRadioButtonIndicatorWidth() - - GetLayoutHorizontalSpacing(m_wiimote_layout)); - m_wiimote_layout->setColumnStretch(2, 1); - - // Passthrough BT - m_wiimote_layout->addWidget(m_wiimote_passthrough, m_wiimote_layout->rowCount(), 0, 1, -1); - - int sync_row = m_wiimote_layout->rowCount(); - m_wiimote_layout->addWidget(m_wiimote_pt_labels[0], sync_row, 1, 1, 2); - m_wiimote_layout->addWidget(m_wiimote_sync, sync_row, 3); - - int reset_row = m_wiimote_layout->rowCount(); - m_wiimote_layout->addWidget(m_wiimote_pt_labels[1], reset_row, 1, 1, 2); - m_wiimote_layout->addWidget(m_wiimote_reset, reset_row, 3); - - // Emulated BT - m_wiimote_layout->addWidget(m_wiimote_emu, m_wiimote_layout->rowCount(), 0, 1, -1); - - for (size_t i = 0; i < m_wiimote_groups.size(); i++) - { - auto* wm_label = m_wiimote_labels[i] = new QLabel(tr("Wii Remote %1").arg(i + 1)); - auto* wm_box = m_wiimote_boxes[i] = new QComboBox(); - auto* wm_button = m_wiimote_buttons[i] = new QPushButton(tr("Configure")); - - for (const auto& item : {tr("None"), tr("Emulated Wii Remote"), tr("Real Wii Remote")}) - wm_box->addItem(item); - - int wm_row = m_wiimote_layout->rowCount(); - m_wiimote_layout->addWidget(wm_label, wm_row, 1); - m_wiimote_layout->addWidget(wm_box, wm_row, 2); - m_wiimote_layout->addWidget(wm_button, wm_row, 3); - } - - m_wiimote_layout->addWidget(m_wiimote_real_balance_board, m_wiimote_layout->rowCount(), 1, 1, -1); - m_wiimote_layout->addWidget(m_wiimote_speaker_data, m_wiimote_layout->rowCount(), 1, 1, -1); - - m_wiimote_layout->addWidget(m_wiimote_ciface, m_wiimote_layout->rowCount(), 0, 1, -1); - - int continuous_scanning_row = m_wiimote_layout->rowCount(); - m_wiimote_layout->addWidget(m_wiimote_continuous_scanning, continuous_scanning_row, 0, 1, 3); - m_wiimote_layout->addWidget(m_wiimote_refresh, continuous_scanning_row, 3); -} - void ControllersWindow::CreateMainLayout() { auto* layout = new QVBoxLayout(); m_button_box = new QDialogButtonBox(QDialogButtonBox::Close); layout->addWidget(m_gc_box); - layout->addWidget(m_wiimote_box); + layout->addWidget(m_wiimote_controllers); layout->addWidget(m_common); layout->addStretch(); layout->addWidget(m_button_box); @@ -221,38 +116,9 @@ void ControllersWindow::CreateMainLayout() void ControllersWindow::ConnectWidgets() { connect(m_button_box, &QDialogButtonBox::rejected, this, &QDialog::reject); - connect(&Settings::Instance(), &Settings::EmulationStateChanged, this, - &ControllersWindow::UpdateDisabledWiimoteControls); - connect(m_wiimote_passthrough, &QRadioButton::toggled, this, - &ControllersWindow::OnWiimoteModeChanged); - connect(m_wiimote_ciface, &QCheckBox::toggled, this, &ControllersWindow::OnWiimoteModeChanged); - connect(m_wiimote_ciface, &QCheckBox::toggled, this, - &WiimoteReal::HandleWiimotesInControllerInterfaceSettingChange); - connect(m_wiimote_continuous_scanning, &QCheckBox::toggled, this, - &ControllersWindow::OnWiimoteModeChanged); - - connect(m_wiimote_continuous_scanning, &QCheckBox::toggled, this, - &ControllersWindow::SaveSettings); - connect(m_wiimote_real_balance_board, &QCheckBox::toggled, this, - &ControllersWindow::SaveSettings); - connect(m_wiimote_speaker_data, &QCheckBox::toggled, this, &ControllersWindow::SaveSettings); - connect(m_wiimote_sync, &QPushButton::clicked, this, - &ControllersWindow::OnBluetoothPassthroughSyncPressed); - connect(m_wiimote_reset, &QPushButton::clicked, this, - &ControllersWindow::OnBluetoothPassthroughResetPressed); - connect(m_wiimote_refresh, &QPushButton::clicked, this, - &ControllersWindow::OnWiimoteRefreshPressed); - - for (size_t i = 0; i < m_wiimote_groups.size(); i++) + for (size_t i = 0; i < m_gc_groups.size(); i++) { - connect(m_wiimote_boxes[i], qOverload(&QComboBox::currentIndexChanged), this, - &ControllersWindow::SaveSettings); - connect(m_wiimote_boxes[i], qOverload(&QComboBox::currentIndexChanged), this, - &ControllersWindow::OnWiimoteModeChanged); - connect(m_wiimote_buttons[i], &QPushButton::clicked, this, - &ControllersWindow::OnWiimoteConfigure); - connect(m_gc_controller_boxes[i], qOverload(&QComboBox::currentIndexChanged), this, &ControllersWindow::SaveSettings); connect(m_gc_controller_boxes[i], qOverload(&QComboBox::currentIndexChanged), this, @@ -261,52 +127,6 @@ void ControllersWindow::ConnectWidgets() } } -void ControllersWindow::OnWiimoteModeChanged() -{ - SaveSettings(); - - // Make sure continuous scanning setting is applied. - WiimoteReal::Initialize(::Wiimote::InitializeMode::DO_NOT_WAIT_FOR_WIIMOTES); - - UpdateDisabledWiimoteControls(); -} - -void ControllersWindow::UpdateDisabledWiimoteControls() -{ - const bool running = Core::GetState() != Core::State::Uninitialized; - - m_wiimote_emu->setEnabled(!running); - m_wiimote_passthrough->setEnabled(!running); - - const bool running_gc = running && !SConfig::GetInstance().bWii; - const bool enable_passthrough = m_wiimote_passthrough->isChecked() && !running_gc; - const bool enable_emu_bt = !m_wiimote_passthrough->isChecked() && !running_gc; - - m_wiimote_sync->setEnabled(enable_passthrough); - m_wiimote_reset->setEnabled(enable_passthrough); - - for (auto* pt_label : m_wiimote_pt_labels) - pt_label->setEnabled(enable_passthrough); - - for (size_t i = 0; i < m_wiimote_groups.size(); i++) - { - m_wiimote_labels[i]->setEnabled(enable_emu_bt); - m_wiimote_boxes[i]->setEnabled(enable_emu_bt); - - const bool is_emu_wiimote = m_wiimote_boxes[i]->currentIndex() == 1; - m_wiimote_buttons[i]->setEnabled(enable_emu_bt && is_emu_wiimote); - } - - m_wiimote_real_balance_board->setEnabled(enable_emu_bt); - m_wiimote_speaker_data->setEnabled(enable_emu_bt); - - const bool ciface_wiimotes = m_wiimote_ciface->isChecked(); - - m_wiimote_refresh->setEnabled((enable_emu_bt || ciface_wiimotes) && - !m_wiimote_continuous_scanning->isChecked()); - m_wiimote_continuous_scanning->setEnabled(enable_emu_bt || ciface_wiimotes); -} - void ControllersWindow::OnGCTypeChanged(int type) { const auto* box = static_cast(QObject::sender()); @@ -324,50 +144,6 @@ void ControllersWindow::OnGCTypeChanged(int type) SaveSettings(); } -void ControllersWindow::OnBluetoothPassthroughResetPressed() -{ - const auto ios = IOS::HLE::GetIOS(); - - if (!ios) - { - ModalMessageBox::warning( - this, tr("Warning"), - tr("Saved Wii Remote pairings can only be reset when a Wii game is running.")); - return; - } - - auto device = ios->GetDeviceByName("/dev/usb/oh1/57e/305"); - if (device != nullptr) - { - std::static_pointer_cast(device)->TriggerSyncButtonHeldEvent(); - } -} - -void ControllersWindow::OnBluetoothPassthroughSyncPressed() -{ - const auto ios = IOS::HLE::GetIOS(); - - if (!ios) - { - ModalMessageBox::warning(this, tr("Warning"), - tr("A sync can only be triggered when a Wii game is running.")); - return; - } - - auto device = ios->GetDeviceByName("/dev/usb/oh1/57e/305"); - - if (device != nullptr) - { - std::static_pointer_cast(device) - ->TriggerSyncButtonPressedEvent(); - } -} - -void ControllersWindow::OnWiimoteRefreshPressed() -{ - WiimoteReal::Refresh(); -} - void ControllersWindow::OnGCPadConfigure() { size_t index; @@ -412,37 +188,9 @@ void ControllersWindow::OnGCPadConfigure() window->show(); } -void ControllersWindow::OnWiimoteConfigure() -{ - size_t index; - for (index = 0; index < m_wiimote_groups.size(); index++) - { - if (m_wiimote_buttons[index] == QObject::sender()) - break; - } - - MappingWindow::Type type; - switch (m_wiimote_boxes[index]->currentIndex()) - { - case 0: // None - case 2: // Real Wii Remote - return; - case 1: // Emulated Wii Remote - type = MappingWindow::Type::MAPPING_WIIMOTE_EMU; - break; - default: - return; - } - - MappingWindow* window = new MappingWindow(this, type, static_cast(index)); - window->setAttribute(Qt::WA_DeleteOnClose, true); - window->setWindowModality(Qt::WindowModality::WindowModal); - window->show(); -} - void ControllersWindow::LoadSettings() { - for (size_t i = 0; i < m_wiimote_groups.size(); i++) + for (size_t i = 0; i < m_gc_groups.size(); i++) { const std::optional gc_index = ToGCMenuIndex(SConfig::GetInstance().m_SIDevice[i]); if (gc_index) @@ -450,41 +198,11 @@ void ControllersWindow::LoadSettings() m_gc_controller_boxes[i]->setCurrentIndex(*gc_index); m_gc_buttons[i]->setEnabled(*gc_index != 0 && *gc_index != 6); } - m_wiimote_boxes[i]->setCurrentIndex(int(WiimoteCommon::GetSource(u32(i)))); } - m_wiimote_real_balance_board->setChecked(WiimoteCommon::GetSource(WIIMOTE_BALANCE_BOARD) == - WiimoteSource::Real); - m_wiimote_speaker_data->setChecked(SConfig::GetInstance().m_WiimoteEnableSpeaker); - m_wiimote_ciface->setChecked(SConfig::GetInstance().connect_wiimotes_for_ciface); - m_wiimote_continuous_scanning->setChecked(SConfig::GetInstance().m_WiimoteContinuousScanning); - - if (SConfig::GetInstance().m_bt_passthrough_enabled) - m_wiimote_passthrough->setChecked(true); - else - m_wiimote_emu->setChecked(true); - - OnWiimoteModeChanged(); } void ControllersWindow::SaveSettings() { - SConfig::GetInstance().m_WiimoteEnableSpeaker = m_wiimote_speaker_data->isChecked(); - SConfig::GetInstance().connect_wiimotes_for_ciface = m_wiimote_ciface->isChecked(); - SConfig::GetInstance().m_WiimoteContinuousScanning = m_wiimote_continuous_scanning->isChecked(); - SConfig::GetInstance().m_bt_passthrough_enabled = m_wiimote_passthrough->isChecked(); - - WiimoteCommon::SetSource(WIIMOTE_BALANCE_BOARD, m_wiimote_real_balance_board->isChecked() ? - WiimoteSource::Real : - WiimoteSource::None); - - for (size_t i = 0; i < m_wiimote_groups.size(); i++) - { - const int index = m_wiimote_boxes[i]->currentIndex(); - WiimoteCommon::SetSource(u32(i), WiimoteSource(index)); - } - - UICommon::SaveWiimoteSources(); - for (size_t i = 0; i < m_gc_groups.size(); i++) { const int index = m_gc_controller_boxes[i]->currentIndex(); diff --git a/Source/Core/DolphinQt/Config/ControllersWindow.h b/Source/Core/DolphinQt/Config/ControllersWindow.h index b835f09366..13a4d8d73d 100644 --- a/Source/Core/DolphinQt/Config/ControllersWindow.h +++ b/Source/Core/DolphinQt/Config/ControllersWindow.h @@ -19,6 +19,7 @@ class QGroupBox; class QLabel; class QPushButton; class QRadioButton; +class WiimoteControllersWidget; class ControllersWindow final : public QDialog { @@ -27,18 +28,11 @@ public: explicit ControllersWindow(QWidget* parent); private: - void OnWiimoteModeChanged(); - void UpdateDisabledWiimoteControls(); void OnGCTypeChanged(int state); void SaveSettings(); - void OnBluetoothPassthroughSyncPressed(); - void OnBluetoothPassthroughResetPressed(); - void OnWiimoteRefreshPressed(); void OnGCPadConfigure(); - void OnWiimoteConfigure(); void CreateGamecubeLayout(); - void CreateWiimoteLayout(); void CreateMainLayout(); void ConnectWidgets(); void LoadSettings(); @@ -54,23 +48,7 @@ private: std::array m_gc_groups; // Wii Remote - QGroupBox* m_wiimote_box; - QGridLayout* m_wiimote_layout; - std::array m_wiimote_labels; - std::array m_wiimote_boxes; - std::array m_wiimote_buttons; - std::array m_wiimote_groups; - std::array m_wiimote_pt_labels; - - QRadioButton* m_wiimote_emu; - QRadioButton* m_wiimote_passthrough; - QPushButton* m_wiimote_sync; - QPushButton* m_wiimote_reset; - QCheckBox* m_wiimote_continuous_scanning; - QCheckBox* m_wiimote_real_balance_board; - QCheckBox* m_wiimote_speaker_data; - QCheckBox* m_wiimote_ciface; - QPushButton* m_wiimote_refresh; + WiimoteControllersWidget* m_wiimote_controllers; // Common CommonControllersWidget* m_common; diff --git a/Source/Core/DolphinQt/Config/WiimoteControllersWidget.cpp b/Source/Core/DolphinQt/Config/WiimoteControllersWidget.cpp new file mode 100644 index 0000000000..aebc9289b0 --- /dev/null +++ b/Source/Core/DolphinQt/Config/WiimoteControllersWidget.cpp @@ -0,0 +1,345 @@ +// Copyright 2021 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "DolphinQt/Config/WiimoteControllersWidget.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "Core/ConfigManager.h" +#include "Core/Core.h" +#include "Core/HW/Wiimote.h" +#include "Core/HW/WiimoteReal/WiimoteReal.h" +#include "Core/IOS/IOS.h" +#include "Core/IOS/USB/Bluetooth/BTReal.h" + +#include "DolphinQt/Config/Mapping/MappingWindow.h" +#include "DolphinQt/QtUtils/ModalMessageBox.h" +#include "DolphinQt/Settings.h" + +#include "UICommon/UICommon.h" + +WiimoteControllersWidget::WiimoteControllersWidget(QWidget* parent) : QWidget(parent) +{ + CreateLayout(); + LoadSettings(); + ConnectWidgets(); +} + +static int GetRadioButtonIndicatorWidth() +{ + const QStyle* style = QApplication::style(); + QStyleOptionButton opt; + + // TODO: why does the macOS style act different? Is it because of the magic with + // Cocoa widgets it does behind the scenes? + if (style->objectName() == QStringLiteral("macintosh")) + return style->subElementRect(QStyle::SE_RadioButtonIndicator, &opt).width(); + + return style->subElementRect(QStyle::SE_RadioButtonContents, &opt).left(); +} + +static int GetLayoutHorizontalSpacing(const QGridLayout* layout) +{ + // TODO: shouldn't layout->horizontalSpacing() do all this? Why does it return -1? + int hspacing = layout->horizontalSpacing(); + if (hspacing >= 0) + return hspacing; + + // According to docs, this is the fallback if horizontalSpacing() isn't set. + auto style = layout->parentWidget()->style(); + hspacing = style->pixelMetric(QStyle::PM_LayoutHorizontalSpacing); + if (hspacing >= 0) + return hspacing; + + // Docs claim this is deprecated, but on macOS with Qt 5.8 this is the only one that actually + // works. + float pixel_ratio = QGuiApplication::primaryScreen()->devicePixelRatio(); +#ifdef __APPLE__ + // TODO is this still required? + hspacing = pixel_ratio * style->pixelMetric(QStyle::PM_DefaultLayoutSpacing); + if (hspacing >= 0) + return hspacing; +#endif + + // Ripped from qtbase/src/widgets/styles/qcommonstyle.cpp + return pixel_ratio * 6; +} + +void WiimoteControllersWidget::CreateLayout() +{ + m_wiimote_layout = new QGridLayout(); + m_wiimote_box = new QGroupBox(tr("Wii Remotes")); + m_wiimote_box->setLayout(m_wiimote_layout); + + m_wiimote_passthrough = new QRadioButton(tr("Passthrough a Bluetooth adapter")); + m_wiimote_sync = new QPushButton(tr("Sync")); + m_wiimote_reset = new QPushButton(tr("Reset")); + m_wiimote_refresh = new QPushButton(tr("Refresh")); + m_wiimote_pt_labels[0] = new QLabel(tr("Sync real Wii Remotes and pair them")); + m_wiimote_pt_labels[1] = new QLabel(tr("Reset all saved Wii Remote pairings")); + m_wiimote_emu = new QRadioButton(tr("Emulate the Wii's Bluetooth adapter")); + m_wiimote_continuous_scanning = new QCheckBox(tr("Continuous Scanning")); + m_wiimote_real_balance_board = new QCheckBox(tr("Real Balance Board")); + m_wiimote_speaker_data = new QCheckBox(tr("Enable Speaker Data")); + m_wiimote_ciface = new QCheckBox(tr("Connect Wii Remotes for Emulated Controllers")); + + m_wiimote_layout->setVerticalSpacing(7); + m_wiimote_layout->setColumnMinimumWidth(0, GetRadioButtonIndicatorWidth() - + GetLayoutHorizontalSpacing(m_wiimote_layout)); + m_wiimote_layout->setColumnStretch(2, 1); + + // Passthrough BT + m_wiimote_layout->addWidget(m_wiimote_passthrough, m_wiimote_layout->rowCount(), 0, 1, -1); + + int sync_row = m_wiimote_layout->rowCount(); + m_wiimote_layout->addWidget(m_wiimote_pt_labels[0], sync_row, 1, 1, 2); + m_wiimote_layout->addWidget(m_wiimote_sync, sync_row, 3); + + int reset_row = m_wiimote_layout->rowCount(); + m_wiimote_layout->addWidget(m_wiimote_pt_labels[1], reset_row, 1, 1, 2); + m_wiimote_layout->addWidget(m_wiimote_reset, reset_row, 3); + + // Emulated BT + m_wiimote_layout->addWidget(m_wiimote_emu, m_wiimote_layout->rowCount(), 0, 1, -1); + + for (size_t i = 0; i < m_wiimote_groups.size(); i++) + { + auto* wm_label = m_wiimote_labels[i] = new QLabel(tr("Wii Remote %1").arg(i + 1)); + auto* wm_box = m_wiimote_boxes[i] = new QComboBox(); + auto* wm_button = m_wiimote_buttons[i] = new QPushButton(tr("Configure")); + + for (const auto& item : {tr("None"), tr("Emulated Wii Remote"), tr("Real Wii Remote")}) + wm_box->addItem(item); + + int wm_row = m_wiimote_layout->rowCount(); + m_wiimote_layout->addWidget(wm_label, wm_row, 1); + m_wiimote_layout->addWidget(wm_box, wm_row, 2); + m_wiimote_layout->addWidget(wm_button, wm_row, 3); + } + + m_wiimote_layout->addWidget(m_wiimote_real_balance_board, m_wiimote_layout->rowCount(), 1, 1, -1); + m_wiimote_layout->addWidget(m_wiimote_speaker_data, m_wiimote_layout->rowCount(), 1, 1, -1); + + m_wiimote_layout->addWidget(m_wiimote_ciface, m_wiimote_layout->rowCount(), 0, 1, -1); + + int continuous_scanning_row = m_wiimote_layout->rowCount(); + m_wiimote_layout->addWidget(m_wiimote_continuous_scanning, continuous_scanning_row, 0, 1, 3); + m_wiimote_layout->addWidget(m_wiimote_refresh, continuous_scanning_row, 3); + + auto* layout = new QVBoxLayout; + layout->setMargin(0); + layout->setAlignment(Qt::AlignTop); + layout->addWidget(m_wiimote_box); + setLayout(layout); +} + +void WiimoteControllersWidget::ConnectWidgets() +{ + connect(&Settings::Instance(), &Settings::EmulationStateChanged, this, + &WiimoteControllersWidget::UpdateDisabledWiimoteControls); + + connect(m_wiimote_passthrough, &QRadioButton::toggled, this, + &WiimoteControllersWidget::OnWiimoteModeChanged); + connect(m_wiimote_ciface, &QCheckBox::toggled, this, + &WiimoteControllersWidget::OnWiimoteModeChanged); + connect(m_wiimote_ciface, &QCheckBox::toggled, this, + &WiimoteReal::HandleWiimotesInControllerInterfaceSettingChange); + connect(m_wiimote_continuous_scanning, &QCheckBox::toggled, this, + &WiimoteControllersWidget::OnWiimoteModeChanged); + + connect(m_wiimote_continuous_scanning, &QCheckBox::toggled, this, + &WiimoteControllersWidget::SaveSettings); + connect(m_wiimote_real_balance_board, &QCheckBox::toggled, this, + &WiimoteControllersWidget::SaveSettings); + connect(m_wiimote_speaker_data, &QCheckBox::toggled, this, + &WiimoteControllersWidget::SaveSettings); + connect(m_wiimote_sync, &QPushButton::clicked, this, + &WiimoteControllersWidget::OnBluetoothPassthroughSyncPressed); + connect(m_wiimote_reset, &QPushButton::clicked, this, + &WiimoteControllersWidget::OnBluetoothPassthroughResetPressed); + connect(m_wiimote_refresh, &QPushButton::clicked, this, + &WiimoteControllersWidget::OnWiimoteRefreshPressed); + + for (size_t i = 0; i < m_wiimote_groups.size(); i++) + { + connect(m_wiimote_boxes[i], qOverload(&QComboBox::currentIndexChanged), this, + &WiimoteControllersWidget::SaveSettings); + connect(m_wiimote_boxes[i], qOverload(&QComboBox::currentIndexChanged), this, + &WiimoteControllersWidget::OnWiimoteModeChanged); + connect(m_wiimote_buttons[i], &QPushButton::clicked, this, + &WiimoteControllersWidget::OnWiimoteConfigure); + } +} + +void WiimoteControllersWidget::OnWiimoteModeChanged() +{ + SaveSettings(); + + // Make sure continuous scanning setting is applied. + WiimoteReal::Initialize(::Wiimote::InitializeMode::DO_NOT_WAIT_FOR_WIIMOTES); + + UpdateDisabledWiimoteControls(); +} + +void WiimoteControllersWidget::UpdateDisabledWiimoteControls() +{ + const bool running = Core::GetState() != Core::State::Uninitialized; + + m_wiimote_emu->setEnabled(!running); + m_wiimote_passthrough->setEnabled(!running); + + const bool running_gc = running && !SConfig::GetInstance().bWii; + const bool enable_passthrough = m_wiimote_passthrough->isChecked() && !running_gc; + const bool enable_emu_bt = !m_wiimote_passthrough->isChecked() && !running_gc; + + m_wiimote_sync->setEnabled(enable_passthrough); + m_wiimote_reset->setEnabled(enable_passthrough); + + for (auto* pt_label : m_wiimote_pt_labels) + pt_label->setEnabled(enable_passthrough); + + for (size_t i = 0; i < m_wiimote_groups.size(); i++) + { + m_wiimote_labels[i]->setEnabled(enable_emu_bt); + m_wiimote_boxes[i]->setEnabled(enable_emu_bt); + + const bool is_emu_wiimote = m_wiimote_boxes[i]->currentIndex() == 1; + m_wiimote_buttons[i]->setEnabled(enable_emu_bt && is_emu_wiimote); + } + + m_wiimote_real_balance_board->setEnabled(enable_emu_bt); + m_wiimote_speaker_data->setEnabled(enable_emu_bt); + + const bool ciface_wiimotes = m_wiimote_ciface->isChecked(); + + m_wiimote_refresh->setEnabled((enable_emu_bt || ciface_wiimotes) && + !m_wiimote_continuous_scanning->isChecked()); + m_wiimote_continuous_scanning->setEnabled(enable_emu_bt || ciface_wiimotes); +} + +void WiimoteControllersWidget::OnBluetoothPassthroughResetPressed() +{ + const auto ios = IOS::HLE::GetIOS(); + + if (!ios) + { + ModalMessageBox::warning( + this, tr("Warning"), + tr("Saved Wii Remote pairings can only be reset when a Wii game is running.")); + return; + } + + auto device = ios->GetDeviceByName("/dev/usb/oh1/57e/305"); + if (device != nullptr) + { + std::static_pointer_cast(device)->TriggerSyncButtonHeldEvent(); + } +} + +void WiimoteControllersWidget::OnBluetoothPassthroughSyncPressed() +{ + const auto ios = IOS::HLE::GetIOS(); + + if (!ios) + { + ModalMessageBox::warning(this, tr("Warning"), + tr("A sync can only be triggered when a Wii game is running.")); + return; + } + + auto device = ios->GetDeviceByName("/dev/usb/oh1/57e/305"); + + if (device != nullptr) + { + std::static_pointer_cast(device) + ->TriggerSyncButtonPressedEvent(); + } +} + +void WiimoteControllersWidget::OnWiimoteRefreshPressed() +{ + WiimoteReal::Refresh(); +} + +void WiimoteControllersWidget::OnWiimoteConfigure() +{ + size_t index; + for (index = 0; index < m_wiimote_groups.size(); index++) + { + if (m_wiimote_buttons[index] == QObject::sender()) + break; + } + + MappingWindow::Type type; + switch (m_wiimote_boxes[index]->currentIndex()) + { + case 0: // None + case 2: // Real Wii Remote + return; + case 1: // Emulated Wii Remote + type = MappingWindow::Type::MAPPING_WIIMOTE_EMU; + break; + default: + return; + } + + MappingWindow* window = new MappingWindow(this, type, static_cast(index)); + window->setAttribute(Qt::WA_DeleteOnClose, true); + window->setWindowModality(Qt::WindowModality::WindowModal); + window->show(); +} + +void WiimoteControllersWidget::LoadSettings() +{ + for (size_t i = 0; i < m_wiimote_groups.size(); i++) + { + m_wiimote_boxes[i]->setCurrentIndex(int(WiimoteCommon::GetSource(u32(i)))); + } + m_wiimote_real_balance_board->setChecked(WiimoteCommon::GetSource(WIIMOTE_BALANCE_BOARD) == + WiimoteSource::Real); + m_wiimote_speaker_data->setChecked(SConfig::GetInstance().m_WiimoteEnableSpeaker); + m_wiimote_ciface->setChecked(SConfig::GetInstance().connect_wiimotes_for_ciface); + m_wiimote_continuous_scanning->setChecked(SConfig::GetInstance().m_WiimoteContinuousScanning); + + if (SConfig::GetInstance().m_bt_passthrough_enabled) + m_wiimote_passthrough->setChecked(true); + else + m_wiimote_emu->setChecked(true); + + OnWiimoteModeChanged(); +} + +void WiimoteControllersWidget::SaveSettings() +{ + SConfig::GetInstance().m_WiimoteEnableSpeaker = m_wiimote_speaker_data->isChecked(); + SConfig::GetInstance().connect_wiimotes_for_ciface = m_wiimote_ciface->isChecked(); + SConfig::GetInstance().m_WiimoteContinuousScanning = m_wiimote_continuous_scanning->isChecked(); + SConfig::GetInstance().m_bt_passthrough_enabled = m_wiimote_passthrough->isChecked(); + + WiimoteCommon::SetSource(WIIMOTE_BALANCE_BOARD, m_wiimote_real_balance_board->isChecked() ? + WiimoteSource::Real : + WiimoteSource::None); + + for (size_t i = 0; i < m_wiimote_groups.size(); i++) + { + const int index = m_wiimote_boxes[i]->currentIndex(); + WiimoteCommon::SetSource(u32(i), WiimoteSource(index)); + } + + UICommon::SaveWiimoteSources(); + + SConfig::GetInstance().SaveSettings(); +} diff --git a/Source/Core/DolphinQt/Config/WiimoteControllersWidget.h b/Source/Core/DolphinQt/Config/WiimoteControllersWidget.h new file mode 100644 index 0000000000..2837cb6fa1 --- /dev/null +++ b/Source/Core/DolphinQt/Config/WiimoteControllersWidget.h @@ -0,0 +1,56 @@ +// Copyright 2021 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include + +#include + +class QCheckBox; +class QComboBox; +class QHBoxLayout; +class QGridLayout; +class QGroupBox; +class QLabel; +class QPushButton; +class QRadioButton; + +class WiimoteControllersWidget final : public QWidget +{ + Q_OBJECT +public: + explicit WiimoteControllersWidget(QWidget* parent); + +private: + void OnWiimoteModeChanged(); + void UpdateDisabledWiimoteControls(); + void SaveSettings(); + void OnBluetoothPassthroughSyncPressed(); + void OnBluetoothPassthroughResetPressed(); + void OnWiimoteRefreshPressed(); + void OnWiimoteConfigure(); + + void CreateLayout(); + void ConnectWidgets(); + void LoadSettings(); + + QGroupBox* m_wiimote_box; + QGridLayout* m_wiimote_layout; + std::array m_wiimote_labels; + std::array m_wiimote_boxes; + std::array m_wiimote_buttons; + std::array m_wiimote_groups; + std::array m_wiimote_pt_labels; + + QRadioButton* m_wiimote_emu; + QRadioButton* m_wiimote_passthrough; + QPushButton* m_wiimote_sync; + QPushButton* m_wiimote_reset; + QCheckBox* m_wiimote_continuous_scanning; + QCheckBox* m_wiimote_real_balance_board; + QCheckBox* m_wiimote_speaker_data; + QCheckBox* m_wiimote_ciface; + QPushButton* m_wiimote_refresh; +}; diff --git a/Source/Core/DolphinQt/DolphinQt.vcxproj b/Source/Core/DolphinQt/DolphinQt.vcxproj index a3ebddbd13..0f36194a9c 100644 --- a/Source/Core/DolphinQt/DolphinQt.vcxproj +++ b/Source/Core/DolphinQt/DolphinQt.vcxproj @@ -115,6 +115,7 @@ + @@ -283,6 +284,7 @@ +