Qt: Add DS4/DS5 LED settings

This commit is contained in:
Stenzek 2023-01-15 17:00:52 +10:00 committed by lightningterror
parent a0000a8547
commit 43ccb63eb5
14 changed files with 366 additions and 14 deletions

View File

@ -11,6 +11,8 @@ target_sources(pcsx2-qt PRIVATE
AutoUpdaterDialog.cpp AutoUpdaterDialog.cpp
AutoUpdaterDialog.h AutoUpdaterDialog.h
AutoUpdaterDialog.ui AutoUpdaterDialog.ui
ColorPickerButton.cpp
ColorPickerButton.h
CoverDownloadDialog.cpp CoverDownloadDialog.cpp
CoverDownloadDialog.h CoverDownloadDialog.h
CoverDownloadDialog.ui CoverDownloadDialog.ui
@ -50,6 +52,7 @@ target_sources(pcsx2-qt PRIVATE
Settings/ControllerBindingWidget_DualShock2.ui Settings/ControllerBindingWidget_DualShock2.ui
Settings/ControllerBindingWidgets.cpp Settings/ControllerBindingWidgets.cpp
Settings/ControllerBindingWidgets.h Settings/ControllerBindingWidgets.h
Settings/ControllerLEDSettingsDialog.ui
Settings/ControllerGlobalSettingsWidget.cpp Settings/ControllerGlobalSettingsWidget.cpp
Settings/ControllerGlobalSettingsWidget.h Settings/ControllerGlobalSettingsWidget.h
Settings/ControllerGlobalSettingsWidget.ui Settings/ControllerGlobalSettingsWidget.ui

View File

@ -0,0 +1,66 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "PrecompiledHeader.h"
#include "ColorPickerButton.h"
#include "QtUtils.h"
#include <QtWidgets/QColorDialog>
ColorPickerButton::ColorPickerButton(QWidget* parent)
: QPushButton(parent)
{
connect(this, &QPushButton::clicked, this, &ColorPickerButton::onClicked);
updateBackgroundColor();
}
u32 ColorPickerButton::color()
{
return m_color;
}
void ColorPickerButton::setColor(u32 rgb)
{
if (m_color == rgb)
return;
m_color = rgb;
updateBackgroundColor();
}
void ColorPickerButton::updateBackgroundColor()
{
setStyleSheet(QStringLiteral("background-color: #%1;").arg(static_cast<uint>(m_color), 8, 16, QChar('0')));
}
void ColorPickerButton::onClicked()
{
const u32 red = (m_color >> 16) & 0xff;
const u32 green = (m_color >> 8) & 0xff;
const u32 blue = m_color & 0xff;
const QColor initial(QColor::fromRgb(red, green, blue));
const QColor selected(QColorDialog::getColor(initial, QtUtils::GetRootWidget(this), tr("Select LED Color")));
// QColorDialog returns Invalid on cancel, and apparently initial == Invalid is true...
if (!selected.isValid() || initial == selected)
return;
const u32 new_rgb =
(static_cast<u32>(selected.red()) << 16) | (static_cast<u32>(selected.green()) << 8) | static_cast<u32>(selected.blue());
m_color = new_rgb;
updateBackgroundColor();
emit colorChanged(new_rgb);
}

View File

@ -0,0 +1,42 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "common/Pcsx2Defs.h"
#include <QtWidgets/QPushButton>
class ColorPickerButton : public QPushButton
{
Q_OBJECT
public:
ColorPickerButton(QWidget* parent);
Q_SIGNALS:
void colorChanged(quint32 new_color);
public Q_SLOTS:
quint32 color();
void setColor(quint32 rgb);
private Q_SLOTS:
void onClicked();
private:
void updateBackgroundColor();
u32 m_color = 0;
};

View File

@ -22,6 +22,10 @@
#include "QtUtils.h" #include "QtUtils.h"
#include "SettingWidgetBinder.h" #include "SettingWidgetBinder.h"
#ifdef SDL_BUILD
#include "pcsx2/Frontend/SDLInputSource.h"
#endif
ControllerGlobalSettingsWidget::ControllerGlobalSettingsWidget(QWidget* parent, ControllerSettingsDialog* dialog) ControllerGlobalSettingsWidget::ControllerGlobalSettingsWidget(QWidget* parent, ControllerSettingsDialog* dialog)
: QWidget(parent) : QWidget(parent)
, m_dialog(dialog) , m_dialog(dialog)
@ -30,8 +34,16 @@ ControllerGlobalSettingsWidget::ControllerGlobalSettingsWidget(QWidget* parent,
SettingsInterface* sif = dialog->getProfileSettingsInterface(); SettingsInterface* sif = dialog->getProfileSettingsInterface();
#ifdef SDL_BUILD
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.enableSDLSource, "InputSources", "SDL", true); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.enableSDLSource, "InputSources", "SDL", true);
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.enableSDLEnhancedMode, "InputSources", "SDLControllerEnhancedMode", false); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.enableSDLEnhancedMode, "InputSources", "SDLControllerEnhancedMode", false);
connect(m_ui.enableSDLSource, &QCheckBox::stateChanged, this, &ControllerGlobalSettingsWidget::updateSDLOptionsEnabled);
connect(m_ui.ledSettings, &QToolButton::clicked, this, &ControllerGlobalSettingsWidget::ledSettingsClicked);
#else
m_ui.enableSDLSource->setEnabled(false);
m_ui.ledSettings->setEnabled(false);
#endif
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.enableMouseMapping, "UI", "EnableMouseMapping", false); SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.enableMouseMapping, "UI", "EnableMouseMapping", false);
ControllerSettingWidgetBinder::BindWidgetToInputProfileBool(sif, m_ui.multitapPort1, "Pad", "MultitapPort1", false); ControllerSettingWidgetBinder::BindWidgetToInputProfileBool(sif, m_ui.multitapPort1, "Pad", "MultitapPort1", false);
ControllerSettingWidgetBinder::BindWidgetToInputProfileBool(sif, m_ui.multitapPort2, "Pad", "MultitapPort2", false); ControllerSettingWidgetBinder::BindWidgetToInputProfileBool(sif, m_ui.multitapPort2, "Pad", "MultitapPort2", false);
@ -66,12 +78,13 @@ ControllerGlobalSettingsWidget::ControllerGlobalSettingsWidget(QWidget* parent,
m_ui.profileSettings = nullptr; m_ui.profileSettings = nullptr;
} }
connect(m_ui.enableSDLSource, &QCheckBox::stateChanged, this, &ControllerGlobalSettingsWidget::updateSDLOptionsEnabled);
for (QCheckBox* cb : {m_ui.multitapPort1, m_ui.multitapPort2}) for (QCheckBox* cb : {m_ui.multitapPort1, m_ui.multitapPort2})
connect(cb, &QCheckBox::stateChanged, this, [this]() { emit bindingSetupChanged(); }); connect(cb, &QCheckBox::stateChanged, this, [this]() { emit bindingSetupChanged(); });
connect(m_ui.pointerXScale, &QSlider::valueChanged, this, [this](int value) { m_ui.pointerXScaleLabel->setText(QStringLiteral("%1").arg(value)); }); connect(m_ui.pointerXScale, &QSlider::valueChanged, this,
connect(m_ui.pointerYScale, &QSlider::valueChanged, this, [this](int value) { m_ui.pointerYScaleLabel->setText(QStringLiteral("%1").arg(value)); }); [this](int value) { m_ui.pointerXScaleLabel->setText(QStringLiteral("%1").arg(value)); });
connect(m_ui.pointerYScale, &QSlider::valueChanged, this,
[this](int value) { m_ui.pointerYScaleLabel->setText(QStringLiteral("%1").arg(value)); });
m_ui.pointerXScaleLabel->setText(QStringLiteral("%1").arg(m_ui.pointerXScale->value())); m_ui.pointerXScaleLabel->setText(QStringLiteral("%1").arg(m_ui.pointerXScale->value()));
m_ui.pointerYScaleLabel->setText(QStringLiteral("%1").arg(m_ui.pointerYScale->value())); m_ui.pointerYScaleLabel->setText(QStringLiteral("%1").arg(m_ui.pointerYScale->value()));
@ -106,4 +119,40 @@ void ControllerGlobalSettingsWidget::updateSDLOptionsEnabled()
{ {
const bool enabled = m_ui.enableSDLSource->isChecked(); const bool enabled = m_ui.enableSDLSource->isChecked();
m_ui.enableSDLEnhancedMode->setEnabled(enabled); m_ui.enableSDLEnhancedMode->setEnabled(enabled);
m_ui.ledSettings->setEnabled(enabled);
}
void ControllerGlobalSettingsWidget::ledSettingsClicked()
{
ControllerLEDSettingsDialog dialog(this, m_dialog);
dialog.exec();
}
ControllerLEDSettingsDialog::ControllerLEDSettingsDialog(QWidget* parent, ControllerSettingsDialog* dialog)
: QDialog(parent)
, m_dialog(dialog)
{
m_ui.setupUi(this);
linkButton(m_ui.SDL0LED, 0);
linkButton(m_ui.SDL1LED, 1);
linkButton(m_ui.SDL2LED, 2);
linkButton(m_ui.SDL3LED, 3);
connect(m_ui.buttonBox->button(QDialogButtonBox::Close), &QPushButton::clicked, this, &QDialog::accept);
}
ControllerLEDSettingsDialog::~ControllerLEDSettingsDialog() = default;
void ControllerLEDSettingsDialog::linkButton(ColorPickerButton* button, u32 player_id)
{
#ifdef SDL_BUILD
std::string key(fmt::format("Player{}LED", player_id));
const u32 current_value = SDLInputSource::ParseRGBForPlayerId(m_dialog->getStringValue("SDLExtra", key.c_str(), ""), player_id);
button->setColor(current_value);
connect(button, &ColorPickerButton::colorChanged, this, [this, player_id, key = std::move(key)](u32 new_rgb) {
m_dialog->setStringValue("SDLExtra", key.c_str(), fmt::format("{:06X}", new_rgb).c_str());
});
#endif
} }

