add theme override customizations
This commit is contained in:
@@ -18,6 +18,7 @@ using LightlessSync.PlayerData.Pairs;
|
||||
using LightlessSync.Services;
|
||||
using LightlessSync.Services.Mediator;
|
||||
using LightlessSync.Services.ServerConfiguration;
|
||||
using LightlessSync.UI.Style;
|
||||
using LightlessSync.Utils;
|
||||
using LightlessSync.UtilsEnum.Enum;
|
||||
using LightlessSync.WebAPI;
|
||||
@@ -44,6 +45,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
private readonly ApiController _apiController;
|
||||
private readonly CacheMonitor _cacheMonitor;
|
||||
private readonly LightlessConfigService _configService;
|
||||
private readonly UiThemeConfigService _themeConfigService;
|
||||
private readonly ConcurrentDictionary<GameObjectHandler, Dictionary<string, FileDownloadStatus>> _currentDownloads = new();
|
||||
private readonly DalamudUtilService _dalamudUtilService;
|
||||
private readonly HttpClient _httpClient;
|
||||
@@ -94,7 +96,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
private bool _wasOpen = false;
|
||||
|
||||
public SettingsUi(ILogger<SettingsUi> logger,
|
||||
UiSharedService uiShared, LightlessConfigService configService,
|
||||
UiSharedService uiShared, LightlessConfigService configService, UiThemeConfigService themeConfigService,
|
||||
PairManager pairManager,
|
||||
ServerConfigurationManager serverConfigurationManager,
|
||||
PlayerPerformanceConfigService playerPerformanceConfigService,
|
||||
@@ -110,6 +112,7 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
NameplateHandler nameplateHandler) : base(logger, mediator, "Lightless Sync Settings", performanceCollector)
|
||||
{
|
||||
_configService = configService;
|
||||
_themeConfigService = themeConfigService;
|
||||
_pairManager = pairManager;
|
||||
_serverConfigurationManager = serverConfigurationManager;
|
||||
_playerPerformanceConfigService = playerPerformanceConfigService;
|
||||
@@ -241,6 +244,253 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
return ((color & 0xFFu) << 16) | (color & 0xFF00u) | ((color >> 16) & 0xFFu);
|
||||
}
|
||||
|
||||
private static Vector4 PackedThemeColorToVector4(uint packed)
|
||||
=> new(
|
||||
(packed & 0xFF) / 255f,
|
||||
((packed >> 8) & 0xFF) / 255f,
|
||||
((packed >> 16) & 0xFF) / 255f,
|
||||
((packed >> 24) & 0xFF) / 255f);
|
||||
|
||||
private static uint ThemeVector4ToPackedColor(Vector4 color)
|
||||
{
|
||||
static byte ToByte(float channel)
|
||||
{
|
||||
var scaled = MathF.Round(Math.Clamp(channel, 0f, 1f) * 255.0f);
|
||||
return (byte)Math.Clamp((int)scaled, 0, 255);
|
||||
}
|
||||
|
||||
var r = ToByte(color.X);
|
||||
var g = ToByte(color.Y);
|
||||
var b = ToByte(color.Z);
|
||||
var a = ToByte(color.W);
|
||||
return (uint)(r | (g << 8) | (b << 16) | (a << 24));
|
||||
}
|
||||
|
||||
private void UpdateStyleOverride(string key, Action<UiStyleOverride> updater)
|
||||
{
|
||||
var overrides = _themeConfigService.Current.StyleOverrides;
|
||||
|
||||
if (!overrides.TryGetValue(key, out var entry))
|
||||
entry = new UiStyleOverride();
|
||||
|
||||
updater(entry);
|
||||
|
||||
if (entry.IsEmpty)
|
||||
overrides.Remove(key);
|
||||
else
|
||||
overrides[key] = entry;
|
||||
|
||||
_themeConfigService.Save();
|
||||
}
|
||||
|
||||
private void DrawThemeOverridesSection()
|
||||
{
|
||||
ImGui.TextUnformatted("Lightless Theme Overrides");
|
||||
_uiShared.DrawHelpText("Adjust the Lightless redesign theme. Overrides only apply when the redesign is enabled.");
|
||||
|
||||
if (!_configService.Current.UseLightlessRedesign)
|
||||
UiSharedService.ColorTextWrapped("The Lightless redesign is currently disabled. Enable it to see these changes take effect.", UIColors.Get("DimRed"));
|
||||
|
||||
const ImGuiTableFlags flags = ImGuiTableFlags.Borders | ImGuiTableFlags.RowBg | ImGuiTableFlags.SizingStretchProp;
|
||||
if (!ImGui.BeginTable("##ThemeOverridesTable", 3, flags))
|
||||
return;
|
||||
|
||||
ImGui.TableSetupColumn("Element", ImGuiTableColumnFlags.WidthFixed, 325f);
|
||||
ImGui.TableSetupColumn("Value", ImGuiTableColumnFlags.WidthStretch);
|
||||
ImGui.TableSetupColumn("Reset", ImGuiTableColumnFlags.WidthFixed, 70f);
|
||||
ImGui.TableHeadersRow();
|
||||
|
||||
DrawThemeCategoryRow("Colors");
|
||||
foreach (var option in MainStyle.ColorOptions)
|
||||
DrawThemeColorRow(option);
|
||||
|
||||
DrawThemeCategoryRow("Spacing & Padding");
|
||||
foreach (var option in MainStyle.Vector2Options)
|
||||
DrawThemeVectorRow(option);
|
||||
|
||||
DrawThemeCategoryRow("Rounding & Sizes");
|
||||
foreach (var option in MainStyle.FloatOptions)
|
||||
DrawThemeFloatRow(option);
|
||||
|
||||
ImGui.EndTable();
|
||||
}
|
||||
|
||||
private static void DrawThemeCategoryRow(string label)
|
||||
{
|
||||
ImGui.TableNextRow();
|
||||
ImGui.TableSetColumnIndex(0);
|
||||
ImGui.TextColored(UIColors.Get("LightlessPurple"), label);
|
||||
ImGui.TableSetColumnIndex(1);
|
||||
ImGui.TableSetColumnIndex(2);
|
||||
}
|
||||
|
||||
private void DrawThemeColorRow(MainStyle.StyleColorOption option)
|
||||
{
|
||||
ImGui.TableNextRow();
|
||||
ImGui.TableSetColumnIndex(0);
|
||||
ImGui.TextUnformatted(option.Label);
|
||||
bool showTooltip = ImGui.IsItemHovered();
|
||||
|
||||
var tooltip = string.Empty;
|
||||
if (!string.IsNullOrEmpty(option.Description))
|
||||
tooltip = option.Description;
|
||||
|
||||
var overrides = _themeConfigService.Current.StyleOverrides;
|
||||
overrides.TryGetValue(option.Key, out var existing);
|
||||
|
||||
if (!string.IsNullOrEmpty(option.UiColorKey))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(tooltip))
|
||||
tooltip += "\n";
|
||||
tooltip += $"Default uses UIColors[\"{option.UiColorKey}\"]";
|
||||
|
||||
ImGui.SameLine();
|
||||
ImGui.TextDisabled($"(UIColors.{option.UiColorKey})");
|
||||
if (ImGui.IsItemHovered())
|
||||
showTooltip = true;
|
||||
}
|
||||
|
||||
ImGui.TableSetColumnIndex(2);
|
||||
if (DrawStyleResetButton(option.Key, existing?.Color is not null))
|
||||
{
|
||||
UpdateStyleOverride(option.Key, entry =>
|
||||
{
|
||||
entry.Color = null;
|
||||
entry.Float = null;
|
||||
entry.Vector2 = null;
|
||||
});
|
||||
|
||||
existing = null;
|
||||
}
|
||||
|
||||
if (showTooltip && !string.IsNullOrEmpty(tooltip))
|
||||
ImGui.SetTooltip(tooltip);
|
||||
|
||||
var defaultColor = MainStyle.NormalizeColorVector(option.DefaultValue());
|
||||
var current = existing?.Color is { } packed ? PackedThemeColorToVector4(packed) : defaultColor;
|
||||
var edit = current;
|
||||
|
||||
ImGui.TableSetColumnIndex(1);
|
||||
if (ImGui.ColorEdit4($"##theme-color-{option.Key}", ref edit, ImGuiColorEditFlags.AlphaPreviewHalf))
|
||||
{
|
||||
UpdateStyleOverride(option.Key, entry =>
|
||||
{
|
||||
entry.Color = ThemeVector4ToPackedColor(edit);
|
||||
entry.Float = null;
|
||||
entry.Vector2 = null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawThemeVectorRow(MainStyle.StyleVector2Option option)
|
||||
{
|
||||
ImGui.TableNextRow();
|
||||
ImGui.TableSetColumnIndex(0);
|
||||
ImGui.TextUnformatted(option.Label);
|
||||
if (!string.IsNullOrEmpty(option.Description) && ImGui.IsItemHovered())
|
||||
ImGui.SetTooltip(option.Description);
|
||||
|
||||
var overrides = _themeConfigService.Current.StyleOverrides;
|
||||
overrides.TryGetValue(option.Key, out var existing);
|
||||
|
||||
ImGui.TableSetColumnIndex(2);
|
||||
if (DrawStyleResetButton(option.Key, existing?.Vector2 is not null))
|
||||
{
|
||||
UpdateStyleOverride(option.Key, entry =>
|
||||
{
|
||||
entry.Vector2 = null;
|
||||
entry.Color = null;
|
||||
entry.Float = null;
|
||||
});
|
||||
existing = null;
|
||||
}
|
||||
|
||||
var defaultValue = option.DefaultValue();
|
||||
var current = existing?.Vector2 is { } vectorOverride ? (Vector2)vectorOverride : defaultValue;
|
||||
var edit = current;
|
||||
|
||||
ImGui.TableSetColumnIndex(1);
|
||||
if (ImGui.DragFloat2($"##theme-vector-{option.Key}", ref edit, option.Speed))
|
||||
{
|
||||
if (option.Min is { } min)
|
||||
edit = Vector2.Max(edit, min);
|
||||
if (option.Max is { } max)
|
||||
edit = Vector2.Min(edit, max);
|
||||
|
||||
UpdateStyleOverride(option.Key, entry =>
|
||||
{
|
||||
entry.Vector2 = new Vector2Config(edit.X, edit.Y);
|
||||
entry.Color = null;
|
||||
entry.Float = null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawThemeFloatRow(MainStyle.StyleFloatOption option)
|
||||
{
|
||||
ImGui.TableNextRow();
|
||||
ImGui.TableSetColumnIndex(0);
|
||||
ImGui.TextUnformatted(option.Label);
|
||||
if (!string.IsNullOrEmpty(option.Description) && ImGui.IsItemHovered())
|
||||
ImGui.SetTooltip(option.Description);
|
||||
|
||||
var overrides = _themeConfigService.Current.StyleOverrides;
|
||||
overrides.TryGetValue(option.Key, out var existing);
|
||||
|
||||
ImGui.TableSetColumnIndex(2);
|
||||
if (DrawStyleResetButton(option.Key, existing?.Float is not null))
|
||||
{
|
||||
UpdateStyleOverride(option.Key, entry =>
|
||||
{
|
||||
entry.Float = null;
|
||||
entry.Color = null;
|
||||
entry.Vector2 = null;
|
||||
});
|
||||
existing = null;
|
||||
}
|
||||
|
||||
var current = existing?.Float ?? option.DefaultValue;
|
||||
var edit = current;
|
||||
|
||||
var min = option.Min ?? float.MinValue;
|
||||
var max = option.Max ?? float.MaxValue;
|
||||
|
||||
ImGui.TableSetColumnIndex(1);
|
||||
if (ImGui.DragFloat($"##theme-float-{option.Key}", ref edit, option.Speed, min, max, "%.2f"))
|
||||
{
|
||||
if (option.Min.HasValue)
|
||||
edit = MathF.Max(option.Min.Value, edit);
|
||||
if (option.Max.HasValue)
|
||||
edit = MathF.Min(option.Max.Value, edit);
|
||||
|
||||
UpdateStyleOverride(option.Key, entry =>
|
||||
{
|
||||
entry.Float = edit;
|
||||
entry.Color = null;
|
||||
entry.Vector2 = null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private bool DrawStyleResetButton(string key, bool hasOverride, string? tooltipOverride = null)
|
||||
{
|
||||
using var id = ImRaii.PushId($"reset-{key}");
|
||||
using var disabled = ImRaii.Disabled(!hasOverride);
|
||||
var availableWidth = ImGui.GetContentRegionAvail().X;
|
||||
bool pressed = false;
|
||||
using (ImRaii.PushFont(UiBuilder.IconFont))
|
||||
{
|
||||
if (ImGui.Button(FontAwesomeIcon.Undo.ToIconString(), new Vector2(availableWidth, 0)))
|
||||
pressed = true;
|
||||
}
|
||||
|
||||
var tooltip = tooltipOverride ?? (hasOverride
|
||||
? "Reset this style override to its default value."
|
||||
: "Value already matches the default.");
|
||||
UiSharedService.AttachToolTip(tooltip);
|
||||
return pressed;
|
||||
}
|
||||
|
||||
private void DrawBlockedTransfers()
|
||||
{
|
||||
_lastTab = "BlockedTransfers";
|
||||
@@ -1642,6 +1892,8 @@ public class SettingsUi : WindowMediatorSubscriberBase
|
||||
}
|
||||
_uiShared.DrawHelpText("This changes the vanity colored UID's in pair list.");
|
||||
|
||||
DrawThemeOverridesSection();
|
||||
|
||||
_uiShared.ColoredSeparator(UIColors.Get("LightlessPurple"), 1.5f);
|
||||
ImGui.TreePop();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user