From dd3a0ea0692a0ac8382dd4260566ba256b0dec3f Mon Sep 17 00:00:00 2001 From: JonKazama-Hellion Date: Tue, 5 May 2026 13:51:31 +0200 Subject: [PATCH] =?UTF-8?q?feat(themes):=20wire=20theme=20engine=20into=20?= =?UTF-8?q?plugin=20draw=20pipeline=20+=20migrate=20v13=E2=86=92v14?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit HellionStyle.PushGlobal nimmt jetzt eine Theme-Instance + Window-Opacity und liest alle Color- und Style-Slots aus dem aktiven Theme statt aus einer fixen Konstanten-Tabelle. Plugin hält die ThemeRegistry und schaltet beim Init auf das in Config.Theme gespeicherte Slug. Configuration v13 → v14: - Neue Felder Theme (slug), WindowOpacity, ReduceMotion, UseCompactDensity, ShowThemeQuickPicker - HellionThemeEnabled und HellionThemeWindowOpacity sind ab v14 [Obsolete] und bleiben bis v1.2.0 als JSON-Safety-Net erhalten - Migration setzt alle Bestandsuser auf hellion-arctic; chat2-classic bleibt im Themes-Tab als Upstream-Look wählbar - WindowOpacity übernimmt den Wert von HellionThemeWindowOpacity, alte HellionThemeEnabled-Flag entfällt funktional (Theme-Engine ist immer aktiv) Konsumenten der alten Felder (ChatLogWindow.BgAlpha, Popout.BgAlpha) lesen jetzt das neue WindowOpacity. Die Settings-UI in Appearance.cs schreibt übergangsweise weiter in die Obsolete-Felder; Phase J ersetzt diesen Block durch den dedizierten Themes-Tab. CS0612/CS0618 sind dort gezielt mit pragma gekapselt. --- HellionChat/Configuration.cs | 26 ++- HellionChat/Plugin.cs | 39 +++- HellionChat/Ui/ChatLogWindow.cs | 4 +- HellionChat/Ui/HellionStyle.cs | 259 +++++++--------------- HellionChat/Ui/Popout.cs | 4 +- HellionChat/Ui/SettingsTabs/Appearance.cs | 8 + 6 files changed, 153 insertions(+), 187 deletions(-) diff --git a/HellionChat/Configuration.cs b/HellionChat/Configuration.cs index fbe7fdc..da3b4d6 100755 --- a/HellionChat/Configuration.cs +++ b/HellionChat/Configuration.cs @@ -34,10 +34,23 @@ public class ConfigKeyBind [Serializable] public class Configuration : IPluginConfiguration { - private const int LatestVersion = 13; + private const int LatestVersion = 14; public int Version { get; set; } = LatestVersion; + // v1.1.0 — Theme-Engine. Slug-basiert; ThemeRegistry liefert das Objekt. + public string Theme = "hellion-arctic"; + + // v1.1.0 — Globale Window-Opacity, theme-übergreifend. Migration aus + // HellionThemeWindowOpacity beim Bump v13 → v14. + public float WindowOpacity = 0.85f; + + // v1.1.0 — Felder für künftige UI-Toggles (v1.2.0 / v1.3.0). Werden + // vorab angelegt, damit später keine Migration nötig ist. + public bool ReduceMotion; + public bool UseCompactDensity; + public bool ShowThemeQuickPicker; + // Hellion Chat — Privacy filter (DSGVO Art. 25 Privacy by Default). // Master-switch defaults to true; set false to restore upstream behavior. public bool PrivacyFilterEnabled = true; @@ -70,12 +83,14 @@ public class Configuration : IPluginConfiguration // Hellion Chat global ImGui theme — applied to every plugin window in // Plugin.Draw. Default ON; users who prefer the upstream Dalamud look // can flip this off in the Privacy tab. + [Obsolete("Replaced by Theme slug + WindowOpacity in v14")] public bool HellionThemeEnabled = true; // Window background opacity, 0.5–1.0. Lower values make the plugin // panes more glass-like so the game shines through. Default 0.5 // matches the maintainer's daily-driver preference; users who want // a less translucent look bump it up in Aussehen → Theme. + [Obsolete("Replaced by WindowOpacity in v14")] public float HellionThemeWindowOpacity = 0.5f; // Use the bundled Exo 2 font (OFL-1.1) for the regular plugin font @@ -321,10 +336,19 @@ public class Configuration : IPluginConfiguration RetentionLastRunAt = other.RetentionLastRunAt; FirstRunCompleted = other.FirstRunCompleted; +#pragma warning disable CS0612, CS0618 // Obsolete-Felder bleiben bis v1.2.0 als JSON-Safety-Net erhalten HellionThemeEnabled = other.HellionThemeEnabled; HellionThemeWindowOpacity = other.HellionThemeWindowOpacity; +#pragma warning restore CS0612, CS0618 UseHellionFont = other.UseHellionFont; + // v1.1.0 theme engine fields + Theme = other.Theme; + WindowOpacity = other.WindowOpacity; + ReduceMotion = other.ReduceMotion; + UseCompactDensity = other.UseCompactDensity; + ShowThemeQuickPicker = other.ShowThemeQuickPicker; + EnableAutoTellTabs = other.EnableAutoTellTabs; AutoTellTabsLimit = other.AutoTellTabsLimit; AutoTellTabsCompactDisplay = other.AutoTellTabsCompactDisplay; diff --git a/HellionChat/Plugin.cs b/HellionChat/Plugin.cs index 992600a..e5e7770 100755 --- a/HellionChat/Plugin.cs +++ b/HellionChat/Plugin.cs @@ -63,6 +63,7 @@ public sealed class Plugin : IDalamudPlugin internal ExtraChat ExtraChat { get; } internal TypingIpc TypingIpc { get; } internal FontManager FontManager { get; } + internal Themes.ThemeRegistry ThemeRegistry { get; private set; } = null!; internal int DeferredSaveFrames = -1; @@ -237,6 +238,27 @@ public sealed class Plugin : IDalamudPlugin }); } + // Hellion Chat v13 → v14 — theme-engine migration. Alle User landen + // auf "hellion-arctic" als neues Default-Theme; die alte + // HellionThemeEnabled-Flag wird deprecated und nur noch ein Release + // als Safety-Net im JSON behalten. Window-Opacity wandert von + // HellionThemeWindowOpacity in das neue WindowOpacity-Feld. + if (Config.Version < 14) + { + Config.Theme = "hellion-arctic"; + #pragma warning disable CS0612, CS0618 // Obsolete: HellionThemeWindowOpacity bleibt readable bis v1.2.0 + Config.WindowOpacity = Config.HellionThemeWindowOpacity; + #pragma warning restore CS0612, CS0618 + Config.ReduceMotion = false; + Config.UseCompactDensity = false; + Config.ShowThemeQuickPicker = false; + Config.Version = 14; + SaveConfig(); + Log.Information( + "Migrated config v13 → v14: theme engine introduced, all users land on hellion-arctic; " + + "pick chat2-classic in Settings → Themes for the upstream look"); + } + // Hellion v1.0.0 default tab layout. Five thematically separated // tabs: General catches the immediate-surroundings public chat // (Say/Yell/Shout) only; System absorbs the rest of the technical @@ -266,6 +288,12 @@ public sealed class Plugin : IDalamudPlugin ExtraChat = new ExtraChat(); FontManager = new FontManager(); + // v1.1.0 — Theme-Engine init. Custom-Themes liegen in + // pluginConfigs/HellionChat/themes/, lazy geladen beim ersten Get. + var customThemesDir = Path.Combine(Interface.ConfigDirectory.FullName, "themes"); + ThemeRegistry = new Themes.ThemeRegistry(customThemesDir); + ThemeRegistry.Switch(Config.Theme); + MessageManager = new MessageManager(this); // Does it require UI? // Hellion Chat — Auto-Tell-Tabs service. Subscribes to the @@ -559,13 +587,10 @@ public sealed class Plugin : IDalamudPlugin private void Draw() { - // Hellion theme is pushed once per frame here so every plugin window - // (chat log, settings, viewers, wizard, file dialog) renders with - // the same palette. Skipping the push leaves the upstream Dalamud - // look untouched for users who flipped the toggle off. - using IDisposable? _style = Config.HellionThemeEnabled - ? HellionStyle.PushGlobal(Config.HellionThemeWindowOpacity) - : null; + // Theme-Engine ist ab v14 immer aktiv; Klassik ist jetzt ein eigenes + // Theme statt einem deaktivierten Hellion-Theme. Active wird einmal + // pro Frame aus der Registry gelesen. + using IDisposable _style = HellionStyle.PushGlobal(ThemeRegistry.Active, Config.WindowOpacity); ChatLogWindow.BeginFrame(); diff --git a/HellionChat/Ui/ChatLogWindow.cs b/HellionChat/Ui/ChatLogWindow.cs index cd7c8db..f5fda68 100644 --- a/HellionChat/Ui/ChatLogWindow.cs +++ b/HellionChat/Ui/ChatLogWindow.cs @@ -494,9 +494,7 @@ public sealed class ChatLogWindow : Window Flags |= ImGuiWindowFlags.NoTitleBar; if (LastViewport == ImGuiHelpers.MainViewport.Handle && !WasDocked) - BgAlpha = Plugin.Config.HellionThemeEnabled - ? Plugin.Config.HellionThemeWindowOpacity - : Plugin.Config.WindowAlpha / 100f; + BgAlpha = Plugin.Config.WindowOpacity; LastViewport = ImGui.GetWindowViewport().Handle; WasDocked = ImGui.IsWindowDocked(); diff --git a/HellionChat/Ui/HellionStyle.cs b/HellionChat/Ui/HellionStyle.cs index 026c464..39d839b 100644 --- a/HellionChat/Ui/HellionStyle.cs +++ b/HellionChat/Ui/HellionStyle.cs @@ -1,3 +1,4 @@ +using HellionChat.Themes; using HellionChat.Util; using Dalamud.Bindings.ImGui; using Dalamud.Interface.Utility.Raii; @@ -5,207 +6,119 @@ using Dalamud.Interface.Utility.Raii; namespace HellionChat.Ui; /// -/// ImGui style override for Hellion Chat. Industrial HUD palette with three -/// distinct accents — cyan-teal as the primary action color, industrial -/// amber for active state highlights, slate-violet for title bars and -/// active tabs — on a deep-slate frame background with steel borders. -/// -/// Two entry points: -/// Push — local color stack, scoped via using-block. Use inside -/// Hellion-only surfaces (Privacy tab, first-run wizard). -/// PushGlobal — full color + style variable stack. Pushed once per frame -/// in Plugin.Draw so every Hellion-rendered window inherits -/// the look. Cheap to pop because ImGui keeps its own stack. +/// ImGui style override for Hellion Chat. v1.1.0 ist die Engine +/// theme-getrieben: PushGlobal nimmt eine Theme-Instance + Window- +/// Opacity, die gesamten Color- und Style-Slots werden aus dem Theme +/// gelesen statt aus einer fixen Konstanten-Tabelle. /// internal static class HellionStyle { - // Encoded as 0xRRGGBBAA, matching ChatTwo convention (see Settings.cs - // Ko-fi buttons). RgbaToAbgr handles the byte swap to the format ImGui - // expects. Hex values are sourced from the Hellion Online Media brand - // guide ("Arctic Cyan + Ember Glow", BRANDING.md in the website repo). - - // Primary — Arctic Cyan, used for every interactive control (buttons, - // checks, sliders, separators when hovered). Three brand stages plus a - // hover that lifts to brand-color-light and a press that drops to - // brand-color-dark. - private const uint PrimaryRgba = 0x00BED2FF; // brand-color - private const uint PrimaryHoverRgba = 0x4DD9E8FF; // brand-color-light - private const uint PrimaryActiveRgba = 0x0097A7FF; // brand-color-dark - - // Identity — brand-color-dark teal for window title bars and the - // active tab. Sits visibly below the primary cyan on buttons so the - // user sees "where am I" (deep teal) versus "what can I click" - // (brand cyan) without leaving the cyan family. - private const uint IdentityRgba = 0x0097A7FF; // brand-color-dark - private const uint IdentityHoverRgba = 0x4DD9E8FF; // brand-color-light - private const uint IdentityDeepRgba = 0x005670FF; // dimmer teal for unfocused-active tab - - // Accent — Ember Orange for warm highlights on grips and scrollbar - // pulls. Replaces the previous industrial amber so the plugin matches - // the website's CTA palette. AccentActive is reserved for any future - // pressed-state on accent surfaces; the current slots only need - // AccentRgba and AccentHoverRgba. - private const uint AccentRgba = 0xF97316FF; // accent-color - private const uint AccentHoverRgba = 0xFB923CFF; // accent-color-light - - // Surfaces — Hellion brand background ladder. Window darkest, frame - // hover ladder climbs into surface tones. Matches the website's - // background / background-medium / background-light / surface vars. - private const uint WindowBgRgba = 0x070B12FF; // background - private const uint ChildBgRgba = 0x0C1220FF; // background-medium - private const uint PopupBgRgba = 0x0C1220FF; // background-medium - private const uint FrameBgRgba = 0x141E30FF; // background-light - private const uint FrameBgHoverRgba = 0x1A2538FF; // surface - private const uint FrameBgActiveRgba = 0x22303FFF; // surface-hover - // Cyan-tinted border — matches website --border-brand (cyan @ 40% α). - private const uint BorderRgba = 0x00BED266; - private const uint BorderShadowRgba = 0x00000000; - - // Headers / collapsing-headers / tree nodes / selectables — same - // surface ladder as frames so panels feel consistent. - private const uint HeaderRgba = 0x141E30FF; - private const uint HeaderHoverRgba = 0x1A2538FF; - private const uint HeaderActiveRgba = 0x22303FFF; - - // Title bars — Identity teal on active so the focused window reads - // as "yours" without using accent or primary slots. - private const uint TitleBgRgba = 0x070B12FF; - private const uint TitleBgActiveRgba = IdentityRgba; - private const uint TitleBgCollapsedRgba = 0x05080EFF; - - // Tabs — neutral inactive, Identity-light on hover, Identity teal on - // active. Unfocused-active uses the deeper Identity stage so an - // unfocused window's active tab still reads but does not pull focus. - private const uint TabRgba = 0x141E30FF; - private const uint TabHoveredRgba = IdentityHoverRgba; - private const uint TabActiveRgba = IdentityRgba; - private const uint TabUnfocusedRgba = 0x0C1220FF; - private const uint TabUnfocusedActiveRgba = IdentityDeepRgba; - - // Scrollbar — Ember on grab so the pull stands out without competing - // with the cyan action buttons. Idle grab is a subtle surface tone, - // hover/active climb into accent. - private const uint ScrollbarBgRgba = 0x070B12FF; - private const uint ScrollbarGrabRgba = 0x22303FFF; // surface-hover - private const uint ScrollbarGrabHoveredRgba = AccentHoverRgba; - private const uint ScrollbarGrabActiveRgba = AccentRgba; - - // Resize grip — same Ember treatment as the scrollbar. - private const uint ResizeGripRgba = 0x141E30FF; - private const uint ResizeGripHoveredRgba = AccentHoverRgba; - private const uint ResizeGripActiveRgba = AccentRgba; - - // Separator and check mark / slider follow the primary cyan. - /// - /// Local color stack for Hellion-only surfaces. Cheap. Use inside a - /// `using var _ = HellionStyle.Push();` block. + /// Local color stack auf Basis des aktiven Themes. Cheap. Use inside a + /// `using var _ = HellionStyle.Push(theme);` block. /// - internal static IDisposable Push() + internal static IDisposable Push(Theme theme) { + var c = theme.Colors; var stack = new StackHandle(); - stack.PushColor(ImGuiCol.Button, PrimaryRgba); - stack.PushColor(ImGuiCol.ButtonHovered, PrimaryHoverRgba); - stack.PushColor(ImGuiCol.ButtonActive, PrimaryActiveRgba); - stack.PushColor(ImGuiCol.FrameBg, FrameBgRgba); - stack.PushColor(ImGuiCol.FrameBgHovered, FrameBgHoverRgba); - stack.PushColor(ImGuiCol.FrameBgActive, FrameBgActiveRgba); - stack.PushColor(ImGuiCol.Border, BorderRgba); - stack.PushColor(ImGuiCol.Header, HeaderRgba); - stack.PushColor(ImGuiCol.HeaderHovered, HeaderHoverRgba); - stack.PushColor(ImGuiCol.HeaderActive, HeaderActiveRgba); - stack.PushColor(ImGuiCol.CheckMark, PrimaryRgba); - stack.PushColor(ImGuiCol.SliderGrab, PrimaryRgba); - stack.PushColor(ImGuiCol.SliderGrabActive, PrimaryHoverRgba); + stack.PushColor(ImGuiCol.Button, c.Primary); + stack.PushColor(ImGuiCol.ButtonHovered, c.PrimaryLight); + stack.PushColor(ImGuiCol.ButtonActive, c.PrimaryDark); + stack.PushColor(ImGuiCol.FrameBg, c.FrameBg); + stack.PushColor(ImGuiCol.FrameBgHovered, c.SurfaceHover); + stack.PushColor(ImGuiCol.FrameBgActive, c.Surface); + stack.PushColor(ImGuiCol.Border, c.Border); + stack.PushColor(ImGuiCol.Header, c.Surface); + stack.PushColor(ImGuiCol.HeaderHovered, c.SurfaceHover); + stack.PushColor(ImGuiCol.HeaderActive, c.Identity); + stack.PushColor(ImGuiCol.CheckMark, c.Primary); + stack.PushColor(ImGuiCol.SliderGrab, c.Primary); + stack.PushColor(ImGuiCol.SliderGrabActive, c.PrimaryLight); return stack; } /// /// Global color and style-variable stack pushed once per frame in - /// Plugin.Draw. Covers every ImGui surface the plugin renders so the - /// Hellion look is consistent across upstream and Hellion tabs. + /// Plugin.Draw. Drives every Hellion-rendered window from the active + /// theme's palette and layout values. /// - /// Window background alpha (0.5–1.0). Lower - /// values let the game shine through the plugin panes. - internal static IDisposable PushGlobal(float windowOpacity = 1.0f) + /// Active theme from ThemeRegistry. + /// Window background alpha (0.5–1.0). + internal static IDisposable PushGlobal(Theme theme, float windowOpacity = 1.0f) { + var c = theme.Colors; + var l = theme.Layout; var stack = new StackHandle(); - // Mix the configured opacity into both the outer window and the - // inner content child backgrounds — without ChildBg following the - // slider the chat log stays opaque inside even when the user - // wants to see the game behind it during combat. Form fields and - // popups (FrameBg, PopupBg) still stay opaque so input is readable. var alphaByte = (uint)Math.Clamp((int)(windowOpacity * 255f), 0x55, 0xFF); - var windowBgWithAlpha = (WindowBgRgba & 0xFFFFFF00u) | alphaByte; - var childBgWithAlpha = (ChildBgRgba & 0xFFFFFF00u) | alphaByte; + var windowBgWithAlpha = (c.WindowBg & 0xFFFFFF00u) | alphaByte; + var childBgWithAlpha = (c.ChildBg & 0xFFFFFF00u) | alphaByte; - // Layout — geometric edges, modest rounding, single-pixel borders. - stack.PushStyleVar(ImGuiStyleVar.WindowRounding, 4f); - stack.PushStyleVar(ImGuiStyleVar.ChildRounding, 3f); - stack.PushStyleVar(ImGuiStyleVar.PopupRounding, 3f); - stack.PushStyleVar(ImGuiStyleVar.FrameRounding, 2f); - stack.PushStyleVar(ImGuiStyleVar.GrabRounding, 2f); - stack.PushStyleVar(ImGuiStyleVar.TabRounding, 2f); - stack.PushStyleVar(ImGuiStyleVar.ScrollbarRounding, 2f); - stack.PushStyleVar(ImGuiStyleVar.WindowBorderSize, 1f); - stack.PushStyleVar(ImGuiStyleVar.FrameBorderSize, 1f); + // Layout + stack.PushStyleVar(ImGuiStyleVar.WindowRounding, l.WindowRounding); + stack.PushStyleVar(ImGuiStyleVar.ChildRounding, l.ChildRounding); + stack.PushStyleVar(ImGuiStyleVar.PopupRounding, l.PopupRounding); + stack.PushStyleVar(ImGuiStyleVar.FrameRounding, l.FrameRounding); + stack.PushStyleVar(ImGuiStyleVar.GrabRounding, l.GrabRounding); + stack.PushStyleVar(ImGuiStyleVar.TabRounding, l.TabRounding); + stack.PushStyleVar(ImGuiStyleVar.ScrollbarRounding, l.ScrollbarRounding); + stack.PushStyleVar(ImGuiStyleVar.WindowBorderSize, l.WindowBorderSize); + stack.PushStyleVar(ImGuiStyleVar.FrameBorderSize, l.FrameBorderSize); - // Surfaces. - stack.PushColor(ImGuiCol.WindowBg, windowBgWithAlpha); - stack.PushColor(ImGuiCol.ChildBg, childBgWithAlpha); - stack.PushColor(ImGuiCol.PopupBg, PopupBgRgba); - stack.PushColor(ImGuiCol.Border, BorderRgba); - stack.PushColor(ImGuiCol.BorderShadow, BorderShadowRgba); + // Surfaces + stack.PushColor(ImGuiCol.WindowBg, windowBgWithAlpha); + stack.PushColor(ImGuiCol.ChildBg, childBgWithAlpha); + stack.PushColor(ImGuiCol.PopupBg, c.ChildBg); + stack.PushColor(ImGuiCol.Border, c.Border); + stack.PushColor(ImGuiCol.BorderShadow, 0u); - // Frames (input fields, combos, sliders). - stack.PushColor(ImGuiCol.FrameBg, FrameBgRgba); - stack.PushColor(ImGuiCol.FrameBgHovered, FrameBgHoverRgba); - stack.PushColor(ImGuiCol.FrameBgActive, FrameBgActiveRgba); + // Frames + stack.PushColor(ImGuiCol.FrameBg, c.FrameBg); + stack.PushColor(ImGuiCol.FrameBgHovered, c.SurfaceHover); + stack.PushColor(ImGuiCol.FrameBgActive, c.Surface); - // Title bars — tertiary identity on active. - stack.PushColor(ImGuiCol.TitleBg, TitleBgRgba); - stack.PushColor(ImGuiCol.TitleBgActive, TitleBgActiveRgba); - stack.PushColor(ImGuiCol.TitleBgCollapsed, TitleBgCollapsedRgba); + // Title bars + stack.PushColor(ImGuiCol.TitleBg, c.WindowBg); + stack.PushColor(ImGuiCol.TitleBgActive, c.Identity); + stack.PushColor(ImGuiCol.TitleBgCollapsed, c.WindowBg); - // Buttons — primary cyan. - stack.PushColor(ImGuiCol.Button, PrimaryRgba); - stack.PushColor(ImGuiCol.ButtonHovered, PrimaryHoverRgba); - stack.PushColor(ImGuiCol.ButtonActive, PrimaryActiveRgba); + // Buttons + stack.PushColor(ImGuiCol.Button, c.Primary); + stack.PushColor(ImGuiCol.ButtonHovered, c.PrimaryLight); + stack.PushColor(ImGuiCol.ButtonActive, c.PrimaryDark); - // Headers / selectables — slate with subtle steps. - stack.PushColor(ImGuiCol.Header, HeaderRgba); - stack.PushColor(ImGuiCol.HeaderHovered, HeaderHoverRgba); - stack.PushColor(ImGuiCol.HeaderActive, HeaderActiveRgba); + // Headers / selectables + stack.PushColor(ImGuiCol.Header, c.Surface); + stack.PushColor(ImGuiCol.HeaderHovered, c.SurfaceHover); + stack.PushColor(ImGuiCol.HeaderActive, c.Identity); - // Tabs — tertiary identity for the active tab. - stack.PushColor(ImGuiCol.Tab, TabRgba); - stack.PushColor(ImGuiCol.TabHovered, TabHoveredRgba); - stack.PushColor(ImGuiCol.TabActive, TabActiveRgba); - stack.PushColor(ImGuiCol.TabUnfocused, TabUnfocusedRgba); - stack.PushColor(ImGuiCol.TabUnfocusedActive, TabUnfocusedActiveRgba); + // Tabs + stack.PushColor(ImGuiCol.Tab, c.FrameBg); + stack.PushColor(ImGuiCol.TabHovered, c.PrimaryLight); + stack.PushColor(ImGuiCol.TabActive, c.Identity); + stack.PushColor(ImGuiCol.TabUnfocused, c.ChildBg); + stack.PushColor(ImGuiCol.TabUnfocusedActive, c.PrimaryDark); - // Scrollbar. - stack.PushColor(ImGuiCol.ScrollbarBg, ScrollbarBgRgba); - stack.PushColor(ImGuiCol.ScrollbarGrab, ScrollbarGrabRgba); - stack.PushColor(ImGuiCol.ScrollbarGrabHovered, ScrollbarGrabHoveredRgba); - stack.PushColor(ImGuiCol.ScrollbarGrabActive, ScrollbarGrabActiveRgba); + // Scrollbar + stack.PushColor(ImGuiCol.ScrollbarBg, c.WindowBg); + stack.PushColor(ImGuiCol.ScrollbarGrab, c.Surface); + stack.PushColor(ImGuiCol.ScrollbarGrabHovered, c.AccentLight); + stack.PushColor(ImGuiCol.ScrollbarGrabActive, c.Accent); - // Resize grip — secondary amber on active. - stack.PushColor(ImGuiCol.ResizeGrip, ResizeGripRgba); - stack.PushColor(ImGuiCol.ResizeGripHovered, ResizeGripHoveredRgba); - stack.PushColor(ImGuiCol.ResizeGripActive, ResizeGripActiveRgba); + // Resize grip + stack.PushColor(ImGuiCol.ResizeGrip, c.FrameBg); + stack.PushColor(ImGuiCol.ResizeGripHovered, c.AccentLight); + stack.PushColor(ImGuiCol.ResizeGripActive, c.Accent); - // Check mark + slider grab — primary cyan. - stack.PushColor(ImGuiCol.CheckMark, PrimaryRgba); - stack.PushColor(ImGuiCol.SliderGrab, PrimaryRgba); - stack.PushColor(ImGuiCol.SliderGrabActive, PrimaryHoverRgba); + // Check mark + slider grab + stack.PushColor(ImGuiCol.CheckMark, c.Primary); + stack.PushColor(ImGuiCol.SliderGrab, c.Primary); + stack.PushColor(ImGuiCol.SliderGrabActive, c.PrimaryLight); - // Separator — primary cyan when hovered/active so the eye - // immediately sees that splitters are interactive. - stack.PushColor(ImGuiCol.Separator, BorderRgba); - stack.PushColor(ImGuiCol.SeparatorHovered, PrimaryHoverRgba); - stack.PushColor(ImGuiCol.SeparatorActive, PrimaryRgba); + // Separator + stack.PushColor(ImGuiCol.Separator, c.Border); + stack.PushColor(ImGuiCol.SeparatorHovered, c.PrimaryLight); + stack.PushColor(ImGuiCol.SeparatorActive, c.Primary); return stack; } diff --git a/HellionChat/Ui/Popout.cs b/HellionChat/Ui/Popout.cs index a3944ff..f86c980 100644 --- a/HellionChat/Ui/Popout.cs +++ b/HellionChat/Ui/Popout.cs @@ -103,9 +103,7 @@ internal class Popout : Window } else { - BgAlpha = Plugin.Config.HellionThemeEnabled - ? Plugin.Config.HellionThemeWindowOpacity - : Plugin.Config.WindowAlpha / 100f; + BgAlpha = Plugin.Config.WindowOpacity; } } } diff --git a/HellionChat/Ui/SettingsTabs/Appearance.cs b/HellionChat/Ui/SettingsTabs/Appearance.cs index 6517f74..ce09f4c 100644 --- a/HellionChat/Ui/SettingsTabs/Appearance.cs +++ b/HellionChat/Ui/SettingsTabs/Appearance.cs @@ -45,6 +45,13 @@ internal sealed class Appearance : ISettingsTab using (ImRaii.PushIndent(ImGui.GetStyle().IndentSpacing, false)) { + // v1.1.0 — Diese Settings-UI wird in Phase J durch den dedizierten + // Themes-Tab ersetzt. Bis dahin bleiben die alten Toggles erhalten, + // damit die Settings-Seite kompiliert; sie schreiben in die mit + // [Obsolete] markierten Felder, die bis v1.2.0 als JSON-Safety-Net + // bestehen bleiben. Das pragma unterdrückt die CS0612-Warnungen + // gezielt für diesen Übergangs-Block. +#pragma warning disable CS0612, CS0618 ImGui.Checkbox(HellionStrings.Theme_Enabled_Name, ref Mutable.HellionThemeEnabled); ImGuiUtil.HelpMarker(HellionStrings.Theme_Enabled_Description); @@ -81,6 +88,7 @@ internal sealed class Appearance : ISettingsTab { ImGuiUtil.DragFloatVertical(Language.Options_WindowOpacity_Name, ref Mutable.WindowAlpha, .25f, 0f, 100f, $"{Mutable.WindowAlpha:N2}%%", ImGuiSliderFlags.AlwaysClamp); } +#pragma warning restore CS0612, CS0618 } }