mirror of
https://github.com/ricoriedel/wipe.git
synced 2024-11-16 21:16:39 +00:00
Allow skipping frames
This commit is contained in:
parent
94888dcc7d
commit
7500e5af1b
@ -5,8 +5,8 @@ use crate::timer::Timer;
|
|||||||
|
|
||||||
/// Periodically calls [Renderer::render] and [Renderer::present].
|
/// Periodically calls [Renderer::render] and [Renderer::present].
|
||||||
pub struct Runner<TTimer, TRenderer> {
|
pub struct Runner<TTimer, TRenderer> {
|
||||||
|
duration: Duration,
|
||||||
timer: TTimer,
|
timer: TTimer,
|
||||||
ticks: u128,
|
|
||||||
renderer: TRenderer,
|
renderer: TRenderer,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -14,19 +14,23 @@ impl<T1: Timer, T2: Renderer> Runner<T1, T2> {
|
|||||||
pub fn new(duration: Duration,
|
pub fn new(duration: Duration,
|
||||||
timer: T1,
|
timer: T1,
|
||||||
renderer: T2) -> Self {
|
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> {
|
pub fn run(mut self) -> Result<(), Error> {
|
||||||
for i in 0..=self.ticks {
|
self.timer.set();
|
||||||
let step = i as f32 / self.ticks as f32;
|
|
||||||
|
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.render(step);
|
||||||
self.renderer.present()?;
|
self.renderer.present()?;
|
||||||
self.timer.sleep();
|
self.timer.sleep();
|
||||||
}
|
}
|
||||||
|
self.renderer.render(1.0);
|
||||||
|
self.renderer.present()?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -46,19 +50,21 @@ mod test {
|
|||||||
let mut renderer = MockRenderer::new();
|
let mut renderer = MockRenderer::new();
|
||||||
let seq = &mut Sequence::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_render().once().with(eq(0.0)).in_sequence(seq).return_const(());
|
||||||
renderer.expect_present().once().in_sequence(seq).returning(|| Ok(()));
|
renderer.expect_present().once().in_sequence(seq).returning(|| Ok(()));
|
||||||
timer.expect_sleep().once().in_sequence(seq).return_const(());
|
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_render().once().with(eq(0.5)).in_sequence(seq).return_const(());
|
||||||
renderer.expect_present().once().in_sequence(seq).returning(|| Ok(()));
|
renderer.expect_present().once().in_sequence(seq).returning(|| Ok(()));
|
||||||
timer.expect_sleep().once().in_sequence(seq).return_const(());
|
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_render().once().with(eq(1.0)).in_sequence(seq).return_const(());
|
||||||
renderer.expect_present().once().in_sequence(seq).returning(|| Ok(()));
|
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);
|
let runner = Runner::new(Duration::from_secs(4), timer, renderer);
|
||||||
|
|
||||||
|
26
src/timer.rs
26
src/timer.rs
@ -7,29 +7,43 @@ use mockall::automock;
|
|||||||
/// Allows for periodic execution of code.
|
/// Allows for periodic execution of code.
|
||||||
#[cfg_attr(test, automock)]
|
#[cfg_attr(test, automock)]
|
||||||
pub trait Timer {
|
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.
|
/// Sleep until the next tick starts.
|
||||||
fn sleep(&mut self);
|
fn sleep(&mut self);
|
||||||
|
|
||||||
/// Get the delay between ticks.
|
|
||||||
fn delay(&self) -> Duration;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A simple [Timer] based on the system clock.
|
/// A simple [Timer] based on the system clock.
|
||||||
pub struct SimpleTimer {
|
pub struct SimpleTimer {
|
||||||
delay: Duration,
|
delay: Duration,
|
||||||
|
start: Instant,
|
||||||
last: Instant
|
last: Instant
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SimpleTimer {
|
impl SimpleTimer {
|
||||||
pub fn new(delay: Duration) -> Self {
|
pub fn new(delay: Duration) -> Self {
|
||||||
Self {
|
Self {
|
||||||
last: Instant::now(),
|
|
||||||
delay,
|
delay,
|
||||||
|
start: Instant::now(),
|
||||||
|
last: Instant::now(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Timer for SimpleTimer {
|
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) {
|
fn sleep(&mut self) {
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
|
|
||||||
@ -38,8 +52,4 @@ impl Timer for SimpleTimer {
|
|||||||
}
|
}
|
||||||
self.last = Instant::now();
|
self.last = Instant::now();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn delay(&self) -> Duration {
|
|
||||||
self.delay
|
|
||||||
}
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user