From 1ab4e2f94be84649d8a4737da52a8f7311a31afa Mon Sep 17 00:00:00 2001 From: cake Date: Fri, 26 Dec 2025 22:26:29 +0100 Subject: [PATCH] Added color options for header --- LightlessSync/UI/SettingsUi.cs | 25 ++++++----- LightlessSync/UI/Style/AnimatedHeader.cs | 53 +++++++++++++++++++----- LightlessSync/UI/UIColors.cs | 16 ++++--- 3 files changed, 68 insertions(+), 26 deletions(-) diff --git a/LightlessSync/UI/SettingsUi.cs b/LightlessSync/UI/SettingsUi.cs index 91f69d5..a6b9c33 100644 --- a/LightlessSync/UI/SettingsUi.cs +++ b/LightlessSync/UI/SettingsUi.cs @@ -2795,16 +2795,21 @@ public class SettingsUi : WindowMediatorSubscriberBase var colorNames = new[] { - ("LightlessPurple", "Primary Purple", "Section titles and dividers"), - ("LightlessPurpleActive", "Primary Purple (Active)", "Active tabs and hover highlights"), - ("LightlessPurpleDefault", "Primary Purple (Inactive)", "Inactive tabs and default dividers"), - ("LightlessBlue", "Secondary Blue", "Secondary title colors, visable pairs"), - ("LightlessGreen", "Success Green", "Join buttons and success messages"), - ("LightlessYellow", "Warning Yellow", "Warning colors"), - ("LightlessOrange", "Performance Orange", "Performance notifications and warnings"), - ("PairBlue", "Syncshell Blue", "Syncshell headers, toggle highlights, and moderator actions"), - ("DimRed", "Error Red", "Error and offline colors") - }; + ("LightlessPurple", "Primary Purple", "Section titles and dividers"), + ("LightlessPurpleActive", "Primary Purple (Active)", "Active tabs and hover highlights"), + ("LightlessPurpleDefault", "Primary Purple (Inactive)", "Inactive tabs and default dividers"), + ("LightlessBlue", "Secondary Blue", "Secondary title colors, visable pairs"), + ("LightlessGreen", "Success Green", "Join buttons and success messages"), + ("LightlessYellow", "Warning Yellow", "Warning colors"), + ("LightlessOrange", "Performance Orange", "Performance notifications and warnings"), + ("PairBlue", "Syncshell Blue", "Syncshell headers, toggle highlights, and moderator actions"), + ("DimRed", "Error Red", "Error and offline colors"), + ("HeaderGradientTop", "Header Gradient (Top)", "Top color of the animated header background"), + ("HeaderGradientBottom", "Header Gradient (Bottom)", "Bottom color of the animated header background"), + ("HeaderStaticStar", "Header Stars", "Tint color for the static background stars in the header"), + ("HeaderShootingStar", "Header Shooting Star", "Tint color for the shooting star effect"), + }; + if (ImGui.BeginTable("##ColorTable", 3, ImGuiTableFlags.Borders | ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingFixedFit)) { diff --git a/LightlessSync/UI/Style/AnimatedHeader.cs b/LightlessSync/UI/Style/AnimatedHeader.cs index 839c704..9df0847 100644 --- a/LightlessSync/UI/Style/AnimatedHeader.cs +++ b/LightlessSync/UI/Style/AnimatedHeader.cs @@ -43,8 +43,19 @@ public class AnimatedHeader private const float _extendedParticleHeight = 40f; public float Height { get; set; } = 150f; + + // Color keys for theming + public string? TopColorKey { get; set; } = "HeaderGradientTop"; + public string? BottomColorKey { get; set; } = "HeaderGradientBottom"; + public string? StaticStarColorKey { get; set; } = "HeaderStaticStar"; + public string? ShootingStarColorKey { get; set; } = "HeaderShootingStar"; + + // Fallbacks if the color keys are not found public Vector4 TopColor { get; set; } = new(0.08f, 0.05f, 0.15f, 1.0f); public Vector4 BottomColor { get; set; } = new(0.12f, 0.08f, 0.20f, 1.0f); + public Vector4 StaticStarColor { get; set; } = new(1f, 1f, 1f, 1f); + public Vector4 ShootingStarColor { get; set; } = new(0.4f, 0.8f, 1.0f, 1.0f); + public bool EnableParticles { get; set; } = true; public bool EnableBottomGradient { get; set; } = true; @@ -148,16 +159,21 @@ public class AnimatedHeader { var drawList = ImGui.GetWindowDrawList(); + var top = ResolveColor(TopColorKey, TopColor); + var bottom = ResolveColor(BottomColorKey, BottomColor); + drawList.AddRectFilledMultiColor( headerStart, headerEnd, - ImGui.GetColorU32(TopColor), - ImGui.GetColorU32(TopColor), - ImGui.GetColorU32(BottomColor), - ImGui.GetColorU32(BottomColor) + ImGui.GetColorU32(top), + ImGui.GetColorU32(top), + ImGui.GetColorU32(bottom), + ImGui.GetColorU32(bottom) ); // Draw static background stars + var starBase = ResolveColor(StaticStarColorKey, StaticStarColor); + var random = new Random(42); for (int i = 0; i < 50; i++) { @@ -166,7 +182,9 @@ public class AnimatedHeader (float)random.NextDouble() * (headerEnd.Y - headerStart.Y) ); var brightness = 0.3f + (float)random.NextDouble() * 0.4f; - drawList.AddCircleFilled(starPos, 1f, ImGui.GetColorU32(new Vector4(1f, 1f, 1f, brightness))); + var starColor = starBase with { W = starBase.W * brightness }; + + drawList.AddCircleFilled(starPos, 1f, ImGui.GetColorU32(starColor)); } } @@ -174,15 +192,18 @@ public class AnimatedHeader { var drawList = ImGui.GetWindowDrawList(); var gradientHeight = GradientHeight; + var bottom = ResolveColor(BottomColorKey, BottomColor); for (int i = 0; i < gradientHeight; i++) { var progress = i / gradientHeight; var smoothProgress = progress * progress; - var r = BottomColor.X + (0.0f - BottomColor.X) * smoothProgress; - var g = BottomColor.Y + (0.0f - BottomColor.Y) * smoothProgress; - var b = BottomColor.Z + (0.0f - BottomColor.Z) * smoothProgress; + + var r = bottom.X + (0.0f - bottom.X) * smoothProgress; + var g = bottom.Y + (0.0f - bottom.Y) * smoothProgress; + var b = bottom.Z + (0.0f - bottom.Z) * smoothProgress; var alpha = 1f - smoothProgress; + var gradientColor = new Vector4(r, g, b, alpha); drawList.AddLine( new Vector2(headerStart.X, headerEnd.Y + i), @@ -310,9 +331,11 @@ public class AnimatedHeader ? baseAlpha * (0.6f + 0.4f * MathF.Sin(particle.Twinkle)) : baseAlpha; + var shootingBase = ResolveColor(ShootingStarColorKey, ShootingStarColor); + if (particle.Type == ParticleType.ShootingStar && particle.Trail != null && particle.Trail.Count > 1) { - var cyanColor = new Vector4(0.4f, 0.8f, 1.0f, 1.0f); + var baseColor = shootingBase; for (int t = 1; t < particle.Trail.Count; t++) { @@ -321,17 +344,18 @@ public class AnimatedHeader var trailWidth = (1f - trailProgress) * 3f + 1f; var glowAlpha = trailAlpha * 0.4f; + drawList.AddLine( bannerStart + particle.Trail[t - 1], bannerStart + particle.Trail[t], - ImGui.GetColorU32(cyanColor with { W = glowAlpha }), + ImGui.GetColorU32(baseColor with { W = glowAlpha }), trailWidth + 4f ); drawList.AddLine( bannerStart + particle.Trail[t - 1], bannerStart + particle.Trail[t], - ImGui.GetColorU32(cyanColor with { W = trailAlpha }), + ImGui.GetColorU32(baseColor with { W = trailAlpha }), trailWidth ); } @@ -450,6 +474,13 @@ public class AnimatedHeader Hue = 270f }); } + private static Vector4 ResolveColor(string? key, Vector4 fallback) + { + if (string.IsNullOrWhiteSpace(key)) + return fallback; + + return UIColors.Get(key); + } /// /// Clears all active particles. Useful when closing or hiding a window with an animated header. diff --git a/LightlessSync/UI/UIColors.cs b/LightlessSync/UI/UIColors.cs index 9d7f770..1decb77 100644 --- a/LightlessSync/UI/UIColors.cs +++ b/LightlessSync/UI/UIColors.cs @@ -6,7 +6,7 @@ namespace LightlessSync.UI { internal static class UIColors { - private static readonly Dictionary DefaultHexColors = new(StringComparer.OrdinalIgnoreCase) + private static readonly Dictionary _defaultHexColors = new(StringComparer.OrdinalIgnoreCase) { { "LightlessPurple", "#ad8af5" }, { "LightlessPurpleActive", "#be9eff" }, @@ -31,6 +31,12 @@ namespace LightlessSync.UI { "ProfileBodyGradientTop", "#2f283fff" }, { "ProfileBodyGradientBottom", "#372d4d00" }, + + { "HeaderGradientTop", "#140D26FF" }, + { "HeaderGradientBottom", "#1F1433FF" }, + + { "HeaderStaticStar", "#FFFFFFFF" }, + { "HeaderShootingStar", "#66CCFFFF" }, }; private static LightlessConfigService? _configService; @@ -45,7 +51,7 @@ namespace LightlessSync.UI if (_configService?.Current.CustomUIColors.TryGetValue(name, out var customColorHex) == true) return HexToRgba(customColorHex); - if (!DefaultHexColors.TryGetValue(name, out var hex)) + if (!_defaultHexColors.TryGetValue(name, out var hex)) throw new ArgumentException($"Color '{name}' not found in UIColors.", nameof(name)); return HexToRgba(hex); @@ -53,7 +59,7 @@ namespace LightlessSync.UI public static void Set(string name, Vector4 color) { - if (!DefaultHexColors.ContainsKey(name)) + if (!_defaultHexColors.ContainsKey(name)) throw new ArgumentException($"Color '{name}' not found in UIColors.", nameof(name)); if (_configService != null) @@ -83,7 +89,7 @@ namespace LightlessSync.UI public static Vector4 GetDefault(string name) { - if (!DefaultHexColors.TryGetValue(name, out var hex)) + if (!_defaultHexColors.TryGetValue(name, out var hex)) throw new ArgumentException($"Color '{name}' not found in UIColors.", nameof(name)); return HexToRgba(hex); @@ -96,7 +102,7 @@ namespace LightlessSync.UI public static IEnumerable GetColorNames() { - return DefaultHexColors.Keys; + return _defaultHexColors.Keys; } public static Vector4 HexToRgba(string hexColor)