diff --git a/crates/bevy_core/src/time/timer.rs b/crates/bevy_core/src/time/timer.rs index 7322118e0558e..dcc3cac1019c8 100644 --- a/crates/bevy_core/src/time/timer.rs +++ b/crates/bevy_core/src/time/timer.rs @@ -4,37 +4,53 @@ use bevy_property::Properties; use std::time::Duration; /// Tracks elapsed time. Enters the finished state once `duration` is reached. +/// +/// Non repeating timers will stop tracking and stay in the finished state until reset. +/// Repeating timers will only be in the finished state on each tick `duration` is reached or exceeded, and can still be reset at any given point. #[derive(Clone, Debug, Default, Properties)] pub struct Timer { pub elapsed: f32, pub duration: f32, pub finished: bool, + /// Will only be true on the tick `duration` is reached or exceeded. + pub just_finished: bool, + pub repeating: bool, } impl Timer { - pub fn new(duration: Duration) -> Self { + pub fn new(duration: Duration, repeating: bool) -> Self { Timer { duration: duration.as_secs_f32(), + repeating, ..Default::default() } } - pub fn from_seconds(seconds: f32) -> Self { + pub fn from_seconds(seconds: f32, repeating: bool) -> Self { Timer { duration: seconds, + repeating, ..Default::default() } } pub fn tick(&mut self, delta: f32) { - self.elapsed = (self.elapsed + delta).min(self.duration); - if self.elapsed >= self.duration { - self.finished = true; + let prev_finished = self.elapsed >= self.duration; + if !prev_finished { + self.elapsed += delta; + } + + self.finished = self.elapsed >= self.duration; + self.just_finished = !prev_finished && self.finished; + + if self.repeating && self.finished { + self.elapsed %= self.duration; } } pub fn reset(&mut self) { self.finished = false; + self.just_finished = false; self.elapsed = 0.0; } } diff --git a/crates/bevy_diagnostic/src/print_diagnostics_plugin.rs b/crates/bevy_diagnostic/src/print_diagnostics_plugin.rs index 9409485e151e4..db7878ad3b22e 100644 --- a/crates/bevy_diagnostic/src/print_diagnostics_plugin.rs +++ b/crates/bevy_diagnostic/src/print_diagnostics_plugin.rs @@ -30,7 +30,7 @@ impl Default for PrintDiagnosticsPlugin { impl Plugin for PrintDiagnosticsPlugin { fn build(&self, app: &mut bevy_app::AppBuilder) { app.add_resource(PrintDiagnosticsState { - timer: Timer::new(self.wait_duration), + timer: Timer::new(self.wait_duration, true), filter: self.filter.clone(), }); @@ -82,8 +82,6 @@ impl PrintDiagnosticsPlugin { Self::print_diagnostic(diagnostic); } } - - state.timer.reset(); } } @@ -105,8 +103,6 @@ impl PrintDiagnosticsPlugin { println!("{:#?}\n", diagnostic); } } - - state.timer.reset(); } } } diff --git a/examples/2d/sprite_sheet.rs b/examples/2d/sprite_sheet.rs index 5fb37661b61ea..edc559718cbd6 100644 --- a/examples/2d/sprite_sheet.rs +++ b/examples/2d/sprite_sheet.rs @@ -12,11 +12,10 @@ fn animate_sprite_system( texture_atlases: Res>, mut query: Query<(&mut Timer, &mut TextureAtlasSprite, &Handle)>, ) { - for (mut timer, mut sprite, texture_atlas_handle) in &mut query.iter() { + for (timer, mut sprite, texture_atlas_handle) in &mut query.iter() { if timer.finished { let texture_atlas = texture_atlases.get(&texture_atlas_handle).unwrap(); sprite.index = ((sprite.index as usize + 1) % texture_atlas.textures.len()) as u32; - timer.reset(); } } } @@ -43,5 +42,5 @@ fn setup( scale: Scale(6.0), ..Default::default() }) - .with(Timer::from_seconds(0.1)); + .with(Timer::from_seconds(0.1, true)); } diff --git a/examples/app/plugin.rs b/examples/app/plugin.rs index 1fd8c80a0e9bd..c1d3e14140ec6 100644 --- a/examples/app/plugin.rs +++ b/examples/app/plugin.rs @@ -27,7 +27,7 @@ impl Plugin for PrintMessagePlugin { fn build(&self, app: &mut AppBuilder) { let state = PrintMessageState { message: self.message.clone(), - timer: Timer::new(self.wait_duration), + timer: Timer::new(self.wait_duration, true), }; app.add_resource(state) .add_system(print_message_system.system()); @@ -43,6 +43,5 @@ fn print_message_system(mut state: ResMut, time: Res