using Gommon; using Ryujinx.Common.Helper; using System; using System.Drawing; using System.Threading; using System.Threading.Tasks; namespace Ryujinx.Common.Utilities { public static class Rainbow { public static bool CyclingEnabled { get; set; } public static void Enable() { if (!CyclingEnabled) { CyclingEnabled = true; Executor.ExecuteBackgroundAsync(async () => { while (CyclingEnabled) { await Task.Delay(20); Tick(); } }); } } public static void Disable() { CyclingEnabled = false; } public static float Speed { get; set; } = 1; private static readonly Lock _lock = new(); private static Color _color = Color.Blue; public static ref Color Color { get { lock (_lock) { return ref _color; } } } public static void Tick() { lock (_lock) { _color = HsbToRgb((_color.GetHue() + Speed) / 360); _updatedHandler.Call(ref _color); } } public static void Reset() { _updatedHandler.Clear(); lock (_lock) _color = Color.Blue; } public static event RefEvent.Handler Updated { add => _updatedHandler.Add(value); remove => _updatedHandler.Remove(value); } private static readonly RefEvent _updatedHandler = new(); private static Color HsbToRgb(float hue, float saturation = 1, float brightness = 1) { 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)); } } }