//! This example illustrates how to create a button that changes color and text based on its
//! interaction state.
use std::f32::consts::PI;
use bevy::{color::palettes::basic::*, prelude::*, winit::WinitSettings};
fn main() {
App::new()
.add_plugins(DefaultPlugins)
// Only run the app when there is user input. This will significantly reduce CPU/GPU use.
.insert_resource(WinitSettings::desktop_app())
.add_systems(Startup, setup)
.add_systems(Update, button_system)
.run();
}
const NORMAL_BUTTON: Color = Color::srgb(0.15, 0.15, 0.15);
const HOVERED_BUTTON: Color = Color::srgb(0.25, 0.25, 0.25);
const PRESSED_BUTTON: Color = Color::srgb(0.35, 0.75, 0.35);
fn button_system(
mut interaction_query: Query<
(
&Interaction,
&mut BackgroundColor,
&mut BorderColor,
&Children,
),
(Changed<Interaction>, With<Button>),
>,
mut text_query: Query<&mut Text>,
) {
for (interaction, mut color, mut border_color, children) in &mut interaction_query {
let mut text = text_query.get_mut(children[0]).unwrap();
match *interaction {
Interaction::Pressed => {
**text = "Press".to_string();
*color = PRESSED_BUTTON.into();
border_color.0 = RED.into();
}
Interaction::Hovered => {
**text = "Hover".to_string();
*color = HOVERED_BUTTON.into();
border_color.0 = Color::WHITE;
}
Interaction::None => {
**text = "Button".to_string();
*color = NORMAL_BUTTON.into();
border_color.0 = Color::BLACK;
}
}
}
}
fn setup(mut commands: Commands, assets: Res<AssetServer>) {
// ui camera
commands.spawn(Camera2d);
commands.spawn(button(&assets));
}
fn button(asset_server: &AssetServer) -> impl Bundle + use<> {
(
Node {
width: Val::Percent(100.0),
height: Val::Percent(100.0),
align_items: AlignItems::Center,
justify_content: JustifyContent::Center,
..default()
},
children![(
Button,
Node {
width: Val::Px(150.0),
height: Val::Px(65.0),
border: UiRect::all(Val::Px(5.0)),
// horizontally center child text
justify_content: JustifyContent::Center,
// vertically center child text
align_items: AlignItems::Center,
..default()
},
Transform {
rotation: Quat::from_rotation_z(0.25 * PI),
..default()
},
BorderColor(Color::BLACK),
BorderRadius::MAX,
BackgroundColor(NORMAL_BUTTON),
children![(
Text::new("Button"),
TextFont {
font: asset_server.load("fonts/FiraSans-Bold.ttf"),
font_size: 33.0,
..default()
},
TextColor(Color::srgb(0.9, 0.9, 0.9)),
TextShadow::default(),
)]
)],
)
}
The button is drawn at angle, but it responds only when the pointer is over where it would be before the rotation is applied.
UI picking assumes that all UI nodes are axis aligned and unscaled.
It also makes similar assumptions with clipping.
Bevy version
0.16
What you did
Add a rotation to the button example
The button is drawn at angle, but it responds only when the pointer is over where it would be before the rotation is applied.
What went wrong
UI picking assumes that all UI nodes are axis aligned and unscaled.
It also makes similar assumptions with clipping.