diff --git a/src/runner.rs b/src/runner.rs index 34755f6..1dfeddc 100644 --- a/src/runner.rs +++ b/src/runner.rs @@ -5,8 +5,8 @@ use crate::timer::Timer; /// Periodically calls [Renderer::render] and [Renderer::present]. pub struct Runner { + duration: Duration, timer: TTimer, - ticks: u128, renderer: TRenderer, } @@ -14,19 +14,23 @@ impl Runner { pub fn new(duration: Duration, timer: T1, renderer: T2) -> Self { - let ticks = duration.as_nanos() / timer.delay().as_nanos(); - Self { timer, ticks, renderer } + Self { duration, timer, renderer } } pub fn run(mut self) -> Result<(), Error> { - for i in 0..=self.ticks { - let step = i as f32 / self.ticks as f32; + self.timer.set(); + + while self.timer.elapsed() < self.duration { + let step = self.timer.elapsed().as_secs_f32() / self.duration.as_secs_f32(); self.renderer.render(step); self.renderer.present()?; self.timer.sleep(); } + self.renderer.render(1.0); + self.renderer.present()?; + Ok(()) } } @@ -46,19 +50,21 @@ mod test { let mut renderer = MockRenderer::new(); let seq = &mut Sequence::new(); - timer.expect_delay().return_const(Duration::from_secs(2)); + timer.expect_set().once().in_sequence(seq).return_const(()); + timer.expect_elapsed().times(2).in_sequence(seq).return_const(Duration::from_secs(0)); renderer.expect_render().once().with(eq(0.0)).in_sequence(seq).return_const(()); renderer.expect_present().once().in_sequence(seq).returning(|| Ok(())); timer.expect_sleep().once().in_sequence(seq).return_const(()); + timer.expect_elapsed().times(2).in_sequence(seq).return_const(Duration::from_secs(2)); renderer.expect_render().once().with(eq(0.5)).in_sequence(seq).return_const(()); renderer.expect_present().once().in_sequence(seq).returning(|| Ok(())); timer.expect_sleep().once().in_sequence(seq).return_const(()); + timer.expect_elapsed().times(1).in_sequence(seq).return_const(Duration::from_secs(4)); renderer.expect_render().once().with(eq(1.0)).in_sequence(seq).return_const(()); renderer.expect_present().once().in_sequence(seq).returning(|| Ok(())); - timer.expect_sleep().once().in_sequence(seq).return_const(()); let runner = Runner::new(Duration::from_secs(4), timer, renderer); diff --git a/src/timer.rs b/src/timer.rs index 387dd5b..fecf037 100644 --- a/src/timer.rs +++ b/src/timer.rs @@ -7,29 +7,43 @@ use mockall::automock; /// Allows for periodic execution of code. #[cfg_attr(test, automock)] pub trait Timer { + /// Set the start time of the timer. + fn set(&mut self); + + /// Get the elapsed time since calling [Timer::set]. + fn elapsed(&self) -> Duration; + /// Sleep until the next tick starts. fn sleep(&mut self); - - /// Get the delay between ticks. - fn delay(&self) -> Duration; } /// A simple [Timer] based on the system clock. pub struct SimpleTimer { delay: Duration, + start: Instant, last: Instant } impl SimpleTimer { pub fn new(delay: Duration) -> Self { Self { - last: Instant::now(), delay, + start: Instant::now(), + last: Instant::now(), } } } impl Timer for SimpleTimer { + fn set(&mut self) { + self.start = Instant::now(); + self.last = self.start; + } + + fn elapsed(&self) -> Duration { + Instant::now() - self.start + } + fn sleep(&mut self) { let now = Instant::now(); @@ -38,8 +52,4 @@ impl Timer for SimpleTimer { } self.last = Instant::now(); } - - fn delay(&self) -> Duration { - self.delay - } } \ No newline at end of file