View File

@ -20,7 +20,10 @@
#include <array> #include <array>
#include <vector> #include <vector>
#include "ColorPickerButton.h"
#include "ui_ControllerGlobalSettingsWidget.h" #include "ui_ControllerGlobalSettingsWidget.h"
#include "ui_ControllerLEDSettingsDialog.h"
class ControllerSettingsDialog; class ControllerSettingsDialog;
@ -38,9 +41,26 @@ public:
Q_SIGNALS: Q_SIGNALS:
void bindingSetupChanged(); void bindingSetupChanged();
private: private Q_SLOTS:
void updateSDLOptionsEnabled(); void updateSDLOptionsEnabled();
void ledSettingsClicked();
private:
Ui::ControllerGlobalSettingsWidget m_ui; Ui::ControllerGlobalSettingsWidget m_ui;
ControllerSettingsDialog* m_dialog; ControllerSettingsDialog* m_dialog;
}; };
class ControllerLEDSettingsDialog : public QDialog
{
Q_OBJECT
public:
ControllerLEDSettingsDialog(QWidget* parent, ControllerSettingsDialog* dialog);
~ControllerLEDSettingsDialog();
private:
void linkButton(ColorPickerButton* button, u32 player_id);
Ui::ControllerLEDSettingsDialog m_ui;
ControllerSettingsDialog* m_dialog;
};

