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

commit62e51e0264a61faee0e2b188aaa9cd816c965aaa
parented40b88120
authorLucas Galante <[email protected]>
date2026-08-24 14:40
droplet: superellipse silhouette curves (DropletSpec::curve)

The silhouette's corner family (and the dome profile riding it) takes
the DE's superellipse exponent instead of hardcoded circular arcs:
curvature ramps to zero at both ends of every quadrant, so the
attach↔side↔bottom junctions — now deliberately UNEQUAL (defaults
attach 0.42 / sheet_r 0.58, filling the whole height) — read as one
continuous bottom-heavy curve, and the contact eases out of the flat
top like a meniscus instead of ending on an arc join. Default
exponent 2.6, clamp [2, 6]; 2 restores plain circles.

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

 src/backend/window_runner.rs |  2 +-
 src/scene/paint.rs           | 20 ++++++++++++++++----
 2 files changed, 17 insertions(+), 5 deletions(-)

diff --git a/src/backend/window_runner.rs b/src/backend/window_runner.rs
index 1bca0dc..17fed56 100644
--- a/src/backend/window_runner.rs
+++ b/src/backend/window_runner.rs
@@ -2026,7 +2026,7 @@ pub fn tessellate_display_list(
                     host: [sr * scale, spec.clarity.clamp(0.0, 1.0), spec.dome, ar * scale],
                     specular_tint: [1.0, 1.0, 1.0, bow * scale],
                     mode: 10.0,
-                    shape: 2.0,
+                    shape: spec.curve.clamp(2.0, 6.0),
                 });
             }
             Prim::Droplet { rect, color, spec } => {
diff --git a/src/scene/paint.rs b/src/scene/paint.rs
index 18db1c4..ad2a554 100644
--- a/src/scene/paint.rs
+++ b/src/scene/paint.rs
@@ -105,20 +105,31 @@ pub struct DropletSpec {
     /// stays subtle at the middle while a narrow drop curves visibly. 0
     /// disables it (flat bottom run between the corner arcs).
     pub bow: f32,
+    /// Corner-curve exponent for the silhouette (and the dome profile riding
+    /// it): 2 = circular arcs, above 2 = superellipse quadrants whose
+    /// curvature ramps to ZERO at both ends of each arc — every junction
+    /// (attach↔side, side↔bottom, curve↔flat top) becomes curvature-
+    /// continuous, so unequal attach/sheet_r radii read as ONE flowing curve
+    /// instead of two arcs meeting, and the contact eases out of the flat
+    /// top like a meniscus. Clamped to [2, 6].
+    pub curve: f32,
 }
 
 impl Default for DropletSpec {
     fn default() -> Self {
         // The oval dewdrop: no belly, no sag — one continuous curve from a
-        // tapered attach line to a fully round bottom. The pendant-pool look
-        // is reachable by setting `belly` > 0 (and usually some `sag`).
+        // tapered attach line to a fully round bottom. attach + sheet_r fill
+        // the whole height (no straight side segment), biased bottom-heavy,
+        // and the superellipse curve exponent keeps the unequal pair
+        // curvature-continuous. The pendant-pool look is reachable by
+        // setting `belly` > 0 (and usually some `sag`).
         Self {
             sag: 0.0,
             belly: 0.0,
             belly_w: 0.5,
             blend: 0.35,
-            sheet_r: 0.55,
-            attach: 0.35,
+            sheet_r: 0.58,
+            attach: 0.42,
             clarity: 0.5,
             dome: 0.9,
             band: 0.9,
@@ -126,6 +137,7 @@ impl Default for DropletSpec {
             shine: 32.0,
             rim: 0.5,
             bow: 0.12,
+            curve: 2.6,
         }
     }
 }