diff --git a/src/Ryujinx.Common/Configuration/Hid/Controller/LedConfigController.cs b/src/Ryujinx.Common/Configuration/Hid/Controller/LedConfigController.cs
index 8ed68cd07..93b75d32c 100644
--- a/src/Ryujinx.Common/Configuration/Hid/Controller/LedConfigController.cs
+++ b/src/Ryujinx.Common/Configuration/Hid/Controller/LedConfigController.cs
@@ -12,6 +12,11 @@
///
public bool TurnOffLed { get; set; }
+ ///
+ /// Ignores the color and uses the rainbow color functionality for the LED.
+ ///
+ public bool UseRainbow { get; set; }
+
///
/// Packed RGB int of the color
///
diff --git a/src/Ryujinx.Common/Utilities/Rainbow.cs b/src/Ryujinx.Common/Utilities/Rainbow.cs
new file mode 100644
index 000000000..42222f157
--- /dev/null
+++ b/src/Ryujinx.Common/Utilities/Rainbow.cs
@@ -0,0 +1,76 @@
+using System;
+using System.Drawing;
+
+namespace Ryujinx.Common.Utilities
+{
+ public class Rainbow
+ {
+ public const float Speed = 1;
+
+ public static Color Color { get; private set; } = Color.Blue;
+
+ public static void Tick()
+ {
+ Color = HsbToRgb(
+ (Color.GetHue() + Speed) / 360,
+ 1,
+ 1
+ );
+
+ RainbowColorUpdated?.Invoke(Color.ToArgb());
+ }
+
+ public static event Action RainbowColorUpdated;
+
+ private static Color HsbToRgb(float hue, float saturation, float brightness)
+ {
+ int r = 0, g = 0, b = 0;
+ if (saturation == 0)
+ {
+ r = g = b = (int)(brightness * 255.0f + 0.5f);
+ }
+ else
+ {
+ float h = (hue - (float)Math.Floor(hue)) * 6.0f;
+ float f = h - (float)Math.Floor(h);
+ float p = brightness * (1.0f - saturation);
+ float q = brightness * (1.0f - saturation * f);
+ float t = brightness * (1.0f - (saturation * (1.0f - f)));
+ switch ((int)h)
+ {
+ case 0:
+ r = (int)(brightness * 255.0f + 0.5f);
+ g = (int)(t * 255.0f + 0.5f);
+ b = (int)(p * 255.0f + 0.5f);
+ break;
+ case 1:
+ r = (int)(q * 255.0f + 0.5f);
+ g = (int)(brightness * 255.0f + 0.5f);
+ b = (int)(p * 255.0f + 0.5f);
+ break;
+ case 2:
+ r = (int)(p * 255.0f + 0.5f);
+ g = (int)(brightness * 255.0f + 0.5f);
+ b = (int)(t * 255.0f + 0.5f);
+ break;
+ case 3:
+ r = (int)(p * 255.0f + 0.5f);
+ g = (int)(q * 255.0f + 0.5f);
+ b = (int)(brightness * 255.0f + 0.5f);
+ break;
+ case 4:
+ r = (int)(t * 255.0f + 0.5f);
+ g = (int)(p * 255.0f + 0.5f);
+ b = (int)(brightness * 255.0f + 0.5f);
+ break;
+ case 5:
+ r = (int)(brightness * 255.0f + 0.5f);
+ g = (int)(p * 255.0f + 0.5f);
+ b = (int)(q * 255.0f + 0.5f);
+ break;
+ }
+ }
+ return Color.FromArgb(Convert.ToByte(255), Convert.ToByte(r), Convert.ToByte(g), Convert.ToByte(b));
+ }
+ }
+}
diff --git a/src/Ryujinx.Input.SDL2/SDL2Gamepad.cs b/src/Ryujinx.Input.SDL2/SDL2Gamepad.cs
index f64e1c479..00d079a2b 100644
--- a/src/Ryujinx.Input.SDL2/SDL2Gamepad.cs
+++ b/src/Ryujinx.Input.SDL2/SDL2Gamepad.cs
@@ -1,6 +1,7 @@
using Ryujinx.Common.Configuration.Hid;
using Ryujinx.Common.Configuration.Hid.Controller;
using Ryujinx.Common.Logging;
+using Ryujinx.Common.Utilities;
using Ryujinx.HLE.HOS.Services.Hid;
using SDL2;
using System;
@@ -235,8 +236,11 @@ namespace Ryujinx.Input.SDL2
{
if (_configuration.Led.TurnOffLed)
(this as IGamepad).ClearLed();
+ else if (_configuration.Led.UseRainbow)
+ Rainbow.RainbowColorUpdated += clr => SetLed((uint)clr);
else
SetLed(_configuration.Led.LedColor);
+
}
_buttonsUserMapping.Clear();
diff --git a/src/Ryujinx.SDL2.Common/SDL2Driver.cs b/src/Ryujinx.SDL2.Common/SDL2Driver.cs
index 851c07867..47c5e60c5 100644
--- a/src/Ryujinx.SDL2.Common/SDL2Driver.cs
+++ b/src/Ryujinx.SDL2.Common/SDL2Driver.cs
@@ -1,5 +1,6 @@
using Ryujinx.Common.Configuration;
using Ryujinx.Common.Logging;
+using Ryujinx.Common.Utilities;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@@ -167,6 +168,8 @@ namespace Ryujinx.SDL2.Common
HandleSDLEvent(ref evnt);
}
});
+
+ Rainbow.Tick();
waitHandle.Wait(WaitTimeMs);
}
diff --git a/src/Ryujinx/Assets/locales.json b/src/Ryujinx/Assets/locales.json
index d4a52c003..4946a24f5 100644
--- a/src/Ryujinx/Assets/locales.json
+++ b/src/Ryujinx/Assets/locales.json
@@ -7628,7 +7628,7 @@
"ar_SA": "",
"de_DE": "",
"el_GR": "",
- "en_US": "Custom LED",
+ "en_US": "LED",
"es_ES": "",
"fr_FR": "",
"he_IL": "",
@@ -7672,6 +7672,31 @@
"zh_TW": ""
}
},
+ {
+ "ID": "ControllerSettingsLedColorRainbow",
+ "Translations": {
+ "ar_SA": "",
+ "de_DE": "",
+ "el_GR": "",
+ "en_US": "Rainbow",
+ "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": {
@@ -23023,4 +23048,4 @@
}
}
]
-}
\ No newline at end of file
+}
diff --git a/src/Ryujinx/UI/Models/Input/GamepadInputConfig.cs b/src/Ryujinx/UI/Models/Input/GamepadInputConfig.cs
index ae3676853..6f0f7f47f 100644
--- a/src/Ryujinx/UI/Models/Input/GamepadInputConfig.cs
+++ b/src/Ryujinx/UI/Models/Input/GamepadInputConfig.cs
@@ -388,42 +388,6 @@ namespace Ryujinx.Ava.UI.Models.Input
}
}
- private bool _enableLedChanging;
-
- public bool EnableLedChanging
- {
- get => _enableLedChanging;
- set
- {
- _enableLedChanging = value;
- OnPropertyChanged();
- }
- }
-
- private bool _turnOffLed;
-
- public bool TurnOffLed
- {
- get => _turnOffLed;
- set
- {
- _turnOffLed = value;
- OnPropertyChanged();
- }
- }
-
- private Color _ledColor;
-
- public Color LedColor
- {
- get => _ledColor;
- set
- {
- _ledColor = value;
- OnPropertyChanged();
- }
- }
-
private bool _enableMotion;
public bool EnableMotion
{
@@ -445,6 +409,58 @@ namespace Ryujinx.Ava.UI.Models.Input
OnPropertyChanged();
}
}
+
+ private bool _enableLedChanging;
+
+ public bool EnableLedChanging
+ {
+ get => _enableLedChanging;
+ set
+ {
+ _enableLedChanging = value;
+ OnPropertyChanged();
+ }
+ }
+
+ public bool ShowLedColorPicker => !TurnOffLed && !UseRainbowLed;
+
+ private bool _turnOffLed;
+
+ public bool TurnOffLed
+ {
+ get => _turnOffLed;
+ set
+ {
+ _turnOffLed = value;
+ OnPropertyChanged();
+ OnPropertyChanged(nameof(ShowLedColorPicker));
+ }
+ }
+
+ private bool _useRainbowLed;
+
+ public bool UseRainbowLed
+ {
+ get => _useRainbowLed;
+ set
+ {
+ _useRainbowLed = value;
+ OnPropertyChanged();
+ OnPropertyChanged(nameof(ShowLedColorPicker));
+ }
+ }
+
+ private Color _ledColor;
+
+ public Color LedColor
+ {
+ get => _ledColor;
+ set
+ {
+ _ledColor = value;
+ OnPropertyChanged();
+ }
+ }
public GamepadInputConfig(InputConfig config)
{
@@ -525,6 +541,7 @@ namespace Ryujinx.Ava.UI.Models.Input
{
EnableLedChanging = controllerInput.Led.EnableLed;
TurnOffLed = controllerInput.Led.TurnOffLed;
+ UseRainbowLed = controllerInput.Led.UseRainbow;
uint rawColor = controllerInput.Led.LedColor;
byte alpha = (byte)(rawColor >> 24);
byte red = (byte)(rawColor >> 16);
@@ -593,6 +610,7 @@ namespace Ryujinx.Ava.UI.Models.Input
{
EnableLed = EnableLedChanging,
TurnOffLed = this.TurnOffLed,
+ UseRainbow = UseRainbowLed,
LedColor = LedColor.ToUInt32()
},
Version = InputConfig.CurrentVersion,
diff --git a/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml b/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml
index 6b8673a9f..a4218c61e 100644
--- a/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml
+++ b/src/Ryujinx/UI/Views/Input/ControllerInputView.axaml
@@ -495,19 +495,20 @@
Margin="0,-1,0,0">
+
-
+
+
+