Skip to content

Commit

Permalink
Add support for border radii (#261)
Browse files Browse the repository at this point in the history
* Add support for border radii

* Run `cargo fmt --all`

---------

Co-authored-by: Nilirad <gisquerin@gmail.com>
  • Loading branch information
ladvoc and Nilirad authored Nov 13, 2024
1 parent b1e5c23 commit b434b7d
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 8 deletions.
27 changes: 27 additions & 0 deletions examples/rectangle.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
use bevy::{color::palettes::css::*, prelude::*};
use bevy_prototype_lyon::prelude::*;

fn main() {
App::new()
.add_plugins((DefaultPlugins, ShapePlugin))
.add_systems(Startup, setup_system)
.run();
}

fn setup_system(mut commands: Commands) {
let rect = shapes::Rectangle {
extents: Vec2::splat(175.0),
origin: RectangleOrigin::Center,
radii: Some(BorderRadii::single(25.0)),
};

commands.spawn((Camera2d, Msaa::Sample4));
commands.spawn((
ShapeBundle {
path: GeometryBuilder::build_as(&rect),
..default()
},
Stroke::new(BLACK, 10.0),
Fill::color(RED),
));
}
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,6 @@ pub mod prelude {
geometry::{Geometry, GeometryBuilder},
path::{PathBuilder, ShapePath},
plugin::ShapePlugin,
shapes::{self, RectangleOrigin, RegularPolygon, RegularPolygonFeature},
shapes::{self, BorderRadii, RectangleOrigin, RegularPolygon, RegularPolygonFeature},
};
}
93 changes: 86 additions & 7 deletions src/shapes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ use lyon_tessellation::{
geom::euclid::default::Size2D,
math::{point, Angle, Box2D, Point, Vector},
path::{
builder::WithSvg, path::Builder, traits::SvgPathBuilder, ArcFlags, Polygon as LyonPolygon,
Winding,
builder::{BorderRadii as LyonBorderRadii, WithSvg},
path::Builder,
traits::SvgPathBuilder,
ArcFlags, Polygon as LyonPolygon, Winding,
},
};
use svgtypes::{PathParser, PathSegment};
Expand Down Expand Up @@ -38,18 +40,93 @@ impl Default for RectangleOrigin {
}
}

/// Radii for the four corners of a rectangle.
#[derive(Debug, Default, Clone, Copy, PartialEq)]
pub struct BorderRadii {
/// Radius for the top left corner.
pub top_left: f32,
/// Radius for the top right corner.
pub top_right: f32,
/// Radius for the bottom left corner.
pub bottom_left: f32,
/// Radius for the bottom right corner.
pub bottom_right: f32,
}

