Skip to main content

bevy_round_ui/
round_rect.rs

1use bevy::{asset::load_internal_asset, prelude::*, render::render_resource::*};
2
3use crate::types::*;
4
5pub const ROUND_RECT_SHADER_HANDLE: Handle<Shader> = Handle::weak_from_u128(66552904175742639684);
6
7/// Plugin which adds a `RoundRectUiMaterial` to the app.
8pub struct RoundRectMaterialPlugin;
9
10impl Plugin for RoundRectMaterialPlugin {
11    fn build(&self, app: &mut App) {
12        load_internal_asset!(
13            app,
14            ROUND_RECT_SHADER_HANDLE,
15            "round_rect.wgsl",
16            Shader::from_wgsl
17        );
18
19        app.add_plugins(UiMaterialPlugin::<RoundRectUiMaterial>::default());
20    }
21}
22
23/// UI Material that renders a rounded rect with an optional offset color and position.
24#[derive(AsBindGroup, Asset, Debug, Clone, Reflect)]
25#[reflect(Default, Debug)]
26pub struct RoundRectUiMaterial {
27    /// The background color of the material
28    #[uniform(0)]
29    pub background_color: Color,
30
31    /// The border color of the material
32    #[uniform(0)]
33    pub border_color: Color,
34
35    /// The border radius of each corner
36    /// E.g. Vec4::new(bottom_right, top_right, bottom_left, top_left)
37    #[uniform(0)]
38    pub border_radius: Vec4,
39
40    /// The border offset along each side of the rect
41    /// E.g. Vec4::new((top, left, bottom, right)
42    #[uniform(0)]
43    pub offset: Vec4,
44}
45
46impl Default for RoundRectUiMaterial {
47    fn default() -> Self {
48        Self {
49            background_color: Color::WHITE,
50            border_color: Color::NONE,
51            border_radius: Vec4::splat(0.),
52            offset: Vec4::splat(0.),
53        }
54    }
55}
56
57impl UiMaterial for RoundRectUiMaterial {
58    fn fragment_shader() -> ShaderRef {
59        ROUND_RECT_SHADER_HANDLE.into()
60    }
61}
62
63impl RoundRectUiMaterial {
64    pub fn get_padding(&self) -> UiRect {
65        let offset: RoundUiOffset = self.offset.into();
66        let border: RoundUiBorder = self.border_radius.into();
67        UiRect {
68            left: Val::Px(offset.left + border.top_left.max(border.bottom_left)),
69            right: Val::Px(offset.right + border.top_right.max(border.bottom_right)),
70            top: Val::Px(offset.top + border.top_left.max(border.top_right)),
71            bottom: Val::Px(offset.bottom + border.bottom_left.max(border.bottom_right)),
72        }
73    }
74}