use bevy::prelude::*; fn main() { App::build() .add_default_plugins() .init_resource::() .add_startup_system(setup.system()) .add_system(button_system.system()) .run(); } struct ButtonMaterials { normal: Handle, hovered: Handle, pressed: Handle, } impl FromResources for ButtonMaterials { fn from_resources(resources: &Resources) -> Self { let mut materials = resources.get_mut::>().unwrap(); ButtonMaterials { normal: materials.add(Color::rgb(0.02, 0.02, 0.02).into()), hovered: materials.add(Color::rgb(0.05, 0.05, 0.05).into()), pressed: materials.add(Color::rgb(0.1, 0.5, 0.1).into()), } } } fn button_system( button_materials: Res, mut click_query: Query<( &Button, Mutated, Option<&Hover>, &mut Handle, &Children, )>, mut hover_query: Query<( &Button, Mutated, Option<&Click>, &mut Handle, &Children, )>, text_query: Query<&mut Text>, ) { for (_button, hover, click, mut material, children) in &mut hover_query.iter() { let mut text = text_query.get_mut::(children[0]).unwrap(); match *hover { Hover::Hovered => { if let Some(Click::Released) = click { text.value = "Hover".to_string(); *material = button_materials.hovered; } } Hover::NotHovered => { if let Some(Click::Pressed) = click { text.value = "Press".to_string(); *material = button_materials.pressed; } else { text.value = "Button".to_string(); *material = button_materials.normal; } } } } for (_button, click, hover, mut material, children) in &mut click_query.iter() { let mut text = text_query.get_mut::(children[0]).unwrap(); match *click { Click::Pressed => { text.value = "Press".to_string(); *material = button_materials.pressed; } Click::Released => { if let Some(Hover::Hovered) = hover { text.value = "Hover".to_string(); *material = button_materials.hovered; } else { text.value = "Button".to_string(); *material = button_materials.normal; } } } } } fn setup( mut commands: Commands, mut materials: ResMut>, asset_server: Res, button_materials: Res, ) { commands // ui camera .spawn(UiCameraComponents::default()) // wrapper component to center with flexbox .spawn(NodeComponents { flex: Flex { size: Size { width: Dimension::Percent(1.0), height: Dimension::Percent(1.0), }, align_items: AlignItems::Center, justify_content: JustifyContent::Center, ..Default::default() }, material: materials.add(Color::NONE.into()), ..Default::default() }) .with_children(|parent| { parent .spawn(ButtonComponents { flex: Flex { size: Size { width: Dimension::Points(150.0), height: Dimension::Points(70.0), }, ..Default::default() }, material: button_materials.normal, ..Default::default() }) .with_children(|parent| { parent.spawn(TextComponents { flex: Flex { size: Size { width: Dimension::Percent(1.0), height: Dimension::Percent(1.0), }, margin: Rect { top: Dimension::Points(10.0), ..Default::default() }, ..Default::default() }, text: Text { value: "Button".to_string(), font: asset_server.load("assets/fonts/FiraSans-Bold.ttf").unwrap(), style: TextStyle { font_size: 40.0, color: Color::rgb(0.8, 0.8, 0.8), align: TextAlign::Center, }, }, ..Default::default() }); }); }); }