ObsidianDragon - DragonX ImGui Wallet
Full-node GUI wallet for DragonX cryptocurrency. Built with Dear ImGui, SDL3, and OpenGL3/DX11. Features: - Send/receive shielded and transparent transactions - Autoshield with merged transaction display - Built-in CPU mining (xmrig) - Peer management and network monitoring - Wallet encryption with PIN lock - QR code generation for receive addresses - Transaction history with pagination - Console for direct RPC commands - Cross-platform (Linux, Windows)
This commit is contained in:
244
src/ui/effects/theme_effects.h
Normal file
244
src/ui/effects/theme_effects.h
Normal file
@@ -0,0 +1,244 @@
|
||||
// DragonX Wallet - ImGui Edition
|
||||
// Copyright 2024-2026 The Hush Developers
|
||||
// Released under the GPLv3
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <imgui.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
namespace dragonx {
|
||||
namespace ui {
|
||||
namespace effects {
|
||||
|
||||
/**
|
||||
* @brief Per-theme visual effects system.
|
||||
*
|
||||
* Draws animated accents (hue-cycling, rainbow borders, shimmer sweeps,
|
||||
* glow pulses, positional tinting) driven entirely by TOML theme config.
|
||||
* All effects use ImDrawList primitives — no shaders or texture uploads.
|
||||
*/
|
||||
class ThemeEffects {
|
||||
public:
|
||||
static ThemeEffects& instance();
|
||||
|
||||
/// Called once per frame (timing updates)
|
||||
void beginFrame();
|
||||
|
||||
/// Master toggle (from settings)
|
||||
void setEnabled(bool enabled) { enabled_ = enabled; }
|
||||
bool isEnabled() const { return enabled_; }
|
||||
|
||||
/// Background opacity (from window opacity slider). Multiplies
|
||||
/// all effect alphas so they fade with the backdrop while UI stays opaque.
|
||||
void setBackgroundOpacity(float o) { bgOpacity_ = std::max(0.0f, std::min(1.0f, o)); }
|
||||
float backgroundOpacity() const { return bgOpacity_; }
|
||||
|
||||
/// Reduced transparency suppresses shimmer + rainbow border
|
||||
void setReducedTransparency(bool rt) { reduced_transparency_ = rt; }
|
||||
bool isReducedTransparency() const { return reduced_transparency_; }
|
||||
|
||||
/// Reload [effects] config from the active UISchema overlay
|
||||
void loadFromTheme();
|
||||
|
||||
// === Drawing APIs ===
|
||||
|
||||
/// Get the current hue-cycled accent color (optionally phase-shifted)
|
||||
ImU32 getAccentColor(float phaseOffset = 0.0f) const;
|
||||
|
||||
/// Draw rainbow gradient border around a rect (for glass panels)
|
||||
void drawRainbowBorder(ImDrawList* dl, ImVec2 pMin, ImVec2 pMax,
|
||||
float rounding, float thickness) const;
|
||||
|
||||
/// Draw shimmer sweep over a rect
|
||||
void drawShimmer(ImDrawList* dl, ImVec2 pMin, ImVec2 pMax,
|
||||
float rounding) const;
|
||||
|
||||
/// Get positional hue tint for a given screen Y
|
||||
ImU32 getPositionalTint(float screenY) const;
|
||||
|
||||
/// Tint an existing color by positional hue
|
||||
ImU32 tintByPosition(ImU32 baseColor, float screenY) const;
|
||||
|
||||
/// Draw glow pulse behind a rect (for active elements)
|
||||
void drawGlowPulse(ImDrawList* dl, ImVec2 pMin, ImVec2 pMax,
|
||||
float rounding) const;
|
||||
|
||||
/// Draw a light that traces along the border perimeter
|
||||
void drawEdgeTrace(ImDrawList* dl, ImVec2 pMin, ImVec2 pMax,
|
||||
float rounding) const;
|
||||
|
||||
/// Draw a border that shifts between two colors over time (gem-like)
|
||||
void drawGradientBorderShift(ImDrawList* dl, ImVec2 pMin, ImVec2 pMax,
|
||||
float rounding) const;
|
||||
|
||||
/// Draw ember particles that rise from an element (fire theme)
|
||||
void drawEmberRise(ImDrawList* dl, ImVec2 pMin, ImVec2 pMax) const;
|
||||
|
||||
/// Draw specular glare highlights on a panel (polished surface look)
|
||||
void drawSpecularGlare(ImDrawList* dl, ImVec2 pMin, ImVec2 pMax,
|
||||
float rounding) const;
|
||||
|
||||
/// Draw viewport-wide ambient ember particles (fire theme atmosphere)
|
||||
void drawViewportEmbers(ImDrawList* dl) const;
|
||||
|
||||
/// Draw viewport-wide sandstorm particles (wind-driven diagonal sand/dust)
|
||||
void drawSandstorm(ImDrawList* dl) const;
|
||||
|
||||
/// Draw shader-like viewport overlay (color wash + vignette post-processing)
|
||||
void drawViewportOverlay(ImDrawList* dl) const;
|
||||
|
||||
/// Draw all applicable panel effects (edge trace + ember rise on glass panels)
|
||||
/// phaseKey provides per-panel phase diversity based on panel position
|
||||
void drawPanelEffects(ImDrawList* dl, ImVec2 pMin, ImVec2 pMax,
|
||||
float rounding) const;
|
||||
|
||||
// === Query which effects are available ===
|
||||
bool hasRainbowBorder() const { return enabled_ && !reduced_transparency_ && rainbow_border_.enabled; }
|
||||
bool hasShimmer() const { return enabled_ && !reduced_transparency_ && shimmer_.enabled; }
|
||||
bool hasGlowPulse() const { return enabled_ && glow_pulse_.enabled; }
|
||||
bool hasHueCycle() const { return enabled_ && hue_cycle_.enabled; }
|
||||
bool hasPositionalHue() const { return enabled_ && positional_hue_.enabled; }
|
||||
bool hasEdgeTrace() const { return enabled_ && edge_trace_.enabled; } bool hasGradientBorder() const { return enabled_ && gradient_border_.enabled; } bool hasEmberRise() const { return enabled_ && ember_rise_.enabled; }
|
||||
bool hasSpecularGlare() const { return enabled_ && !reduced_transparency_ && specular_glare_.enabled; }
|
||||
bool hasSandstorm() const { return enabled_ && sandstorm_.enabled; }
|
||||
bool hasViewportOverlay() const { return enabled_ && (viewport_overlay_.colorWashEnabled || viewport_overlay_.vignetteEnabled); }
|
||||
|
||||
/// True when any time-dependent effect is active and needs continuous redraws
|
||||
bool hasActiveAnimation() const {
|
||||
if (!enabled_) return false;
|
||||
return hue_cycle_.enabled || rainbow_border_.enabled || shimmer_.enabled
|
||||
|| glow_pulse_.enabled || edge_trace_.enabled || ember_rise_.enabled
|
||||
|| gradient_border_.enabled || specular_glare_.enabled || sandstorm_.enabled
|
||||
|| (viewport_overlay_.colorWashEnabled
|
||||
&& (viewport_overlay_.washRotateSpeed > 0.0f || viewport_overlay_.washPulseSpeed > 0.0f));
|
||||
}
|
||||
|
||||
private:
|
||||
ThemeEffects() = default;
|
||||
|
||||
bool enabled_ = true;
|
||||
bool reduced_transparency_ = false;
|
||||
float time_ = 0.0f;
|
||||
float bgOpacity_ = 1.0f; ///< window-opacity multiplier for effect alphas
|
||||
|
||||
// Viewport bounds (set each frame)
|
||||
float vpMinY_ = 0.0f;
|
||||
float vpMaxY_ = 1.0f;
|
||||
|
||||
// ---- Cached config from [effects] ----
|
||||
|
||||
struct HueCycleConfig {
|
||||
bool enabled = false;
|
||||
float speed = 0.1f, sat = 0.6f, val = 0.85f;
|
||||
float range = 1.0f, offset = 0.0f;
|
||||
} hue_cycle_;
|
||||
|
||||
struct RainbowBorderConfig {
|
||||
bool enabled = false;
|
||||
float speed = 0.05f, alpha = 0.25f;
|
||||
std::vector<ImU32> stops;
|
||||
} rainbow_border_;
|
||||
|
||||
struct ShimmerConfig {
|
||||
bool enabled = false;
|
||||
float speed = 0.12f, width = 80.0f, alpha = 0.06f, angle = 30.0f;
|
||||
ImU32 color = IM_COL32(255,255,255,255);
|
||||
} shimmer_;
|
||||
|
||||
struct PositionalHueConfig {
|
||||
bool enabled = false;
|
||||
ImVec4 topColor{1,0.42f,0.62f,1};
|
||||
ImVec4 bottomColor{0.4f,0.91f,0.98f,1};
|
||||
float strength = 0.3f;
|
||||
} positional_hue_;
|
||||
|
||||
struct GlowPulseConfig {
|
||||
bool enabled = false;
|
||||
float speed = 2.0f, minAlpha = 0.0f, maxAlpha = 0.15f, radius = 4.0f;
|
||||
ImU32 color = IM_COL32(255,255,255,255);
|
||||
} glow_pulse_;
|
||||
|
||||
struct EdgeTraceConfig {
|
||||
bool enabled = false;
|
||||
float speed = 0.3f; ///< full circuits per second
|
||||
float length = 0.20f; ///< fraction of perimeter lit (tail length)
|
||||
float thickness = 1.5f; ///< line thickness in pixels
|
||||
float alpha = 0.6f; ///< peak alpha at head of trace
|
||||
ImU32 color = IM_COL32(255,255,255,255);
|
||||
} edge_trace_;
|
||||
|
||||
struct EmberRiseConfig {
|
||||
bool enabled = false;
|
||||
int count = 8; ///< number of ember particles
|
||||
float speed = 0.4f; ///< rise cycles per second
|
||||
float particleSize = 1.5f;///< ember radius in pixels
|
||||
float alpha = 0.5f; ///< peak alpha
|
||||
ImU32 color = IM_COL32(255, 120, 20, 255);
|
||||
} ember_rise_;
|
||||
|
||||
struct GradientBorderConfig {
|
||||
bool enabled = false;
|
||||
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
|
||||
ImU32 colorA = IM_COL32(206, 147, 216, 255); ///< first color (amethyst)
|
||||
ImU32 colorB = IM_COL32(26, 35, 126, 255); ///< second color (indigo)
|
||||
} gradient_border_;
|
||||
|
||||
struct SpecularGlareConfig {
|
||||
bool enabled = false;
|
||||
float speed = 0.02f; ///< drift speed (Lissajous orbit cycles/sec)
|
||||
float intensity = 0.06f; ///< peak alpha at glare center
|
||||
float radius = 0.5f; ///< glare radius as fraction of panel min-dim
|
||||
int count = 2; ///< number of specular spots per panel
|
||||
ImU32 color = IM_COL32(255, 255, 255, 255);
|
||||
} specular_glare_;
|
||||
|
||||
struct SandstormConfig {
|
||||
bool enabled = false;
|
||||
int count = 80; ///< number of sand particles
|
||||
float speed = 0.35f; ///< base horizontal velocity (viewport widths/sec)
|
||||
float windAngle = 15.0f; ///< degrees from horizontal (+ve = downward)
|
||||
float particleSize = 1.5f; ///< base particle radius in pixels
|
||||
float alpha = 0.35f; ///< peak particle alpha
|
||||
float gustSpeed = 0.07f; ///< gust oscillation frequency (Hz)
|
||||
float gustStrength = 0.4f; ///< speed variation from gusts (fraction)
|
||||
float streakLength = 3.0f; ///< motion blur multiplier for fast particles
|
||||
ImU32 color = IM_COL32(200, 160, 96, 255);
|
||||
} sandstorm_;
|
||||
|
||||
struct ViewportOverlayConfig {
|
||||
// --- Color wash: full-screen 4-corner gradient overlay ---
|
||||
bool colorWashEnabled = false;
|
||||
ImU32 cornerTL = IM_COL32(255,100,0,255); ///< top-left corner color (RGB; alpha applied separately)
|
||||
ImU32 cornerTR = IM_COL32(68,34,0,255); ///< top-right
|
||||
ImU32 cornerBL = IM_COL32(68,17,0,255); ///< bottom-left
|
||||
ImU32 cornerBR = IM_COL32(255,153,0,255); ///< bottom-right
|
||||
float washAlpha = 0.05f; ///< overall wash intensity
|
||||
float washRotateSpeed = 0.0f; ///< corner color rotation (turns/sec)
|
||||
float washPulseSpeed = 0.0f; ///< alpha breathing speed (Hz)
|
||||
float washPulseDepth = 0.0f; ///< pulse depth (0=none, 1=full fade)
|
||||
|
||||
// --- Vignette: edge darkening/tinting ---
|
||||
bool vignetteEnabled = false;
|
||||
ImU32 vignetteColor = IM_COL32(0,0,0,255); ///< tint color at edges
|
||||
float vignetteRadius = 0.35f; ///< fade zone as fraction of viewport
|
||||
float vignetteAlpha = 0.30f; ///< max alpha at outer edge
|
||||
} viewport_overlay_;
|
||||
|
||||
/// Map a 0..1 fraction to a point on the rounded rect perimeter
|
||||
ImVec2 perimeterPoint(ImVec2 pMin, ImVec2 pMax, float t, float rounding = 0.0f) const;
|
||||
|
||||
// Helper: parse hex color string "#RRGGBB" or "#RRGGBBAA" to ImU32
|
||||
static ImU32 parseHexColor(const std::string& hex, ImU32 fallback = IM_COL32(255,255,255,255));
|
||||
static ImVec4 parseHexColorVec4(const std::string& hex, ImVec4 fallback = ImVec4(1,1,1,1));
|
||||
|
||||
// Helper: sample a rotating multi-stop gradient
|
||||
ImU32 sampleGradient(float t) const;
|
||||
};
|
||||
|
||||
} // namespace effects
|
||||
} // namespace ui
|
||||
} // namespace dragonx
|
||||
Reference in New Issue
Block a user