Skip to content

Commit

Permalink
Allow timers to be paused and encapsulate fields (#914)
Browse files Browse the repository at this point in the history
Allow timers to be paused and encapsulate fields
  • Loading branch information
ambeeeeee authored Nov 26, 2020
1 parent 8e4eb41 commit f69cc6f
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 24 deletions.
1 change: 0 additions & 1 deletion crates/bevy_core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ impl Plugin for CorePlugin {
.register_property::<Quat>()
.register_property::<Option<String>>()
.add_system_to_stage(stage::FIRST, time_system)
.add_system_to_stage(stage::FIRST, timer_system)
.add_system_to_stage(stage::PRE_UPDATE, entity_labels_system);
}
}
86 changes: 70 additions & 16 deletions crates/bevy_core/src/time/timer.rs
Original file line number Diff line number Diff line change
@@ -1,23 +1,21 @@
use crate::time::Time;
use bevy_ecs::prelude::*;
use bevy_property::Properties;
use bevy_utils::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.
///
/// Paused timers will not have elapsed time increased.
#[derive(Clone, Debug, Default, Properties)]
pub struct Timer {
/// Time elapsed on the timer. Guaranteed to be between 0.0 and `duration`, inclusive.
pub elapsed: f32,
pub duration: f32,
/// 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.
pub finished: bool,
elapsed: f32,
duration: f32,
finished: bool,
/// Will only be true on the tick `duration` is reached or exceeded.
pub just_finished: bool,
pub repeating: bool,
just_finished: bool,
paused: bool,
repeating: bool,
}

impl Timer {
Expand All @@ -37,6 +35,67 @@ impl Timer {
}
}

#[inline]
pub fn pause(&mut self) {
self.paused = true
}

#[inline]
pub fn resume(&mut self) {
self.paused = false
}

#[inline]
pub fn is_paused(&self) -> bool {
self.paused
}

/// Returns the time elapsed on the timer. Guaranteed to be between 0.0 and `duration`, inclusive.
#[inline]
pub fn elapsed(&self) -> f32 {
self.elapsed
}

#[inline]
pub fn set_elapsed(&mut self, elapsed: f32) {
self.elapsed = elapsed
}

#[inline]
pub fn duration(&self) -> f32 {
self.duration
}

#[inline]
pub fn set_duration(&mut self, duration: f32) {
self.duration = duration
}

/// Returns the finished state of the timer.
///
/// 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.
#[inline]
pub fn is_finished(&self) -> bool {
self.finished
}

/// Will only be true on the tick the timer's duration is reached or exceeded.
#[inline]
pub fn just_finished(&self) -> bool {
self.just_finished
}

#[inline]
pub fn is_repeating(&self) -> bool {
self.repeating
}

#[inline]
pub fn set_repeating(&mut self, repeating: bool) {
self.repeating = repeating
}

/// Advances the timer by `delta` seconds.
pub fn tick(&mut self, delta: f32) -> &Self {
let prev_finished = self.finished;
Expand All @@ -56,6 +115,7 @@ impl Timer {
self
}

#[inline]
pub fn reset(&mut self) {
self.finished = false;
self.just_finished = false;
Expand All @@ -73,12 +133,6 @@ impl Timer {
}
}

pub(crate) fn timer_system(time: Res<Time>, mut query: Query<&mut Timer>) {
for mut timer in query.iter_mut() {
timer.tick(time.delta_seconds);
}
}

#[cfg(test)]
mod tests {
use super::Timer;
Expand Down
4 changes: 2 additions & 2 deletions crates/bevy_diagnostic/src/print_diagnostics_plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ impl PrintDiagnosticsPlugin {
time: Res<Time>,
diagnostics: Res<Diagnostics>,
) {
if state.timer.tick(time.delta_seconds).finished {
if state.timer.tick(time.delta_seconds).is_finished() {
println!("Diagnostics:");
println!("{}", "-".repeat(93));
if let Some(ref filter) = state.filter {
Expand All @@ -86,7 +86,7 @@ impl PrintDiagnosticsPlugin {
time: Res<Time>,
diagnostics: Res<Diagnostics>,
) {
if state.timer.tick(time.delta_seconds).finished {
if state.timer.tick(time.delta_seconds).is_finished() {
println!("Diagnostics (Debug):");
println!("{}", "-".repeat(93));
if let Some(ref filter) = state.filter {
Expand Down
2 changes: 1 addition & 1 deletion examples/2d/contributors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ fn select_system(
) {
let mut timer_fired = false;
for mut t in tq.iter_mut() {
if !t.just_finished {
if !t.just_finished() {
continue;
}
t.reset();
Expand Down
2 changes: 1 addition & 1 deletion examples/2d/sprite_sheet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ fn animate_sprite_system(
mut query: Query<(&mut Timer, &mut TextureAtlasSprite, &Handle<TextureAtlas>)>,
) {
for (timer, mut sprite, texture_atlas_handle) in query.iter_mut() {
if timer.finished {
if timer.is_finished() {
let texture_atlas = texture_atlases.get(texture_atlas_handle).unwrap();
sprite.index = ((sprite.index as usize + 1) % texture_atlas.textures.len()) as u32;
}
Expand Down
2 changes: 1 addition & 1 deletion examples/app/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ struct PrintMessageState {
}

fn print_message_system(mut state: ResMut<PrintMessageState>, time: Res<Time>) {
if state.timer.tick(time.delta_seconds).finished {
if state.timer.tick(time.delta_seconds).is_finished() {
println!("{}", state.message);
}
}
2 changes: 1 addition & 1 deletion examples/ecs/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ fn event_trigger_system(
mut state: ResMut<EventTriggerState>,
mut my_events: ResMut<Events<MyEvent>>,
) {
if state.event_timer.tick(time.delta_seconds).finished {
if state.event_timer.tick(time.delta_seconds).is_finished() {
my_events.send(MyEvent {
message: "MyEvent just happened!".to_string(),
});
Expand Down
2 changes: 1 addition & 1 deletion examples/ui/font_atlas_debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ fn atlas_render_system(
}

fn text_update_system(mut state: ResMut<State>, time: Res<Time>, mut query: Query<&mut Text>) {
if state.timer.tick(time.delta_seconds).finished {
if state.timer.tick(time.delta_seconds).is_finished() {
for mut text in query.iter_mut() {
let c = rand::random::<u8>() as char;
if !text.value.contains(c) {
Expand Down

0 comments on commit f69cc6f

Please sign in to comment.