ui_material/
ui_material.rs1use bevy::{
4 color::palettes::css::DARK_BLUE, prelude::*, reflect::TypePath, render::render_resource::*,
5 shader::ShaderRef,
6};
7
8const SHADER_ASSET_PATH: &str = "shaders/custom_ui_material.wgsl";
10
11fn main() {
12 App::new()
13 .add_plugins(DefaultPlugins)
14 .add_plugins(UiMaterialPlugin::<CustomUiMaterial>::default())
15 .add_systems(Startup, setup)
16 .add_systems(Update, animate)
17 .run();
18}
19
20fn setup(
21 mut commands: Commands,
22 mut ui_materials: ResMut<Assets<CustomUiMaterial>>,
23 asset_server: Res<AssetServer>,
24) {
25 commands.spawn(Camera2d);
27
28 commands
29 .spawn(Node {
30 width: percent(100),
31 height: percent(100),
32 align_items: AlignItems::Center,
33 justify_content: JustifyContent::Center,
34 ..default()
35 })
36 .with_children(|parent| {
37 let banner_scale_factor = 0.5;
38 parent.spawn((
39 Node {
40 position_type: PositionType::Absolute,
41 width: px(905.0 * banner_scale_factor),
42 height: px(363.0 * banner_scale_factor),
43 border: UiRect::all(px(20)),
44 ..default()
45 },
46 MaterialNode(ui_materials.add(CustomUiMaterial {
47 color: LinearRgba::WHITE.to_f32_array().into(),
48 slider: Vec4::splat(0.5),
49 color_texture: asset_server.load("branding/banner.png"),
50 border_color: LinearRgba::WHITE.to_f32_array().into(),
51 })),
52 BorderRadius::all(px(20)),
53 Outline {
55 width: px(2),
56 offset: px(100),
57 color: DARK_BLUE.into(),
58 },
59 ));
60 });
61}
62
63#[derive(AsBindGroup, Asset, TypePath, Debug, Clone)]
64struct CustomUiMaterial {
65 #[uniform(0)]
67 color: Vec4,
68 #[uniform(1)]
72 slider: Vec4,
73 #[texture(2)]
75 #[sampler(3)]
76 color_texture: Handle<Image>,
77 #[uniform(4)]
79 border_color: Vec4,
80}
81
82impl UiMaterial for CustomUiMaterial {
83 fn fragment_shader() -> ShaderRef {
84 SHADER_ASSET_PATH.into()
85 }
86}
87
88fn animate(
91 mut materials: ResMut<Assets<CustomUiMaterial>>,
92 q: Query<&MaterialNode<CustomUiMaterial>>,
93 time: Res<Time>,
94) {
95 let duration = 2.0;
96 for handle in &q {
97 if let Some(material) = materials.get_mut(handle) {
98 let new_color = Color::hsl((time.elapsed_secs() * 60.0) % 360.0, 1., 0.5);
100 let border_color = Color::hsl((time.elapsed_secs() * 60.0) % 360.0, 0.75, 0.75);
101 material.color = new_color.to_linear().to_vec4();
102 material.slider.x =
103 ((time.elapsed_secs() % (duration * 2.0)) - duration).abs() / duration;
104 material.border_color = border_color.to_linear().to_vec4();
105 }
106 }
107}