View File

@ -50,11 +50,27 @@
</widget> </widget>
</item> </item>
<item row="1" column="1"> <item row="1" column="1">
<widget class="QCheckBox" name="enableSDLEnhancedMode"> <layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="text"> <item>
<string>DualShock 4 / DualSense Enhanced Mode</string> <widget class="QCheckBox" name="enableSDLEnhancedMode">
</property> <property name="text">
</widget> <string>DualShock 4 / DualSense Enhanced Mode</string>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="ledSettings">
<property name="toolTip">
<string>Controller LED Settings</string>
</property>
<property name="icon">
<iconset theme="lightbulb-line">
<normaloff>.</normaloff>.
</iconset>
</property>
</widget>
</item>
</layout>
</item> </item>
</layout> </layout>
</widget> </widget>

View File

@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ControllerLEDSettingsDialog</class>
<widget class="QDialog" name="ControllerLEDSettingsDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>501</width>
<height>108</height>
</rect>
</property>
<property name="windowTitle">
<string>Controller LED Settings</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QGroupBox" name="groupBox">
<property name="title">
<string>SDL-0 LED</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
<widget class="ColorPickerButton" name="SDL0LED"/>
</item>
</layout>
</widget>
</item>
<item row="0" column="1">
<widget class="QGroupBox" name="groupBox_2">
<property name="title">
<string>SDL-1 LED</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<widget class="ColorPickerButton" name="SDL1LED"/>
</item>
</layout>
</widget>
</item>
<item row="0" column="2">
<widget class="QGroupBox" name="groupBox_3">
<property name="title">
<string>SDL-2 LED</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="ColorPickerButton" name="SDL2LED"/>
</item>
</layout>
</widget>
</item>
<item row="0" column="3">
<widget class="QGroupBox" name="groupBox_4">
<property name="title">
<string>SDL-3 LED</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="ColorPickerButton" name="SDL3LED"/>
</item>
</layout>
</widget>
</item>
<item row="1" column="0" colspan="4">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="standardButtons">
<set>QDialogButtonBox::Close</set>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>ColorPickerButton</class>
<extends>QPushButton</extends>
<header>ColorPickerButton.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@ -46,6 +46,7 @@
<AdditionalIncludeDirectories>$(SolutionDir)3rdparty\lzma\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>$(SolutionDir)3rdparty\lzma\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)3rdparty\demangler\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>$(SolutionDir)3rdparty\demangler\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)3rdparty\rapidyaml\rapidyaml\ext\c4core\src\c4\ext\fast_float\include;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>$(SolutionDir)3rdparty\rapidyaml\rapidyaml\ext\c4core\src\c4\ext\fast_float\include;%(AdditionalIncludeDirectories);</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(SolutionDir)3rdparty\sdl2\include;$(SolutionDir)3rdparty\sdl2\SDL\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>$(ProjectDir);$(SolutionDir)pcsx2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>$(ProjectDir);$(SolutionDir)pcsx2;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<!-- Needed for moc pch --> <!-- Needed for moc pch -->
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(ProjectDir)\Settings;$(ProjectDir)\GameList;$(ProjectDir)\Tools\InputRecording;$(ProjectDir)\Debugger;$(ProjectDir)\Debugger\Models</AdditionalIncludeDirectories> <AdditionalIncludeDirectories>%(AdditionalIncludeDirectories);$(ProjectDir)\Settings;$(ProjectDir)\GameList;$(ProjectDir)\Tools\InputRecording;$(ProjectDir)\Debugger;$(ProjectDir)\Debugger\Models</AdditionalIncludeDirectories>
@ -135,6 +136,7 @@
<Manifest Include="..\pcsx2\windows\PCSX2.manifest" /> <Manifest Include="..\pcsx2\windows\PCSX2.manifest" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="ColorPickerButton.cpp" />
<ClCompile Include="EarlyHardwareCheck.cpp" /> <ClCompile Include="EarlyHardwareCheck.cpp" />
<ClCompile Include="QtProgressCallback.cpp" /> <ClCompile Include="QtProgressCallback.cpp" />
<ClCompile Include="Settings\DebugSettingsWidget.cpp" /> <ClCompile Include="Settings\DebugSettingsWidget.cpp" />
@ -211,6 +213,7 @@
<QtMoc Include="Settings\DEV9SettingsWidget.h" /> <QtMoc Include="Settings\DEV9SettingsWidget.h" />
<QtMoc Include="Settings\DEV9UiCommon.h" /> <QtMoc Include="Settings\DEV9UiCommon.h" />
<QtMoc Include="QtProgressCallback.h" /> <QtMoc Include="QtProgressCallback.h" />
<QtMoc Include="ColorPickerButton.h" />
<ClInclude Include="Settings\ControllerSettingWidgetBinder.h" /> <ClInclude Include="Settings\ControllerSettingWidgetBinder.h" />
<QtMoc Include="Settings\FolderSettingsWidget.h" /> <QtMoc Include="Settings\FolderSettingsWidget.h" />
<QtMoc Include="Settings\DebugSettingsWidget.h" /> <QtMoc Include="Settings\DebugSettingsWidget.h" />
@ -292,6 +295,7 @@
<ClCompile Include="$(IntDir)GameList\moc_GameListWidget.cpp" /> <ClCompile Include="$(IntDir)GameList\moc_GameListWidget.cpp" />
<ClCompile Include="$(IntDir)moc_AboutDialog.cpp" /> <ClCompile Include="$(IntDir)moc_AboutDialog.cpp" />
<ClCompile Include="$(IntDir)moc_AutoUpdaterDialog.cpp" /> <ClCompile Include="$(IntDir)moc_AutoUpdaterDialog.cpp" />
<ClCompile Include="$(IntDir)moc_ColorPickerButton.cpp" />
<ClCompile Include="$(IntDir)moc_CoverDownloadDialog.cpp" /> <ClCompile Include="$(IntDir)moc_CoverDownloadDialog.cpp" />
<ClCompile Include="$(IntDir)moc_DisplayWidget.cpp" /> <ClCompile Include="$(IntDir)moc_DisplayWidget.cpp" />
<ClCompile Include="$(IntDir)moc_MainWindow.cpp" /> <ClCompile Include="$(IntDir)moc_MainWindow.cpp" />
@ -414,6 +418,9 @@
<QtUi Include="Settings\DebugSettingsWidget.ui"> <QtUi Include="Settings\DebugSettingsWidget.ui">
<FileType>Document</FileType> <FileType>Document</FileType>
</QtUi> </QtUi>
<QtUi Include="Settings\ControllerLEDSettingsDialog.ui">
<FileType>Document</FileType>
</QtUi>
<None Include="Settings\USBBindingWidget_DrivingForce.ui" /> <None Include="Settings\USBBindingWidget_DrivingForce.ui" />
<None Include="Settings\USBBindingWidget_GTForce.ui" /> <None Include="Settings\USBBindingWidget_GTForce.ui" />
<QtUi Include="Settings\USBDeviceWidget.ui"> <QtUi Include="Settings\USBDeviceWidget.ui">
@ -430,4 +437,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<Import Project="$(SolutionDir)common\vsprops\QtCompile.targets" /> <Import Project="$(SolutionDir)common\vsprops\QtCompile.targets" />
<ImportGroup Label="ExtensionTargets" /> <ImportGroup Label="ExtensionTargets" />
</Project> </Project>

