diff --git a/src/Ryujinx.Common/Configuration/Hid/Controller/LedConfigController.cs b/src/Ryujinx.Common/Configuration/Hid/Controller/LedConfigController.cs index 21727d62e..8ed68cd07 100644 --- a/src/Ryujinx.Common/Configuration/Hid/Controller/LedConfigController.cs +++ b/src/Ryujinx.Common/Configuration/Hid/Controller/LedConfigController.cs @@ -2,14 +2,19 @@ { public class LedConfigController { - /// - /// Packed RGB int of the color - /// - public uint LedColor { get; set; } - /// /// Enable LED color changing by the emulator /// public bool EnableLed { get; set; } + + /// + /// Ignores the color and disables the LED entirely. + /// + public bool TurnOffLed { get; set; } + + /// + /// Packed RGB int of the color + /// + public uint LedColor { get; set; } } } diff --git a/src/Ryujinx.Input.SDL2/SDL2Gamepad.cs b/src/Ryujinx.Input.SDL2/SDL2Gamepad.cs index ba11fab87..f64e1c479 100644 --- a/src/Ryujinx.Input.SDL2/SDL2Gamepad.cs +++ b/src/Ryujinx.Input.SDL2/SDL2Gamepad.cs @@ -106,11 +106,11 @@ namespace Ryujinx.Input.SDL2 public void SetLed(uint packedRgb) { if (!Features.HasFlag(GamepadFeaturesFlag.Led)) return; - - byte red = (byte)(packedRgb >> 16); - byte green = (byte)(packedRgb >> 8); - byte blue = (byte)(packedRgb % 256); + byte red = packedRgb > 0 ? (byte)(packedRgb >> 16) : (byte)0; + byte green = packedRgb > 0 ? (byte)(packedRgb >> 8) : (byte)0; + byte blue = packedRgb > 0 ? (byte)(packedRgb % 256) : (byte)0; + if (SDL_GameControllerSetLED(_gamepadHandle, red, green, blue) != 0) Logger.Error?.Print(LogClass.Hid, "LED is not supported on this game controller."); } @@ -232,7 +232,12 @@ namespace Ryujinx.Input.SDL2 _configuration = (StandardControllerInputConfig)configuration; if (Features.HasFlag(GamepadFeaturesFlag.Led) && _configuration.Led.EnableLed) - SetLed(_configuration.Led.LedColor); + { + if (_configuration.Led.TurnOffLed) + (this as IGamepad).ClearLed(); + else + SetLed(_configuration.Led.LedColor); + } _buttonsUserMapping.Clear(); diff --git a/src/Ryujinx.Input/IGamepad.cs b/src/Ryujinx.Input/IGamepad.cs index 6781c0faa..832950660 100644 --- a/src/Ryujinx.Input/IGamepad.cs +++ b/src/Ryujinx.Input/IGamepad.cs @@ -72,6 +72,8 @@ namespace Ryujinx.Input /// The packed RGB integer. void SetLed(uint packedRgb); + public void ClearLed() => SetLed(0); + /// /// Starts a rumble effect on the gamepad. /// diff --git a/src/Ryujinx/Assets/locales.json b/src/Ryujinx/Assets/locales.json index 8ceef5f67..d4a52c003 100644 --- a/src/Ryujinx/Assets/locales.json +++ b/src/Ryujinx/Assets/locales.json @@ -7647,6 +7647,31 @@ "zh_TW": "" } }, + { + "ID": "ControllerSettingsLedColorDisable", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Disable", + "es_ES": "", + "fr_FR": "", + "he_IL": "", + "it_IT": "", + "ja_JP": "", + "ko_KR": "", + "no_NO": "", + "pl_PL": "", + "pt_BR": "", + "ru_RU": "", + "sv_SE": "", + "th_TH": "", + "tr_TR": "", + "uk_UA": "", + "zh_CN": "", + "zh_TW": "" + } + }, { "ID": "ControllerSettingsSave", "Translations": { diff --git a/src/Ryujinx/UI/Models/Input/GamepadInputConfig.cs b/src/Ryujinx/UI/Models/Input/GamepadInputConfig.cs index ea7dd34c3..ae3676853 100644 --- a/src/Ryujinx/UI/Models/Input/GamepadInputConfig.cs +++ b/src/Ryujinx/UI/Models/Input/GamepadInputConfig.cs @@ -400,6 +400,18 @@ namespace Ryujinx.Ava.UI.Models.Input } } + private bool _turnOffLed; + + public bool TurnOffLed + { + get => _turnOffLed; + set + { + _turnOffLed = value; + OnPropertyChanged(); + } + } + private Color _ledColor; public Color LedColor @@ -512,6 +524,7 @@ namespace Ryujinx.Ava.UI.Models.Input if (controllerInput.Led != null) { EnableLedChanging = controllerInput.Led.EnableLed; + TurnOffLed = controllerInput.Led.TurnOffLed; uint rawColor = controllerInput.Led.LedColor; byte alpha = (byte)(rawColor >> 24); byte red = (byte)(rawColor >> 16); @@ -579,6 +592,7 @@ namespace Ryujinx.Ava.UI.Models.Input Led = new LedConfigController { EnableLed = EnableLedChanging, + TurnOffLed = this.TurnOffLed, LedColor = LedColor.ToUInt32() }, Version = InputConfig.CurrentVersion, diff --git a/src/Ryujinx/UI/ViewModels/Input/ControllerInputViewModel.cs b/src/Ryujinx/UI/ViewModels/Input/ControllerInputViewModel.cs index 107b543ca..d291f09a0 100644 --- a/src/Ryujinx/UI/ViewModels/Input/ControllerInputViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/Input/ControllerInputViewModel.cs @@ -1,6 +1,8 @@ using Avalonia.Svg.Skia; using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.Input; using FluentAvalonia.UI.Controls; +using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Models.Input; using Ryujinx.Ava.UI.Views.Input; @@ -58,6 +60,16 @@ namespace Ryujinx.Ava.UI.ViewModels.Input await RumbleInputView.Show(this); } + public RelayCommand LedDisabledChanged => Commands.Create(() => + { + if (!Config.EnableLedChanging) return; + + if (Config.TurnOffLed) + ParentModel.SelectedGamepad.ClearLed(); + else + ParentModel.SelectedGamepad.SetLed(Config.LedColor.ToUInt32()); + }); + public void OnParentModelChanged() { IsLeft = ParentModel.IsLeft; diff --git a/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs b/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs index 720a43614..c59ec540c 100644 --- a/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/Input/InputViewModel.cs @@ -3,6 +3,7 @@ using Avalonia.Controls; using Avalonia.Svg.Skia; using Avalonia.Threading; using CommunityToolkit.Mvvm.ComponentModel; +using Gommon; using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Input; using Ryujinx.Ava.UI.Helpers; @@ -54,7 +55,18 @@ namespace Ryujinx.Ava.UI.ViewModels.Input private static readonly InputConfigJsonSerializerContext _serializerContext = new(JsonHelper.GetDefaultSerializerOptions()); public IGamepadDriver AvaloniaKeyboardDriver { get; } - public IGamepad SelectedGamepad { get; private set; } + + private IGamepad _selectedGamepad; + + public IGamepad SelectedGamepad + { + get => _selectedGamepad; + private set + { + _selectedGamepad = value; + OnPropertiesChanged(nameof(HasLed), nameof(CanClearLed)); + } + } public ObservableCollection PlayerIndexes { get; set; } public ObservableCollection<(DeviceType Type, string Id, string Name)> Devices { get; set; } @@ -70,6 +82,7 @@ namespace Ryujinx.Ava.UI.ViewModels.Input public bool IsLeft { get; set; } public bool HasLed => SelectedGamepad.Features.HasFlag(GamepadFeaturesFlag.Led); + public bool CanClearLed => SelectedGamepad.Name.ContainsIgnoreCase("DualSense"); public bool IsModified { get; set; } public event Action NotifyChangesEvent; diff --git a/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml b/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml index 3592df7cd..6b8673a9f 100644 --- a/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml +++ b/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml @@ -495,6 +495,7 @@ Margin="0,-1,0,0"> + @@ -505,8 +506,18 @@ IsChecked="{Binding Config.EnableLedChanging, Mode=TwoWay}"> - + + + @@ -235,13 +237,13 @@ namespace Ryujinx.Ava.UI.Views.Input _currentAssigner?.Cancel(); _currentAssigner = null; } - + private void ColorPickerButton_OnColorChanged(ColorPickerButton sender, ColorButtonColorChangedEventArgs args) { if (!args.NewColor.HasValue) return; if (DataContext is not ControllerInputViewModel cVm) return; if (!cVm.Config.EnableLedChanging) return; - + cVm.ParentModel.SelectedGamepad.SetLed(args.NewColor.Value.ToUInt32()); } @@ -249,7 +251,7 @@ namespace Ryujinx.Ava.UI.Views.Input { if (DataContext is not ControllerInputViewModel cVm) return; if (!cVm.Config.EnableLedChanging) return; - + cVm.ParentModel.SelectedGamepad.SetLed(cVm.Config.LedColor.ToUInt32()); } } diff --git a/src/Ryujinx/Utilities/Configuration/ConfigurationState.Migration.cs b/src/Ryujinx/Utilities/Configuration/ConfigurationState.Migration.cs index 025f6bdb8..78e3dfc0f 100644 --- a/src/Ryujinx/Utilities/Configuration/ConfigurationState.Migration.cs +++ b/src/Ryujinx/Utilities/Configuration/ConfigurationState.Migration.cs @@ -422,6 +422,7 @@ namespace Ryujinx.Ava.Utilities.Configuration config.Led = new LedConfigController { EnableLed = false, + TurnOffLed = false, LedColor = new Color(255, 5, 1, 253).ToUInt32() }; }