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( ...@@ -11,8 +11,12 @@ pub fn extract_images(
image_manager: &Res<ImageManager>, image_manager: &Res<ImageManager>,
dpi: f32, dpi: f32,
) -> Vec<ExtractQuadBundle> { ) -> Vec<ExtractQuadBundle> {
let (layout, handle) = match render_command { let (border_radius, layout, handle) = match render_command {
RenderPrimitive::Image { layout, handle } => (layout, handle), RenderPrimitive::Image {
border_radius,
layout,
handle,
} => (*border_radius, layout, handle),
_ => panic!(""), _ => panic!(""),
}; };
...@@ -29,7 +33,7 @@ pub fn extract_images( ...@@ -29,7 +33,7 @@ pub fn extract_images(
font_handle: None, font_handle: None,
quad_type: UIQuadType::Image, quad_type: UIQuadType::Image,
type_index: 0, type_index: 0,
border_radius: (0.0, 0.0, 0.0, 0.0), border_radius,
image: image_manager image: image_manager
.get_handle(handle) .get_handle(handle)
.and_then(|a| Some(a.clone_weak())), .and_then(|a| Some(a.clone_weak())),
......
...@@ -7,32 +7,58 @@ use crate::{ ...@@ -7,32 +7,58 @@ use crate::{
}; };
pub fn extract_quads(render_primitive: &RenderPrimitive, dpi: f32) -> Vec<ExtractQuadBundle> { 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 { RenderPrimitive::Quad {
background_color, background_color,
layout, layout,
border_radius, border_radius,
} => (background_color, layout, border_radius), border,
} => (background_color, layout, border_radius, border),
_ => panic!(""), _ => panic!(""),
}; };
vec![ExtractQuadBundle { vec![
extracted_quad: ExtractedQuad { // Border
rect: Rect { ExtractQuadBundle {
min: Vec2::new(layout.posx, layout.posy), extracted_quad: ExtractedQuad {
max: Vec2::new(layout.posx + layout.width, layout.posy + layout.height) * dpi, 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 { ...@@ -17,8 +17,8 @@ struct VertexOutput {
[[location(1)]] uv: vec3<f32>; [[location(1)]] uv: vec3<f32>;
[[location(2)]] pos: vec2<f32>; [[location(2)]] pos: vec2<f32>;
[[location(3)]] size: vec2<f32>; [[location(3)]] size: vec2<f32>;
[[location(4)]] screen_position: vec2<f32>; [[location(4)]] border_radius: f32;
[[location(5)]] border_radius: f32; [[location(5)]] pixel_position: vec2<f32>;
}; };
[[stage(vertex)]] [[stage(vertex)]]
...@@ -30,9 +30,9 @@ fn vertex( ...@@ -30,9 +30,9 @@ fn vertex(
) -> VertexOutput { ) -> VertexOutput {
var out: VertexOutput; var out: VertexOutput;
out.color = vertex_color; 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.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.uv = vertex_uv.xyz;
out.size = vertex_pos_size.zw; out.size = vertex_pos_size.zw;
out.border_radius = vertex_uv.w; out.border_radius = vertex_uv.w;
...@@ -51,39 +51,26 @@ var image_sampler: sampler; ...@@ -51,39 +51,26 @@ var image_sampler: sampler;
let RADIUS: f32 = 0.1; let RADIUS: f32 = 0.1;
fn sd_box_rounded( fn sdRoundBox(p: vec2<f32>, b: vec2<f32>, r: f32) -> f32
frag_coord: vec2<f32>, {
position: vec2<f32>, var q = abs(p)-b+r;
size: vec2<f32>, return min(max(q.x, q.y), 0.0) + length(max(q, vec2<f32>(0.0))) - r;
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);
} }
[[stage(fragment)]] [[stage(fragment)]]
fn fragment(in: VertexOutput) -> [[location(0)]] vec4<f32> { fn fragment(in: VertexOutput) -> [[location(0)]] vec4<f32> {
if (quad_type.t == 0) { if (quad_type.t == 0) {
var dist = sd_box_rounded( var border = 10.0;
in.position.xy, var size = in.size;
in.pos, var pos = in.pos.xy * 2.0;
in.size, var bs = min(in.border_radius * 2.0, min(in.size.x, in.size.y));
in.border_radius, var rect_dist = sdRoundBox(
pos - size,
size,
bs,
); );
dist = 1.0 - smoothStep( rect_dist = 1.0 - smoothStep(0.0, fwidth(rect_dist), rect_dist);
max(in.border_radius - 0.5, 0.0), return vec4<f32>(in.color.rgb, rect_dist);
in.border_radius + 0.5,
dist);
return vec4<f32>(in.color.rgb, dist);
} }
if (quad_type.t == 1) { if (quad_type.t == 1) {
var px_range = 3.5; var px_range = 3.5;
...@@ -93,12 +80,18 @@ fn fragment(in: VertexOutput) -> [[location(0)]] vec4<f32> { ...@@ -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 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 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); var a = clamp(sig_dist + 0.5, 0.0, 1.0);
return vec4<f32>(in.color.rgb, a); return vec4<f32>(in.color.rgb, a);
} }
if (quad_type.t == 2) { 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)); 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; return in.color;
} }
\ No newline at end of file
...@@ -3,6 +3,7 @@ use bevy::{ ...@@ -3,6 +3,7 @@ use bevy::{
window::WindowDescriptor, window::WindowDescriptor,
DefaultPlugins, DefaultPlugins,
}; };
use kayak_core::styles::PositionType;
use kayak_ui::bevy::{BevyContext, BevyKayakUIPlugin, ImageManager, UICameraBundle}; use kayak_ui::bevy::{BevyContext, BevyKayakUIPlugin, ImageManager, UICameraBundle};
use kayak_ui::core::{ use kayak_ui::core::{
render, render,
...@@ -23,6 +24,10 @@ fn startup( ...@@ -23,6 +24,10 @@ fn startup(
let context = BevyContext::new(|context| { let context = BevyContext::new(|context| {
let image_styles = Style { 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)), width: StyleProp::Value(Units::Pixels(200.0)),
height: StyleProp::Value(Units::Pixels(182.0)), height: StyleProp::Value(Units::Pixels(182.0)),
..Style::default() ..Style::default()
......
...@@ -336,19 +336,55 @@ impl<'a> morphorm::Node<'a> for Index { ...@@ -336,19 +336,55 @@ impl<'a> morphorm::Node<'a> for Index {
Some(1) 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) 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) 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) 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) Some(morphorm::Units::Auto)
} }
} }
...@@ -14,6 +14,7 @@ pub enum RenderPrimitive { ...@@ -14,6 +14,7 @@ pub enum RenderPrimitive {
Quad { Quad {
layout: Rect, layout: Rect,
background_color: Color, background_color: Color,
border: (f32, f32, f32, f32),
border_radius: (f32, f32, f32, f32), border_radius: (f32, f32, f32, f32),
}, },
Text { Text {
...@@ -26,6 +27,7 @@ pub enum RenderPrimitive { ...@@ -26,6 +27,7 @@ pub enum RenderPrimitive {
size: f32, size: f32,
}, },
Image { Image {
border_radius: (f32, f32, f32, f32),
layout: Rect, layout: Rect,
handle: u16, handle: u16,
}, },
...@@ -68,6 +70,7 @@ impl From<&Style> for RenderPrimitive { ...@@ -68,6 +70,7 @@ impl From<&Style> for RenderPrimitive {
RenderCommand::Quad => Self::Quad { RenderCommand::Quad => Self::Quad {
background_color: background_color, background_color: background_color,
border_radius: style.border_radius.resolve(), border_radius: style.border_radius.resolve(),
border: style.border.resolve(),
layout: Rect::default(), layout: Rect::default(),
}, },
RenderCommand::Text { RenderCommand::Text {
...@@ -86,6 +89,7 @@ impl From<&Style> for RenderPrimitive { ...@@ -86,6 +89,7 @@ impl From<&Style> for RenderPrimitive {
size, size,
}, },
RenderCommand::Image { handle } => Self::Image { RenderCommand::Image { handle } => Self::Image {
border_radius: style.border_radius.resolve(),
layout: Rect::default(), layout: Rect::default(),
handle, handle,
}, },
......
...@@ -36,29 +36,30 @@ where ...@@ -36,29 +36,30 @@ where
pub struct Style { pub struct Style {
pub background_color: StyleProp<Color>, pub background_color: StyleProp<Color>,
pub border_radius: StyleProp<(f32, f32, f32, f32)>, pub border_radius: StyleProp<(f32, f32, f32, f32)>,
pub border: StyleProp<(f32, f32, f32, f32)>,
pub bottom: StyleProp<Units>, pub bottom: StyleProp<Units>,
pub color: StyleProp<Color>, pub color: StyleProp<Color>,
pub height: StyleProp<Units>, pub height: StyleProp<Units>,
pub layout_type: StyleProp<LayoutType>, pub layout_type: StyleProp<LayoutType>,
pub left: StyleProp<Units>, pub left: StyleProp<Units>,
pub position_type: StyleProp<PositionType>, pub margin_bottom: StyleProp<Units>,
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_left: StyleProp<Units>, pub margin_left: StyleProp<Units>,
pub margin_right: StyleProp<Units>, pub margin_right: StyleProp<Units>,
pub margin_top: 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_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 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 { impl Default for Style {
...@@ -66,29 +67,30 @@ impl Default for Style { ...@@ -66,29 +67,30 @@ impl Default for Style {
Self { Self {
background_color: StyleProp::Default, background_color: StyleProp::Default,
border_radius: StyleProp::Default, border_radius: StyleProp::Default,
render_command: StyleProp::Value(RenderCommand::Empty), border: StyleProp::Default,
bottom: StyleProp::Default, bottom: StyleProp::Default,
color: StyleProp::Inherit, color: StyleProp::Inherit,
height: StyleProp::Default, height: StyleProp::Default,
layout_type: StyleProp::Default, layout_type: StyleProp::Default,
left: StyleProp::Default, left: StyleProp::Default,
position_type: StyleProp::Default, margin_bottom: 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_left: StyleProp::Default, margin_left: StyleProp::Default,
margin_right: StyleProp::Default, margin_right: StyleProp::Default,
margin_top: 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_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, 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 { ...@@ -107,6 +109,12 @@ impl Style {
} }
_ => (), _ => (),
} }
match self.border {
StyleProp::Inherit => {
self.border = other.border.clone();
}
_ => (),
}
match self.bottom { match self.bottom {
StyleProp::Inherit => { StyleProp::Inherit => {
self.bottom = other.bottom.clone(); self.bottom = other.bottom.clone();
......
...@@ -18,6 +18,7 @@ pub fn Window( ...@@ -18,6 +18,7 @@ pub fn Window(
) { ) {
*styles = Some(Style { *styles = Some(Style {
background_color: StyleProp::Value(Color::new(0.125, 0.125, 0.125, 1.0)), 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)), border_radius: StyleProp::Value((5.0, 5.0, 5.0, 5.0)),
render_command: StyleProp::Value(RenderCommand::Quad), render_command: StyleProp::Value(RenderCommand::Quad),
position_type: StyleProp::Value(PositionType::SelfDirected), position_type: StyleProp::Value(PositionType::SelfDirected),
...@@ -35,8 +36,8 @@ pub fn Window( ...@@ -35,8 +36,8 @@ pub fn Window(
padding_right: StyleProp::Value(Units::Pixels(5.0)), padding_right: StyleProp::Value(Units::Pixels(5.0)),
padding_top: StyleProp::Value(Units::Pixels(5.0)), padding_top: StyleProp::Value(Units::Pixels(5.0)),
padding_bottom: StyleProp::Value(Units::Pixels(5.0)), padding_bottom: StyleProp::Value(Units::Pixels(5.0)),
width: StyleProp::Value(Units::Pixels(size.0)), width: StyleProp::Value(Units::Stretch(1.0)),
height: StyleProp::Value(Units::Pixels(size.1)), height: StyleProp::Value(Units::Stretch(1.0)),
max_width: StyleProp::Value(Units::Pixels(size.0)), max_width: StyleProp::Value(Units::Pixels(size.0)),
max_height: StyleProp::Value(Units::Pixels(size.1)), max_height: StyleProp::Value(Units::Pixels(size.1)),
..Style::default() ..Style::default()
...@@ -46,6 +47,7 @@ pub fn Window( ...@@ -46,6 +47,7 @@ pub fn Window(
background_color: StyleProp::Value(Color::new(0.0781, 0.0898, 0.101, 1.0)), 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)), border_radius: StyleProp::Value((5.0, 0.0, 0.0, 5.0)),
height: StyleProp::Value(Units::Pixels(24.0)), height: StyleProp::Value(Units::Pixels(24.0)),
width: StyleProp::Value(Units::Stretch(1.0)),
left: StyleProp::Value(Units::Pixels(0.0)), left: StyleProp::Value(Units::Pixels(0.0)),
right: StyleProp::Value(Units::Pixels(0.0)), right: StyleProp::Value(Units::Pixels(0.0)),
top: 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