diff --git a/MareSynchronos/MareConfiguration/Configurations/MareConfig.cs b/MareSynchronos/MareConfiguration/Configurations/MareConfig.cs index a755304..24df7f5 100644 --- a/MareSynchronos/MareConfiguration/Configurations/MareConfig.cs +++ b/MareSynchronos/MareConfiguration/Configurations/MareConfig.cs @@ -1,4 +1,5 @@ using MareSynchronos.MareConfiguration.Models; +using MareSynchronos.UI; using Microsoft.Extensions.Logging; namespace MareSynchronos.MareConfiguration.Configurations; @@ -14,6 +15,9 @@ public class MareConfig : IMareConfiguration public bool ShowUidInDtrTooltip { get; set; } = true; public bool PreferNoteInDtrTooltip { get; set; } = false; public bool UseColorsInDtr { get; set; } = true; + public DtrEntry.Colors DtrColorsDefault { get; set; } = default; + public DtrEntry.Colors DtrColorsNotConnected { get; set; } = new(Glow: 0x0428FFu); + public DtrEntry.Colors DtrColorsPairsInRange { get; set; } = new(Glow: 0xFFBA47u); public bool EnableRightClickMenus { get; set; } = true; public NotificationLocation ErrorNotification { get; set; } = NotificationLocation.Both; public string ExportFolder { get; set; } = string.Empty; diff --git a/MareSynchronos/UI/DtrEntry.cs b/MareSynchronos/UI/DtrEntry.cs index 026a5c2..6339c6e 100644 --- a/MareSynchronos/UI/DtrEntry.cs +++ b/MareSynchronos/UI/DtrEntry.cs @@ -1,5 +1,6 @@ using Dalamud.Game.Gui.Dtr; using Dalamud.Game.Text.SeStringHandling; +using Dalamud.Game.Text.SeStringHandling.Payloads; using Dalamud.Plugin.Services; using MareSynchronos.MareConfiguration; using MareSynchronos.MareConfiguration.Configurations; @@ -8,6 +9,7 @@ using MareSynchronos.Services.Mediator; using MareSynchronos.WebAPI; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; +using System.Runtime.InteropServices; namespace MareSynchronos.UI; @@ -40,7 +42,7 @@ public sealed class DtrEntry : IDisposable, IHostedService private Task? _runTask; private string? _text; private string? _tooltip; - private StatusColorId _color; + private Colors _colors; public DtrEntry(ILogger logger, IDtrBar dtrBar, ConfigurationServiceBase configService, MareMediator mareMediator, PairManager pairManager, ApiController apiController) { @@ -94,7 +96,7 @@ public sealed class DtrEntry : IDisposable, IHostedService _logger.LogInformation("Clearing entry"); _text = null; _tooltip = null; - _color = default; + _colors = default; _entry.Value.Shown = false; } @@ -139,7 +141,7 @@ public sealed class DtrEntry : IDisposable, IHostedService string text; string tooltip; - StatusColorId color; + Colors colors; if (_apiController.IsConnected) { var pairCount = _pairManager.GetVisibleUserCount(); @@ -162,30 +164,30 @@ public sealed class DtrEntry : IDisposable, IHostedService } tooltip = $"Loporrit: Connected{Environment.NewLine}----------{Environment.NewLine}{string.Join(Environment.NewLine, visiblePairs)}"; - color = StatusColorId.PairsInRange; + colors = _configService.Current.DtrColorsPairsInRange; } else { tooltip = "Loporrit: Connected"; - color = default; + colors = _configService.Current.DtrColorsDefault; } } else { text = RenderDtrStyle(_configService.Current.DtrStyle, "\uE04C"); tooltip = "Loporrit: Not Connected"; - color = StatusColorId.NotConnected; + colors = _configService.Current.DtrColorsNotConnected; } if (!_configService.Current.UseColorsInDtr) - color = default; + colors = default; - if (!string.Equals(text, _text, StringComparison.Ordinal) || !string.Equals(tooltip, _tooltip, StringComparison.Ordinal) || color != _color) + if (!string.Equals(text, _text, StringComparison.Ordinal) || !string.Equals(tooltip, _tooltip, StringComparison.Ordinal) || colors != _colors) { _text = text; _tooltip = tooltip; - _color = color; - _entry.Value.Text = color != default ? BuildColoredSeString(text, color) : text; + _colors = colors; + _entry.Value.Text = BuildColoredSeString(text, colors); _entry.Value.Tooltip = tooltip; } } @@ -208,13 +210,32 @@ public sealed class DtrEntry : IDisposable, IHostedService }; } - private static SeString BuildColoredSeString(string text, StatusColorId color) - => new SeStringBuilder().AddUiGlow(text, (ushort)color).Build(); + #region Colored SeString + private const byte _colorTypeForeground = 0x13; + private const byte _colorTypeGlow = 0x14; - private enum StatusColorId : ushort + private static SeString BuildColoredSeString(string text, Colors colors) { - None = default, - NotConnected = 518, - PairsInRange = 526, + var ssb = new SeStringBuilder(); + if (colors.Foreground != default) + ssb.Add(BuildColorStartPayload(_colorTypeForeground, colors.Foreground)); + if (colors.Glow != default) + ssb.Add(BuildColorStartPayload(_colorTypeGlow, colors.Glow)); + ssb.AddText(text); + if (colors.Glow != default) + ssb.Add(BuildColorEndPayload(_colorTypeGlow)); + if (colors.Foreground != default) + ssb.Add(BuildColorEndPayload(_colorTypeForeground)); + return ssb.Build(); } + + private static RawPayload BuildColorStartPayload(byte colorType, uint color) + => new(unchecked([0x02, colorType, 0x05, 0xF6, byte.Max((byte)color, 0x01), byte.Max((byte)(color >> 8), 0x01), byte.Max((byte)(color >> 16), 0x01), 0x03])); + + private static RawPayload BuildColorEndPayload(byte colorType) + => new([0x02, colorType, 0x02, 0xEC, 0x03]); + + [StructLayout(LayoutKind.Sequential)] + public readonly record struct Colors(uint Foreground = default, uint Glow = default); + #endregion } diff --git a/MareSynchronos/UI/SettingsUi.cs b/MareSynchronos/UI/SettingsUi.cs index fc68b9c..6be7a45 100644 --- a/MareSynchronos/UI/SettingsUi.cs +++ b/MareSynchronos/UI/SettingsUi.cs @@ -980,6 +980,9 @@ public class SettingsUi : WindowMediatorSubscriberBase var showUidInDtrTooltip = _configService.Current.ShowUidInDtrTooltip; var preferNoteInDtrTooltip = _configService.Current.PreferNoteInDtrTooltip; var useColorsInDtr = _configService.Current.UseColorsInDtr; + var dtrColorsDefault = _configService.Current.DtrColorsDefault; + var dtrColorsNotConnected = _configService.Current.DtrColorsNotConnected; + var dtrColorsPairsInRange = _configService.Current.DtrColorsPairsInRange; if (ImGui.Checkbox("Enable Game Right Click Menu Entries", ref enableRightClickMenu)) { @@ -1023,6 +1026,30 @@ public class SettingsUi : WindowMediatorSubscriberBase _configService.Current.UseColorsInDtr = useColorsInDtr; _configService.Save(); } + + using (ImRaii.Disabled(!useColorsInDtr)) + { + using var indent2 = ImRaii.PushIndent(); + if (InputDtrColors("Default", ref dtrColorsDefault)) + { + _configService.Current.DtrColorsDefault = dtrColorsDefault; + _configService.Save(); + } + + ImGui.SameLine(); + if (InputDtrColors("Not Connected", ref dtrColorsNotConnected)) + { + _configService.Current.DtrColorsNotConnected = dtrColorsNotConnected; + _configService.Save(); + } + + ImGui.SameLine(); + if (InputDtrColors("Pairs in Range", ref dtrColorsPairsInRange)) + { + _configService.Current.DtrColorsPairsInRange = dtrColorsPairsInRange; + _configService.Save(); + } + } } if (ImGui.Checkbox("Show separate Visible group", ref showVisibleSeparate)) @@ -1157,6 +1184,37 @@ public class SettingsUi : WindowMediatorSubscriberBase } } + private static bool InputDtrColors(string label, ref DtrEntry.Colors colors) + { + using var id = ImRaii.PushId(label); + var innerSpacing = ImGui.GetStyle().ItemInnerSpacing.X; + var foregroundColor = ConvertColor(colors.Foreground); + var glowColor = ConvertColor(colors.Glow); + + var ret = ImGui.ColorEdit3("###foreground", ref foregroundColor, ImGuiColorEditFlags.NoInputs | ImGuiColorEditFlags.NoLabel | ImGuiColorEditFlags.Uint8); + if (ImGui.IsItemHovered()) + ImGui.SetTooltip("Foreground Color - Set to pure black (#000000) to use the default color"); + + ImGui.SameLine(0.0f, innerSpacing); + ret |= ImGui.ColorEdit3("###glow", ref glowColor, ImGuiColorEditFlags.NoInputs | ImGuiColorEditFlags.NoLabel | ImGuiColorEditFlags.Uint8); + if (ImGui.IsItemHovered()) + ImGui.SetTooltip("Glow Color - Set to pure black (#000000) to use the default color"); + + ImGui.SameLine(0.0f, innerSpacing); + ImGui.TextUnformatted(label); + + if (ret) + colors = new(ConvertBackColor(foregroundColor), ConvertBackColor(glowColor)); + + return ret; + + static Vector3 ConvertColor(uint color) + => unchecked(new((byte)color / 255.0f, (byte)(color >> 8) / 255.0f, (byte)(color >> 16) / 255.0f)); + + static uint ConvertBackColor(Vector3 color) + => byte.CreateSaturating(color.X * 255.0f) | ((uint)byte.CreateSaturating(color.Y * 255.0f) << 8) | ((uint)byte.CreateSaturating(color.Z * 255.0f) << 16); + } + private void DrawServerConfiguration() { _lastTab = "Service Settings";