diff --git a/Source/Android/jni/Input/ControlGroup.cpp b/Source/Android/jni/Input/ControlGroup.cpp index 045ab1b519..4c21f26c12 100644 --- a/Source/Android/jni/Input/ControlGroup.cpp +++ b/Source/Android/jni/Input/ControlGroup.cpp @@ -55,14 +55,14 @@ JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_features_input_model_controlleremu_ControlGroup_getEnabled( JNIEnv* env, jobject obj) { - return static_cast(GetPointer(env, obj)->enabled); + return static_cast(GetPointer(env, obj)->enabled.GetValue()); } JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_features_input_model_controlleremu_ControlGroup_setEnabled( JNIEnv* env, jobject obj, jboolean value) { - GetPointer(env, obj)->enabled = value; + GetPointer(env, obj)->enabled.SetValue(value); } JNIEXPORT jint JNICALL diff --git a/Source/Core/Core/HW/WiimoteEmu/Dynamics.cpp b/Source/Core/Core/HW/WiimoteEmu/Dynamics.cpp index b3864e3c8b..05df72bec7 100644 --- a/Source/Core/Core/HW/WiimoteEmu/Dynamics.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/Dynamics.cpp @@ -311,7 +311,7 @@ void EmulateIMUCursor(IMUCursorState* state, ControllerEmu::IMUCursor* imu_ir_gr const auto ang_vel = imu_gyroscope_group->GetState(); // Reset if pointing is disabled or we have no gyro data. - if (!imu_ir_group->enabled || !ang_vel.has_value()) + if (!imu_ir_group->enabled.GetValue() || !ang_vel.has_value()) { *state = {}; return; diff --git a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp index 265d39a4d7..75ab7083da 100644 --- a/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp +++ b/Source/Core/Core/HW/WiimoteEmu/WiimoteEmu.cpp @@ -497,7 +497,7 @@ void Wiimote::BuildDesiredWiimoteState(DesiredWiimoteState* target_state, ConvertAccelData(GetTotalAcceleration(), ACCEL_ZERO_G << 2, ACCEL_ONE_G << 2); // Calculate IR camera state. - if (m_ir_passthrough->enabled) + if (m_ir_passthrough->enabled.GetValue()) { target_state->camera_points = GetPassthroughCameraPoints(m_ir_passthrough); } diff --git a/Source/Core/DolphinQt/Config/Mapping/MappingIndicator.cpp b/Source/Core/DolphinQt/Config/Mapping/MappingIndicator.cpp index e16da45970..f2b2383a18 100644 --- a/Source/Core/DolphinQt/Config/Mapping/MappingIndicator.cpp +++ b/Source/Core/DolphinQt/Config/Mapping/MappingIndicator.cpp @@ -893,7 +893,8 @@ void IRPassthroughMappingIndicator::Draw() p.scale(1.0, -1.0); - auto pen = GetInputDotPen(m_ir_group.enabled ? GetAdjustedInputColor() : GetRawInputColor()); + auto pen = + GetInputDotPen(m_ir_group.enabled.GetValue() ? GetAdjustedInputColor() : GetRawInputColor()); for (std::size_t i = 0; i != WiimoteEmu::CameraLogic::NUM_POINTS; ++i) { diff --git a/Source/Core/DolphinQt/Config/Mapping/MappingWidget.cpp b/Source/Core/DolphinQt/Config/Mapping/MappingWidget.cpp index 536754f6fc..061be00684 100644 --- a/Source/Core/DolphinQt/Config/Mapping/MappingWidget.cpp +++ b/Source/Core/DolphinQt/Config/Mapping/MappingWidget.cpp @@ -102,15 +102,48 @@ QGroupBox* MappingWidget::CreateGroupBox(const QString& name, ControllerEmu::Con break; } - if (indicator) + // Mapping indicator. + if (indicator != nullptr) { - const auto indicator_layout = new QBoxLayout(QBoxLayout::Direction::Down); + auto* const indicator_layout = new QBoxLayout(QBoxLayout::Direction::Down); indicator_layout->addWidget(indicator); indicator_layout->setAlignment(Qt::AlignCenter); form_layout->addRow(indicator_layout); connect(this, &MappingWidget::Update, indicator, qOverload<>(&MappingIndicator::update)); + } + // "Enabled" checkbox. + if (group->HasEnabledSetting()) + { + AddSettingWidget(form_layout, group->enabled_setting.get()); + + auto enable_labels = [form_layout, start_index = form_layout->rowCount()](bool enabled) { + // Skipping the "Enabled" checkbox row itself and the mapping indicator, if it exists. + for (int i = start_index; i < form_layout->count(); ++i) + { + auto* const item = form_layout->itemAt(i, QFormLayout::LabelRole); + if (item == nullptr) + continue; + + auto* const widget = item->widget(); + if (widget == nullptr) + continue; + + widget->setEnabled(enabled); + } + }; + + connect(this, &MappingWidget::Update, this, [group, enable_labels, enabled = true]() mutable { + if (enabled == group->enabled_setting->GetValue()) + return; + enable_labels(enabled = !enabled); + }); + } + + // "Calibrate" button. + if (indicator != nullptr) + { const bool need_calibration = group->type == ControllerEmu::GroupType::Cursor || group->type == ControllerEmu::GroupType::Stick || group->type == ControllerEmu::GroupType::Tilt || @@ -131,28 +164,6 @@ QGroupBox* MappingWidget::CreateGroupBox(const QString& name, ControllerEmu::Con AddSettingWidgets(form_layout, group, ControllerEmu::SettingVisibility::Normal); - if (group->default_value != ControllerEmu::ControlGroup::DefaultValue::AlwaysEnabled) - { - QLabel* group_enable_label = new QLabel(tr("Enable")); - QCheckBox* group_enable_checkbox = new QCheckBox(); - group_enable_checkbox->setChecked(group->enabled); - form_layout->insertRow(0, group_enable_label, group_enable_checkbox); - auto enable_group_by_checkbox = [group, form_layout, group_enable_label, - group_enable_checkbox] { - group->enabled = group_enable_checkbox->isChecked(); - for (int i = 0; i < form_layout->count(); ++i) - { - QWidget* widget = form_layout->itemAt(i)->widget(); - if (widget != nullptr && widget != group_enable_label && widget != group_enable_checkbox) - widget->setEnabled(group->enabled); - } - }; - enable_group_by_checkbox(); - connect(group_enable_checkbox, &QCheckBox::toggled, this, enable_group_by_checkbox); - connect(this, &MappingWidget::ConfigChanged, this, - [group_enable_checkbox, group] { group_enable_checkbox->setChecked(group->enabled); }); - } - const auto advanced_setting_count = std::ranges::count(group->numeric_settings, ControllerEmu::SettingVisibility::Advanced, &ControllerEmu::NumericSettingBase::GetVisibility); @@ -201,36 +212,42 @@ void MappingWidget::AddSettingWidgets(QFormLayout* layout, ControllerEmu::Contro if (setting->GetVisibility() != visibility) continue; - QWidget* setting_widget = nullptr; + AddSettingWidget(layout, setting.get()); + } +} - switch (setting->GetType()) - { - case ControllerEmu::SettingType::Double: - setting_widget = new MappingDouble( - this, static_cast*>(setting.get())); - break; +void MappingWidget::AddSettingWidget(QFormLayout* layout, + ControllerEmu::NumericSettingBase* setting) +{ + QWidget* setting_widget = nullptr; - case ControllerEmu::SettingType::Bool: - setting_widget = - new MappingBool(this, static_cast*>(setting.get())); - break; + switch (setting->GetType()) + { + case ControllerEmu::SettingType::Double: + setting_widget = + new MappingDouble(this, static_cast*>(setting)); + break; - default: - // FYI: Widgets for additional types can be implemented as needed. - break; - } + case ControllerEmu::SettingType::Bool: + setting_widget = + new MappingBool(this, static_cast*>(setting)); + break; - if (setting_widget) - { - const auto hbox = new QHBoxLayout; + default: + // FYI: Widgets for additional types can be implemented as needed. + break; + } - hbox->addWidget(setting_widget); - setting_widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + if (setting_widget != nullptr) + { + auto* const hbox = new QHBoxLayout; - hbox->addWidget(CreateSettingAdvancedMappingButton(*setting)); + hbox->addWidget(setting_widget); + setting_widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - layout->addRow(tr(setting->GetUIName()), hbox); - } + hbox->addWidget(CreateSettingAdvancedMappingButton(*setting)); + + layout->addRow(tr(setting->GetUIName()), hbox); } } diff --git a/Source/Core/DolphinQt/Config/Mapping/MappingWidget.h b/Source/Core/DolphinQt/Config/Mapping/MappingWidget.h index f993968590..5be8e99e33 100644 --- a/Source/Core/DolphinQt/Config/Mapping/MappingWidget.h +++ b/Source/Core/DolphinQt/Config/Mapping/MappingWidget.h @@ -50,8 +50,11 @@ protected: int columns); void CreateControl(const ControllerEmu::Control* control, QFormLayout* layout, bool indicator); QPushButton* CreateSettingAdvancedMappingButton(ControllerEmu::NumericSettingBase& setting); + + void AddSettingWidget(QFormLayout* layout, ControllerEmu::NumericSettingBase* setting); void AddSettingWidgets(QFormLayout* layout, ControllerEmu::ControlGroup* group, ControllerEmu::SettingVisibility visibility); + void ShowAdvancedControlGroupDialog(ControllerEmu::ControlGroup* group); private: diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/ControlGroup.cpp b/Source/Core/InputCommon/ControllerEmu/ControlGroup/ControlGroup.cpp index 93367649f9..b619ae1b08 100644 --- a/Source/Core/InputCommon/ControllerEmu/ControlGroup/ControlGroup.cpp +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/ControlGroup.cpp @@ -13,8 +13,9 @@ namespace ControllerEmu { -ControlGroup::ControlGroup(std::string name_, const GroupType type_, DefaultValue default_value_) - : name(name_), ui_name(std::move(name_)), type(type_), default_value(default_value_) +ControlGroup::ControlGroup(const std::string& name_, const GroupType type_, + DefaultValue default_value_) + : ControlGroup{name_, name_, type_, default_value_} { } @@ -23,6 +24,12 @@ ControlGroup::ControlGroup(std::string name_, std::string ui_name_, const GroupT : name(std::move(name_)), ui_name(std::move(ui_name_)), type(type_), default_value(default_value_) { + if (default_value_ != DefaultValue::AlwaysEnabled) + { + enabled_setting = std::make_unique>( + &enabled, NumericSettingDetails{_trans("Enabled")}, + (default_value_ == DefaultValue::Enabled), false, true); + } } void ControlGroup::AddVirtualNotchSetting(SettingValue* value, double max_virtual_notch_deg) @@ -53,8 +60,8 @@ void ControlGroup::LoadConfig(Common::IniFile::Section* sec, const std::string& const std::string group(base + name + "/"); // enabled - if (default_value != DefaultValue::AlwaysEnabled) - sec->Get(group + "Enabled", &enabled, default_value != DefaultValue::Disabled); + if (HasEnabledSetting()) + enabled_setting->LoadFromIni(*sec, group); for (auto& setting : numeric_settings) setting->LoadFromIni(*sec, group); @@ -79,7 +86,8 @@ void ControlGroup::SaveConfig(Common::IniFile::Section* sec, const std::string& const std::string group(base + name + "/"); // enabled - sec->Set(group + "Enabled", enabled, default_value != DefaultValue::Disabled); + if (HasEnabledSetting()) + enabled_setting->SaveToIni(*sec, group); for (auto& setting : numeric_settings) setting->SaveToIni(*sec, group); @@ -99,6 +107,9 @@ void ControlGroup::SaveConfig(Common::IniFile::Section* sec, const std::string& void ControlGroup::UpdateReferences(ciface::ExpressionParser::ControlEnvironment& env) { + if (HasEnabledSetting()) + enabled_setting->GetInputReference().UpdateReference(env); + for (auto& control : controls) control->control_ref->UpdateReference(env); @@ -126,4 +137,9 @@ void ControlGroup::AddOutput(Translatability translate, std::string name_) controls.emplace_back(std::make_unique(translate, std::move(name_))); } +bool ControlGroup::HasEnabledSetting() const +{ + return enabled_setting != nullptr; +} + } // namespace ControllerEmu diff --git a/Source/Core/InputCommon/ControllerEmu/ControlGroup/ControlGroup.h b/Source/Core/InputCommon/ControllerEmu/ControlGroup/ControlGroup.h index 7928fb61a9..c67b0ac132 100644 --- a/Source/Core/InputCommon/ControllerEmu/ControlGroup/ControlGroup.h +++ b/Source/Core/InputCommon/ControllerEmu/ControlGroup/ControlGroup.h @@ -15,6 +15,7 @@ #include "Common/IniFile.h" #include "InputCommon/ControllerEmu/Control/Control.h" +#include "InputCommon/ControllerEmu/Setting/NumericSetting.h" #include "InputCommon/ControllerInterface/CoreDevice.h" namespace ControllerEmu @@ -62,7 +63,7 @@ public: Disabled, }; - explicit ControlGroup(std::string name, GroupType type = GroupType::Other, + explicit ControlGroup(const std::string& name, GroupType type = GroupType::Other, DefaultValue default_value = DefaultValue::AlwaysEnabled); ControlGroup(std::string name, std::string ui_name, GroupType type = GroupType::Other, DefaultValue default_value = DefaultValue::AlwaysEnabled); @@ -98,12 +99,17 @@ public: return std::copysign(std::max(T{0}, std::abs(input) - deadzone) / (T{1} - deadzone), input); } + bool HasEnabledSetting() const; + const std::string name; const std::string ui_name; const GroupType type; - const DefaultValue default_value; - bool enabled = true; + // The default "enabled" state. + const DefaultValue default_value; + SettingValue enabled; + std::unique_ptr> enabled_setting; + std::vector> controls; std::vector> numeric_settings; };