diff --git a/HellionChat/Ui/Components/Settings/TabSidebar.cs b/HellionChat/Ui/Components/Settings/TabSidebar.cs index 15ea805..e8237ea 100644 --- a/HellionChat/Ui/Components/Settings/TabSidebar.cs +++ b/HellionChat/Ui/Components/Settings/TabSidebar.cs @@ -38,18 +38,14 @@ internal sealed class TabSidebar var min = ImGui.GetWindowPos(); var max = min + ImGui.GetWindowSize(); - var surface = ColourUtil.RgbaToAbgr(_resolver.Resolve(Token.SurfaceBase, colors)); var accent = ColourUtil.RgbaToAbgr(_resolver.Resolve(Token.AccentPrimary, colors)); - // Darker than the content pane so the two read as separate planes rather - // than one wide surface with a line drawn down it. - dl.DrawVerticalGradient( - min, - max, - ColourUtil.LerpTowardBlack(surface, 0.25f), - topLift: 0.10f, - bottomDrop: 0.06f - ); + // A wash of black rather than a repainted surface. The window has drawn + // its own background already; filling over it stacks a second layer and + // turns a translucent window solid. This only needs to read as the + // darker of two planes, and a tint does that. + var opacity = ((ImGui.GetColorU32(ImGuiCol.WindowBg) >> 24) & 0xFFu) / 255f; + dl.AddRectFilled(min, max, (uint)(0x38 * opacity) << 24); // The icon font has no ASCII glyphs, so anything textual drawn inside a // FontAwesome scope comes out blank -- twice bitten in this plugin. The diff --git a/HellionChat/Ui/StyleEngine/AmbientParticles.cs b/HellionChat/Ui/StyleEngine/AmbientParticles.cs index ccc25ad..387f9c4 100644 --- a/HellionChat/Ui/StyleEngine/AmbientParticles.cs +++ b/HellionChat/Ui/StyleEngine/AmbientParticles.cs @@ -104,13 +104,13 @@ internal sealed class AmbientParticles dl.AddCircleFilled( pos, radius * 2.1f, - ColourUtil.ApplyAlpha(accentAbgr, 0.13f * edge * pulse * intensity), + ColourUtil.ApplyAlpha(accentAbgr, 0.075f * edge * pulse * intensity), 10 ); dl.AddCircleFilled( pos, radius, - ColourUtil.ApplyAlpha(accentAbgr, 0.42f * edge * pulse * intensity), + ColourUtil.ApplyAlpha(accentAbgr, 0.20f * edge * pulse * intensity), 10 ); } diff --git a/HellionChat/Ui/StyleEngine/SurfaceBackdrop.cs b/HellionChat/Ui/StyleEngine/SurfaceBackdrop.cs index d62d5c7..c833fae 100644 --- a/HellionChat/Ui/StyleEngine/SurfaceBackdrop.cs +++ b/HellionChat/Ui/StyleEngine/SurfaceBackdrop.cs @@ -35,37 +35,37 @@ internal sealed class SurfaceBackdrop var max = min + ImGui.GetWindowSize(); var colors = _themes.Active.Colors; - // Opacity taken from the window's own background colour rather than - // assumed. BgAlpha only reaches WindowBg, so a draw-list fill painted at - // full opacity turns a deliberately translucent window into a solid - // block -- which is exactly how the settings pane ended up looking like - // a foreign object next to the chat window. - var windowAlpha = ((ImGui.GetColorU32(ImGuiCol.WindowBg) >> 24) & 0xFFu) / 255f; + // Modulation, not a second ground. The window has already painted its + // own background; filling the same area again stacked two layers and + // made a deliberately translucent window read as solid. Worse, an opaque + // fill had to carry the whole gradient by itself, which is what produced + // the banding -- a shallow ramp across an opaque surface crosses few + // enough 8-bit values that each covers a visible stripe. + // + // Near-transparent white over black instead: the window colour stays + // visible underneath, the ramp only tints it, and the game showing + // through breaks up any step that is left. + var opacity = ((ImGui.GetColorU32(ImGuiCol.WindowBg) >> 24) & 0xFFu) / 255f; + var lift = 0x00FFFFFFu | ((uint)(0x0E * opacity) << 24); + var drop = 0x00000000u | ((uint)(0x1A * opacity) << 24); + dl.AddRectFilledMultiColor(min, max, lift, lift, drop, drop); - var surface = ColourUtil.RgbaToAbgr(_resolver.Resolve(Token.SurfaceBase, colors)); if (darken > 0f) - surface = ColourUtil.LerpTowardBlack(surface, darken); - surface = ColourUtil.ApplyAlpha(surface, windowAlpha); + dl.AddRectFilled(min, max, (uint)(0xFF * darken * opacity) << 24); var accent = ColourUtil.RgbaToAbgr(_resolver.Resolve(Token.AccentPrimary, colors)); - // Shallower than it was. The banding people see in a large gradient is - // 8-bit quantisation: a gentle ramp crosses few enough values that each - // one covers a visible band of pixels. Less range means fewer, fainter - // steps, and the window's translucency breaks up what is left. - dl.DrawVerticalGradient(min, max, surface, topLift: 0.10f, bottomDrop: 0.07f); - if (accentWashHeight > 0f) dl.AddRectFilledMultiColor( min, new Vector2(max.X, min.Y + (max.Y - min.Y) * accentWashHeight), - ColourUtil.ApplyAlpha(accent, 0.09f * windowAlpha), - ColourUtil.ApplyAlpha(accent, 0.045f * windowAlpha), + ColourUtil.ApplyAlpha(accent, 0.07f * opacity), + ColourUtil.ApplyAlpha(accent, 0.035f * opacity), accent & 0x00FFFFFFu, accent & 0x00FFFFFFu ); if (moteIntensity > 0f) - _motes.Draw(dl, min, max, accent, moteIntensity * windowAlpha); + _motes.Draw(dl, min, max, accent, moteIntensity * opacity); } } diff --git a/HellionChat/Ui/Windows/MainWindow.cs b/HellionChat/Ui/Windows/MainWindow.cs index a2e76b1..9ad68c2 100644 --- a/HellionChat/Ui/Windows/MainWindow.cs +++ b/HellionChat/Ui/Windows/MainWindow.cs @@ -389,7 +389,7 @@ internal sealed class MainWindow : Window, IFocusableChatWindow // a settings pane, which is read in glances; a chat log is read // line by line, and anything drifting behind the text competes // with it. What is left is barely a texture. - _backdrop.Draw(accentWashHeight: 0f, moteIntensity: 0.18f); + _backdrop.Draw(accentWashHeight: 0f, moteIntensity: 0.10f); if (_activeTab is not null) _messages.Draw(_activeTab);