Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Merged by Bors] - Replace the bool argument of Timer with TimerMode #6247

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions crates/bevy_diagnostic/src/log_diagnostics_plugin.rs
Expand Up @@ -2,7 +2,7 @@ use super::{Diagnostic, DiagnosticId, Diagnostics};
use bevy_app::prelude::*;
use bevy_ecs::system::{Res, ResMut, Resource};
use bevy_log::{debug, info};
use bevy_time::{Time, Timer};
use bevy_time::{Time, Timer, TimerMode};
use bevy_utils::Duration;

/// An App Plugin that logs diagnostics to the console
Expand Down Expand Up @@ -32,7 +32,7 @@ impl Default for LogDiagnosticsPlugin {
impl Plugin for LogDiagnosticsPlugin {
fn build(&self, app: &mut App) {
app.insert_resource(LogDiagnosticsState {
timer: Timer::new(self.wait_duration, true),
timer: Timer::new(self.wait_duration, TimerMode::Repeating),
filter: self.filter.clone(),
});

Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_time/src/lib.rs
Expand Up @@ -16,7 +16,7 @@ use crossbeam_channel::{Receiver, Sender};
pub mod prelude {
//! The Bevy Time Prelude.
#[doc(hidden)]
pub use crate::{Time, Timer};
pub use crate::{Time, Timer, TimerMode};
}

use bevy_app::prelude::*;
Expand Down
96 changes: 61 additions & 35 deletions crates/bevy_time/src/timer.rs
Expand Up @@ -14,7 +14,7 @@ use bevy_utils::Duration;
pub struct Timer {
stopwatch: Stopwatch,
duration: Duration,
repeating: bool,
mode: TimerMode,
finished: bool,
times_finished_this_tick: u32,
}
Expand All @@ -23,10 +23,10 @@ impl Timer {
/// Creates a new timer with a given duration.
///
/// See also [`Timer::from_seconds`](Timer::from_seconds).
pub fn new(duration: Duration, repeating: bool) -> Self {
pub fn new(duration: Duration, mode: TimerMode) -> Self {
Self {
duration,
repeating,
mode,
..Default::default()
}
}
Expand All @@ -36,12 +36,12 @@ impl Timer {
/// # Example
/// ```
/// # use bevy_time::*;
/// let mut timer = Timer::from_seconds(1.0, false);
/// let mut timer = Timer::from_seconds(1.0, TimerMode::Once);
/// ```
pub fn from_seconds(duration: f32, repeating: bool) -> Self {
pub fn from_seconds(duration: f32, mode: TimerMode) -> Self {
Self {
duration: Duration::from_secs_f32(duration),
repeating,
mode,
..Default::default()
}
}
Expand All @@ -52,7 +52,7 @@ impl Timer {
/// ```
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut timer = Timer::from_seconds(1.0, false);
/// let mut timer = Timer::from_seconds(1.0, TimerMode::Once);
/// timer.tick(Duration::from_secs_f32(1.5));
/// assert!(timer.finished());
/// timer.tick(Duration::from_secs_f32(0.5));
Expand All @@ -69,7 +69,7 @@ impl Timer {
/// ```
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut timer = Timer::from_seconds(1.0, false);
/// let mut timer = Timer::from_seconds(1.0, TimerMode::Once);
/// timer.tick(Duration::from_secs_f32(1.5));
/// assert!(timer.just_finished());
/// timer.tick(Duration::from_secs_f32(0.5));
Expand All @@ -89,7 +89,7 @@ impl Timer {
/// ```
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut timer = Timer::from_seconds(1.0, false);
/// let mut timer = Timer::from_seconds(1.0, TimerMode::Once);
/// timer.tick(Duration::from_secs_f32(0.5));
/// assert_eq!(timer.elapsed(), Duration::from_secs_f32(0.5));
/// ```
Expand All @@ -113,7 +113,7 @@ impl Timer {
/// ```
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut timer = Timer::from_seconds(1.0, false);
/// let mut timer = Timer::from_seconds(1.0, TimerMode::Once);
/// timer.set_elapsed(Duration::from_secs(2));
/// assert_eq!(timer.elapsed(), Duration::from_secs(2));
/// // the timer is not finished even if the elapsed time is greater than the duration.
Expand All @@ -130,7 +130,7 @@ impl Timer {
/// ```
/// # use bevy_time::*;
/// use std::time::Duration;
/// let timer = Timer::new(Duration::from_secs(1), false);
/// let timer = Timer::new(Duration::from_secs(1), TimerMode::Once);
/// assert_eq!(timer.duration(), Duration::from_secs(1));
/// ```
#[inline]
Expand All @@ -144,7 +144,7 @@ impl Timer {
/// ```
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut timer = Timer::from_seconds(1.5, false);
/// let mut timer = Timer::from_seconds(1.5, TimerMode::Once);
/// timer.set_duration(Duration::from_secs(1));
/// assert_eq!(timer.duration(), Duration::from_secs(1));
/// ```
Expand All @@ -158,30 +158,34 @@ impl Timer {
/// # Examples
/// ```
/// # use bevy_time::*;
/// let mut timer = Timer::from_seconds(1.0, true);
/// let mut timer = Timer::from_seconds(1.0, TimerMode::Repeating);
/// assert!(timer.repeating());
/// ```
#[inline]
pub fn repeating(&self) -> bool {
self.repeating
self.mode.repeating()
}
lovelymono marked this conversation as resolved.
Show resolved Hide resolved

/// Sets whether the timer is repeating or not.
///
/// # Examples
/// ```
/// # use bevy_time::*;
/// let mut timer = Timer::from_seconds(1.0, true);
/// let mut timer = Timer::from_seconds(1.0, TimerMode::Repeating);
/// timer.set_repeating(false);
/// assert!(!timer.repeating());
/// ```
#[inline]
pub fn set_repeating(&mut self, repeating: bool) {
if !self.repeating && repeating && self.finished {
if !self.mode.repeating() && repeating && self.finished {
self.stopwatch.reset();
self.finished = self.just_finished();
}
self.repeating = repeating;
self.mode = if repeating {
TimerMode::Repeating
} else {
TimerMode::Once
};
}
lovelymono marked this conversation as resolved.
Show resolved Hide resolved

/// Advance the timer by `delta` seconds.
Expand All @@ -194,8 +198,8 @@ impl Timer {
/// ```
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut timer = Timer::from_seconds(1.0, false);
/// let mut repeating = Timer::from_seconds(1.0, true);
/// let mut timer = Timer::from_seconds(1.0, TimerMode::Once);
/// let mut repeating = Timer::from_seconds(1.0, TimerMode::Repeating);
/// timer.tick(Duration::from_secs_f32(1.5));
/// repeating.tick(Duration::from_secs_f32(1.5));
/// assert_eq!(timer.elapsed_secs(), 1.0);
Expand Down Expand Up @@ -243,7 +247,7 @@ impl Timer {
/// ```
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut timer = Timer::from_seconds(1.0, false);
/// let mut timer = Timer::from_seconds(1.0, TimerMode::Once);
/// timer.pause();
/// timer.tick(Duration::from_secs_f32(0.5));
/// assert_eq!(timer.elapsed_secs(), 0.0);
Expand All @@ -261,7 +265,7 @@ impl Timer {
/// ```
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut timer = Timer::from_seconds(1.0, false);
/// let mut timer = Timer::from_seconds(1.0, TimerMode::Once);
/// timer.pause();
/// timer.tick(Duration::from_secs_f32(0.5));
/// timer.unpause();
Expand All @@ -280,7 +284,7 @@ impl Timer {
/// # Examples
/// ```
/// # use bevy_time::*;
/// let mut timer = Timer::from_seconds(1.0, false);
/// let mut timer = Timer::from_seconds(1.0, TimerMode::Once);
/// assert!(!timer.paused());
/// timer.pause();
/// assert!(timer.paused());
Expand All @@ -300,7 +304,7 @@ impl Timer {
/// ```
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut timer = Timer::from_seconds(1.0, false);
/// let mut timer = Timer::from_seconds(1.0, TimerMode::Once);
/// timer.tick(Duration::from_secs_f32(1.5));
/// timer.reset();
/// assert!(!timer.finished());
Expand All @@ -319,7 +323,7 @@ impl Timer {
/// ```
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut timer = Timer::from_seconds(2.0, false);
/// let mut timer = Timer::from_seconds(2.0, TimerMode::Once);
/// timer.tick(Duration::from_secs_f32(0.5));
/// assert_eq!(timer.percent(), 0.25);
/// ```
Expand All @@ -334,7 +338,7 @@ impl Timer {
/// ```
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut timer = Timer::from_seconds(2.0, false);
/// let mut timer = Timer::from_seconds(2.0, TimerMode::Once);
/// timer.tick(Duration::from_secs_f32(0.5));
/// assert_eq!(timer.percent_left(), 0.75);
/// ```
Expand All @@ -350,7 +354,7 @@ impl Timer {
/// # use bevy_time::*;
/// use std::cmp::Ordering;
/// use std::time::Duration;
/// let mut timer = Timer::from_seconds(2.0, false);
/// let mut timer = Timer::from_seconds(2.0, TimerMode::Once);
/// timer.tick(Duration::from_secs_f32(0.5));
/// let result = timer.remaining_secs().total_cmp(&1.5);
/// assert_eq!(Ordering::Equal, result);
Expand All @@ -366,7 +370,7 @@ impl Timer {
/// ```
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut timer = Timer::from_seconds(2.0, false);
/// let mut timer = Timer::from_seconds(2.0, TimerMode::Once);
/// timer.tick(Duration::from_secs_f32(0.5));
/// assert_eq!(timer.remaining(), Duration::from_secs_f32(1.5));
/// ```
Expand All @@ -385,7 +389,7 @@ impl Timer {
/// ```
/// # use bevy_time::*;
/// use std::time::Duration;
/// let mut timer = Timer::from_seconds(1.0, true);
/// let mut timer = Timer::from_seconds(1.0, TimerMode::Repeating);
/// timer.tick(Duration::from_secs_f32(6.0));
/// assert_eq!(timer.times_finished_this_tick(), 6);
/// timer.tick(Duration::from_secs_f32(2.0));
Expand All @@ -399,14 +403,36 @@ impl Timer {
}
}

/// Specifies [`Timer`] behavior.
#[derive(Debug, Clone, Copy, Reflect)]
lovelymono marked this conversation as resolved.
Show resolved Hide resolved
#[reflect(Default)]
pub enum TimerMode {
/// Run once and stop.
Once,
/// Reset when finished.
Repeating,
}

impl TimerMode {
pub fn repeating(self) -> bool {
matches!(self, Self::Repeating)
}
lovelymono marked this conversation as resolved.
Show resolved Hide resolved
}

impl Default for TimerMode {
fn default() -> Self {
Self::Once
}
}
lovelymono marked this conversation as resolved.
Show resolved Hide resolved

#[cfg(test)]
#[allow(clippy::float_cmp)]
mod tests {
use super::*;

#[test]
fn non_repeating_timer() {
let mut t = Timer::from_seconds(10.0, false);
let mut t = Timer::from_seconds(10.0, TimerMode::Once);
// Tick once, check all attributes
t.tick(Duration::from_secs_f32(0.25));
assert_eq!(t.elapsed_secs(), 0.25);
Expand Down Expand Up @@ -449,7 +475,7 @@ mod tests {

#[test]
fn repeating_timer() {
let mut t = Timer::from_seconds(2.0, true);
let mut t = Timer::from_seconds(2.0, TimerMode::Repeating);
// Tick once, check all attributes
t.tick(Duration::from_secs_f32(0.75));
assert_eq!(t.elapsed_secs(), 0.75);
Expand Down Expand Up @@ -480,7 +506,7 @@ mod tests {

#[test]
fn times_finished_repeating() {
let mut t = Timer::from_seconds(1.0, true);
let mut t = Timer::from_seconds(1.0, TimerMode::Repeating);
assert_eq!(t.times_finished_this_tick(), 0);
t.tick(Duration::from_secs_f32(3.5));
assert_eq!(t.times_finished_this_tick(), 3);
Expand All @@ -493,7 +519,7 @@ mod tests {

#[test]
fn times_finished_this_tick() {
let mut t = Timer::from_seconds(1.0, false);
let mut t = Timer::from_seconds(1.0, TimerMode::Once);
assert_eq!(t.times_finished_this_tick(), 0);
t.tick(Duration::from_secs_f32(1.5));
assert_eq!(t.times_finished_this_tick(), 1);
Expand All @@ -503,7 +529,7 @@ mod tests {

#[test]
fn times_finished_this_tick_precise() {
let mut t = Timer::from_seconds(0.01, true);
let mut t = Timer::from_seconds(0.01, TimerMode::Repeating);
let duration = Duration::from_secs_f64(0.333);

// total duration: 0.333 => 33 times finished
Expand All @@ -522,7 +548,7 @@ mod tests {

#[test]
fn paused() {
let mut t = Timer::from_seconds(10.0, false);
let mut t = Timer::from_seconds(10.0, TimerMode::Once);

t.tick(Duration::from_secs_f32(10.0));
assert!(t.just_finished());
Expand All @@ -536,7 +562,7 @@ mod tests {

#[test]
fn paused_repeating() {
let mut t = Timer::from_seconds(10.0, true);
let mut t = Timer::from_seconds(10.0, TimerMode::Repeating);

t.tick(Duration::from_secs_f32(10.0));
assert!(t.just_finished());
Expand Down
2 changes: 1 addition & 1 deletion examples/2d/sprite_sheet.rs
Expand Up @@ -49,6 +49,6 @@ fn setup(
transform: Transform::from_scale(Vec3::splat(6.0)),
..default()
},
AnimationTimer(Timer::from_seconds(0.1, true)),
AnimationTimer(Timer::from_seconds(0.1, TimerMode::Repeating)),
));
}
2 changes: 1 addition & 1 deletion examples/app/plugin.rs
Expand Up @@ -29,7 +29,7 @@ impl Plugin for PrintMessagePlugin {
fn build(&self, app: &mut App) {
let state = PrintMessageState {
message: self.message.clone(),
timer: Timer::new(self.wait_duration, true),
timer: Timer::new(self.wait_duration, TimerMode::Repeating),
};
app.insert_resource(state).add_system(print_message_system);
}
Expand Down
2 changes: 1 addition & 1 deletion examples/ecs/event.rs
Expand Up @@ -30,7 +30,7 @@ struct EventTriggerState {
impl Default for EventTriggerState {
fn default() -> Self {
EventTriggerState {
event_timer: Timer::from_seconds(1.0, true),
event_timer: Timer::from_seconds(1.0, TimerMode::Repeating),
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions examples/ecs/generic_system.rs
Expand Up @@ -51,13 +51,13 @@ fn main() {

fn setup_system(mut commands: Commands) {
commands.spawn((
PrinterTick(Timer::from_seconds(1.0, true)),
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, true)),
PrinterTick(Timer::from_seconds(1.0, TimerMode::Repeating)),
TextToPrint("I will always print".to_string()),
LevelUnload,
));
Expand Down