diff --git a/src/intro.rs b/src/intro.rs index 1fd2ba5..6e1100b 100644 --- a/src/intro.rs +++ b/src/intro.rs @@ -7,32 +7,38 @@ pub(crate) struct IntroPlugin; impl Plugin for IntroPlugin { fn build(&self, app: &mut App) { app.init_resource::() - .add_systems( - OnExit(GameState::Loading), - init_intro_text - .run_if(resource_exists::()) - .run_if(run_once()), - ) - .add_systems(OnEnter(GameState::Intro), manage_intro) - .add_systems(OnExit(GameState::Intro), (deactivate::, cleanup_intro)) - // All of these run during GameState::Intro - .add_systems( - Update, - ( - menu::exit_to_menu, - manage_intro.run_if(any_component_removed::()), - // Started when the TextScrollAnimation component is added to the parent entity - // Updated for as long as there is scrolling text - manage_scroll_text_animation - .run_if(any_component_added::.or_else( - |keys: Res>| -> bool { keys.just_pressed(KeyCode::Return) }, - )), - // Play intro manages playing the intro of each individual paragraph - // Runs every time the TextScroll component (managed by manage_scroll_text_animation) is updated - scroll_text - .run_if(any_with_component::()), - ).run_if(in_state(GameState::Intro)) - ); + .add_systems( + OnExit(GameState::Loading), + init_intro_text + .run_if(resource_exists::()) + .run_if(run_once()), + ) + .add_systems(OnEnter(GameState::Intro), manage_intro) + .add_systems( + OnExit(GameState::Intro), + (deactivate::, cleanup_intro), + ) + // All of these run during GameState::Intro + .add_systems( + Update, + ( + menu::exit_to_menu, + manage_intro.run_if(any_component_removed::()), + // Started when the TextScrollAnimation component is added to the parent entity + // Updated for as long as there is scrolling text + manage_scroll_text_animation.run_if( + any_component_added::.or_else( + |keys: Res>| -> bool { + keys.just_pressed(KeyCode::Return) + }, + ), + ), + // Play intro manages playing the intro of each individual paragraph + // Runs every time the TextScroll component (managed by manage_scroll_text_animation) is updated + scroll_text.run_if(any_with_component::()), + ) + .run_if(in_state(GameState::Intro)), + ); } } @@ -144,9 +150,13 @@ fn cleanup_intro( info!("Cleaning up intro"); query.iter().for_each(|e| { - commands.entity(e).remove::().remove::().insert(Visibility::Hidden); + commands + .entity(e) + .remove::() + .remove::() + .insert(Visibility::Hidden); }); - + { // Reset text colors let tweak = tweaks.get(tweaks_file.handle.clone()).expect("Load tweaks"); @@ -166,7 +176,13 @@ fn cleanup_intro( struct CurrentIntroParagraph(Option); fn manage_scroll_text_animation( - roots: Query, Added)>>, + roots: Query< + Entity, + Or<( + With, + Added, + )>, + >, texts: Query, With)>, animated_texts: Query<&ui::TextScroll>, parents: Query<&Parent>, diff --git a/src/main.rs b/src/main.rs index 9e1dbc7..59fae68 100644 --- a/src/main.rs +++ b/src/main.rs @@ -97,6 +97,7 @@ fn activate( ), >, ) { + info!("Activating state"); entities.iter_mut().for_each(|mut visibility| { *visibility = Visibility::Visible; }); diff --git a/src/menu.rs b/src/menu.rs index 48ac676..b56c74a 100644 --- a/src/menu.rs +++ b/src/menu.rs @@ -13,11 +13,10 @@ impl Plugin for MenuPlugin { .add_systems( Update, ( - handle_menu_button::, - handle_menu_quit, - bevy::window::close_on_esc, - ) - .run_if(in_state(GameState::Menu)), + handle_menu_button::, // Run in all states + handle_menu_quit.run_if(in_state(GameState::Menu)), + bevy::window::close_on_esc.run_if(in_state(GameState::Menu)), + ), ) .add_systems( OnEnter(GameState::Menu), @@ -88,35 +87,6 @@ fn init_menu_ui(mut commands: Commands) { )); }); - parent - .spawn(( - GameState::Play, - tutorial::TutorialState::Intro, - ButtonBundle { - style: Style { - padding: UiRect::all(Val::Px(5.0)), - margin: UiRect::all(Val::Px(5.0)), - ..default() - }, - background_color: Color::ORANGE.with_a(0.5).into(), - ..default() - }, - )) - .with_children(|parent| { - parent.spawn(( - GameState::Play, - tutorial::TutorialState::Intro, - TextBundle::from_section( - "Tutorial", - TextStyle { - color: Color::BLACK, - font_size: 32.0, - ..default() - }, - ), - )); - }); - parent .spawn(( GameState::Credits, diff --git a/src/tutorial.rs b/src/tutorial.rs index 121ca47..4b0c4d6 100644 --- a/src/tutorial.rs +++ b/src/tutorial.rs @@ -16,7 +16,7 @@ impl Plugin for TutorialPlugin { ) .add_systems( Update, - menu::handle_menu_button::.run_if(in_state(GameState::Menu)), + menu::handle_menu_button::.run_if(in_state(GameState::Play)), ) .add_systems( Update, @@ -39,10 +39,7 @@ impl Plugin for TutorialPlugin { ), ) .add_systems(OnExit(GameState::Play), deactivate::) - .add_systems( - OnEnter(GameState::Play), - activate_tutorial_step.run_if(state_exists::()), - ) + .add_systems(OnEnter(GameState::Play), activate::) .add_systems( Update, activate_tutorial_step.run_if(state_changed::()), @@ -50,6 +47,9 @@ impl Plugin for TutorialPlugin { } } +#[derive(Debug, States, Hash, Default, PartialEq, Eq, Clone, Component)] +pub(crate) struct Tutorial; + #[derive(Debug, States, Hash, Default, PartialEq, Eq, Clone, Component)] pub(crate) enum TutorialState { #[default] @@ -84,6 +84,39 @@ fn initialize_tutorial( info!("Initializing tutorial entities"); + // Tutorial button used for toggling on/off during gameplay + { + commands + .spawn(( + TutorialState::Intro, // Marks the button to start the tutorial + Tutorial, // Marks the button for activate:: + GameState::Play, // Marks the button to be ignored during tutorial step cleanup + ButtonBundle { + style: Style { + padding: UiRect::all(Val::Px(5.0)), + margin: UiRect::all(Val::Px(5.0)), + position_type: PositionType::Absolute, + top: Val::Px(0.0), + right: Val::Px(0.0), + ..default() + }, + background_color: Color::ORANGE.with_a(0.5).into(), + visibility: Visibility::Hidden, + ..default() + }, + )) + .with_children(|parent| { + parent.spawn((TextBundle::from_section( + "Tutorial", + TextStyle { + color: Color::BLACK, + font_size: 16.0, + ..default() + }, + ),)); + }); + } + let background_hex = tweak.get::("tutorial_rgba_background").unwrap(); let text_visible_hex = tweak.get::("tutorial_rgba_visible").unwrap();