Skip to content

Commit

Permalink
Event loop control
Browse files Browse the repository at this point in the history
  • Loading branch information
nanoqsh committed Jan 8, 2024
1 parent c09d46b commit 047e1a8
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 38 deletions.
62 changes: 52 additions & 10 deletions dunge/src/el.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use {
update::Update,
window::View,
},
std::{error, fmt},
std::{error, fmt, time::Duration},
wgpu::SurfaceError,
winit::{
error::EventLoopError,
Expand All @@ -16,9 +16,20 @@ use {
},
};

pub(crate) struct Loop(pub EventLoop<()>);
pub(crate) struct Loop(EventLoop<()>);

impl Loop {
pub fn new() -> Result<Self, EventLoopError> {
use winit::event_loop::EventLoopBuilder;

let inner = EventLoopBuilder::with_user_event().build()?;
Ok(Self(inner))
}

pub fn inner(&self) -> &EventLoop<()> {
&self.0
}

#[cfg(not(target_arch = "wasm32"))]
pub fn run<U>(self, cx: Context, view: View, update: U) -> Result<(), LoopError>
where
Expand Down Expand Up @@ -51,6 +62,26 @@ impl fmt::Display for LoopError {

impl error::Error for LoopError {}

pub struct Control {
close: bool,
min_delta_time: Duration,
fps: u32,
}

impl Control {
pub fn close(&mut self) {
self.close = true;
}

pub fn set_min_delta_time(&mut self, min_delta_time: Duration) {
self.min_delta_time = min_delta_time;
}

pub fn fps(&self) -> u32 {
self.fps
}
}

type Event = event::Event<()>;
type Target = event_loop::EventLoopWindowTarget<()>;

Expand All @@ -62,15 +93,27 @@ where
event::{KeyEvent, StartCause, WindowEvent},
event_loop::ControlFlow,
keyboard::{KeyCode, PhysicalKey},
std::time::Duration,
};

let mut ctrl = Control {
close: false,
min_delta_time: Duration::from_secs_f32(1. / 60.),
fps: 0,
};

let mut render = Render::default();
let mut time = Time::now();
let mut fps = Fps::default();
move |ev: Event, target: &Target| match ev {
move |ev, target| match ev {
Event::NewEvents(cause) => match cause {
StartCause::ResumeTimeReached { .. } => view.request_redraw(),
StartCause::ResumeTimeReached { .. } => {
if ctrl.close {
target.exit();
return;
}

view.request_redraw()
}
StartCause::WaitCancelled {
requested_resume, ..
} => {
Expand Down Expand Up @@ -101,19 +144,18 @@ where
} => target.exit(),
WindowEvent::RedrawRequested => {
let delta_time = time.delta();
let min_delta_time = 1. / 60.;
if delta_time < min_delta_time {
let wait = Duration::from_secs_f32(min_delta_time - delta_time);
if delta_time < ctrl.min_delta_time {
let wait = ctrl.min_delta_time - delta_time;
target.set_control_flow(ControlFlow::wait_duration(wait));
return;
}

time.reset();
if let Some(fps) = fps.count(delta_time) {
println!("fps: {fps}");
ctrl.fps = fps;
}

update.update();
update.update(&mut ctrl);
match view.output() {
Ok(output) => {
let view = RenderView::from_output(&output);
Expand Down
5 changes: 3 additions & 2 deletions dunge/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,15 @@ pub mod mesh;
pub mod shader;
pub mod state;
pub mod texture;
pub mod update;
pub mod vertex;

#[cfg(feature = "winit")]
mod el;
#[cfg(feature = "winit")]
mod time;
#[cfg(feature = "winit")]
pub mod update;
#[cfg(feature = "winit")]
pub mod window;

pub use {
Expand All @@ -27,4 +28,4 @@ pub use {
};

#[cfg(feature = "winit")]
pub use crate::init::window;
pub use {crate::init::window, el::Control};
28 changes: 16 additions & 12 deletions dunge/src/time.rs
Original file line number Diff line number Diff line change
@@ -1,46 +1,50 @@
use instant::Instant;
use {instant::Instant, std::time::Duration};

pub(crate) struct Time {
last: Instant,
delta: f32,
delta: Duration,
}

impl Time {
pub fn now() -> Self {
Self {
last: Instant::now(),
delta: 0.,
delta: Duration::ZERO,
}
}

pub fn delta(&mut self) -> f32 {
pub fn delta(&mut self) -> Duration {
let now = Instant::now();
let delta = now.duration_since(self.last);
self.last = now;
self.delta += delta.as_secs_f32();
self.delta += delta;
self.delta
}

pub fn reset(&mut self) {
self.delta = 0.;
self.delta = Duration::ZERO;
}
}

#[derive(Default)]
pub(crate) struct Fps {
timer: f32,
timer: Duration,
counter: u32,
}

impl Fps {
pub fn count(&mut self, delta_time: f32) -> Option<u32> {
pub fn count(&mut self, delta_time: Duration) -> Option<u32> {
const SECOND: Duration = Duration::from_secs(1);

self.timer += delta_time;
self.counter += 1;
(self.timer > 1.).then(|| {
self.timer = 0.;
if self.timer > SECOND {
self.timer = Duration::ZERO;
let n = self.counter;
self.counter = 0;
n
})
Some(n)
} else {
None
}
}
}
12 changes: 6 additions & 6 deletions dunge/src/update.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use crate::{draw::Draw, state::Frame};
use crate::{draw::Draw, el::Control, state::Frame};

pub trait Update: Draw {
fn update(&mut self);
fn update(&mut self, ctrl: &mut Control);
}

pub fn from_fn<U, D>(update: U, draw: D) -> impl Update
where
U: FnMut(),
U: FnMut(&mut Control),
D: Fn(Frame),
{
struct Func<U, D>(U, D);
Expand All @@ -22,11 +22,11 @@ where

impl<U, D> Update for Func<U, D>
where
U: FnMut(),
U: FnMut(&mut Control),
D: Fn(Frame),
{
fn update(&mut self) {
(self.0)();
fn update(&mut self, ctrl: &mut Control) {
(self.0)(ctrl);
}
}

Expand Down
11 changes: 3 additions & 8 deletions dunge/src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ use {
},
winit::{
error::{EventLoopError, OsError},
event_loop::EventLoop,
window::{self, WindowId},
},
};
Expand Down Expand Up @@ -62,23 +61,19 @@ impl WindowBuilder {
pub(crate) fn build(self, cx: Context, instance: &Instance) -> Result<Window, Error> {
use winit::{dpi::PhysicalSize, window::Fullscreen};

let el = EventLoop::new()?;
let el = Loop::new()?;
let inner = {
let builder = window::WindowBuilder::new().with_title(self.title);
let builder = match self.size {
Some((width, height)) => builder.with_inner_size(PhysicalSize::new(width, height)),
None => builder.with_fullscreen(Some(Fullscreen::Borderless(None))),
};

builder.build(&el)?
builder.build(el.inner())?
};

let view = View::new(cx.state(), instance, inner)?;
Ok(Window {
cx,
el: Loop(el),
view,
})
Ok(Window { cx, el, view })
}
}

Expand Down

0 comments on commit 047e1a8

Please sign in to comment.