//! Generic types allow us to reuse logic across many related systems, //! allowing us to specialize our function's behavior based on which type (or types) are passed in. //! //! This is commonly useful for working on related components or resources, //! where we want to have unique types for querying purposes but want them all to work the same way. //! This is particularly powerful when combined with user-defined traits to add more functionality to these related types. //! Remember to insert a specialized copy of the system into the schedule for each type that you want to operate on! //! //! For more advice on working with generic types in Rust, check out //! or use bevy::prelude::*; #[derive(Debug, Default, Clone, Copy, Eq, PartialEq, Hash)] enum AppState { #[default] MainMenu, InGame, } impl States for AppState { type Iter = std::array::IntoIter; fn variants() -> Self::Iter { [AppState::MainMenu, AppState::InGame].into_iter() } } #[derive(Component)] struct TextToPrint(String); #[derive(Component, Deref, DerefMut)] struct PrinterTick(Timer); #[derive(Component)] struct MenuClose; #[derive(Component)] struct LevelUnload; fn main() { App::new() .add_plugins(DefaultPlugins) .add_state::() .add_startup_system(setup_system) .add_system(print_text_system) .add_system(transition_to_in_game_system.in_set(OnUpdate(AppState::MainMenu))) // add the cleanup systems .add_system_to_schedule( OnExit(AppState::MainMenu), // Pass in the types your system should operate on using the :: (turbofish) syntax cleanup_system::, ) .add_system_to_schedule(OnExit(AppState::InGame), cleanup_system::) .run(); } fn setup_system(mut commands: Commands) { commands.spawn(( PrinterTick(Timer::from_seconds(1.0, TimerMode::Repeating)), TextToPrint("I will print until you press space.".to_string()), MenuClose, )); commands.spawn(( PrinterTick(Timer::from_seconds(1.0, TimerMode::Repeating)), TextToPrint("I will always print".to_string()), LevelUnload, )); } fn print_text_system(time: Res