use std::{future::Future, time::Instant};
use crate::{
graphics,
keyboard::{self, Key},
math::Vec2,
mouse,
};
#[cfg(feature = "async-custom")]
mod custom_async;
#[cfg(not(any(feature = "async-custom", feature = "_async-tokio-internal")))]
mod polling;
#[cfg(feature = "_async-tokio-internal")]
mod tokio_event;
#[derive(Debug)]
pub enum EventData {
KeyEvent {
key: Key,
pressed: bool,
},
MouseMoved {
position: Vec2,
},
MouseClick {
button: i32,
pressed: bool,
},
}
#[derive(Debug)]
pub struct Event {
pub timestamp: Instant,
pub data: EventData,
}
pub fn init() {
graphics::init();
}
pub fn end_frame() {
#[cfg(feature = "graphics")]
graphics::present();
keyboard::reset();
mouse::reset();
}
pub fn main_loop<T>(init_fn: impl FnOnce() -> T + 'static, mut loop_fn: impl FnMut(&mut T) + 'static) {
main_loop_manual(move || {
init();
init_fn()
}, move |data| {
loop_fn(data);
end_frame();
});
}
pub fn main_loop_manual<T>(init_fn: impl FnOnce() -> T + 'static, loop_fn: impl FnMut(&mut T) + 'static) {
#[cfg(feature = "window")]
crate::window::run(init_fn, loop_fn);
#[cfg(not(feature = "window"))]
{
let mut data = init_fn();
loop {
loop_fn(&mut data);
}
}
}
#[cfg(all(feature = "async-custom", feature = "_async-tokio-internal"))]
compile_error!("Only one async executor feature can be enabled at a time.");
pub fn main_async(fut: impl Future<Output = ()> + 'static + Send) {
#[cfg(not(any(feature = "async-custom", feature = "_async-tokio-internal")))]
polling::async_executor(fut, true);
#[cfg(feature = "async-custom")]
custom_async::async_executor(fut, true);
#[cfg(feature = "_async-tokio-internal")]
tokio_event::async_executor(fut, true);
}
pub fn main_async_manual(fut: impl Future<Output = ()> + 'static + Send) {
#[cfg(not(any(feature = "async-custom", feature = "_async-tokio-internal")))]
polling::async_executor(fut, false);
#[cfg(feature = "async-custom")]
custom_async::async_executor(fut, false);
#[cfg(feature = "_async-tokio-internal")]
tokio_event::async_executor(fut, false);
}
pub async fn next_frame() {
#[cfg(not(any(feature = "async-custom", feature = "_async-tokio-internal")))]
return polling::next_frame().await;
#[cfg(feature = "async-custom")]
return custom_async::next_frame().await;
#[cfg(feature = "_async-tokio-internal")]
return tokio_event::next_frame().await;
}
pub async fn async_yield() {
#[cfg(feature = "async-custom")]
return custom_async::async_yield().await;
#[cfg(feature = "_async-tokio-internal")]
return tokio_event::async_yield().await;
}
pub fn spawn(task: impl Future<Output = ()> + 'static + Send) {
#[cfg(not(any(feature = "async-custom", feature = "_async-tokio-internal")))]
panic!("The polling/null executor does not support spawning multiple tasks.");
#[cfg(feature = "async-custom")]
return custom_async::spawn(task);
#[cfg(feature = "_async-tokio-internal")]
return tokio_event::spawn(task);
}
pub fn handle_event(ev: Event) {
match ev.data {
EventData::KeyEvent { key, pressed } => crate::keyboard::process_key_event(key, pressed),
EventData::MouseMoved { position } => crate::mouse::process_mouse_moved_event(position),
EventData::MouseClick { button, pressed } => {
crate::mouse::process_mouse_click_event(button, pressed)
}
}
}