feat(effects): overlay-time live-framebuffer blur behind the portfolio modal
The acrylic system only blurred a frozen snapshot of the static app background. Add an overlay-time re-capture so the Manage-portfolio modal blurs the LIVE tab content behind it. - AcrylicMaterial::captureLiveFramebuffer() (GL blit of FB 0 / DX11 CopyResource of the backbuffer + no-backend stub) mirrors captureBackgroundDirect but bypasses the dirtyFrames_ gate so it refreshes every frame the overlay is open, forcing a re-blur. - ImGuiAcrylic::GetLiveCaptureCallback() returns a draw callback for it. - market_tab: the modal inserts that callback (+ ImDrawCallback_ResetRenderState) at the START of its overlay draw list, before the backdrop, so the capture holds the app UI drawn below and the backdrop blurs it. On close, InvalidateCapture() re-captures the background so other glass panels don't keep blurring the stale live capture. - Panel theme-effects are suppressed during the market render while the modal is open (their foreground-draw-list borders draw above all windows and would otherwise bleed over the overlay). Market tab body is rendered again (no longer skipped). - Backdrop draws the acrylic at full strength (fallbackColor.w=1) over an opaque base so the blurred content reads clearly; lighter dim. Design mapped via an Explore investigation of the capture/blur pipeline; compiles on both OpenGL (Linux) and DX11 (Windows cross-build). Needs on-device visual verification. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -16,6 +16,8 @@
|
||||
#include "../material/colors.h"
|
||||
#include "../material/typography.h"
|
||||
#include "../material/project_icons.h"
|
||||
#include "../effects/theme_effects.h"
|
||||
#include "../effects/imgui_acrylic.h"
|
||||
#include "../../util/text_format.h"
|
||||
#include "../../embedded/IconsMaterialDesign.h"
|
||||
#include "../../util/platform.h"
|
||||
@@ -410,6 +412,12 @@ static void RenderPortfolioEditor(App* app)
|
||||
ImGuiWindowFlags_NoScrollbar | ImGuiWindowFlags_NoScrollWithMouse |
|
||||
ImGuiWindowFlags_NoNav | ImGuiWindowFlags_NoSavedSettings);
|
||||
ImDrawList* dl = ImGui::GetWindowDrawList();
|
||||
// Capture the live UI drawn below this overlay (then reset ImGui's render state) so the backdrop
|
||||
// blurs the live tab content, not the frozen wallpaper. Must precede the backdrop draw.
|
||||
if (ImDrawCallback liveCap = effects::ImGuiAcrylic::GetLiveCaptureCallback()) {
|
||||
dl->AddCallback(liveCap, nullptr);
|
||||
dl->AddCallback(ImDrawCallback_ResetRenderState, nullptr);
|
||||
}
|
||||
material::DrawFullWindowBlurBackdrop(dl, vpPos, ImVec2(vpPos.x + vpSize.x, vpPos.y + vpSize.y));
|
||||
ImGui::SetCursorScreenPos(vpPos);
|
||||
ImGui::InvisibleButton("##pfInputBlocker", vpSize,
|
||||
@@ -933,8 +941,10 @@ static void RenderPortfolioEditor(App* app)
|
||||
if (!popupOpen && !ImGui::IsWindowAppearing() && ImGui::IsMouseClicked(ImGuiMouseButton_Left)
|
||||
&& !ImGui::IsMouseHoveringRect(cardMin, cardMax))
|
||||
s_portfolio_editor_open = false;
|
||||
// Commit named edits on any close path (X / Esc / outside-click); unnamed drafts are dropped.
|
||||
if (!s_portfolio_editor_open) commitIfNeeded();
|
||||
// Commit named edits on any close path (Esc / outside-click / Close); unnamed drafts are dropped.
|
||||
// Also invalidate the acrylic capture so the background (not the last live capture) is re-captured
|
||||
// for the other glass panels once the overlay is gone.
|
||||
if (!s_portfolio_editor_open) { commitIfNeeded(); effects::ImGuiAcrylic::InvalidateCapture(); }
|
||||
|
||||
ImGui::End();
|
||||
ImGui::PopStyleColor();
|
||||
@@ -972,10 +982,11 @@ void RenderMarketTab(App* app)
|
||||
const auto& currentExchange = registry[s_exchange_idx];
|
||||
if (s_pair_idx >= (int)currentExchange.pairs.size()) s_pair_idx = 0;
|
||||
|
||||
// When the Manage-portfolio modal is open it fully covers the tab, so skip rendering the tab
|
||||
// body (and its foreground theme effects, which would otherwise bleed over the overlay) — the
|
||||
// modal floats on the app's blurred backdrop instead of the sharp tab content.
|
||||
if (s_portfolio_editor_open) { RenderPortfolioEditor(app); return; }
|
||||
// While the modal is open the overlay captures + blurs the live tab content behind it. Suppress
|
||||
// panel theme-effects for this render so their foreground-draw-list borders don't bleed over the
|
||||
// overlay (foreground draws above all windows). Restored after the modal is rendered.
|
||||
bool fxSuppressed = s_portfolio_editor_open && effects::ThemeEffects::instance().isEnabled();
|
||||
if (fxSuppressed) effects::ThemeEffects::instance().setEnabled(false);
|
||||
|
||||
ImVec2 marketAvail = ImGui::GetContentRegionAvail();
|
||||
// Scrollable (the portfolio grid can extend past the window) but with no visible scrollbar —
|
||||
@@ -1908,7 +1919,11 @@ void RenderMarketTab(App* app)
|
||||
}
|
||||
|
||||
ImGui::EndChild(); // ##MarketScroll
|
||||
// (When the editor is open the tab body is skipped above and the modal is rendered there.)
|
||||
|
||||
// Portfolio editor modal (rendered outside the scroll child so it overlays the page). It captures
|
||||
// + blurs the live content drawn above, so it must render after the tab body.
|
||||
RenderPortfolioEditor(app);
|
||||
if (fxSuppressed) effects::ThemeEffects::instance().setEnabled(true);
|
||||
}
|
||||
|
||||
} // namespace ui
|
||||
|
||||
Reference in New Issue
Block a user