git.lucas.co / cce-ui
GPU-accelerated UI toolkit (Vulkan)
git clone https://git.lucas.co/cce-ui.git

commitabb3ae0ebf93ae7a2cf11b71d8d837e26788bf18
parentac6af20c0b
authorLucas Galante <[email protected]>
date2026-07-24 14:59
feat: param_plate_fill helper + share blur snapshot across a run

param_plate_fill() is the one source for the params plate's final fill
(tint x opacity, blur marker); ParametersBg::color() now calls it so any
surface matching the plate stays in lockstep. The renderer only takes a
fresh blur snapshot on the first of a consecutive blur-plate run — a row
of blur plates (the designer's node bodies) costs one full-frame copy,
not one each; a non-blur draw between them re-arms it.

Co-Authored-By: Claude Fable 5 <[email protected]>

 src/color.rs                          | 14 ++++++++++++++
 src/vk/renderer.rs                    | 14 ++++++++++++--
 src/widget/container/parameters_bg.rs |  7 +------
 3 files changed, 27 insertions(+), 8 deletions(-)

diff --git a/src/color.rs b/src/color.rs
index a9ae58c..6cc0808 100644
--- a/src/color.rs
+++ b/src/color.rs
@@ -919,6 +919,20 @@ pub fn set_param_bg_color(color: [f32; 4]) {
     }
 }
 
+/// The params plate's final fill as the renderer consumes it: the tint scaled
+/// by the global plate opacity, alpha negated as the blur-behind marker when
+/// plate blur is on. The single source both `ParametersBg`'s own plate and any
+/// surface that wants to match it (the designer's node bodies) draw from, so
+/// they track a live retint / opacity / blur toggle together.
+pub fn param_plate_fill() -> [f32; 4] {
+    let mut c = param_bg_color();
+    c[3] *= crate::layout::plate_opacity();
+    if plate_blur() {
+        c[3] = -c[3].abs();
+    }
+    c
+}
+
 pub const PANEL_MENU_BG: [f32; 4] = [0.08, 0.08, 0.12, 1.0];
 pub const PANEL_MENU_HOVER: [f32; 4] = [0.18, 0.18, 0.25, 1.0];
 pub const PANEL_MENU_FOCUSED: [f32; 4] = [0.08, 0.16, 0.28, 1.0];
diff --git a/src/vk/renderer.rs b/src/vk/renderer.rs
index c1573f0..704c18b 100644
--- a/src/vk/renderer.rs
+++ b/src/vk/renderer.rs
@@ -1698,11 +1698,21 @@ impl VkRenderer {
                 // so blur plates sample the frame-so-far, and later blur plates
                 // sample refreshed copies that include earlier ones.
                 let mut active_set = self.descriptor_set;
+                // CONSECUTIVE blur plates share one snapshot: only a non-blur
+                // draw invalidates it. A run of blur plates (the designer's
+                // node bodies) costs one copy, not one per plate — they don't
+                // see each other, which only matters where they overlap.
+                let mut snapshot_fresh = false;
 
                 for batch in batches {
                     if batch.blur_behind {
-                        self.snapshot_frame_so_far(cmd, image_index as usize);
-                        active_set = self.descriptor_set_snapshot;
+                        if !snapshot_fresh {
+                            self.snapshot_frame_so_far(cmd, image_index as usize);
+                            active_set = self.descriptor_set_snapshot;
+                            snapshot_fresh = true;
+                        }
+                    } else if batch.start < batch.end {
+                        snapshot_fresh = false;
                     }
                     // Resolve the batch scissor; a degenerate one skips the
                     // vertex draws (images still process on their own clips).
diff --git a/src/widget/container/parameters_bg.rs b/src/widget/container/parameters_bg.rs
index 1d7c172..0f9ff82 100644
--- a/src/widget/container/parameters_bg.rs
+++ b/src/widget/container/parameters_bg.rs
@@ -1242,12 +1242,7 @@ impl Paint for ParametersBg {
         if !self.visible {
             return [0.0, 0.0, 0.0, 0.0];
         }
-        let mut c = colors::param_bg_color();
-        c[3] *= crate::layout::plate_opacity();
-        if colors::plate_blur() {
-            c[3] = -c[3].abs();
-        }
-        c
+        colors::param_plate_fill()
     }
 
     /// The shared plate corner radius (rounded on all four corners when non-zero).