diff --git a/res/themes/jade.toml b/res/themes/jade.toml index ecabeb4..e1a7988 100644 --- a/res/themes/jade.toml +++ b/res/themes/jade.toml @@ -115,10 +115,13 @@ surface-inline-alpha = 0.58 background-inline-alpha = 0.40 # --------------------------------------------------------------------------- -# Theme Visual Effects — Jade (polished stone sheen + gold veining) -# A soft jade specular highlight drifts across panels like light on -# polished nephrite; the active sidebar button traces a jade-to-gold -# border echoing the stone's veins — restrained, like Obsidian. +# Theme Visual Effects — Jade (veins of gold shifting through the stone) +# Jade's signature is a slow jade→gold color-shifting border on every glass +# panel + the active nav button — a vein of gold surfacing through nephrite. +# It's drawn via AddRect so it hugs the real rounded corners (no polygonal +# edge-trace). Sparse jade motes drift up the viewport. No other theme turns +# gradient-border-panels on, so the panel-wide vein is Jade's own — +# deliberately NOT Obsidian's specular glare. # --------------------------------------------------------------------------- [effects] hue-cycle-enabled = { size = 0.0 } @@ -130,25 +133,45 @@ shimmer-enabled = { size = 0.0 } positional-hue-enabled = { size = 0.0 } glow-pulse-enabled = { size = 0.0 } -edge-trace-enabled = { size = 0.0 } -# Specular glare — soft blurred jade highlights -specular-glare-enabled = { size = 1.0 } +# Edge-trace OFF — its hand-walked perimeter chamfers rounded corners. +# Jade's vein is the gradient-border below (corner-clean via AddRect). +edge-trace-enabled = { size = 0.0 } +edge-trace-speed = { size = 0.16 } +edge-trace-length = { size = 0.34 } +edge-trace-thickness = { size = 1.6 } +edge-trace-alpha = { size = 0.55 } +edge-trace-color = { color = "#C9A24E" } + +# Specular glare OFF — that's Obsidian's signature; Jade shouldn't echo it. +specular-glare-enabled = { size = 0.0 } specular-glare-speed = { size = 0.018 } specular-glare-intensity = { size = 0.008 } specular-glare-radius = { size = 0.65 } specular-glare-count = { size = 1.0 } specular-glare-color = { color = "rgba(150,220,180,1.0)" } -# Jade-to-gold color-shifting border on the active sidebar button +# HERO — vein of gold: a slow jade→gold color-shifting border on the active +# nav button AND (via gradient-border-panels) every glass panel. Drawn with +# AddRect so it follows the rounded corners exactly. Panels drift at a softer +# alpha and position-phased offset, so a screenful reads like veins at +# different depths rather than one synchronized pulse. gradient-border-enabled = { size = 1.0 } -gradient-border-speed = { size = 0.12 } +gradient-border-panels = { size = 1.0 } +gradient-border-speed = { size = 0.10 } gradient-border-thickness = { size = 1.5 } gradient-border-alpha = { size = 0.55 } gradient-border-color-a = { color = "#7FD1B5" } gradient-border-color-b = { color = "#C9A24E" } -ember-rise-enabled = { size = 0.0 } +# Ambient jade motes — sparse, slow, cool green particles drifting up the +# viewport (recolored ember-rise; a different mood from dragonx's fire embers). +ember-rise-enabled = { size = 1.0 } +ember-rise-count = { size = 5.0 } +ember-rise-speed = { size = 0.18 } +ember-rise-particle-size = { size = 1.4 } +ember-rise-alpha = { size = 0.26 } +ember-rise-color = { color = "#7FD1B5" } # Shader-like viewport overlay — deep green stone atmosphere viewport-wash-enabled = { size = 1.0 } diff --git a/src/ui/effects/theme_effects.cpp b/src/ui/effects/theme_effects.cpp index 999fcdb..d799060 100644 --- a/src/ui/effects/theme_effects.cpp +++ b/src/ui/effects/theme_effects.cpp @@ -160,6 +160,10 @@ void ThemeEffects::loadFromTheme() { // ---- Gradient Border Shift ---- gradient_border_.enabled = eff("gradient-border-enabled").sizeOr(0.0f) > 0.5f; + // Opt-in: also draw the shifting border on every glass panel (not just the + // active nav button). Off by default so themes that only want the button + // accent (e.g. Obsidian) are unaffected; Jade turns it on as its hero. + gradient_border_.panels = eff("gradient-border-panels").sizeOr(0.0f) > 0.5f; gradient_border_.speed = eff("gradient-border-speed").sizeOr(0.15f); gradient_border_.thickness = eff("gradient-border-thickness").sizeOr(1.5f); gradient_border_.alpha = eff("gradient-border-alpha").sizeOr(0.6f); @@ -512,11 +516,15 @@ void ThemeEffects::drawGlowPulse(ImDrawList* dl, ImVec2 pMin, ImVec2 pMax, // ============================================================================ void ThemeEffects::drawGradientBorderShift(ImDrawList* dl, ImVec2 pMin, ImVec2 pMax, - float rounding) const { + float rounding, float phaseOffset, + float alphaMul) const { if (!enabled_ || !gradient_border_.enabled) return; - // Smooth sinusoidal oscillation between color A and color B - float phase = std::sin(time_ * gradient_border_.speed * 2.0f * 3.14159265f) * 0.5f + 0.5f; + // Smooth sinusoidal oscillation between color A and color B. + // phaseOffset shifts where in the cycle this element sits so a wall of + // panels reads like veins at different depths rather than one pulse. + float phase = std::sin((time_ * gradient_border_.speed + phaseOffset) + * 2.0f * 3.14159265f) * 0.5f + 0.5f; // Extract RGBA from both colors and lerp RGB ca = unpackRGB(gradient_border_.colorA); @@ -525,7 +533,7 @@ void ThemeEffects::drawGradientBorderShift(ImDrawList* dl, ImVec2 pMin, ImVec2 p int r = ca.r + (int)((cb.r - ca.r) * phase); int g = ca.g + (int)((cb.g - ca.g) * phase); int b = ca.b + (int)((cb.b - ca.b) * phase); - int a = scaledAlpha(gradient_border_.alpha, bgOpacity_); + int a = scaledAlpha(gradient_border_.alpha * alphaMul, bgOpacity_); // Draw the shifting border dl->AddRect(pMin, pMax, IM_COL32(r, g, b, a), @@ -896,6 +904,22 @@ void ThemeEffects::drawPanelEffects(ImDrawList* dl, ImVec2 pMin, ImVec2 pMax, float rounding) const { if (!enabled_ || effects::isLowSpecMode()) return; + // Gradient border on panels — a slow color-shifting outline that hugs the + // panel's rounded corners (drawn via AddRect, so it follows the rounding + // exactly — no polygonal corners). Position-based phase offset makes each + // panel drift like a vein at a different depth; softer than the active + // nav button (alphaMul 0.6) so a screenful of panels stays calm. + if (gradient_border_.enabled && gradient_border_.panels) { + float w = pMax.x - pMin.x; + float h = pMax.y - pMin.y; + if (w > 80 && h > 40) { // skip small panels + float posKey = (pMin.x * 0.0073f + pMin.y * 0.0137f); + posKey = posKey - (int)posKey; // fractional 0..1 + if (posKey < 0) posKey += 1.0f; + drawGradientBorderShift(dl, pMin, pMax, rounding, posKey, 0.6f); + } + } + // Edge trace on panels — use position-based phase offset so each // panel's tracer is at a different position around the border if (edge_trace_.enabled) { diff --git a/src/ui/effects/theme_effects.h b/src/ui/effects/theme_effects.h index e83d813..c5cce20 100644 --- a/src/ui/effects/theme_effects.h +++ b/src/ui/effects/theme_effects.h @@ -69,9 +69,12 @@ public: void drawEdgeTrace(ImDrawList* dl, ImVec2 pMin, ImVec2 pMax, float rounding) const; - /// Draw a border that shifts between two colors over time (gem-like) + /// Draw a border that shifts between two colors over time (gem-like). + /// phaseOffset (0..1) shifts this element's point in the color cycle so + /// many panels don't pulse in unison; alphaMul scales the whole effect. void drawGradientBorderShift(ImDrawList* dl, ImVec2 pMin, ImVec2 pMax, - float rounding) const; + float rounding, float phaseOffset = 0.0f, + float alphaMul = 1.0f) const; /// Draw ember particles that rise from an element (fire theme) void drawEmberRise(ImDrawList* dl, ImVec2 pMin, ImVec2 pMax) const; @@ -186,6 +189,7 @@ private: struct GradientBorderConfig { bool enabled = false; + bool panels = false; ///< also draw on glass panels, not just the active nav button float speed = 0.15f; ///< full color shift cycles per second float thickness = 1.5f; ///< border line thickness in pixels float alpha = 0.6f; ///< peak alpha