233 lines
13 KiB
C#
233 lines
13 KiB
C#
// inspiration: brio because it's style is fucking amazing
|
|
|
|
using Dalamud.Bindings.ImGui;
|
|
using LightlessSync.LightlessConfiguration;
|
|
using LightlessSync.LightlessConfiguration.Configurations;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Numerics;
|
|
|
|
namespace LightlessSync.UI.Style;
|
|
|
|
internal static class MainStyle
|
|
{
|
|
public readonly record struct StyleColorOption(string Key, string Label, Func<Vector4> DefaultValue, ImGuiCol Target, string? Description = null, string? UiColorKey = null);
|
|
public readonly record struct StyleFloatOption(string Key, string Label, float DefaultValue, ImGuiStyleVar Target, float? Min = null, float? Max = null, float Speed = 0.25f, string? Description = null);
|
|
public readonly record struct StyleVector2Option(string Key, string Label, Func<Vector2> DefaultValue, ImGuiStyleVar Target, Vector2? Min = null, Vector2? Max = null, float Speed = 0.25f, string? Description = null);
|
|
|
|
private static LightlessConfigService? _config;
|
|
private static UiThemeConfigService? _themeConfig;
|
|
public static void Init(LightlessConfigService config, UiThemeConfigService themeConfig)
|
|
{
|
|
_config = config;
|
|
_themeConfig = themeConfig;
|
|
}
|
|
public static bool ShouldUseTheme => _config?.Current.UseLightlessRedesign ?? false;
|
|
|
|
private static bool _hasPushed;
|
|
private static int _pushedColorCount;
|
|
private static int _pushedStyleVarCount;
|
|
|
|
private static readonly StyleColorOption[] _colorOptions =
|
|
[
|
|
new("color.text", "Text", () => Rgba(255, 255, 255, 255), ImGuiCol.Text),
|
|
new("color.textDisabled", "Text (Disabled)", () => Rgba(128, 128, 128, 255), ImGuiCol.TextDisabled),
|
|
new("color.windowBg", "Window Background", () => Rgba(23, 23, 23, 248), ImGuiCol.WindowBg),
|
|
new("color.childBg", "Child Background", () => Rgba(23, 23, 23, 66), ImGuiCol.ChildBg),
|
|
new("color.popupBg", "Popup Background", () => Rgba(23, 23, 23, 248), ImGuiCol.PopupBg),
|
|
new("color.border", "Border", () => Rgba(65, 65, 65, 255), ImGuiCol.Border),
|
|
new("color.borderShadow", "Border Shadow", () => Rgba(0, 0, 0, 150), ImGuiCol.BorderShadow),
|
|
new("color.frameBg", "Frame Background", () => Rgba(40, 40, 40, 255), ImGuiCol.FrameBg),
|
|
new("color.frameBgHovered", "Frame Background (Hover)", () => Rgba(50, 50, 50, 100), ImGuiCol.FrameBgHovered),
|
|
new("color.frameBgActive", "Frame Background (Active)", () => Rgba(30, 30, 30, 255), ImGuiCol.FrameBgActive),
|
|
new("color.titleBg", "Title Background", () => Rgba(22, 14, 41, 255), ImGuiCol.TitleBg),
|
|
new("color.titleBgActive", "Title Background (Active)", () => Rgba(22, 14, 41, 255), ImGuiCol.TitleBgActive),
|
|
new("color.titleBgCollapsed", "Title Background (Collapsed)", () => Rgba(22, 14, 41, 255), ImGuiCol.TitleBgCollapsed),
|
|
|
|
new("color.menuBarBg", "Menu Bar Background", () => Rgba(36, 36, 36, 255), ImGuiCol.MenuBarBg),
|
|
new("color.scrollbarBg", "Scrollbar Background", () => Rgba(0, 0, 0, 0), ImGuiCol.ScrollbarBg),
|
|
new("color.scrollbarGrab", "Scrollbar Grab", () => Rgba(62, 62, 62, 255), ImGuiCol.ScrollbarGrab),
|
|
new("color.scrollbarGrabHovered", "Scrollbar Grab (Hover)", () => Rgba(70, 70, 70, 255), ImGuiCol.ScrollbarGrabHovered),
|
|
new("color.scrollbarGrabActive", "Scrollbar Grab (Active)", () => Rgba(70, 70, 70, 255), ImGuiCol.ScrollbarGrabActive),
|
|
new("color.checkMark", "Check Mark", () => UIColors.Get("LightlessPurple"), ImGuiCol.CheckMark, UiColorKey: "LightlessPurple"),
|
|
new("color.sliderGrab", "Slider Grab", () => Rgba(101, 101, 101, 255), ImGuiCol.SliderGrab),
|
|
new("color.sliderGrabActive", "Slider Grab (Active)", () => Rgba(123, 123, 123, 255), ImGuiCol.SliderGrabActive),
|
|
new("color.button", "Button", () => UIColors.Get("ButtonDefault"), ImGuiCol.Button, UiColorKey: "ButtonDefault"),
|
|
new("color.buttonHovered", "Button (Hover)", () => UIColors.Get("LightlessPurple"), ImGuiCol.ButtonHovered, UiColorKey: "LightlessPurple"),
|
|
new("color.buttonActive", "Button (Active)", () => UIColors.Get("LightlessPurpleActive"), ImGuiCol.ButtonActive, UiColorKey: "LightlessPurpleActive"),
|
|
new("color.header", "Header", () => Rgba(0, 0, 0, 60), ImGuiCol.Header),
|
|
new("color.headerHovered", "Header (Hover)", () => Rgba(0, 0, 0, 90), ImGuiCol.HeaderHovered),
|
|
new("color.headerActive", "Header (Active)", () => Rgba(0, 0, 0, 120), ImGuiCol.HeaderActive),
|
|
new("color.separator", "Separator", () => Rgba(75, 75, 75, 121), ImGuiCol.Separator),
|
|
new("color.separatorHovered", "Separator (Hover)", () => UIColors.Get("LightlessPurple"), ImGuiCol.SeparatorHovered, UiColorKey: "LightlessPurple"),
|
|
new("color.separatorActive", "Separator (Active)", () => UIColors.Get("LightlessPurpleActive"), ImGuiCol.SeparatorActive, UiColorKey: "LightlessPurpleActive"),
|
|
new("color.resizeGrip", "Resize Grip", () => Rgba(0, 0, 0, 0), ImGuiCol.ResizeGrip),
|
|
new("color.resizeGripHovered", "Resize Grip (Hover)", () => Rgba(0, 0, 0, 0), ImGuiCol.ResizeGripHovered),
|
|
new("color.resizeGripActive", "Resize Grip (Active)", () => UIColors.Get("LightlessPurpleActive"), ImGuiCol.ResizeGripActive, UiColorKey: "LightlessPurpleActive"),
|
|
new("color.tab", "Tab", () => Rgba(40, 40, 40, 255), ImGuiCol.Tab),
|
|
new("color.tabHovered", "Tab (Hover)", () => UIColors.Get("LightlessPurple"), ImGuiCol.TabHovered, UiColorKey: "LightlessPurple"),
|
|
new("color.tabActive", "Tab (Active)", () => UIColors.Get("LightlessPurpleActive"), ImGuiCol.TabActive, UiColorKey: "LightlessPurpleActive"),
|
|
new("color.tabUnfocused", "Tab (Unfocused)", () => Rgba(40, 40, 40, 255), ImGuiCol.TabUnfocused),
|
|
new("color.tabUnfocusedActive", "Tab (Unfocused Active)", () => UIColors.Get("LightlessPurpleActive"), ImGuiCol.TabUnfocusedActive, UiColorKey: "LightlessPurpleActive"),
|
|
new("color.dockingPreview", "Docking Preview", () => UIColors.Get("LightlessPurpleActive"), ImGuiCol.DockingPreview, UiColorKey: "LightlessPurpleActive"),
|
|
new("color.dockingEmptyBg", "Docking Empty Background", () => Rgba(50, 50, 50, 255), ImGuiCol.DockingEmptyBg),
|
|
new("color.plotLines", "Plot Lines", () => Rgba(150, 150, 150, 255), ImGuiCol.PlotLines),
|
|
new("color.tableHeaderBg", "Table Header Background", () => Rgba(48, 48, 48, 255), ImGuiCol.TableHeaderBg),
|
|
new("color.tableBorderStrong", "Table Border Strong", () => Rgba(79, 79, 89, 255), ImGuiCol.TableBorderStrong),
|
|
new("color.tableBorderLight", "Table Border Light", () => Rgba(59, 59, 64, 255), ImGuiCol.TableBorderLight),
|
|
new("color.tableRowBg", "Table Row Background", () => Rgba(0, 0, 0, 0), ImGuiCol.TableRowBg),
|
|
new("color.tableRowBgAlt", "Table Row Background (Alt)", () => Rgba(255, 255, 255, 15), ImGuiCol.TableRowBgAlt),
|
|
new("color.textSelectedBg", "Text Selection Background", () => Rgba(173, 138, 245, 255), ImGuiCol.TextSelectedBg),
|
|
new("color.dragDropTarget", "Drag & Drop Target", () => Rgba(173, 138, 245, 255), ImGuiCol.DragDropTarget),
|
|
new("color.navHighlight", "Navigation Highlight", () => Rgba(173, 138, 245, 179), ImGuiCol.NavHighlight),
|
|
new("color.navWindowingDimBg", "Navigation Window Dim", () => Rgba(204, 204, 204, 51), ImGuiCol.NavWindowingDimBg),
|
|
new("color.navWindowingHighlight", "Navigation Window Highlight", () => Rgba(204, 204, 204, 89), ImGuiCol.NavWindowingHighlight)
|
|
];
|
|
|
|
private static readonly StyleVector2Option[] _vector2Options =
|
|
[
|
|
new("vector.windowPadding", "Window Padding", () => new Vector2(6f, 6f), ImGuiStyleVar.WindowPadding),
|
|
new("vector.framePadding", "Frame Padding", () => new Vector2(4f, 3f), ImGuiStyleVar.FramePadding),
|
|
new("vector.cellPadding", "Cell Padding", () => new Vector2(4f, 4f), ImGuiStyleVar.CellPadding),
|
|
new("vector.itemSpacing", "Item Spacing", () => new Vector2(4f, 4f), ImGuiStyleVar.ItemSpacing),
|
|
new("vector.itemInnerSpacing", "Item Inner Spacing", () => new Vector2(4f, 4f), ImGuiStyleVar.ItemInnerSpacing)
|
|
];
|
|
|
|
private static readonly StyleFloatOption[] _floatOptions =
|
|
[
|
|
new("float.indentSpacing", "Indent Spacing", 21f, ImGuiStyleVar.IndentSpacing, 0f, 100f, 0.5f),
|
|
new("float.scrollbarSize", "Scrollbar Size", 10f, ImGuiStyleVar.ScrollbarSize, 4f, 30f, 0.5f),
|
|
new("float.grabMinSize", "Grab Minimum Size", 20f, ImGuiStyleVar.GrabMinSize, 1f, 80f, 0.5f),
|
|
new("float.windowBorderSize", "Window Border Size", 1.5f, ImGuiStyleVar.WindowBorderSize, 0f, 5f, 0.1f),
|
|
new("float.childBorderSize", "Child Border Size", 1.5f, ImGuiStyleVar.ChildBorderSize, 0f, 5f, 0.1f),
|
|
new("float.popupBorderSize", "Popup Border Size", 1.5f, ImGuiStyleVar.PopupBorderSize, 0f, 5f, 0.1f),
|
|
new("float.frameBorderSize", "Frame Border Size", 0f, ImGuiStyleVar.FrameBorderSize, 0f, 5f, 0.1f),
|
|
new("float.windowRounding", "Window Rounding", 7f, ImGuiStyleVar.WindowRounding, 0f, 20f, 0.2f),
|
|
new("float.childRounding", "Child Rounding", 4f, ImGuiStyleVar.ChildRounding, 0f, 20f, 0.2f),
|
|
new("float.frameRounding", "Frame Rounding", 4f, ImGuiStyleVar.FrameRounding, 0f, 20f, 0.2f),
|
|
new("float.popupRounding", "Popup Rounding", 4f, ImGuiStyleVar.PopupRounding, 0f, 20f, 0.2f),
|
|
new("float.scrollbarRounding", "Scrollbar Rounding", 4f, ImGuiStyleVar.ScrollbarRounding, 0f, 20f, 0.2f),
|
|
new("float.grabRounding", "Grab Rounding", 4f, ImGuiStyleVar.GrabRounding, 0f, 20f, 0.2f),
|
|
new("float.tabRounding", "Tab Rounding", 4f, ImGuiStyleVar.TabRounding, 0f, 20f, 0.2f)
|
|
];
|
|
|
|
public static IReadOnlyList<StyleColorOption> ColorOptions => _colorOptions;
|
|
public static IReadOnlyList<StyleFloatOption> FloatOptions => _floatOptions;
|
|
public static IReadOnlyList<StyleVector2Option> Vector2Options => _vector2Options;
|
|
|
|
public static void PushStyle()
|
|
{
|
|
if (_hasPushed)
|
|
PopStyle();
|
|
|
|
if (!ShouldUseTheme)
|
|
{
|
|
_hasPushed = false;
|
|
return;
|
|
}
|
|
|
|
_hasPushed = true;
|
|
_pushedColorCount = 0;
|
|
_pushedStyleVarCount = 0;
|
|
|
|
foreach (var option in _colorOptions)
|
|
Push(option.Target, ResolveColor(option));
|
|
|
|
foreach (var option in _vector2Options)
|
|
PushStyleVar(option.Target, ResolveVector(option));
|
|
|
|
foreach (var option in _floatOptions)
|
|
PushStyleVar(option.Target, ResolveFloat(option));
|
|
}
|
|
|
|
public static void PopStyle()
|
|
{
|
|
if (!_hasPushed)
|
|
return;
|
|
|
|
if (_pushedStyleVarCount > 0)
|
|
ImGui.PopStyleVar(_pushedStyleVarCount);
|
|
if (_pushedColorCount > 0)
|
|
ImGui.PopStyleColor(_pushedColorCount);
|
|
|
|
_hasPushed = false;
|
|
_pushedColorCount = 0;
|
|
_pushedStyleVarCount = 0;
|
|
}
|
|
|
|
private static Vector4 ResolveColor(StyleColorOption option)
|
|
{
|
|
var defaultValue = NormalizeColorVector(option.DefaultValue());
|
|
if (_themeConfig?.Current.StyleOverrides.TryGetValue(option.Key, out var overrideValue) == true && overrideValue.Color is { } packed)
|
|
return PackedColorToVector4(packed);
|
|
|
|
return defaultValue;
|
|
}
|
|
|
|
private static Vector2 ResolveVector(StyleVector2Option option)
|
|
{
|
|
var value = option.DefaultValue();
|
|
if (_themeConfig?.Current.StyleOverrides.TryGetValue(option.Key, out var overrideValue) == true && overrideValue.Vector2 is { } vectorOverride)
|
|
{
|
|
value = vectorOverride;
|
|
}
|
|
|
|
if (option.Min is { } min)
|
|
value = Vector2.Max(value, min);
|
|
if (option.Max is { } max)
|
|
value = Vector2.Min(value, max);
|
|
return value;
|
|
}
|
|
|
|
private static float ResolveFloat(StyleFloatOption option)
|
|
{
|
|
var value = option.DefaultValue;
|
|
if (_themeConfig?.Current.StyleOverrides.TryGetValue(option.Key, out var overrideValue) == true && overrideValue.Float is { } floatOverride)
|
|
{
|
|
value = floatOverride;
|
|
}
|
|
|
|
if (option.Min.HasValue)
|
|
value = MathF.Max(option.Min.Value, value);
|
|
if (option.Max.HasValue)
|
|
value = MathF.Min(option.Max.Value, value);
|
|
return value;
|
|
}
|
|
|
|
private static void Push(ImGuiCol col, Vector4 rgba)
|
|
{
|
|
rgba = NormalizeColorVector(rgba);
|
|
ImGui.PushStyleColor(col, rgba);
|
|
_pushedColorCount++;
|
|
}
|
|
|
|
private static void PushStyleVar(ImGuiStyleVar var, float value)
|
|
{
|
|
ImGui.PushStyleVar(var, value);
|
|
_pushedStyleVarCount++;
|
|
}
|
|
|
|
private static void PushStyleVar(ImGuiStyleVar var, Vector2 value)
|
|
{
|
|
ImGui.PushStyleVar(var, value);
|
|
_pushedStyleVarCount++;
|
|
}
|
|
|
|
private static Vector4 Rgba(byte r, byte g, byte b, byte a = 255)
|
|
=> new Vector4(r / 255f, g / 255f, b / 255f, a / 255f);
|
|
|
|
internal static Vector4 NormalizeColorVector(Vector4 rgba)
|
|
{
|
|
if (rgba.X > 1f || rgba.Y > 1f || rgba.Z > 1f || rgba.W > 1f)
|
|
rgba /= 255f;
|
|
return rgba;
|
|
}
|
|
|
|
internal static Vector4 PackedColorToVector4(uint color)
|
|
=> new(
|
|
(color & 0xFF) / 255f,
|
|
((color >> 8) & 0xFF) / 255f,
|
|
((color >> 16) & 0xFF) / 255f,
|
|
((color >> 24) & 0xFF) / 255f);
|
|
}
|