View File

@ -27,9 +27,7 @@
</Filter> </Filter>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ResourceCompile Include="..\pcsx2\PCSX2.rc"> <ResourceCompile Include="..\pcsx2\windows\PCSX2.rc" />
<Filter>Resources</Filter>
</ResourceCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="PrecompiledHeader.cpp" /> <ClCompile Include="PrecompiledHeader.cpp" />
@ -313,6 +311,10 @@
<ClCompile Include="$(IntDir)Debugger\Models\moc_StackModel.cpp"> <ClCompile Include="$(IntDir)Debugger\Models\moc_StackModel.cpp">
<Filter>moc</Filter> <Filter>moc</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="ColorPickerButton.cpp" />
<ClCompile Include="$(IntDir)moc_ColorPickerButton.cpp">
<Filter>moc</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Manifest Include="..\pcsx2\windows\PCSX2.manifest"> <Manifest Include="..\pcsx2\windows\PCSX2.manifest">
@ -459,6 +461,7 @@
<QtMoc Include="Debugger\Models\StackModel.h"> <QtMoc Include="Debugger\Models\StackModel.h">
<Filter>Debugger\Models</Filter> <Filter>Debugger\Models</Filter>
</QtMoc> </QtMoc>
<QtMoc Include="ColorPickerButton.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<QtResource Include="resources\resources.qrc"> <QtResource Include="resources\resources.qrc">
@ -577,6 +580,9 @@
<QtUi Include="Debugger\BreakpointDialog.ui"> <QtUi Include="Debugger\BreakpointDialog.ui">
<Filter>Debugger</Filter> <Filter>Debugger</Filter>
</QtUi> </QtUi>
<QtUi Include="Settings\ControllerLEDSettingsDialog.ui">
<Filter>Settings</Filter>
</QtUi>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="Settings\FolderSettingsWidget.ui"> <None Include="Settings\FolderSettingsWidget.ui">

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M9.973 18H11v-5h2v5h1.027c.132-1.202.745-2.194 1.74-3.277.113-.122.832-.867.917-.973a6 6 0 1 0-9.37-.002c.086.107.807.853.918.974.996 1.084 1.609 2.076 1.741 3.278zM10 20v1h4v-1h-4zm-4.246-5a8 8 0 1 1 12.49.002C17.624 15.774 16 17 16 18.5V21a2 2 0 0 1-2 2h-4a2 2 0 0 1-2-2v-2.5C8 17 6.375 15.774 5.754 15z" fill="#000000"/></svg>

