button/
button.rs

1//! This example illustrates how to create a button that changes color and text based on its
2//! interaction state.
3
4use bevy::{color::palettes::basic::*, prelude::*, winit::WinitSettings};
5
6fn main() {
7    App::new()
8        .add_plugins(DefaultPlugins)
9        // Only run the app when there is user input. This will significantly reduce CPU/GPU use.
10        .insert_resource(WinitSettings::desktop_app())
11        .add_systems(Startup, setup)
12        .add_systems(Update, button_system)
13        .run();
14}
15
16const NORMAL_BUTTON: Color = Color::srgb(0.15, 0.15, 0.15);
17const HOVERED_BUTTON: Color = Color::srgb(0.25, 0.25, 0.25);
18const PRESSED_BUTTON: Color = Color::srgb(0.35, 0.75, 0.35);
19
20fn button_system(
21    mut interaction_query: Query<
22        (
23            &Interaction,
24            &mut BackgroundColor,
25            &mut BorderColor,
26            &Children,
27        ),
28        (Changed<Interaction>, With<Button>),
29    >,
30    mut text_query: Query<&mut Text>,
31) {
32    for (interaction, mut color, mut border_color, children) in &mut interaction_query {
33        let mut text = text_query.get_mut(children[0]).unwrap();
34        match *interaction {
35            Interaction::Pressed => {
36                **text = "Press".to_string();
37                *color = PRESSED_BUTTON.into();
38                border_color.0 = RED.into();
39            }
40            Interaction::Hovered => {
41                **text = "Hover".to_string();
42                *color = HOVERED_BUTTON.into();
43                border_color.0 = Color::WHITE;
44            }
45            Interaction::None => {
46                **text = "Button".to_string();
47                *color = NORMAL_BUTTON.into();
48                border_color.0 = Color::BLACK;
49            }
50        }
51    }
52}
53
54fn setup(mut commands: Commands, assets: Res<AssetServer>) {
55    // ui camera
56    commands.spawn(Camera2d);
57    commands.spawn(button(&assets));
58}
59
60fn button(asset_server: &AssetServer) -> impl Bundle + use<> {
61    (
62        Node {
63            width: Val::Percent(100.0),
64            height: Val::Percent(100.0),
65            align_items: AlignItems::Center,
66            justify_content: JustifyContent::Center,
67            ..default()
68        },
69        children![(
70            Button,
71            Node {
72                width: Val::Px(150.0),
73                height: Val::Px(65.0),
74                border: UiRect::all(Val::Px(5.0)),
75                // horizontally center child text
76                justify_content: JustifyContent::Center,
77                // vertically center child text
78                align_items: AlignItems::Center,
79                ..default()
80            },
81            BorderColor(Color::BLACK),
82            BorderRadius::MAX,
83            BackgroundColor(NORMAL_BUTTON),
84            children![(
85                Text::new("Button"),
86                TextFont {
87                    font: asset_server.load("fonts/FiraSans-Bold.ttf"),
88                    font_size: 33.0,
89                    ..default()
90                },
91                TextColor(Color::srgb(0.9, 0.9, 0.9)),
92                TextShadow::default(),
93            )]
94        )],
95    )
96}