impl BorderRadii {
/// Use a single radius for all corners.
pub fn single(radius: f32) -> Self {

Check failure on line 58 in src/shapes.rs

View workflow job for this annotation

GitHub Actions / clippy

this method could have a `#[must_use]` attribute

error: this method could have a `#[must_use]` attribute --> src/shapes.rs:58:5 | 58 | pub fn single(radius: f32) -> Self { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn single(radius: f32) -> Self` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#must_use_candidate = note: `-D clippy::must-use-candidate` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::must_use_candidate)]`

Check failure on line 58 in src/shapes.rs

View workflow job for this annotation

GitHub Actions / clippy

this method could have a `#[must_use]` attribute

error: this method could have a `#[must_use]` attribute --> src/shapes.rs:58:5 | 58 | pub fn single(radius: f32) -> Self { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn single(radius: f32) -> Self` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#must_use_candidate = note: `-D clippy::must-use-candidate` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::must_use_candidate)]`
Self {
top_left: radius,
top_right: radius,
bottom_left: radius,
bottom_right: radius,
}
}

/// Use a single radius for the top corners and zero for the bottom corners.
pub fn top(radius: f32) -> Self {

Check failure on line 68 in src/shapes.rs

View workflow job for this annotation

GitHub Actions / clippy

this method could have a `#[must_use]` attribute

error: this method could have a `#[must_use]` attribute --> src/shapes.rs:68:5 | 68 | pub fn top(radius: f32) -> Self { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn top(radius: f32) -> Self` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#must_use_candidate

Check failure on line 68 in src/shapes.rs

View workflow job for this annotation

GitHub Actions / clippy

this method could have a `#[must_use]` attribute

error: this method could have a `#[must_use]` attribute --> src/shapes.rs:68:5 | 68 | pub fn top(radius: f32) -> Self { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn top(radius: f32) -> Self` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#must_use_candidate
Self {
top_left: radius,
top_right: radius,
..Default::default()
}
}

/// Use a single radius for the bottom corners and zero for the top corners.
pub fn bottom(radius: f32) -> Self {

Check failure on line 77 in src/shapes.rs

View workflow job for this annotation

GitHub Actions / clippy

this method could have a `#[must_use]` attribute

error: this method could have a `#[must_use]` attribute --> src/shapes.rs:77:5 | 77 | pub fn bottom(radius: f32) -> Self { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn bottom(radius: f32) -> Self` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#must_use_candidate

Check failure on line 77 in src/shapes.rs

View workflow job for this annotation

GitHub Actions / clippy

this method could have a `#[must_use]` attribute

error: this method could have a `#[must_use]` attribute --> src/shapes.rs:77:5 | 77 | pub fn bottom(radius: f32) -> Self { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn bottom(radius: f32) -> Self` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#must_use_candidate
Self {
bottom_left: radius,
bottom_right: radius,
..Default::default()
}
}

/// Use a single radius for the left corners and zero for the right corners.
pub fn left(radius: f32) -> Self {

Check failure on line 86 in src/shapes.rs

View workflow job for this annotation

GitHub Actions / clippy

this method could have a `#[must_use]` attribute

error: this method could have a `#[must_use]` attribute --> src/shapes.rs:86:5 | 86 | pub fn left(radius: f32) -> Self { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn left(radius: f32) -> Self` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#must_use_candidate

Check failure on line 86 in src/shapes.rs

View workflow job for this annotation

GitHub Actions / clippy

this method could have a `#[must_use]` attribute

error: this method could have a `#[must_use]` attribute --> src/shapes.rs:86:5 | 86 | pub fn left(radius: f32) -> Self { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn left(radius: f32) -> Self` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#must_use_candidate
Self {
top_left: radius,
bottom_left: radius,
..Default::default()
}
}

/// Use a single radius for the right corners and zero for the left corners.
pub fn right(radius: f32) -> Self {

Check failure on line 95 in src/shapes.rs

View workflow job for this annotation

GitHub Actions / clippy

this method could have a `#[must_use]` attribute

error: this method could have a `#[must_use]` attribute --> src/shapes.rs:95:5 | 95 | pub fn right(radius: f32) -> Self { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn right(radius: f32) -> Self` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#must_use_candidate

Check failure on line 95 in src/shapes.rs

View workflow job for this annotation

GitHub Actions / clippy

this method could have a `#[must_use]` attribute

error: this method could have a `#[must_use]` attribute --> src/shapes.rs:95:5 | 95 | pub fn right(radius: f32) -> Self { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn right(radius: f32) -> Self` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#must_use_candidate
Self {
top_right: radius,
bottom_right: radius,
..Default::default()
}
}
}

impl From<BorderRadii> for LyonBorderRadii {
fn from(source: BorderRadii) -> Self {
// swap top and bottom
LyonBorderRadii {

Check failure on line 107 in src/shapes.rs

View workflow job for this annotation

GitHub Actions / clippy

unnecessary structure name repetition

error: unnecessary structure name repetition --> src/shapes.rs:107:9 | 107 | LyonBorderRadii { | ^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#use_self = note: `-D clippy::use-self` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::use_self)]`

Check failure on line 107 in src/shapes.rs

View workflow job for this annotation

GitHub Actions / clippy

unnecessary structure name repetition

error: unnecessary structure name repetition --> src/shapes.rs:107:9 | 107 | LyonBorderRadii { | ^^^^^^^^^^^^^^^ help: use the applicable keyword: `Self` | = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#use_self = note: `-D clippy::use-self` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::use_self)]`
top_left: source.bottom_left.abs(),
top_right: source.bottom_right.abs(),
bottom_left: source.top_left.abs(),
bottom_right: source.top_right.abs(),
}
}
}

#[allow(missing_docs)]
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Rectangle {
pub extents: Vec2,
pub origin: RectangleOrigin,
pub radii: Option<BorderRadii>,
}

impl Default for Rectangle {
fn default() -> Self {
Self {
extents: Vec2::ONE,
origin: RectangleOrigin::default(),
radii: None,
}
}
}
Expand All @@ -66,11 +143,13 @@ impl Geometry for Rectangle {
Point::new(v.x - self.extents.x / 2.0, v.y - self.extents.y / 2.0)
}
};

b.add_rectangle(
&Box2D::from_origin_and_size(origin, Size2D::new(self.extents.x, self.extents.y)),
Winding::Positive,
);
let rect =
&Box2D::from_origin_and_size(origin, Size2D::new(self.extents.x, self.extents.y));
let Some(radii) = self.radii else {
b.add_rectangle(rect, Winding::Positive);
return;
};
b.add_rounded_rectangle(rect, &radii.into(), Winding::Positive);
}
}

Expand Down

0 comments on commit b434b7d

Please sign in to comment.