Files
ObsidianDragon/src/ui/effects/imgui_acrylic.h
DanS 0e8816e220 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>
2026-07-03 20:26:11 -05:00

395 lines
12 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// DragonX Wallet - ImGui Edition
// Copyright 2024-2026 The Hush Developers
// Released under the GPLv3
#pragma once
#include "acrylic.h"
#include "imgui.h"
namespace dragonx {
namespace ui {
namespace effects {
/**
* @brief ImGui integration for acrylic effects
*
* Provides convenient wrappers around AcrylicMaterial for use with
* standard ImGui rendering patterns.
*/
namespace ImGuiAcrylic {
// ============================================================================
// Initialization
// ============================================================================
/**
* @brief Initialize the acrylic system
*
* Call once at application startup, after OpenGL context is created.
* @return true if successful
*/
bool Init();
/**
* @brief Shutdown the acrylic system
*
* Call at application shutdown before destroying OpenGL context.
*/
void Shutdown();
/**
* @brief Check if acrylic is available and initialized
*/
bool IsAvailable();
// ============================================================================
// Frame Operations
// ============================================================================
/**
* @brief Begin a new frame for acrylic rendering
*
* Call this at the start of your render loop, before any ImGui rendering.
* This captures the current screen content for blur source.
*
* @param width Viewport width
* @param height Viewport height
*/
void BeginFrame(int width, int height);
/**
* @brief End the acrylic frame
*
* Call this after all regular content is rendered but before acrylic overlays.
* Captures the current framebuffer content for blur.
*/
void CaptureBackground();
/**
* @brief Invalidate the acrylic capture so the next frame re-captures
* and re-blurs. Call after theme/skin changes that alter the
* background gradient, image, or colors.
*/
void InvalidateCapture();
/**
* @brief Get a draw callback for background capture.
*
* Insert this callback at the end of the BackgroundDrawList (after all
* background commands). During RenderDrawData() it fires right after
* the background is rasterized — before any UI windows — and blits
* the clean background into the acrylic capture buffer.
*
* Usage in main.cpp:
* @code
* bgDL->AddCallback(ImGuiAcrylic::GetBackgroundCaptureCallback(), nullptr);
* bgDL->AddCallback(ImDrawCallback_ResetRenderState, nullptr);
* @endcode
*/
ImDrawCallback GetBackgroundCaptureCallback();
/**
* @brief Returns a draw callback that captures the LIVE framebuffer (no dirtyFrames_
* gate). Insert it at the START of a full-window modal overlay's draw list — before the
* overlay draws its own backdrop — so the acrylic blurs the live app UI behind the modal:
* @code
* ImDrawList* dl = ImGui::GetWindowDrawList();
* dl->AddCallback(ImGuiAcrylic::GetLiveCaptureCallback(), nullptr);
* dl->AddCallback(ImDrawCallback_ResetRenderState, nullptr);
* // ... then draw the overlay's acrylic/dim backdrop ...
* @endcode
*/
ImDrawCallback GetLiveCaptureCallback();
// ============================================================================
// Drawing Functions
// ============================================================================
/**
* @brief Draw an acrylic-filled rectangle
*
* @param drawList ImGui draw list to add the rectangle to
* @param pMin Top-left corner (screen coordinates)
* @param pMax Bottom-right corner (screen coordinates)
* @param params Acrylic appearance parameters
* @param rounding Corner rounding radius
*/
void DrawAcrylicRect(ImDrawList* drawList,
const ImVec2& pMin, const ImVec2& pMax,
const AcrylicParams& params,
float rounding = 0.0f);
/**
* @brief Draw an acrylic-filled rectangle with default preset
*/
void DrawAcrylicRect(ImDrawList* drawList,
const ImVec2& pMin, const ImVec2& pMax,
float rounding = 0.0f);
// ============================================================================
// Window Wrappers
// ============================================================================
/**
* @brief Begin an acrylic-background window
*
* Works like ImGui::Begin but with acrylic background.
* Must be paired with EndAcrylicWindow().
*
* @param name Window name/ID
* @param p_open Optional close button flag
* @param flags ImGui window flags
* @param params Acrylic appearance parameters
* @return true if window is visible
*/
bool BeginAcrylicWindow(const char* name, bool* p_open = nullptr,
ImGuiWindowFlags flags = 0,
const AcrylicParams& params = AcrylicMaterial::getPopupPreset());
/**
* @brief End an acrylic window
*/
void EndAcrylicWindow();
// ============================================================================
// Child Region Wrappers
// ============================================================================
/**
* @brief Begin an acrylic child region
*
* Works like ImGui::BeginChild but with acrylic background.
* Must be paired with EndAcrylicChild().
*
* @param str_id Child region ID
* @param size Child region size (0,0 = auto)
* @param params Acrylic appearance parameters
* @param child_flags ImGui child flags
* @param window_flags ImGui window flags for the child
* @return true if child is visible
*/
bool BeginAcrylicChild(const char* str_id,
const ImVec2& size = ImVec2(0, 0),
const AcrylicParams& params = AcrylicMaterial::getDarkPreset(),
ImGuiChildFlags child_flags = 0,
ImGuiWindowFlags window_flags = 0);
/**
* @brief End an acrylic child region
*/
void EndAcrylicChild();
// ============================================================================
// Popup Wrappers
// ============================================================================
/**
* @brief Begin an acrylic popup
*
* Works like ImGui::BeginPopup but with acrylic background.
* Must be paired with EndAcrylicPopup().
*
* @param str_id Popup ID
* @param flags ImGui window flags
* @param params Acrylic appearance parameters
* @return true if popup is open
*/
bool BeginAcrylicPopup(const char* str_id,
ImGuiWindowFlags flags = 0,
const AcrylicParams& params = AcrylicMaterial::getPopupPreset());
/**
* @brief End an acrylic popup
*/
void EndAcrylicPopup();
/**
* @brief Begin an acrylic modal popup
*
* Works like ImGui::BeginPopupModal but with acrylic background.
* Must be paired with EndAcrylicPopup().
*/
bool BeginAcrylicPopupModal(const char* name, bool* p_open = nullptr,
ImGuiWindowFlags flags = 0,
const AcrylicParams& params = AcrylicMaterial::getPopupPreset());
// ============================================================================
// Context Menu Helpers
// ============================================================================
/**
* @brief Begin an acrylic context menu for the last item
*
* Works like ImGui::BeginPopupContextItem but with acrylic background.
* Must be paired with EndAcrylicPopup().
*
* @param str_id Popup ID (nullptr to use last item ID)
* @param popup_flags ImGui popup flags
* @param params Acrylic appearance parameters
* @return true if context menu is open
*/
bool BeginAcrylicContextItem(const char* str_id = nullptr,
ImGuiPopupFlags popup_flags = 0,
const AcrylicParams& params = AcrylicMaterial::getPopupPreset());
/**
* @brief Begin an acrylic context menu for the current window
*
* Works like ImGui::BeginPopupContextWindow but with acrylic background.
* Must be paired with EndAcrylicPopup().
*/
bool BeginAcrylicContextWindow(const char* str_id = nullptr,
ImGuiPopupFlags popup_flags = 0,
const AcrylicParams& params = AcrylicMaterial::getPopupPreset());
// ============================================================================
// Sidebar Helper
// ============================================================================
/**
* @brief Draw an acrylic sidebar background
*
* Convenience function for drawing sidebar with DragonX branded acrylic.
*
* @param width Sidebar width
* @param params Optional custom parameters (default: sidebar preset)
*/
void DrawSidebarBackground(float width,
const AcrylicParams& params = AcrylicMaterial::getSidebarPreset());
// ============================================================================
// Settings
// ============================================================================
/**
* @brief Set global acrylic quality
*/
void SetQuality(AcrylicQuality quality);
/**
* @brief Get current quality setting
*/
AcrylicQuality GetQuality();
/**
* @brief Enable/disable acrylic globally
*
* When disabled, all acrylic functions fall back to solid colors.
*/
void SetEnabled(bool enabled);
/**
* @brief Check if acrylic is enabled
*/
bool IsEnabled();
/**
* @brief Set blur radius multiplier (scales all blur radii)
* @param multiplier Value from 0.5 to 2.0 (1.0 = default)
*/
void SetBlurMultiplier(float multiplier);
/**
* @brief Get current blur multiplier
*/
float GetBlurMultiplier();
/**
* @brief Set reduced transparency mode (accessibility)
*
* When enabled, uses solid fallback colors instead of blur effects.
*/
void SetReducedTransparency(bool reduced);
/**
* @brief Check if reduced transparency mode is active
*/
bool GetReducedTransparency();
/**
* @brief Set UI opacity multiplier for cards/sidebar (0.31.0, 1=opaque)
*/
void SetUIOpacity(float opacity);
/**
* @brief Get UI opacity multiplier
*/
float GetUIOpacity();
/**
* @brief Set noise opacity multiplier (0.0 = no noise, 1.0 = default, 2.0 = max)
*/
void SetNoiseOpacity(float multiplier);
/**
* @brief Get noise opacity multiplier
*/
float GetNoiseOpacity();
/**
* @brief Get full acrylic settings
*/
const AcrylicSettings& GetSettings();
/**
* @brief Set full acrylic settings
*/
void SetSettings(const AcrylicSettings& settings);
// ============================================================================
// Presets — combined quality + blur amount
// ============================================================================
/// Number of built-in presets (Off … Frosted)
constexpr int kPresetCount = 6;
/**
* @brief Apply a preset that sets both quality and blur multiplier.
* @param preset Index 05 (Off, Subtle, Light, Standard, Strong, Frosted)
*/
void SetPreset(int preset);
/**
* @brief Derive the closest preset index from current quality + blur.
*/
int GetPreset();
/**
* @brief Human-readable label for a preset index.
*/
const char* GetPresetLabel(int preset);
/**
* @brief Get the quality enum for a given preset index.
*/
AcrylicQuality PresetQuality(int preset);
/**
* @brief Get the blur multiplier for a given preset index.
*/
float PresetBlur(int preset);
/**
* @brief Find closest preset matching a quality + blur pair.
* Useful for migrating from legacy separate settings.
*/
int MatchPreset(AcrylicQuality quality, float blur);
/**
* @brief Apply a continuous blur amount.
*
* Uses Low quality (like the old "Subtle" preset) at any non-zero blur
* level, giving fine-grained control without stepped presets.
* When blur is near zero the effect is disabled entirely.
*
* @param blur Blur multiplier (0.0 = off, up to 4.0 = maximum)
*/
void ApplyBlurAmount(float blur);
} // namespace ImGuiAcrylic
} // namespace effects
} // namespace ui
} // namespace dragonx