diff --git a/crates/editor/src/element.rs b/crates/editor/src/element.rs index 24b4811b61..13856cc8ef 100644 --- a/crates/editor/src/element.rs +++ b/crates/editor/src/element.rs @@ -1129,7 +1129,7 @@ impl EditorElement { bounds, background: Some(color), border, - corner_radii: style.thumb.corner_radius.into(), + corner_radii: style.thumb.corner_radii.into(), }) }; let background_ranges = editor @@ -1189,7 +1189,7 @@ impl EditorElement { bounds, background: Some(color), border, - corner_radii: style.thumb.corner_radius.into(), + corner_radii: style.thumb.corner_radii.into(), }) } } @@ -1198,7 +1198,7 @@ impl EditorElement { bounds: thumb_bounds, border: style.thumb.border, background: style.thumb.background_color, - corner_radii: style.thumb.corner_radius.into(), + corner_radii: style.thumb.corner_radii.into(), }); } diff --git a/crates/gpui/src/elements/container.rs b/crates/gpui/src/elements/container.rs index df6f35caaf..984742e818 100644 --- a/crates/gpui/src/elements/container.rs +++ b/crates/gpui/src/elements/container.rs @@ -9,7 +9,7 @@ use crate::{ }, json::ToJson, platform::CursorStyle, - scene::{self, Border, CursorRegion, Quad}, + scene::{self, Border, CornerRadii, CursorRegion, Quad}, AnyElement, Element, LayoutContext, PaintContext, SceneBuilder, SizeConstraint, View, ViewContext, }; @@ -30,7 +30,7 @@ pub struct ContainerStyle { #[serde(default)] pub border: Border, #[serde(default)] - pub corner_radius: f32, + pub corner_radii: CornerRadii, #[serde(default)] pub shadow: Option, #[serde(default)] @@ -133,7 +133,10 @@ impl Container { } pub fn with_corner_radius(mut self, radius: f32) -> Self { - self.style.corner_radius = radius; + self.style.corner_radii.top_left = radius; + self.style.corner_radii.top_right = radius; + self.style.corner_radii.bottom_right = radius; + self.style.corner_radii.bottom_left = radius; self } @@ -225,7 +228,7 @@ impl Element for Container { if let Some(shadow) = self.style.shadow.as_ref() { scene.push_shadow(scene::Shadow { bounds: quad_bounds + shadow.offset, - corner_radius: self.style.corner_radius, + corner_radii: self.style.corner_radii, sigma: shadow.blur, color: shadow.color, }); @@ -248,7 +251,7 @@ impl Element for Container { bounds: quad_bounds, background: self.style.background_color, border: Default::default(), - corner_radii: self.style.corner_radius.into(), + corner_radii: self.style.corner_radii.into(), }); self.child @@ -259,7 +262,7 @@ impl Element for Container { bounds: quad_bounds, background: self.style.overlay_color, border: self.style.border, - corner_radii: self.style.corner_radius.into(), + corner_radii: self.style.corner_radii.into(), }); scene.pop_layer(); } else { @@ -267,7 +270,7 @@ impl Element for Container { bounds: quad_bounds, background: self.style.background_color, border: self.style.border, - corner_radii: self.style.corner_radius.into(), + corner_radii: self.style.corner_radii.into(), }); let child_origin = child_origin @@ -284,7 +287,7 @@ impl Element for Container { bounds: quad_bounds, background: self.style.overlay_color, border: Default::default(), - corner_radii: self.style.corner_radius.into(), + corner_radii: self.style.corner_radii.into(), }); scene.pop_layer(); } @@ -328,7 +331,7 @@ impl ToJson for ContainerStyle { "padding": self.padding.to_json(), "background_color": self.background_color.to_json(), "border": self.border.to_json(), - "corner_radius": self.corner_radius, + "corner_radius": self.corner_radii, "shadow": self.shadow.to_json(), }) } diff --git a/crates/gpui/src/platform/mac/renderer.rs b/crates/gpui/src/platform/mac/renderer.rs index 1cc3d33b2a..5fe9e34ee4 100644 --- a/crates/gpui/src/platform/mac/renderer.rs +++ b/crates/gpui/src/platform/mac/renderer.rs @@ -509,10 +509,14 @@ impl Renderer { }; for (ix, shadow) in shadows.iter().enumerate() { let shape_bounds = shadow.bounds * scale_factor; + let corner_radii = shadow.corner_radii * scale_factor; let shader_shadow = shaders::GPUIShadow { origin: shape_bounds.origin().to_float2(), size: shape_bounds.size().to_float2(), - corner_radius: shadow.corner_radius * scale_factor, + corner_radius_top_left: corner_radii.top_left, + corner_radius_top_right: corner_radii.top_right, + corner_radius_bottom_right: corner_radii.bottom_right, + corner_radius_bottom_left: corner_radii.bottom_left, sigma: shadow.sigma, color: shadow.color.to_uchar4(), }; diff --git a/crates/gpui/src/platform/mac/shaders/shaders.h b/crates/gpui/src/platform/mac/shaders/shaders.h index ac8389e1f6..b73e5f8e98 100644 --- a/crates/gpui/src/platform/mac/shaders/shaders.h +++ b/crates/gpui/src/platform/mac/shaders/shaders.h @@ -34,7 +34,10 @@ typedef enum { typedef struct { vector_float2 origin; vector_float2 size; - float corner_radius; + float corner_radius_top_left; + float corner_radius_top_right; + float corner_radius_bottom_right; + float corner_radius_bottom_left; float sigma; vector_uchar4 color; } GPUIShadow; diff --git a/crates/gpui/src/platform/mac/shaders/shaders.metal b/crates/gpui/src/platform/mac/shaders/shaders.metal index cc38f3df7a..b803094cf6 100644 --- a/crates/gpui/src/platform/mac/shaders/shaders.metal +++ b/crates/gpui/src/platform/mac/shaders/shaders.metal @@ -146,7 +146,10 @@ struct ShadowFragmentInput { float4 position [[position]]; vector_float2 origin; vector_float2 size; - float corner_radius; + float corner_radius_top_left; + float corner_radius_top_right; + float corner_radius_bottom_right; + float corner_radius_bottom_left; float sigma; vector_uchar4 color; }; @@ -169,7 +172,10 @@ vertex ShadowFragmentInput shadow_vertex( device_position, shadow.origin, shadow.size, - shadow.corner_radius, + shadow.corner_radius_top_left, + shadow.corner_radius_top_right, + shadow.corner_radius_bottom_right, + shadow.corner_radius_bottom_left, shadow.sigma, shadow.color, }; @@ -179,10 +185,24 @@ fragment float4 shadow_fragment( ShadowFragmentInput input [[stage_in]] ) { float sigma = input.sigma; - float corner_radius = input.corner_radius; float2 half_size = input.size / 2.; float2 center = input.origin + half_size; float2 point = input.position.xy - center; + float2 center_to_point = input.position.xy - center; + float corner_radius; + if (center_to_point.x < 0.) { + if (center_to_point.y < 0.) { + corner_radius = input.corner_radius_top_left; + } else { + corner_radius = input.corner_radius_bottom_left; + } + } else { + if (center_to_point.y < 0.) { + corner_radius = input.corner_radius_top_right; + } else { + corner_radius = input.corner_radius_bottom_right; + } + } // The signal is only non-zero in a limited range, so don't waste samples float low = point.y - half_size.y; diff --git a/crates/gpui/src/scene.rs b/crates/gpui/src/scene.rs index abc763b73b..48649c5791 100644 --- a/crates/gpui/src/scene.rs +++ b/crates/gpui/src/scene.rs @@ -6,6 +6,7 @@ use collections::HashSet; use derive_more::Mul; use schemars::JsonSchema; use serde::Deserialize; +use serde_derive::Serialize; use serde_json::json; use std::{borrow::Cow, sync::Arc}; @@ -69,7 +70,7 @@ pub struct Quad { pub corner_radii: CornerRadii, } -#[derive(Default, Debug, Mul, Clone, Copy)] +#[derive(Default, Debug, Mul, Clone, Copy, Deserialize, Serialize, JsonSchema)] pub struct CornerRadii { pub top_left: f32, pub top_right: f32, @@ -91,7 +92,7 @@ impl From for CornerRadii { #[derive(Debug)] pub struct Shadow { pub bounds: RectF, - pub corner_radius: f32, + pub corner_radii: CornerRadii, pub sigma: f32, pub color: Color, }