After

Width:  |  Height:  |  Size: 458 B

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24"><path fill="none" d="M0 0h24v24H0z"/><path d="M9.973 18H11v-5h2v5h1.027c.132-1.202.745-2.194 1.74-3.277.113-.122.832-.867.917-.973a6 6 0 1 0-9.37-.002c.086.107.807.853.918.974.996 1.084 1.609 2.076 1.741 3.278zM10 20v1h4v-1h-4zm-4.246-5a8 8 0 1 1 12.49.002C17.624 15.774 16 17 16 18.5V21a2 2 0 0 1-2 2h-4a2 2 0 0 1-2-2v-2.5C8 17 6.375 15.774 5.754 15z" fill="#ffffff"/></svg>

After

Width:  |  Height:  |  Size: 458 B

View File

@ -37,6 +37,7 @@
<file>icons/black/svg/image-fill.svg</file> <file>icons/black/svg/image-fill.svg</file>
<file>icons/black/svg/keyboard-line.svg</file> <file>icons/black/svg/keyboard-line.svg</file>
<file>icons/black/svg/layout-grid-line.svg</file> <file>icons/black/svg/layout-grid-line.svg</file>
<file>icons/black/svg/lightbulb-line.svg</file>
<file>icons/black/svg/list-check.svg</file> <file>icons/black/svg/list-check.svg</file>
<file>icons/black/svg/login-box-line.svg</file> <file>icons/black/svg/login-box-line.svg</file>
<file>icons/black/svg/pause-line.svg</file> <file>icons/black/svg/pause-line.svg</file>
@ -96,6 +97,7 @@
<file>icons/white/svg/image-fill.svg</file> <file>icons/white/svg/image-fill.svg</file>
<file>icons/white/svg/keyboard-line.svg</file> <file>icons/white/svg/keyboard-line.svg</file>
<file>icons/white/svg/layout-grid-line.svg</file> <file>icons/white/svg/layout-grid-line.svg</file>
<file>icons/white/svg/lightbulb-line.svg</file>
<file>icons/white/svg/list-check.svg</file> <file>icons/white/svg/list-check.svg</file>
<file>icons/white/svg/login-box-line.svg</file> <file>icons/white/svg/login-box-line.svg</file>
<file>icons/white/svg/pause-line.svg</file> <file>icons/white/svg/pause-line.svg</file>

