use bevy::prelude::*; use std::marker::PhantomData; use tomt_bevycss::prelude::*; #[derive(Clone, Copy, Debug, Default)] #[derive(PartialEq, Eq, Hash)] #[derive(States)] pub enum GameState { #[default] MainMenu, InGame, PauseMenu, } #[derive(Clone, Copy, Debug, Default)] #[derive(Resource, Reflect)] enum MainMenuSelection { #[default] None, NewGame, HighScores, Options, ExitGame, } impl std::fmt::Display for MainMenuSelection { fn fmt( &self, formatter: &mut std::fmt::Formatter<'_> ) -> std::fmt::Result { let msg = match *self { Self::None => "NONE", Self::NewGame => "New Game", Self::HighScores => "High Scores", Self::Options => "Options", Self::ExitGame => "Exit Game", }; write!(formatter, "{msg}",) } } #[derive(Clone, Debug, Default)] #[derive(PartialEq, Eq)] #[derive(Component)] pub struct SpawnedBy(PhantomData); const CLASS_MAIN_MENU: &str = "main-menu"; fn main( // no args ) { let mut app = App::new(); app.add_plugins(DefaultPlugins) .add_plugins(BevyCssPlugin::default()) .register_type::() .register_type::(); app.add_systems(Startup, spawn_camera); app.add_state::() .register_type::() .add_systems(OnEnter(GameState::MainMenu), enter_main_menu) .add_systems(OnExit(GameState::MainMenu), exit_main_menu); app.run(); } fn spawn_camera( mut commands: Commands ) { commands.spawn(Camera2dBundle::default()); } fn enter_main_menu( mut commands: Commands, asset_server: Res ) { commands.init_resource::(); // UI root entity (CSS attached here) commands.spawn(NodeBundle{ style: Style { width: Val::Percent(100.0), height: Val::Percent(100.0), ..default() }, ..default() }) .insert(( Name::new("root_ui"), SpawnedBy::::default(), StyleSheet::new(asset_server.load("sheets/menu.css")), Class::new(CLASS_MAIN_MENU), )) .with_children(|parent| { parent.spawn(NodeBundle { style: Style { flex_direction: FlexDirection::Column, align_items: AlignItems::Center, ..default() }, ..default() }) .with_children(|parent| { let mut spawn_btn = |action: MainMenuSelection| { parent.spawn(ButtonBundle::default()) .with_children(|parent| { parent.spawn(TextBundle::from_section( action.to_string(), TextStyle::default(), )); }); }; spawn_btn(MainMenuSelection::NewGame); spawn_btn(MainMenuSelection::HighScores); spawn_btn(MainMenuSelection::Options); spawn_btn(MainMenuSelection::ExitGame); }); }); } fn exit_main_menu( mut commands: Commands, query: Query>>, ) { commands.remove_resource::(); for entity in query.iter() { commands.entity(entity).despawn_recursive(); } }