Allow timers to be paused and encapsulate fields (#914)

Allow timers to be paused and encapsulate fields
This commit is contained in:
Amber Kowalski 2020-11-26 13:25:36 -06:00 committed by GitHub
parent 8e4eb41757
commit f69cc6f94c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 77 additions and 24 deletions

View file

@ -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);
}
}

View file

@ -1,5 +1,3 @@
use crate::time::Time;
use bevy_ecs::prelude::*;
use bevy_property::Properties;
use bevy_utils::Duration;
@ -7,17 +5,17 @@ use bevy_utils::Duration;
///
/// 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 {
@ -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;
@ -56,6 +115,7 @@ impl Timer {
self
}
#[inline]
pub fn reset(&mut self) {
self.finished = false;
self.just_finished = false;
@ -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;

View file

@ -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 {
@ -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 {

View file

@ -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();

View file

@ -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;
}

View file

@ -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);
}
}

View file

@ -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(),
});

View file

@ -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) {