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