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::<Quat>()
.register_property::<Option<String>>() .register_property::<Option<String>>()
.add_system_to_stage(stage::FIRST, time_system) .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); .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_property::Properties;
use bevy_utils::Duration; 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. /// 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. /// 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)] #[derive(Clone, Debug, Default, Properties)]
pub struct Timer { pub struct Timer {
/// Time elapsed on the timer. Guaranteed to be between 0.0 and `duration`, inclusive. elapsed: f32,
pub elapsed: f32, duration: f32,
pub duration: f32, finished: bool,
/// 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,
/// Will only be true on the tick `duration` is reached or exceeded. /// Will only be true on the tick `duration` is reached or exceeded.
pub just_finished: bool, just_finished: bool,
pub repeating: bool, paused: bool,
repeating: bool,
} }
impl Timer { 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. /// Advances the timer by `delta` seconds.
pub fn tick(&mut self, delta: f32) -> &Self { pub fn tick(&mut self, delta: f32) -> &Self {
let prev_finished = self.finished; let prev_finished = self.finished;
@ -56,6 +115,7 @@ impl Timer {
self self
} }
#[inline]
pub fn reset(&mut self) { pub fn reset(&mut self) {
self.finished = false; self.finished = false;
self.just_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)] #[cfg(test)]
mod tests { mod tests {
use super::Timer; use super::Timer;

View File

@ -66,7 +66,7 @@ impl PrintDiagnosticsPlugin {
time: Res<Time>, time: Res<Time>,
diagnostics: Res<Diagnostics>, diagnostics: Res<Diagnostics>,
) { ) {
if state.timer.tick(time.delta_seconds).finished { if state.timer.tick(time.delta_seconds).is_finished() {
println!("Diagnostics:"); println!("Diagnostics:");
println!("{}", "-".repeat(93)); println!("{}", "-".repeat(93));
if let Some(ref filter) = state.filter { if let Some(ref filter) = state.filter {
@ -86,7 +86,7 @@ impl PrintDiagnosticsPlugin {
time: Res<Time>, time: Res<Time>,
diagnostics: Res<Diagnostics>, diagnostics: Res<Diagnostics>,
) { ) {
if state.timer.tick(time.delta_seconds).finished { if state.timer.tick(time.delta_seconds).is_finished() {
println!("Diagnostics (Debug):"); println!("Diagnostics (Debug):");
println!("{}", "-".repeat(93)); println!("{}", "-".repeat(93));
if let Some(ref filter) = state.filter { if let Some(ref filter) = state.filter {

View File

@ -137,7 +137,7 @@ fn select_system(
) { ) {
let mut timer_fired = false; let mut timer_fired = false;
for mut t in tq.iter_mut() { for mut t in tq.iter_mut() {
if !t.just_finished { if !t.just_finished() {
continue; continue;
} }
t.reset(); t.reset();

View File

@ -13,7 +13,7 @@ fn animate_sprite_system(
mut query: Query<(&mut Timer, &mut TextureAtlasSprite, &Handle<TextureAtlas>)>, mut query: Query<(&mut Timer, &mut TextureAtlasSprite, &Handle<TextureAtlas>)>,
) { ) {
for (timer, mut sprite, texture_atlas_handle) in query.iter_mut() { 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(); let texture_atlas = texture_atlases.get(texture_atlas_handle).unwrap();
sprite.index = ((sprite.index as usize + 1) % texture_atlas.textures.len()) as u32; 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>) { 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); println!("{}", state.message);
} }
} }

View File

@ -34,7 +34,7 @@ fn event_trigger_system(
mut state: ResMut<EventTriggerState>, mut state: ResMut<EventTriggerState>,
mut my_events: ResMut<Events<MyEvent>>, 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 { my_events.send(MyEvent {
message: "MyEvent just happened!".to_string(), 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>) { 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() { for mut text in query.iter_mut() {
let c = rand::random::<u8>() as char; let c = rand::random::<u8>() as char;
if !text.value.contains(c) { if !text.value.contains(c) {