feat(market): bump the portfolio backdrop blur radius (64) via sole-consumer isolation
Raising the backdrop radius alone would thrash the shared radius-keyed blur cache (the glass panels blur at ~30). Instead, while a full-window blur overlay is active, glass panels use their opaque fallback (IsFullWindowBlurOverlayActive) — they're covered by the backdrop anyway — so the backdrop is the SOLE applyBlur caller and can use a strong custom radius (64) with the cache staying coherent and frozen. The flag is toggled alongside the theme-effect suppression by a RAII guard in App::render(). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
24
src/app.cpp
24
src/app.cpp
@@ -1243,16 +1243,24 @@ void App::render()
|
||||
// Process deferred encryption from wizard (runs in background)
|
||||
processDeferredEncryption();
|
||||
|
||||
// While the full-window portfolio modal is open, suppress panel theme-effects for the whole
|
||||
// frame so their foreground-draw-list borders (sidebar included) don't bleed over the overlay.
|
||||
// While the full-window portfolio modal is open: (1) suppress panel theme-effects for the whole
|
||||
// frame so their foreground-draw-list borders (sidebar included) don't bleed over the overlay;
|
||||
// (2) mark a full-window blur overlay active so glass panels use their opaque fallback (they're
|
||||
// covered by the overlay backdrop, and this leaves the backdrop as the sole acrylic blur caller).
|
||||
// RAII-restored to the prior state on any return path.
|
||||
struct FxSuppressGuard {
|
||||
bool active;
|
||||
explicit FxSuppressGuard(bool on) : active(on) {
|
||||
if (active) ui::effects::ThemeEffects::instance().setEnabled(false);
|
||||
struct ModalRenderGuard {
|
||||
bool fxOn, wasEffects;
|
||||
explicit ModalRenderGuard(bool modalOpen) {
|
||||
wasEffects = ui::effects::ThemeEffects::instance().isEnabled();
|
||||
fxOn = modalOpen && wasEffects;
|
||||
if (fxOn) ui::effects::ThemeEffects::instance().setEnabled(false);
|
||||
ui::material::SetFullWindowBlurOverlayActive(modalOpen);
|
||||
}
|
||||
~FxSuppressGuard() { if (active) ui::effects::ThemeEffects::instance().setEnabled(true); }
|
||||
} fxGuard(ui::PortfolioEditorActive() && ui::effects::ThemeEffects::instance().isEnabled());
|
||||
~ModalRenderGuard() {
|
||||
if (fxOn) ui::effects::ThemeEffects::instance().setEnabled(true);
|
||||
ui::material::SetFullWindowBlurOverlayActive(false);
|
||||
}
|
||||
} modalGuard(ui::PortfolioEditorActive());
|
||||
|
||||
// Main content area - use full window (no menu bar)
|
||||
ImGuiViewport* viewport = ImGui::GetMainViewport();
|
||||
|
||||
@@ -377,11 +377,19 @@ struct GlassPanelSpec {
|
||||
float borderWidth = 1.0f;
|
||||
};
|
||||
|
||||
// When a full-window blur overlay (e.g. the portfolio modal) is active, glass panels use their
|
||||
// opaque fallback instead of the acrylic blur. They're covered by the overlay's backdrop anyway, and
|
||||
// this leaves the backdrop as the SOLE applyBlur caller — so it can use its own (stronger) blur
|
||||
// radius without thrashing the shared, radius-keyed blur cache. Toggled from App::render().
|
||||
inline bool& FullWindowBlurOverlayActiveRef() { static bool v = false; return v; }
|
||||
inline void SetFullWindowBlurOverlayActive(bool v) { FullWindowBlurOverlayActiveRef() = v; }
|
||||
inline bool IsFullWindowBlurOverlayActive() { return FullWindowBlurOverlayActiveRef(); }
|
||||
|
||||
inline void DrawGlassPanel(ImDrawList* dl, const ImVec2& pMin,
|
||||
const ImVec2& pMax,
|
||||
const GlassPanelSpec& spec = GlassPanelSpec())
|
||||
{
|
||||
if (IsBackdropActive() && !dragonx::ui::effects::isLowSpecMode()) {
|
||||
if (IsBackdropActive() && !dragonx::ui::effects::isLowSpecMode() && !IsFullWindowBlurOverlayActive()) {
|
||||
// --- Cached color lookups (invalidated on theme change) ---
|
||||
// These 3 resolveColor() calls do string parsing + map lookup
|
||||
// each time. Cache them per-frame using the schema generation
|
||||
@@ -490,11 +498,11 @@ inline void DrawFullWindowBlurBackdrop(ImDrawList* dl, const ImVec2& pMin, const
|
||||
dl->AddRectFilled(pMin, pMax, IM_COL32(9, 10, 16, 255)); // opaque base (shows through if the blur is faint)
|
||||
if (allowBlur && IsBackdropActive() && !dragonx::ui::effects::isLowSpecMode()
|
||||
&& effects::ImGuiAcrylic::IsEnabled() && effects::ImGuiAcrylic::IsAvailable()) {
|
||||
// Keep the theme card's blurRadius (do NOT override it): applyBlur caches a single blurred
|
||||
// buffer keyed on radius, shared with every glass panel drawn this frame (market cards + the
|
||||
// modal preview card). A different radius here would thrash that cache every frame and make
|
||||
// the backdrop sample the wrong blur. Same radius => one blur serves all, and it stays frozen.
|
||||
// Safe to use a strong custom radius here: while a full-window overlay is active every glass
|
||||
// panel skips acrylic (IsFullWindowBlurOverlayActive), so the backdrop is the SOLE applyBlur
|
||||
// caller — no other radius contends for the shared, radius-keyed blur cache.
|
||||
auto params = GetCurrentAcrylicTheme().card;
|
||||
params.blurRadius = 64.0f; // strong full-window blur
|
||||
params.fallbackColor.w = 1.0f; // full-strength blur so the live content reads
|
||||
effects::ImGuiAcrylic::DrawAcrylicRect(dl, pMin, pMax, params, 0.0f);
|
||||
dl->AddRectFilled(pMin, pMax, IM_COL32(6, 8, 18, 70)); // slight dim so the card reads as foreground
|
||||
|
||||
Reference in New Issue
Block a user