#![doc = include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/README.md"))]
#![warn(missing_docs)]
use handler::AppHandler;
use web_time::Duration;
use winit::{
event::Event,
event_loop::{ActiveEventLoop, ControlFlow, EventLoop},
};
mod handler;
mod input;
pub use input::{Input, InputState};
pub use anyhow;
pub use winit;
#[derive(Debug)]
pub struct Context {
target_frame_time: Duration,
max_frame_time: Duration,
exit: bool,
delta_time: Duration,
pub input: Input,
}
impl Context {
#[inline]
pub(crate) fn new(fps: u32, max_frame_time: Duration) -> Self {
Self {
target_frame_time: Duration::from_secs_f64(1. / fps as f64),
max_frame_time,
delta_time: Duration::ZERO,
exit: false,
input: Input::new(),
}
}
#[inline]
pub fn frame_time(&self) -> Duration {
self.delta_time
}
#[inline]
pub fn set_target_frame_time(&mut self, time: Duration) {
self.target_frame_time = time;
}
#[inline]
pub fn set_target_fps(&mut self, fps: u32) {
self.target_frame_time = Duration::from_secs_f64(1. / fps as f64);
}
#[inline]
pub fn set_max_frame_time(&mut self, time: Duration) {
self.max_frame_time = time;
}
#[inline]
pub fn exit(&mut self) {
self.exit = true;
}
}
pub trait App {
fn update(&mut self, ctx: &mut Context) -> anyhow::Result<()>;
fn render(&mut self, blending_factor: f64) -> anyhow::Result<()>;
#[inline]
fn handle(&mut self, _event: Event<()>) -> anyhow::Result<()> {
Ok(())
}
}
pub type AppInitFunc<A> = dyn FnOnce(&ActiveEventLoop) -> anyhow::Result<A>;
pub fn start<A>(
fps: u32,
max_frame_time: Duration,
app_init: Box<AppInitFunc<A>>,
) -> anyhow::Result<()>
where
A: App + 'static,
{
let event_loop = EventLoop::new()?;
event_loop.set_control_flow(ControlFlow::Poll);
#[cfg_attr(any(target_arch = "wasm32", target_arch = "wasm64"), allow(unused_mut))]
let mut handler = AppHandler::new(app_init, fps, max_frame_time);
#[cfg(not(any(target_arch = "wasm32", target_arch = "wasm64")))]
event_loop.run_app(&mut handler)?;
#[cfg(any(target_arch = "wasm32", target_arch = "wasm64"))]
winit::platform::web::EventLoopExtWebSys::spawn_app(event_loop, handler);
Ok(())
}