diff --git a/src/duckstation-qt/controllerbindingwidgets.cpp b/src/duckstation-qt/controllerbindingwidgets.cpp index 3e49afb64..ad24b153d 100644 --- a/src/duckstation-qt/controllerbindingwidgets.cpp +++ b/src/duckstation-qt/controllerbindingwidgets.cpp @@ -8,6 +8,12 @@ #include "qtutils.h" #include "settingswindow.h" #include "settingwidgetbinder.h" +#include "ui_controllerbindingwidget_analog_controller.h" +#include "ui_controllerbindingwidget_analog_joystick.h" +#include "ui_controllerbindingwidget_digital_controller.h" +#include "ui_controllerbindingwidget_guncon.h" +#include "ui_controllerbindingwidget_mouse.h" +#include "ui_controllerbindingwidget_negcon.h" #include "core/controller.h" #include "core/host.h" @@ -47,11 +53,6 @@ ControllerBindingWidget::ControllerBindingWidget(QWidget* parent, ControllerSett ControllerBindingWidget::~ControllerBindingWidget() = default; -QIcon ControllerBindingWidget::getIcon() const -{ - return m_bindings_widget->getIcon(); -} - void ControllerBindingWidget::populateControllerTypes() { for (u32 i = 0; i < static_cast(ControllerType::Count); i++) @@ -104,29 +105,69 @@ void ControllerBindingWidget::populateWidgets() m_ui.settings->setEnabled(has_settings); m_ui.macros->setEnabled(has_macros); + m_bindings_widget = new QWidget(this); switch (m_controller_type) { case ControllerType::AnalogController: - m_bindings_widget = ControllerBindingWidget_AnalogController::createInstance(this); - break; + { + Ui::ControllerBindingWidget_AnalogController ui; + ui.setupUi(m_bindings_widget); + bindBindingWidgets(m_bindings_widget); + m_icon = QIcon::fromTheme(QStringLiteral("controller-line")); + } + break; + case ControllerType::AnalogJoystick: - m_bindings_widget = ControllerBindingWidget_AnalogJoystick::createInstance(this); - break; + { + Ui::ControllerBindingWidget_AnalogJoystick ui; + ui.setupUi(m_bindings_widget); + bindBindingWidgets(m_bindings_widget); + m_icon = QIcon::fromTheme(QStringLiteral("joystick-line")); + } + break; + case ControllerType::DigitalController: - m_bindings_widget = ControllerBindingWidget_DigitalController::createInstance(this); - break; + { + Ui::ControllerBindingWidget_DigitalController ui; + ui.setupUi(m_bindings_widget); + bindBindingWidgets(m_bindings_widget); + m_icon = QIcon::fromTheme(QStringLiteral("controller-digital-line")); + } + break; + case ControllerType::GunCon: - m_bindings_widget = ControllerBindingWidget_GunCon::createInstance(this); - break; + { + Ui::ControllerBindingWidget_GunCon ui; + ui.setupUi(m_bindings_widget); + bindBindingWidgets(m_bindings_widget); + m_icon = QIcon::fromTheme(QStringLiteral("guncon-line")); + } + break; + case ControllerType::NeGcon: - m_bindings_widget = ControllerBindingWidget_NeGcon::createInstance(this); - break; + { + Ui::ControllerBindingWidget_NeGcon ui; + ui.setupUi(m_bindings_widget); + bindBindingWidgets(m_bindings_widget); + m_icon = QIcon::fromTheme(QStringLiteral("negcon-line")); + } + break; + case ControllerType::PlayStationMouse: - m_bindings_widget = ControllerBindingWidget_Mouse::createInstance(this); - break; + { + Ui::ControllerBindingWidget_Mouse ui; + ui.setupUi(m_bindings_widget); + bindBindingWidgets(m_bindings_widget); + m_icon = QIcon::fromTheme(QStringLiteral("mouse-line")); + } + break; + default: - m_bindings_widget = new ControllerBindingWidget_Base(this); - break; + { + createBindingWidgets(m_bindings_widget); + m_icon = QIcon::fromTheme(QStringLiteral("controller-strike-line")); + } + break; } m_ui.stackedWidget->addWidget(m_bindings_widget); @@ -301,6 +342,156 @@ void ControllerBindingWidget::saveAndRefresh() g_emu_thread->applySettings(); } +void ControllerBindingWidget::createBindingWidgets(QWidget* parent) +{ + SettingsInterface* sif = getDialog()->getProfileSettingsInterface(); + const ControllerType type = getControllerType(); + const Controller::ControllerInfo* cinfo = Controller::GetControllerInfo(type); + if (!cinfo) + return; + + QGroupBox* axis_gbox = nullptr; + QGridLayout* axis_layout = nullptr; + QGroupBox* button_gbox = nullptr; + QGridLayout* button_layout = nullptr; + + QScrollArea* scrollarea = new QScrollArea(parent); + QWidget* scrollarea_widget = new QWidget(scrollarea); + scrollarea->setWidget(scrollarea_widget); + scrollarea->setWidgetResizable(true); + scrollarea->setFrameShape(QFrame::StyledPanel); + scrollarea->setFrameShadow(QFrame::Plain); + + // We do axes and buttons separately, so we can figure out how many columns to use. + constexpr int NUM_AXIS_COLUMNS = 2; + int column = 0; + int row = 0; + for (const Controller::ControllerBindingInfo& bi : cinfo->bindings) + { + if (bi.type == InputBindingInfo::Type::Axis || bi.type == InputBindingInfo::Type::HalfAxis || + bi.type == InputBindingInfo::Type::Pointer) + { + if (!axis_gbox) + { + axis_gbox = new QGroupBox(tr("Axes"), scrollarea_widget); + axis_layout = new QGridLayout(axis_gbox); + } + + QGroupBox* gbox = new QGroupBox(qApp->translate("USB", bi.display_name), axis_gbox); + QVBoxLayout* temp = new QVBoxLayout(gbox); + InputBindingWidget* widget = new InputBindingWidget(gbox, sif, bi.type, getConfigSection(), bi.name); + temp->addWidget(widget); + axis_layout->addWidget(gbox, row, column); + if ((++column) == NUM_AXIS_COLUMNS) + { + column = 0; + row++; + } + } + } + if (axis_gbox) + axis_layout->addItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::Expanding), ++row, 0); + + const int num_button_columns = axis_layout ? 2 : 4; + row = 0; + column = 0; + for (const Controller::ControllerBindingInfo& bi : cinfo->bindings) + { + if (bi.type == InputBindingInfo::Type::Button) + { + if (!button_gbox) + { + button_gbox = new QGroupBox(tr("Buttons"), scrollarea_widget); + button_layout = new QGridLayout(button_gbox); + } + + QGroupBox* gbox = new QGroupBox(qApp->translate("USB", bi.display_name), button_gbox); + QVBoxLayout* temp = new QVBoxLayout(gbox); + InputBindingWidget* widget = new InputBindingWidget(gbox, sif, bi.type, getConfigSection(), bi.name); + temp->addWidget(widget); + button_layout->addWidget(gbox, row, column); + if ((++column) == num_button_columns) + { + column = 0; + row++; + } + } + } + + if (button_gbox) + button_layout->addItem(new QSpacerItem(1, 1, QSizePolicy::Minimum, QSizePolicy::Expanding), ++row, 0); + + if (!axis_gbox && !button_gbox) + { + delete scrollarea_widget; + return; + } + + QHBoxLayout* layout = new QHBoxLayout(scrollarea_widget); + if (axis_gbox) + layout->addWidget(axis_gbox); + if (button_gbox) + layout->addWidget(button_gbox); + layout->addItem(new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Minimum)); + + QHBoxLayout* main_layout = new QHBoxLayout(parent); + main_layout->addWidget(scrollarea); +} + +void ControllerBindingWidget::bindBindingWidgets(QWidget* parent) +{ + SettingsInterface* sif = getDialog()->getProfileSettingsInterface(); + const ControllerType type = getControllerType(); + const Controller::ControllerInfo* cinfo = Controller::GetControllerInfo(type); + if (!cinfo) + return; + + const std::string& config_section = getConfigSection(); + for (const Controller::ControllerBindingInfo& bi : cinfo->bindings) + { + if (bi.type == InputBindingInfo::Type::Axis || bi.type == InputBindingInfo::Type::HalfAxis || + bi.type == InputBindingInfo::Type::Button || bi.type == InputBindingInfo::Type::Pointer) + { + InputBindingWidget* widget = parent->findChild(QString::fromUtf8(bi.name)); + if (!widget) + { + Log_ErrorPrintf("No widget found for '%s' (%s)", bi.name, cinfo->name); + continue; + } + + widget->initialize(sif, bi.type, config_section, bi.name); + } + } + + switch (cinfo->vibration_caps) + { + case Controller::VibrationCapabilities::LargeSmallMotors: + { + InputVibrationBindingWidget* widget = + parent->findChild(QStringLiteral("LargeMotor")); + if (widget) + widget->setKey(getDialog(), config_section, "LargeMotor"); + + widget = parent->findChild(QStringLiteral("SmallMotor")); + if (widget) + widget->setKey(getDialog(), config_section, "SmallMotor"); + } + break; + + case Controller::VibrationCapabilities::SingleMotor: + { + InputVibrationBindingWidget* widget = parent->findChild(QStringLiteral("Motor")); + if (widget) + widget->setKey(getDialog(), config_section, "Motor"); + } + break; + + case Controller::VibrationCapabilities::NoVibration: + default: + break; + } +} + ////////////////////////////////////////////////////////////////////////// ControllerMacroWidget::ControllerMacroWidget(ControllerBindingWidget* parent) : QWidget(parent) @@ -728,228 +919,3 @@ void ControllerCustomSettingsWidget::restoreDefaults() } } } - -////////////////////////////////////////////////////////////////////////// - -ControllerBindingWidget_Base::ControllerBindingWidget_Base(ControllerBindingWidget* parent) : QWidget(parent) -{ -} - -ControllerBindingWidget_Base::~ControllerBindingWidget_Base() -{ -} - -QIcon ControllerBindingWidget_Base::getIcon() const -{ - return QIcon::fromTheme("controller-strike-line"); -} - -void ControllerBindingWidget_Base::initBindingWidgets() -{ - SettingsInterface* sif = getDialog()->getProfileSettingsInterface(); - const ControllerType type = getControllerType(); - const Controller::ControllerInfo* cinfo = Controller::GetControllerInfo(type); - if (!cinfo) - return; - - const std::string& config_section = getConfigSection(); - for (const Controller::ControllerBindingInfo& bi : cinfo->bindings) - { - if (bi.type == InputBindingInfo::Type::Axis || bi.type == InputBindingInfo::Type::HalfAxis || - bi.type == InputBindingInfo::Type::Button || bi.type == InputBindingInfo::Type::Pointer) - { - InputBindingWidget* widget = findChild(QString::fromUtf8(bi.name)); - if (!widget) - { - Log_ErrorPrintf("No widget found for '%s' (%s)", bi.name, cinfo->name); - continue; - } - - widget->initialize(sif, bi.type, config_section, bi.name); - } - } - - switch (cinfo->vibration_caps) - { - case Controller::VibrationCapabilities::LargeSmallMotors: - { - InputVibrationBindingWidget* widget = findChild(QStringLiteral("LargeMotor")); - if (widget) - widget->setKey(getDialog(), config_section, "LargeMotor"); - - widget = findChild(QStringLiteral("SmallMotor")); - if (widget) - widget->setKey(getDialog(), config_section, "SmallMotor"); - } - break; - - case Controller::VibrationCapabilities::SingleMotor: - { - InputVibrationBindingWidget* widget = findChild(QStringLiteral("Motor")); - if (widget) - widget->setKey(getDialog(), config_section, "Motor"); - } - break; - - case Controller::VibrationCapabilities::NoVibration: - default: - break; - } -} - -////////////////////////////////////////////////////////////////////////// - -ControllerBindingWidget_DigitalController::ControllerBindingWidget_DigitalController(ControllerBindingWidget* parent) - : ControllerBindingWidget_Base(parent) -{ - m_ui.setupUi(this); - initBindingWidgets(); -} - -ControllerBindingWidget_DigitalController::~ControllerBindingWidget_DigitalController() -{ -} - -QIcon ControllerBindingWidget_DigitalController::getIcon() const -{ - return QIcon::fromTheme(QStringLiteral("controller-digital-line")); -} - -ControllerBindingWidget_Base* ControllerBindingWidget_DigitalController::createInstance(ControllerBindingWidget* parent) -{ - return new ControllerBindingWidget_DigitalController(parent); -} - -////////////////////////////////////////////////////////////////////////// - -ControllerBindingWidget_AnalogController::ControllerBindingWidget_AnalogController(ControllerBindingWidget* parent) - : ControllerBindingWidget_Base(parent) -{ - m_ui.setupUi(this); - initBindingWidgets(); -} - -ControllerBindingWidget_AnalogController::~ControllerBindingWidget_AnalogController() -{ -} - -QIcon ControllerBindingWidget_AnalogController::getIcon() const -{ - return QIcon::fromTheme(QStringLiteral("controller-line")); -} - -ControllerBindingWidget_Base* ControllerBindingWidget_AnalogController::createInstance(ControllerBindingWidget* parent) -{ - return new ControllerBindingWidget_AnalogController(parent); -} - -////////////////////////////////////////////////////////////////////////// - -ControllerBindingWidget_AnalogJoystick::ControllerBindingWidget_AnalogJoystick(ControllerBindingWidget* parent) - : ControllerBindingWidget_Base(parent) -{ - m_ui.setupUi(this); - initBindingWidgets(); -} - -ControllerBindingWidget_AnalogJoystick::~ControllerBindingWidget_AnalogJoystick() -{ -} - -QIcon ControllerBindingWidget_AnalogJoystick::getIcon() const -{ - return QIcon::fromTheme(QStringLiteral("joystick-line")); -} - -ControllerBindingWidget_Base* ControllerBindingWidget_AnalogJoystick::createInstance(ControllerBindingWidget* parent) -{ - return new ControllerBindingWidget_AnalogJoystick(parent); -} - -////////////////////////////////////////////////////////////////////////// - -ControllerBindingWidget_NeGcon::ControllerBindingWidget_NeGcon(ControllerBindingWidget* parent) - : ControllerBindingWidget_Base(parent) -{ - m_ui.setupUi(this); - initBindingWidgets(); - - SettingsInterface* sif = getDialog()->getProfileSettingsInterface(); - const std::string& config_section = getConfigSection(); - if (QSlider* widget = findChild(QStringLiteral("SteeringDeadzone")); widget) - { - const float range = static_cast(widget->maximum()); - QLabel* label = findChild(QStringLiteral("SteeringDeadzoneLabel")); - if (label) - { - connect(widget, &QSlider::valueChanged, this, [range, label](int value) { - label->setText(tr("%1%").arg((static_cast(value) / range) * 100.0f, 0, 'f', 0)); - }); - } - - ControllerSettingWidgetBinder::BindWidgetToInputProfileNormalized(sif, widget, config_section, "SteeringDeadzone", - range, 0.0f); - } -} - -ControllerBindingWidget_NeGcon::~ControllerBindingWidget_NeGcon() -{ -} - -QIcon ControllerBindingWidget_NeGcon::getIcon() const -{ - return QIcon::fromTheme(QStringLiteral("negcon-line")); -} - -ControllerBindingWidget_Base* ControllerBindingWidget_NeGcon::createInstance(ControllerBindingWidget* parent) -{ - return new ControllerBindingWidget_NeGcon(parent); -} - -////////////////////////////////////////////////////////////////////////// - -ControllerBindingWidget_GunCon::ControllerBindingWidget_GunCon(ControllerBindingWidget* parent) - : ControllerBindingWidget_Base(parent) -{ - m_ui.setupUi(this); - initBindingWidgets(); -} - -ControllerBindingWidget_GunCon::~ControllerBindingWidget_GunCon() -{ -} - -QIcon ControllerBindingWidget_GunCon::getIcon() const -{ - return QIcon::fromTheme(QStringLiteral("guncon-line")); -} - -ControllerBindingWidget_Base* ControllerBindingWidget_GunCon::createInstance(ControllerBindingWidget* parent) -{ - return new ControllerBindingWidget_GunCon(parent); -} - -////////////////////////////////////////////////////////////////////////// - -ControllerBindingWidget_Mouse::ControllerBindingWidget_Mouse(ControllerBindingWidget* parent) - : ControllerBindingWidget_Base(parent) -{ - m_ui.setupUi(this); - initBindingWidgets(); -} - -ControllerBindingWidget_Mouse::~ControllerBindingWidget_Mouse() -{ -} - -QIcon ControllerBindingWidget_Mouse::getIcon() const -{ - return QIcon::fromTheme(QStringLiteral("mouse-line")); -} - -ControllerBindingWidget_Base* ControllerBindingWidget_Mouse::createInstance(ControllerBindingWidget* parent) -{ - return new ControllerBindingWidget_Mouse(parent); -} - -////////////////////////////////////////////////////////////////////////// diff --git a/src/duckstation-qt/controllerbindingwidgets.h b/src/duckstation-qt/controllerbindingwidgets.h index 95a1fd175..576788402 100644 --- a/src/duckstation-qt/controllerbindingwidgets.h +++ b/src/duckstation-qt/controllerbindingwidgets.h @@ -10,12 +10,6 @@ #include #include "ui_controllerbindingwidget.h" -#include "ui_controllerbindingwidget_analog_controller.h" -#include "ui_controllerbindingwidget_analog_joystick.h" -#include "ui_controllerbindingwidget_digital_controller.h" -#include "ui_controllerbindingwidget_guncon.h" -#include "ui_controllerbindingwidget_mouse.h" -#include "ui_controllerbindingwidget_negcon.h" #include "ui_controllermacroeditwidget.h" #include "ui_controllermacrowidget.h" @@ -26,7 +20,6 @@ class ControllerSettingsWindow; class ControllerCustomSettingsWidget; class ControllerMacroWidget; class ControllerMacroEditWidget; -class ControllerBindingWidget_Base; ////////////////////////////////////////////////////////////////////////// @@ -38,12 +31,11 @@ public: ControllerBindingWidget(QWidget* parent, ControllerSettingsWindow* dialog, u32 port); ~ControllerBindingWidget(); - QIcon getIcon() const; - ALWAYS_INLINE ControllerSettingsWindow* getDialog() const { return m_dialog; } ALWAYS_INLINE const std::string& getConfigSection() const { return m_config_section; } ALWAYS_INLINE ControllerType getControllerType() const { return m_controller_type; } ALWAYS_INLINE u32 getPortNumber() const { return m_port_number; } + ALWAYS_INLINE const QIcon& getIcon() { return m_icon; } private Q_SLOTS: void onTypeChanged(); @@ -56,6 +48,8 @@ private Q_SLOTS: private: void populateControllerTypes(); void populateWidgets(); + void createBindingWidgets(QWidget* parent); + void bindBindingWidgets(QWidget* parent); void updateHeaderToolButtons(); void doDeviceAutomaticBinding(const QString& device); void saveAndRefresh(); @@ -68,7 +62,8 @@ private: ControllerType m_controller_type; u32 m_port_number; - ControllerBindingWidget_Base* m_bindings_widget = nullptr; + QIcon m_icon; + QWidget* m_bindings_widget = nullptr; ControllerCustomSettingsWidget* m_settings_widget = nullptr; ControllerMacroWidget* m_macros_widget = nullptr; }; @@ -145,143 +140,3 @@ private Q_SLOTS: private: ControllerBindingWidget* m_parent; }; - -////////////////////////////////////////////////////////////////////////// - -class ControllerBindingWidget_Base : public QWidget -{ - Q_OBJECT - -public: - ControllerBindingWidget_Base(ControllerBindingWidget* parent); - virtual ~ControllerBindingWidget_Base(); - - ALWAYS_INLINE ControllerSettingsWindow* getDialog() const - { - return static_cast(parent())->getDialog(); - } - ALWAYS_INLINE const std::string& getConfigSection() const - { - return static_cast(parent())->getConfigSection(); - } - ALWAYS_INLINE ControllerType getControllerType() const - { - return static_cast(parent())->getControllerType(); - } - ALWAYS_INLINE u32 getPortNumber() const { return static_cast(parent())->getPortNumber(); } - - virtual QIcon getIcon() const; - -protected: - void initBindingWidgets(); -}; - -////////////////////////////////////////////////////////////////////////// - -class ControllerBindingWidget_DigitalController final : public ControllerBindingWidget_Base -{ - Q_OBJECT - -public: - ControllerBindingWidget_DigitalController(ControllerBindingWidget* parent); - ~ControllerBindingWidget_DigitalController(); - - QIcon getIcon() const override; - - static ControllerBindingWidget_Base* createInstance(ControllerBindingWidget* parent); - -private: - Ui::ControllerBindingWidget_DigitalController m_ui; -}; - -////////////////////////////////////////////////////////////////////////// - -class ControllerBindingWidget_AnalogController final : public ControllerBindingWidget_Base -{ - Q_OBJECT - -public: - ControllerBindingWidget_AnalogController(ControllerBindingWidget* parent); - ~ControllerBindingWidget_AnalogController(); - - QIcon getIcon() const override; - - static ControllerBindingWidget_Base* createInstance(ControllerBindingWidget* parent); - -private: - Ui::ControllerBindingWidget_AnalogController m_ui; -}; - -////////////////////////////////////////////////////////////////////////// - -class ControllerBindingWidget_AnalogJoystick final : public ControllerBindingWidget_Base -{ - Q_OBJECT - -public: - ControllerBindingWidget_AnalogJoystick(ControllerBindingWidget* parent); - ~ControllerBindingWidget_AnalogJoystick(); - - QIcon getIcon() const override; - - static ControllerBindingWidget_Base* createInstance(ControllerBindingWidget* parent); - -private: - Ui::ControllerBindingWidget_AnalogJoystick m_ui; -}; - -////////////////////////////////////////////////////////////////////////// - -class ControllerBindingWidget_NeGcon final : public ControllerBindingWidget_Base -{ - Q_OBJECT - -public: - ControllerBindingWidget_NeGcon(ControllerBindingWidget* parent); - ~ControllerBindingWidget_NeGcon(); - - QIcon getIcon() const override; - - static ControllerBindingWidget_Base* createInstance(ControllerBindingWidget* parent); - -private: - Ui::ControllerBindingWidget_NeGcon m_ui; -}; - -////////////////////////////////////////////////////////////////////////// - -class ControllerBindingWidget_GunCon final : public ControllerBindingWidget_Base -{ - Q_OBJECT - -public: - ControllerBindingWidget_GunCon(ControllerBindingWidget* parent); - ~ControllerBindingWidget_GunCon(); - - QIcon getIcon() const override; - - static ControllerBindingWidget_Base* createInstance(ControllerBindingWidget* parent); - -private: - Ui::ControllerBindingWidget_GunCon m_ui; -}; - -////////////////////////////////////////////////////////////////////////// - -class ControllerBindingWidget_Mouse final : public ControllerBindingWidget_Base -{ - Q_OBJECT - -public: - ControllerBindingWidget_Mouse(ControllerBindingWidget* parent); - ~ControllerBindingWidget_Mouse(); - - QIcon getIcon() const override; - - static ControllerBindingWidget_Base* createInstance(ControllerBindingWidget* parent); - -private: - Ui::ControllerBindingWidget_Mouse m_ui; -}; - -////////////////////////////////////////////////////////////////////////// diff --git a/src/duckstation-qt/controllersettingswindow.ui b/src/duckstation-qt/controllersettingswindow.ui index 789499c99..adf3b5e91 100644 --- a/src/duckstation-qt/controllersettingswindow.ui +++ b/src/duckstation-qt/controllersettingswindow.ui @@ -6,7 +6,7 @@ 0 0 - 1276 + 1279 672 @@ -34,13 +34,13 @@ - 150 + 160 0 - 150 + 160 16777215 @@ -82,8 +82,7 @@ New Profile - - .. + @@ -103,8 +102,7 @@ Delete Profile - - .. + @@ -123,7 +121,7 @@ - QDialogButtonBox::Close + QDialogButtonBox::StandardButton::Close @@ -132,7 +130,7 @@ - +