use bevy::prelude::*; use crate::state::AppState; // ── Markers ───────────────────────────────────────────────────────────────── #[derive(Component)] pub struct MainMenuUi; #[derive(Component)] pub enum MenuButton { ContinueGame, //Needed for later once save game functionality is implemented, should have a check to see if a save game exists and only show this button if it does NewGame, Options, Exit, } // ── Main Menu ─────────────────────────────────────────────────────────────── pub fn setup_main_menu(mut commands: Commands) { let button_style = Node { width: Val::Px(280.0), height: Val::Px(64.0), justify_content: JustifyContent::Center, align_items: AlignItems::Center, ..default() }; let button_text_font = TextFont { font_size: 28.0, ..default() }; commands .spawn(( Node { width: Val::Percent(100.0), height: Val::Percent(100.0), display: Display::Flex, flex_direction: FlexDirection::Column, justify_content: JustifyContent::Center, align_items: AlignItems::Center, row_gap: Val::Px(24.0), ..default() }, BackgroundColor(Color::srgb(0.02, 0.02, 0.06)), MainMenuUi, )) .with_children(|parent| { // Title parent.spawn(( Text::new("VOID::NAV"), TextFont { font_size: 72.0, ..default() }, TextColor(Color::srgb(0.7, 0.85, 1.0)), Node { margin: UiRect::bottom(Val::Px(48.0)), ..default() }, )); // Subtitle parent.spawn(( Text::new("A space exploration RPG"), TextFont { font_size: 18.0, ..default() }, TextColor(Color::srgb(0.4, 0.5, 0.6)), Node { margin: UiRect::bottom(Val::Px(32.0)), ..default() }, )); // Start Game button spawn_menu_button( &mut parent.spawn_empty(), "Start Game", MenuButton::NewGame, &button_style, &button_text_font, ); // Options button spawn_menu_button( &mut parent.spawn_empty(), "Options", MenuButton::Options, &button_style, &button_text_font, ); // Exit button spawn_menu_button( &mut parent.spawn_empty(), "Exit", MenuButton::Exit, &button_style, &button_text_font, ); }); } fn spawn_menu_button( cmd: &mut EntityCommands, label: &str, marker: MenuButton, style: &Node, text_font: &TextFont, ) { cmd.insert(( Button, style.clone(), BackgroundColor(Color::srgb(0.08, 0.1, 0.18)), BorderColor(Color::srgb(0.3, 0.45, 0.7)), BorderRadius::all(Val::Px(8.0)), marker, )) .with_children(|btn| { btn.spawn(( Text::new(label), text_font.clone(), TextColor(Color::srgb(0.75, 0.85, 1.0)), )); }); } pub fn despawn_main_menu(mut commands: Commands, query: Query>) { for entity in &query { commands.entity(entity).despawn(); } } // ── Button Interaction ────────────────────────────────────────────────────── pub fn main_menu_buttons( mut next_state: ResMut>, mut exit: EventWriter, interaction_query: Query<(&Interaction, &MenuButton), Changed>, ) { for (interaction, button) in &interaction_query { if *interaction == Interaction::Pressed { match button { MenuButton::ContinueGame => next_state.set(AppState::InGame), // Placeholder for now MenuButton::NewGame => next_state.set(AppState::Galaxy), MenuButton::Options => next_state.set(AppState::Options), MenuButton::Exit => { exit.write(AppExit::Success); } } } } }