//! All the UI elements for the Pong game client. use bevy::{ color::palettes::css::{DARK_GRAY, GRAY}, prelude::*, }; use crate::GameState; pub const BTN_BORDER_COLOR: Color = Color::WHITE; pub const BTN_BG_COLOR: Color = Color::BLACK; pub const BTN_BG_SELECTED: Color = bevy::prelude::Color::Srgba(DARK_GRAY); pub fn spawn_main_menu(mut commands: Commands) { commands .spawn((Node { width: Val::Percent(100.0), height: Val::Percent(100.0), align_items: AlignItems::Center, justify_content: JustifyContent::Center, flex_direction: FlexDirection::Column, ..Default::default() },)) .with_children(|cmds| { cmds.spawn(( // TODO: A more sharp and square font, maybe "pixel art" bitmap // to really get the chunky feel of Pong. Text::new("Robert's Bad Pong Game"), TextFont::from_font_size(50.0), TextLayout::new_with_justify(Justify::Center), TextShadow::default(), )); let mut start_button = cmds.spawn(button_bundle("Start game")); start_button.observe( |_trigger: On>, mut game_state: ResMut>| { game_state.set(GameState::Connecting); }, ); let mut quit_button = cmds.spawn(button_bundle("Quit Game")); quit_button.observe( |_trigger: On>, mut messages: MessageWriter| { // Quit the game if the quit button was pressed. messages.write(AppExit::Success); }, ); }); } /// Despawns the main menu (which is assumed to be the top-most node) /// /// TODO: Add a marker component, but only in debug builds. A unit test can /// assert this condition so I don't actually have to check it at runtime /// on release builds. pub fn despawn_main_menu( mut commands: Commands, top_node: Single, Without)>, ) { commands.entity(top_node.into_inner()).despawn(); } pub fn spawn_connection_wait_screen(mut commands: Commands) { info!("Spawning connecting notice."); commands.spawn(( Node { width: Val::Percent(100.0), height: Val::Percent(100.0), align_items: AlignItems::Center, justify_content: JustifyContent::Center, flex_direction: FlexDirection::Column, ..Default::default() }, children![Text::new("Connecting...")], )); } pub fn despawn_connection_wait_screen( mut commands: Commands, text_nodes: Single, With)>, ) { info!("Despawning connecting notice."); commands.entity(text_nodes.into_inner()).despawn(); } /// The basic bundle for generic buttons. /// /// It's mostly so I don't have to copy & paste this everywhere I want to use it. fn button_bundle(text: &str) -> impl Bundle { ( Button, Node { width: Val::Px(150.0), height: Val::Px(65.0), border: UiRect::all(Val::Px(4.0)), justify_content: JustifyContent::Center, align_items: AlignItems::Center, margin: UiRect::all(Val::Px(10.0)), ..Default::default() }, BorderColor::all(BTN_BORDER_COLOR), BorderRadius::ZERO, BackgroundColor(BTN_BG_COLOR), children![( Text::new(text), TextColor(GRAY.into()), TextShadow::default(), )], ) } pub fn button_hover_start( trigger: On>, mut button_colors: Query<(&mut BackgroundColor, &mut BorderColor), With