refactor(audit): batch 7 — RPC/settings/lite/effects mechanical dedups
Six behavior-preserving consolidations from the audit: - RPCClient::call() overloads share a private performCall() (payload dump + curl_easy_perform + http code) and a static parseRpcResult() (error->RpcError extraction). The timeout overload restores the prior timeout in both the success and catch paths, exactly as before. - The six UnifiedCallback methods delegate to one splitUnified() that builds the (Callback, ErrorCallback) pair once (null-check preserved). - One liteTrimCopy() in lite_connection_service replaces 5 file-local trim-copy helpers across the lite slice. - lite_wallet_controller's inline height JSON parse now routes through the tested parseLiteHeightResponse(). - theme_effects.cpp: unpackRGB()/scaledAlpha() replace 14 RGB-unpack + 5 alpha-scale copy-paste blocks. - settings.cpp load() uses loadScalar()/loadClamped() helpers for ~44 scalar fields. Besides removing boilerplate this HARDENS loading: ~44 fields that previously only checked contains() now also verify the JSON type, so a malformed value in settings.json falls back to the default instead of throwing/misreading. Custom cases (enum parses, legacy migrations, arrays) stay inline; save() is unchanged. Full-node + Lite build clean; ctest 1/1; hygiene clean. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -15,6 +15,23 @@ namespace dragonx {
|
||||
namespace ui {
|
||||
namespace effects {
|
||||
|
||||
namespace {
|
||||
|
||||
// Colors are packed little-endian RGBA (R at bit 0, G at 8, B at 16, A at 24) — the
|
||||
// same layout IM_COL32 produces. unpackRGB pulls out the three color channels (alpha is
|
||||
// handled separately at each site).
|
||||
struct RGB { int r, g, b; };
|
||||
static inline RGB unpackRGB(ImU32 c) {
|
||||
return RGB{ (int)(c & 0xFF), (int)((c >> 8) & 0xFF), (int)((c >> 16) & 0xFF) };
|
||||
}
|
||||
|
||||
// Scales a 0..1 base alpha by the background opacity into a clamped 0..255 int.
|
||||
static inline int scaledAlpha(float base, float bgOpacity) {
|
||||
return std::clamp((int)(base * bgOpacity * 255.0f), 0, 255);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// ============================================================================
|
||||
// Singleton
|
||||
// ============================================================================
|
||||
@@ -327,16 +344,13 @@ void ThemeEffects::drawShimmer(ImDrawList* dl, ImVec2 pMin, ImVec2 pMax,
|
||||
if (clLeft >= clRight) return;
|
||||
|
||||
float mid = (clLeft + clRight) * 0.5f;
|
||||
int peakA = (int)(shimmer_.alpha * bgOpacity_ * 255.0f);
|
||||
peakA = std::clamp(peakA, 0, 255);
|
||||
int peakA = scaledAlpha(shimmer_.alpha, bgOpacity_);
|
||||
|
||||
// Extract shimmer color RGB (ignore alpha, use shimmer_.alpha)
|
||||
int sR = shimmer_.color & 0xFF;
|
||||
int sG = (shimmer_.color >> 8) & 0xFF;
|
||||
int sB = (shimmer_.color >> 16) & 0xFF;
|
||||
RGB s = unpackRGB(shimmer_.color);
|
||||
|
||||
ImU32 clear = IM_COL32(sR, sG, sB, 0);
|
||||
ImU32 peak = IM_COL32(sR, sG, sB, peakA);
|
||||
ImU32 clear = IM_COL32(s.r, s.g, s.b, 0);
|
||||
ImU32 peak = IM_COL32(s.r, s.g, s.b, peakA);
|
||||
|
||||
// Inset clip rect by corner rounding to prevent shimmer bleeding into rounded corners
|
||||
float cr = std::min(rounding, std::min(w, h) * 0.5f) * 0.3f;
|
||||
@@ -374,9 +388,7 @@ void ThemeEffects::drawSpecularGlare(ImDrawList* dl, ImVec2 pMin, ImVec2 pMax,
|
||||
float minDim = std::min(w, h);
|
||||
float glareR = minDim * specular_glare_.radius;
|
||||
|
||||
int cR = specular_glare_.color & 0xFF;
|
||||
int cG = (specular_glare_.color >> 8) & 0xFF;
|
||||
int cB = (specular_glare_.color >> 16) & 0xFF;
|
||||
RGB c = unpackRGB(specular_glare_.color);
|
||||
|
||||
// Per-panel seed from position — unique drift per panel
|
||||
float seed = pMin.x * 0.0073f + pMin.y * 0.0137f;
|
||||
@@ -410,7 +422,7 @@ void ThemeEffects::drawSpecularGlare(ImDrawList* dl, ImVec2 pMin, ImVec2 pMax,
|
||||
if (a <= 0) continue;
|
||||
|
||||
dl->AddCircleFilled(ImVec2(cx, cy), ringRadius,
|
||||
IM_COL32(cR, cG, cB, a), 32);
|
||||
IM_COL32(c.r, c.g, c.b, a), 32);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -445,18 +457,14 @@ ImU32 ThemeEffects::tintByPosition(ImU32 baseColor, float screenY) const {
|
||||
float s = positional_hue_.strength;
|
||||
float inv = 1.0f - s;
|
||||
|
||||
int bR = baseColor & 0xFF;
|
||||
int bG = (baseColor >> 8) & 0xFF;
|
||||
int bB = (baseColor >> 16) & 0xFF;
|
||||
RGB base = unpackRGB(baseColor);
|
||||
int bA = (baseColor >> 24) & 0xFF;
|
||||
|
||||
int tR = tint & 0xFF;
|
||||
int tG = (tint >> 8) & 0xFF;
|
||||
int tB = (tint >> 16) & 0xFF;
|
||||
RGB t = unpackRGB(tint);
|
||||
|
||||
int r = (int)(bR * inv + tR * s);
|
||||
int g = (int)(bG * inv + tG * s);
|
||||
int b = (int)(bB * inv + tB * s);
|
||||
int r = (int)(base.r * inv + t.r * s);
|
||||
int g = (int)(base.g * inv + t.g * s);
|
||||
int b = (int)(base.b * inv + t.b * s);
|
||||
|
||||
return IM_COL32(r, g, b, bA);
|
||||
}
|
||||
@@ -474,10 +482,8 @@ void ThemeEffects::drawGlowPulse(ImDrawList* dl, ImVec2 pMin, ImVec2 pMax,
|
||||
float alpha = glow_pulse_.minAlpha + phase * (glow_pulse_.maxAlpha - glow_pulse_.minAlpha);
|
||||
if (alpha <= 0.001f) return;
|
||||
|
||||
int a = std::clamp((int)(alpha * bgOpacity_ * 255.0f), 0, 255);
|
||||
int cR = glow_pulse_.color & 0xFF;
|
||||
int cG = (glow_pulse_.color >> 8) & 0xFF;
|
||||
int cB = (glow_pulse_.color >> 16) & 0xFF;
|
||||
int a = scaledAlpha(alpha, bgOpacity_);
|
||||
RGB c = unpackRGB(glow_pulse_.color);
|
||||
|
||||
// Border-only glow: concentric outlines with smooth Gaussian falloff.
|
||||
// Use many fine sub-rings (4× the pixel radius) to avoid visible
|
||||
@@ -496,7 +502,7 @@ void ThemeEffects::drawGlowPulse(ImDrawList* dl, ImVec2 pMin, ImVec2 pMax,
|
||||
dl->AddRect(
|
||||
ImVec2(pMin.x - expand, pMin.y - expand),
|
||||
ImVec2(pMax.x + expand, pMax.y + expand),
|
||||
IM_COL32(cR, cG, cB, ringAlpha),
|
||||
IM_COL32(c.r, c.g, c.b, ringAlpha),
|
||||
rounding + expand * 0.5f, 0, thickness);
|
||||
}
|
||||
}
|
||||
@@ -513,17 +519,13 @@ void ThemeEffects::drawGradientBorderShift(ImDrawList* dl, ImVec2 pMin, ImVec2 p
|
||||
float phase = std::sin(time_ * gradient_border_.speed * 2.0f * 3.14159265f) * 0.5f + 0.5f;
|
||||
|
||||
// Extract RGBA from both colors and lerp
|
||||
int aR = gradient_border_.colorA & 0xFF;
|
||||
int aG = (gradient_border_.colorA >> 8) & 0xFF;
|
||||
int aB = (gradient_border_.colorA >> 16) & 0xFF;
|
||||
int bR = gradient_border_.colorB & 0xFF;
|
||||
int bG = (gradient_border_.colorB >> 8) & 0xFF;
|
||||
int bB = (gradient_border_.colorB >> 16) & 0xFF;
|
||||
RGB ca = unpackRGB(gradient_border_.colorA);
|
||||
RGB cb = unpackRGB(gradient_border_.colorB);
|
||||
|
||||
int r = aR + (int)((bR - aR) * phase);
|
||||
int g = aG + (int)((bG - aG) * phase);
|
||||
int b = aB + (int)((bB - aB) * phase);
|
||||
int a = std::clamp((int)(gradient_border_.alpha * bgOpacity_ * 255.0f), 0, 255);
|
||||
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_);
|
||||
|
||||
// Draw the shifting border
|
||||
dl->AddRect(pMin, pMax, IM_COL32(r, g, b, a),
|
||||
@@ -640,9 +642,7 @@ void ThemeEffects::drawEdgeTrace(ImDrawList* dl, ImVec2 pMin, ImVec2 pMax,
|
||||
float headPos = std::fmod(time_ * edge_trace_.speed, 1.0f);
|
||||
float traceLen = edge_trace_.length;
|
||||
|
||||
int cR = edge_trace_.color & 0xFF;
|
||||
int cG = (edge_trace_.color >> 8) & 0xFF;
|
||||
int cB = (edge_trace_.color >> 16) & 0xFF;
|
||||
RGB c = unpackRGB(edge_trace_.color);
|
||||
|
||||
// Draw the trace as connected line segments with fading alpha.
|
||||
// Use enough segments to make curved corners smooth.
|
||||
@@ -667,16 +667,16 @@ void ThemeEffects::drawEdgeTrace(ImDrawList* dl, ImVec2 pMin, ImVec2 pMax,
|
||||
aFrac = aFrac * aFrac; // quadratic falloff for natural fade
|
||||
int a = (int)(edge_trace_.alpha * aFrac * bgOpacity_ * 255.0f);
|
||||
if (a > 0) {
|
||||
dl->AddLine(prev, pt, IM_COL32(cR, cG, cB, a), edge_trace_.thickness);
|
||||
dl->AddLine(prev, pt, IM_COL32(c.r, c.g, c.b, a), edge_trace_.thickness);
|
||||
}
|
||||
prev = pt;
|
||||
}
|
||||
|
||||
// Bright dot at the head
|
||||
int headA = (int)(edge_trace_.alpha * bgOpacity_ * 255.0f);
|
||||
int headA = scaledAlpha(edge_trace_.alpha, bgOpacity_);
|
||||
ImVec2 headPt = perimeterPoint(pMin, pMax, headPos, rounding);
|
||||
dl->AddCircleFilled(headPt, edge_trace_.thickness * 1.5f,
|
||||
IM_COL32(cR, cG, cB, headA), 8);
|
||||
IM_COL32(c.r, c.g, c.b, headA), 8);
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
@@ -690,9 +690,7 @@ void ThemeEffects::drawEmberRise(ImDrawList* dl, ImVec2 pMin, ImVec2 pMax) const
|
||||
float h = pMax.y - pMin.y;
|
||||
if (w <= 0 || h <= 0) return;
|
||||
|
||||
int cR = ember_rise_.color & 0xFF;
|
||||
int cG = (ember_rise_.color >> 8) & 0xFF;
|
||||
int cB = (ember_rise_.color >> 16) & 0xFF;
|
||||
RGB c = unpackRGB(ember_rise_.color);
|
||||
|
||||
for (int i = 0; i < ember_rise_.count; i++) {
|
||||
// Golden-ratio spacing gives evenly distributed phases
|
||||
@@ -723,11 +721,11 @@ void ThemeEffects::drawEmberRise(ImDrawList* dl, ImVec2 pMin, ImVec2 pMax) const
|
||||
|
||||
// Warm core
|
||||
dl->AddCircleFilled(ImVec2(x, y), size,
|
||||
IM_COL32(cR, cG, cB, a), 6);
|
||||
IM_COL32(c.r, c.g, c.b, a), 6);
|
||||
// Softer outer glow
|
||||
if (a > 30) {
|
||||
dl->AddCircleFilled(ImVec2(x, y), size * 2.0f,
|
||||
IM_COL32(cR, cG, cB, a / 4), 6);
|
||||
IM_COL32(c.r, c.g, c.b, a / 4), 6);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -746,9 +744,7 @@ void ThemeEffects::drawViewportEmbers(ImDrawList* dl) const {
|
||||
float vpY = vp->WorkPos.y;
|
||||
if (vpW <= 0 || vpH <= 0) return;
|
||||
|
||||
int cR = ember_rise_.color & 0xFF;
|
||||
int cG = (ember_rise_.color >> 8) & 0xFF;
|
||||
int cB = (ember_rise_.color >> 16) & 0xFF;
|
||||
RGB c = unpackRGB(ember_rise_.color);
|
||||
|
||||
// Viewport embers: more particles, spread across the whole screen
|
||||
int vpCount = ember_rise_.count * 3;
|
||||
@@ -777,10 +773,10 @@ void ThemeEffects::drawViewportEmbers(ImDrawList* dl) const {
|
||||
if (a <= 0) continue;
|
||||
|
||||
dl->AddCircleFilled(ImVec2(x, y), size,
|
||||
IM_COL32(cR, cG, cB, a), 6);
|
||||
IM_COL32(c.r, c.g, c.b, a), 6);
|
||||
if (a > 20) {
|
||||
dl->AddCircleFilled(ImVec2(x, y), size * 2.5f,
|
||||
IM_COL32(cR, cG, cB, a / 5), 6);
|
||||
IM_COL32(c.r, c.g, c.b, a / 5), 6);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -799,9 +795,7 @@ void ThemeEffects::drawSandstorm(ImDrawList* dl) const {
|
||||
float vpY = vp->WorkPos.y;
|
||||
if (vpW <= 0 || vpH <= 0) return;
|
||||
|
||||
int cR = sandstorm_.color & 0xFF;
|
||||
int cG = (sandstorm_.color >> 8) & 0xFF;
|
||||
int cB = (sandstorm_.color >> 16) & 0xFF;
|
||||
RGB c = unpackRGB(sandstorm_.color);
|
||||
|
||||
// Wind direction vector from angle (degrees from horizontal)
|
||||
float windRad = sandstorm_.windAngle * 3.14159265f / 180.0f;
|
||||
@@ -875,21 +869,21 @@ void ThemeEffects::drawSandstorm(ImDrawList* dl) const {
|
||||
dl->AddLine(
|
||||
ImVec2(x, y),
|
||||
ImVec2(x + sx, y + sy),
|
||||
IM_COL32(cR, cG, cB, a),
|
||||
IM_COL32(c.r, c.g, c.b, a),
|
||||
size * 0.7f);
|
||||
// Bright head dot
|
||||
dl->AddCircleFilled(ImVec2(x, y), size * 0.5f,
|
||||
IM_COL32(cR, cG, cB, std::min(255, a * 3 / 2)), 5);
|
||||
IM_COL32(c.r, c.g, c.b, std::min(255, a * 3 / 2)), 5);
|
||||
} else {
|
||||
// Small/slow particles: simple circle
|
||||
dl->AddCircleFilled(ImVec2(x, y), size,
|
||||
IM_COL32(cR, cG, cB, a), 6);
|
||||
IM_COL32(c.r, c.g, c.b, a), 6);
|
||||
}
|
||||
|
||||
// Occasional larger dust puff (every ~8th particle, double size, half alpha)
|
||||
if (i % 8 == 0 && a > 15) {
|
||||
dl->AddCircleFilled(ImVec2(x, y), size * 2.5f,
|
||||
IM_COL32(cR, cG, cB, a / 4), 8);
|
||||
IM_COL32(c.r, c.g, c.b, a / 4), 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -916,9 +910,7 @@ void ThemeEffects::drawPanelEffects(ImDrawList* dl, ImVec2 pMin, ImVec2 pMax,
|
||||
float headPos = std::fmod(time_ * edge_trace_.speed + posKey, 1.0f);
|
||||
float traceLen = edge_trace_.length;
|
||||
|
||||
int cR = edge_trace_.color & 0xFF;
|
||||
int cG = (edge_trace_.color >> 8) & 0xFF;
|
||||
int cB = (edge_trace_.color >> 16) & 0xFF;
|
||||
RGB c = unpackRGB(edge_trace_.color);
|
||||
|
||||
// Panel edge trace is subtler than sidebar — 60% alpha
|
||||
float panelAlpha = edge_trace_.alpha * 0.6f * bgOpacity_;
|
||||
@@ -935,7 +927,7 @@ void ThemeEffects::drawPanelEffects(ImDrawList* dl, ImVec2 pMin, ImVec2 pMax,
|
||||
aFrac = aFrac * aFrac;
|
||||
int a = (int)(panelAlpha * aFrac * 255.0f);
|
||||
if (a > 0) {
|
||||
dl->AddLine(prev, pt, IM_COL32(cR, cG, cB, a),
|
||||
dl->AddLine(prev, pt, IM_COL32(c.r, c.g, c.b, a),
|
||||
edge_trace_.thickness * 0.8f);
|
||||
}
|
||||
prev = pt;
|
||||
@@ -945,7 +937,7 @@ void ThemeEffects::drawPanelEffects(ImDrawList* dl, ImVec2 pMin, ImVec2 pMax,
|
||||
int headA = (int)(panelAlpha * 255.0f);
|
||||
ImVec2 headPt = perimeterPoint(pMin, pMax, headPos, rounding);
|
||||
dl->AddCircleFilled(headPt, edge_trace_.thickness * 1.2f,
|
||||
IM_COL32(cR, cG, cB, headA), 6);
|
||||
IM_COL32(c.r, c.g, c.b, headA), 6);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -958,9 +950,7 @@ void ThemeEffects::drawPanelEffects(ImDrawList* dl, ImVec2 pMin, ImVec2 pMax,
|
||||
int panelCount = std::max(2, ember_rise_.count / 3);
|
||||
float panelAlpha = ember_rise_.alpha * 0.5f * bgOpacity_;
|
||||
|
||||
int cR = ember_rise_.color & 0xFF;
|
||||
int cG = (ember_rise_.color >> 8) & 0xFF;
|
||||
int cB = (ember_rise_.color >> 16) & 0xFF;
|
||||
RGB c = unpackRGB(ember_rise_.color);
|
||||
|
||||
// Use panel position as seed for unique particle distribution
|
||||
float seed = pMin.x * 0.013f + pMin.y * 0.031f;
|
||||
@@ -987,7 +977,7 @@ void ThemeEffects::drawPanelEffects(ImDrawList* dl, ImVec2 pMin, ImVec2 pMax,
|
||||
if (a <= 0) continue;
|
||||
|
||||
dl->AddCircleFilled(ImVec2(x, y), size,
|
||||
IM_COL32(cR, cG, cB, a), 6);
|
||||
IM_COL32(c.r, c.g, c.b, a), 6);
|
||||
}
|
||||
|
||||
dl->PopClipRect();
|
||||
@@ -1074,14 +1064,12 @@ void ThemeEffects::drawViewportOverlay(ImDrawList* dl) const {
|
||||
// === Vignette: edge darkening/tinting (4 gradient strips) ===
|
||||
// Overlapping strips naturally darken corners more than edges — cinematic look
|
||||
if (viewport_overlay_.vignetteEnabled) {
|
||||
int cR = viewport_overlay_.vignetteColor & 0xFF;
|
||||
int cG = (viewport_overlay_.vignetteColor >> 8) & 0xFF;
|
||||
int cB = (viewport_overlay_.vignetteColor >> 16) & 0xFF;
|
||||
int maxA = std::clamp((int)(viewport_overlay_.vignetteAlpha * bgOpacity_ * 255.0f), 0, 255);
|
||||
RGB c = unpackRGB(viewport_overlay_.vignetteColor);
|
||||
int maxA = scaledAlpha(viewport_overlay_.vignetteAlpha, bgOpacity_);
|
||||
|
||||
if (maxA > 0) {
|
||||
ImU32 edgeCol = IM_COL32(cR, cG, cB, maxA);
|
||||
ImU32 clearCol = IM_COL32(cR, cG, cB, 0);
|
||||
ImU32 edgeCol = IM_COL32(c.r, c.g, c.b, maxA);
|
||||
ImU32 clearCol = IM_COL32(c.r, c.g, c.b, 0);
|
||||
|
||||
float fadeW = vpSize.x * viewport_overlay_.vignetteRadius;
|
||||
float fadeH = vpSize.y * viewport_overlay_.vignetteRadius;
|
||||
|
||||
Reference in New Issue
Block a user