View File

@ -98,6 +98,18 @@ static constexpr const char* s_sdl_hat_direction_names[] = {
// clang-format on // clang-format on
}; };
static constexpr const char* s_sdl_default_led_colors[] = {
"0000ff", // SDL-0
"ff0000", // SDL-1
"00ff00", // SDL-2
"ffff00", // SDL-3
};
static void SetControllerRGBLED(SDL_GameController* gc, u32 color)
{
SDL_GameControllerSetLED(gc, (color >> 16) & 0xff, (color >> 8) & 0xff, color & 0xff);
}
SDLInputSource::SDLInputSource() = default; SDLInputSource::SDLInputSource() = default;
SDLInputSource::~SDLInputSource() SDLInputSource::~SDLInputSource()
@ -159,6 +171,39 @@ void SDLInputSource::LoadSettings(SettingsInterface& si)
{ {
m_controller_enhanced_mode = si.GetBoolValue("InputSources", "SDLControllerEnhancedMode", false); m_controller_enhanced_mode = si.GetBoolValue("InputSources", "SDLControllerEnhancedMode", false);
m_sdl_hints = si.GetKeyValueList("SDLHints"); m_sdl_hints = si.GetKeyValueList("SDLHints");
for (u32 i = 0; i < MAX_LED_COLORS; i++)
{
const u32 color = GetRGBForPlayerId(si, i);
if (m_led_colors[i] == color)
continue;
m_led_colors[i] = color;
const auto it = GetControllerDataForPlayerId(i);
if (it == m_controllers.end() || !it->game_controller || !SDL_GameControllerHasLED(it->game_controller))
continue;
SetControllerRGBLED(it->game_controller, color);
}
}
u32 SDLInputSource::GetRGBForPlayerId(SettingsInterface& si, u32 player_id)
{
return ParseRGBForPlayerId(
si.GetStringValue("SDLExtra", fmt::format("Player{}LED", player_id).c_str(), s_sdl_default_led_colors[player_id]),
player_id);
}
u32 SDLInputSource::ParseRGBForPlayerId(const std::string_view& str, u32 player_id)
{
if (player_id >= MAX_LED_COLORS)
return 0;
const u32 default_color = StringUtil::FromChars<u32>(s_sdl_default_led_colors[player_id], 16).value_or(0);
const u32 color = StringUtil::FromChars<u32>(str, 16).value_or(default_color);
return color;
} }
void SDLInputSource::SetHints() void SDLInputSource::SetHints()
@ -617,6 +662,11 @@ bool SDLInputSource::OpenDevice(int index, bool is_gamecontroller)
if (!cd.haptic && !cd.use_game_controller_rumble) if (!cd.haptic && !cd.use_game_controller_rumble)
Console.Warning("(SDLInputSource) Rumble is not supported on '%s'", name); Console.Warning("(SDLInputSource) Rumble is not supported on '%s'", name);
if (player_id >= 0 && static_cast<u32>(player_id) < MAX_LED_COLORS && gcontroller && SDL_GameControllerHasLED(gcontroller))
{
SetControllerRGBLED(gcontroller, m_led_colors[player_id]);
}
m_controllers.push_back(std::move(cd)); m_controllers.push_back(std::move(cd));
InputManager::OnInputDeviceConnected(StringUtil::StdStringFromFormat("SDL-%d", player_id), name); InputManager::OnInputDeviceConnected(StringUtil::StdStringFromFormat("SDL-%d", player_id), name);
@ -668,7 +718,7 @@ bool SDLInputSource::HandleControllerButtonEvent(const SDL_ControllerButtonEvent
const InputBindingKey key(MakeGenericControllerButtonKey(InputSourceType::SDL, it->player_id, ev->button)); const InputBindingKey key(MakeGenericControllerButtonKey(InputSourceType::SDL, it->player_id, ev->button));
const GenericInputBinding generic_key = (ev->button < std::size(s_sdl_generic_binding_button_mapping)) ? const GenericInputBinding generic_key = (ev->button < std::size(s_sdl_generic_binding_button_mapping)) ?
s_sdl_generic_binding_button_mapping[ev->button] : s_sdl_generic_binding_button_mapping[ev->button] :
GenericInputBinding::Unknown; GenericInputBinding::Unknown;
InputManager::InvokeEvents(key, (ev->state == SDL_PRESSED) ? 1.0f : 0.0f, generic_key); InputManager::InvokeEvents(key, (ev->state == SDL_PRESSED) ? 1.0f : 0.0f, generic_key);
return true; return true;
} }

View File

@ -26,6 +26,8 @@ class SettingsInterface;
class SDLInputSource final : public InputSource class SDLInputSource final : public InputSource
{ {
public: public:
static constexpr u32 MAX_LED_COLORS = 4;
SDLInputSource(); SDLInputSource();
~SDLInputSource(); ~SDLInputSource();
@ -48,6 +50,9 @@ public:
SDL_Joystick* GetJoystickForDevice(const std::string_view& device); SDL_Joystick* GetJoystickForDevice(const std::string_view& device);
static u32 GetRGBForPlayerId(SettingsInterface& si, u32 player_id);
static u32 ParseRGBForPlayerId(const std::string_view& str, u32 player_id);
private: private:
struct ControllerData struct ControllerData
{ {
@ -92,5 +97,6 @@ private:
bool m_sdl_subsystem_initialized = false; bool m_sdl_subsystem_initialized = false;
bool m_controller_enhanced_mode = false; bool m_controller_enhanced_mode = false;
std::array<u32, MAX_LED_COLORS> m_led_colors{};
std::vector<std::pair<std::string, std::string>> m_sdl_hints; std::vector<std::pair<std::string, std::string>> m_sdl_hints;
}; };