Skip to content
Snippets Groups Projects
Commit e21757ce authored by StarArawn's avatar StarArawn
Browse files

Added properly SDF rendering of rounded rectangles. Added borders.

parent 4b61fce3
No related branches found
No related tags found
No related merge requests found
......@@ -11,8 +11,12 @@ pub fn extract_images(
image_manager: &Res<ImageManager>,
dpi: f32,
) -> Vec<ExtractQuadBundle> {
let (layout, handle) = match render_command {
RenderPrimitive::Image { layout, handle } => (layout, handle),
let (border_radius, layout, handle) = match render_command {
RenderPrimitive::Image {
border_radius,
layout,
handle,
} => (*border_radius, layout, handle),
_ => panic!(""),
};
......@@ -29,7 +33,7 @@ pub fn extract_images(
font_handle: None,
quad_type: UIQuadType::Image,
type_index: 0,
border_radius: (0.0, 0.0, 0.0, 0.0),
border_radius,
image: image_manager
.get_handle(handle)
.and_then(|a| Some(a.clone_weak())),
......
......@@ -7,32 +7,58 @@ use crate::{
};
pub fn extract_quads(render_primitive: &RenderPrimitive, dpi: f32) -> Vec<ExtractQuadBundle> {
let (background_color, layout, border_radius) = match render_primitive {
let (background_color, layout, border_radius, border) = match render_primitive {
RenderPrimitive::Quad {
background_color,
layout,
border_radius,
} => (background_color, layout, border_radius),
border,
} => (background_color, layout, border_radius, border),
_ => panic!(""),
};
vec![ExtractQuadBundle {
extracted_quad: ExtractedQuad {
rect: Rect {
min: Vec2::new(layout.posx, layout.posy),
max: Vec2::new(layout.posx + layout.width, layout.posy + layout.height) * dpi,
vec![
// Border
ExtractQuadBundle {
extracted_quad: ExtractedQuad {
rect: Rect {
min: Vec2::new(layout.posx, layout.posy),
max: Vec2::new(layout.posx + layout.width, layout.posy + layout.height) * dpi,
},
color: bevy::prelude::Color::rgba(0.0781, 0.0898, 0.101, 1.0),
vertex_index: 0,
char_id: 0,
z_index: layout.z_index,
font_handle: None,
quad_type: UIQuadType::Quad,
type_index: 0,
border_radius: *border_radius,
image: None,
uv_max: None,
uv_min: None,
},
color: to_bevy_color(background_color),
vertex_index: 0,
char_id: 0,
z_index: layout.z_index,
font_handle: None,
quad_type: UIQuadType::Quad,
type_index: 0,
border_radius: *border_radius,
image: None,
uv_max: None,
uv_min: None,
},
}]
ExtractQuadBundle {
extracted_quad: ExtractedQuad {
rect: Rect {
min: Vec2::new(layout.posx + border.3, layout.posy + border.0),
max: Vec2::new(
(layout.posx + layout.width) - border.1,
(layout.posy + layout.height) - border.2,
) * dpi,
},
color: to_bevy_color(background_color),
vertex_index: 0,
char_id: 0,
z_index: layout.z_index,
font_handle: None,
quad_type: UIQuadType::Quad,
type_index: 0,
border_radius: *border_radius,
image: None,
uv_max: None,
uv_min: None,
},
},
]
}
......@@ -17,8 +17,8 @@ struct VertexOutput {
[[location(1)]] uv: vec3<f32>;
[[location(2)]] pos: vec2<f32>;
[[location(3)]] size: vec2<f32>;
[[location(4)]] screen_position: vec2<f32>;
[[location(5)]] border_radius: f32;
[[location(4)]] border_radius: f32;
[[location(5)]] pixel_position: vec2<f32>;
};
[[stage(vertex)]]
......@@ -30,9 +30,9 @@ fn vertex(
) -> VertexOutput {
var out: VertexOutput;
out.color = vertex_color;
out.pos = vertex_pos_size.xy;
out.pos = (vertex_position.xy - vertex_pos_size.xy);
out.position = view.view_proj * vec4<f32>(vertex_position, 1.0);
out.screen_position = (view.view_proj * vec4<f32>(vertex_position, 1.0)).xy;
out.pixel_position = out.position.xy;
out.uv = vertex_uv.xyz;
out.size = vertex_pos_size.zw;
out.border_radius = vertex_uv.w;
......@@ -51,39 +51,26 @@ var image_sampler: sampler;
let RADIUS: f32 = 0.1;
fn sd_box_rounded(
frag_coord: vec2<f32>,
position: vec2<f32>,
size: vec2<f32>,
radius: f32,
) -> f32 {
var inner_size: vec2<f32> = size - radius * 2.0;
var top_left: vec2<f32> = position + radius;
var bottom_right: vec2<f32> = top_left + inner_size;
var top_left_distance: vec2<f32> = top_left - frag_coord;
var bottom_right_distance: vec2<f32> = frag_coord - bottom_right;
var dist = max(max(top_left_distance, bottom_right_distance), vec2<f32>(0.0));
return length(dist);
fn sdRoundBox(p: vec2<f32>, b: vec2<f32>, r: f32) -> f32
{
var q = abs(p)-b+r;
return min(max(q.x, q.y), 0.0) + length(max(q, vec2<f32>(0.0))) - r;
}
[[stage(fragment)]]
fn fragment(in: VertexOutput) -> [[location(0)]] vec4<f32> {
if (quad_type.t == 0) {
var dist = sd_box_rounded(
in.position.xy,
in.pos,
in.size,
in.border_radius,
var border = 10.0;
var size = in.size;
var pos = in.pos.xy * 2.0;
var bs = min(in.border_radius * 2.0, min(in.size.x, in.size.y));
var rect_dist = sdRoundBox(
pos - size,
size,
bs,
);
dist = 1.0 - smoothStep(
max(in.border_radius - 0.5, 0.0),
in.border_radius + 0.5,
dist);
return vec4<f32>(in.color.rgb, dist);
rect_dist = 1.0 - smoothStep(0.0, fwidth(rect_dist), rect_dist);
return vec4<f32>(in.color.rgb, rect_dist);
}
if (quad_type.t == 1) {
var px_range = 3.5;
......@@ -93,12 +80,18 @@ fn fragment(in: VertexOutput) -> [[location(0)]] vec4<f32> {
var v = max(min(x.r, x.g), min(max(x.r, x.g), x.b));
var sig_dist = (v - 0.5) * dot(msdf_unit, 0.5 / fwidth(in.uv.xy));
var a = clamp(sig_dist + 0.5, 0.0, 1.0);
return vec4<f32>(in.color.rgb, a);
}
if (quad_type.t == 2) {
var bs = min(in.border_radius, min(in.size.x, in.size.y));
var mask = sdRoundBox(
in.pos.xy * 2.0 - (in.size.xy),
in.size.xy,
bs,
);
mask = 1.0 - smoothStep(0.0, fwidth(mask), mask);
var color = textureSample(image_texture, image_sampler, vec2<f32>(in.uv.x, 1.0 - in.uv.y));
return vec4<f32>(color.rgb * in.color.rgb, color.a * in.color.a);
return vec4<f32>(color.rgb * in.color.rgb, color.a * in.color.a * mask);
}
return in.color;
}
\ No newline at end of file
......@@ -3,6 +3,7 @@ use bevy::{
window::WindowDescriptor,
DefaultPlugins,
};
use kayak_core::styles::PositionType;
use kayak_ui::bevy::{BevyContext, BevyKayakUIPlugin, ImageManager, UICameraBundle};
use kayak_ui::core::{
render,
......@@ -23,6 +24,10 @@ fn startup(
let context = BevyContext::new(|context| {
let image_styles = Style {
position_type: StyleProp::Value(PositionType::SelfDirected),
left: StyleProp::Value(Units::Pixels(10.0)),
top: StyleProp::Value(Units::Pixels(10.0)),
border_radius: StyleProp::Value((500.0, 500.0, 500.0, 500.0)),
width: StyleProp::Value(Units::Pixels(200.0)),
height: StyleProp::Value(Units::Pixels(182.0)),
..Style::default()
......
......@@ -336,19 +336,55 @@ impl<'a> morphorm::Node<'a> for Index {
Some(1)
}
fn border_left(&self, _store: &'_ Self::Data) -> Option<morphorm::Units> {
fn border_left(&self, store: &'_ Self::Data) -> Option<morphorm::Units> {
if let Some(node) = store.get(*self) {
if let Some(node) = node {
return match node.styles.border {
StyleProp::Default => Some(morphorm::Units::Auto),
StyleProp::Value(prop) => Some(morphorm::Units::Pixels(prop.3)),
_ => Some(morphorm::Units::Auto),
};
}
}
Some(morphorm::Units::Auto)
}
fn border_right(&self, _store: &'_ Self::Data) -> Option<morphorm::Units> {
fn border_right(&self, store: &'_ Self::Data) -> Option<morphorm::Units> {
if let Some(node) = store.get(*self) {
if let Some(node) = node {
return match node.styles.border {
StyleProp::Default => Some(morphorm::Units::Auto),
StyleProp::Value(prop) => Some(morphorm::Units::Pixels(prop.1)),
_ => Some(morphorm::Units::Auto),
};
}
}
Some(morphorm::Units::Auto)
}
fn border_top(&self, _store: &'_ Self::Data) -> Option<morphorm::Units> {
fn border_top(&self, store: &'_ Self::Data) -> Option<morphorm::Units> {
if let Some(node) = store.get(*self) {
if let Some(node) = node {
return match node.styles.border {
StyleProp::Default => Some(morphorm::Units::Auto),
StyleProp::Value(prop) => Some(morphorm::Units::Pixels(prop.0)),
_ => Some(morphorm::Units::Auto),
};
}
}
Some(morphorm::Units::Auto)
}
fn border_bottom(&self, _store: &'_ Self::Data) -> Option<morphorm::Units> {
fn border_bottom(&self, store: &'_ Self::Data) -> Option<morphorm::Units> {
if let Some(node) = store.get(*self) {
if let Some(node) = node {
return match node.styles.border {
StyleProp::Default => Some(morphorm::Units::Auto),
StyleProp::Value(prop) => Some(morphorm::Units::Pixels(prop.2)),
_ => Some(morphorm::Units::Auto),
};
}
}
Some(morphorm::Units::Auto)
}
}
......@@ -14,6 +14,7 @@ pub enum RenderPrimitive {
Quad {
layout: Rect,
background_color: Color,
border: (f32, f32, f32, f32),
border_radius: (f32, f32, f32, f32),
},
Text {
......@@ -26,6 +27,7 @@ pub enum RenderPrimitive {
size: f32,
},
Image {
border_radius: (f32, f32, f32, f32),
layout: Rect,
handle: u16,
},
......@@ -68,6 +70,7 @@ impl From<&Style> for RenderPrimitive {
RenderCommand::Quad => Self::Quad {
background_color: background_color,
border_radius: style.border_radius.resolve(),
border: style.border.resolve(),
layout: Rect::default(),
},
RenderCommand::Text {
......@@ -86,6 +89,7 @@ impl From<&Style> for RenderPrimitive {
size,
},
RenderCommand::Image { handle } => Self::Image {
border_radius: style.border_radius.resolve(),
layout: Rect::default(),
handle,
},
......
......@@ -36,29 +36,30 @@ where
pub struct Style {
pub background_color: StyleProp<Color>,
pub border_radius: StyleProp<(f32, f32, f32, f32)>,
pub border: StyleProp<(f32, f32, f32, f32)>,
pub bottom: StyleProp<Units>,
pub color: StyleProp<Color>,
pub height: StyleProp<Units>,
pub layout_type: StyleProp<LayoutType>,
pub left: StyleProp<Units>,
pub position_type: StyleProp<PositionType>,
pub render_command: StyleProp<RenderCommand>,
pub right: StyleProp<Units>,
pub top: StyleProp<Units>,
pub width: StyleProp<Units>,
pub padding_left: StyleProp<Units>,
pub padding_right: StyleProp<Units>,
pub padding_top: StyleProp<Units>,
pub padding_bottom: StyleProp<Units>,
pub margin_bottom: StyleProp<Units>,
pub margin_left: StyleProp<Units>,
pub margin_right: StyleProp<Units>,
pub margin_top: StyleProp<Units>,
pub margin_bottom: StyleProp<Units>,
pub min_width: StyleProp<Units>,
pub min_height: StyleProp<Units>,
pub max_width: StyleProp<Units>,
pub max_height: StyleProp<Units>,
pub max_width: StyleProp<Units>,
pub min_height: StyleProp<Units>,
pub min_width: StyleProp<Units>,
pub padding_bottom: StyleProp<Units>,
pub padding_left: StyleProp<Units>,
pub padding_right: StyleProp<Units>,
pub padding_top: StyleProp<Units>,
pub pointer_events: StyleProp<PointerEvents>,
pub position_type: StyleProp<PositionType>,
pub render_command: StyleProp<RenderCommand>,
pub right: StyleProp<Units>,
pub top: StyleProp<Units>,
pub width: StyleProp<Units>,
}
impl Default for Style {
......@@ -66,29 +67,30 @@ impl Default for Style {
Self {
background_color: StyleProp::Default,
border_radius: StyleProp::Default,
render_command: StyleProp::Value(RenderCommand::Empty),
border: StyleProp::Default,
bottom: StyleProp::Default,
color: StyleProp::Inherit,
height: StyleProp::Default,
layout_type: StyleProp::Default,
left: StyleProp::Default,
position_type: StyleProp::Default,
right: StyleProp::Default,
top: StyleProp::Default,
width: StyleProp::Default,
padding_left: StyleProp::Default,
padding_right: StyleProp::Default,
padding_top: StyleProp::Default,
padding_bottom: StyleProp::Default,
margin_bottom: StyleProp::Default,
margin_left: StyleProp::Default,
margin_right: StyleProp::Default,
margin_top: StyleProp::Default,
margin_bottom: StyleProp::Default,
min_width: StyleProp::Default,
min_height: StyleProp::Default,
max_width: StyleProp::Default,
max_height: StyleProp::Default,
max_width: StyleProp::Default,
min_height: StyleProp::Default,
min_width: StyleProp::Default,
padding_bottom: StyleProp::Default,
padding_left: StyleProp::Default,
padding_right: StyleProp::Default,
padding_top: StyleProp::Default,
pointer_events: StyleProp::Default,
position_type: StyleProp::Default,
render_command: StyleProp::Value(RenderCommand::Empty),
right: StyleProp::Default,
top: StyleProp::Default,
width: StyleProp::Default,
}
}
}
......@@ -107,6 +109,12 @@ impl Style {
}
_ => (),
}
match self.border {
StyleProp::Inherit => {
self.border = other.border.clone();
}
_ => (),
}
match self.bottom {
StyleProp::Inherit => {
self.bottom = other.bottom.clone();
......
......@@ -18,6 +18,7 @@ pub fn Window(
) {
*styles = Some(Style {
background_color: StyleProp::Value(Color::new(0.125, 0.125, 0.125, 1.0)),
border: StyleProp::Value((4.0, 4.0, 4.0, 4.0)),
border_radius: StyleProp::Value((5.0, 5.0, 5.0, 5.0)),
render_command: StyleProp::Value(RenderCommand::Quad),
position_type: StyleProp::Value(PositionType::SelfDirected),
......@@ -35,8 +36,8 @@ pub fn Window(
padding_right: StyleProp::Value(Units::Pixels(5.0)),
padding_top: StyleProp::Value(Units::Pixels(5.0)),
padding_bottom: StyleProp::Value(Units::Pixels(5.0)),
width: StyleProp::Value(Units::Pixels(size.0)),
height: StyleProp::Value(Units::Pixels(size.1)),
width: StyleProp::Value(Units::Stretch(1.0)),
height: StyleProp::Value(Units::Stretch(1.0)),
max_width: StyleProp::Value(Units::Pixels(size.0)),
max_height: StyleProp::Value(Units::Pixels(size.1)),
..Style::default()
......@@ -46,6 +47,7 @@ pub fn Window(
background_color: StyleProp::Value(Color::new(0.0781, 0.0898, 0.101, 1.0)),
border_radius: StyleProp::Value((5.0, 0.0, 0.0, 5.0)),
height: StyleProp::Value(Units::Pixels(24.0)),
width: StyleProp::Value(Units::Stretch(1.0)),
left: StyleProp::Value(Units::Pixels(0.0)),
right: StyleProp::Value(Units::Pixels(0.0)),
top: StyleProp::Value(Units::Pixels(0.0)),
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment