1use std::{future::Future, time::Instant};
2
3use crate::{
4 graphics,
5 keyboard::{self, Key},
6 math::Vec2,
7 mouse,
8};
9
10#[cfg(feature = "async-custom")]
11mod custom_async;
12#[cfg(not(any(feature = "async-custom", feature = "_async-tokio-internal")))]
13mod polling;
14#[cfg(feature = "_async-tokio-internal")]
15mod tokio_event;
16
17#[derive(Debug)]
18pub enum EventData {
20 KeyEvent {
22 key: Key,
24 pressed: bool,
26 },
27 MouseMoved {
29 position: Vec2,
31 },
32 MouseClick {
34 button: i32,
36 pressed: bool,
38 },
39}
40
41#[derive(Debug)]
42pub struct Event {
44 pub timestamp: Instant,
46 pub data: EventData,
48}
49
50pub fn init() {
54 graphics::init();
55}
56
57pub fn end_frame() {
61 #[cfg(feature = "graphics")]
62 graphics::present();
63 keyboard::reset();
64 mouse::reset();
65}
66
67pub fn main_loop<T>(init_fn: impl FnOnce() -> T + 'static, mut loop_fn: impl FnMut(&mut T) + 'static) {
69 main_loop_manual(move || {
70 init();
71 init_fn()
72 }, move |data| {
73 loop_fn(data);
74 end_frame();
75 });
76}
77
78pub fn main_loop_manual<T>(init_fn: impl FnOnce() -> T + 'static, loop_fn: impl FnMut(&mut T) + 'static) {
80 #[cfg(feature = "window")]
81 crate::window::run(init_fn, loop_fn);
82 #[cfg(not(feature = "window"))]
83 {
84 let mut data = init_fn();
85 loop {
86 loop_fn(&mut data);
87 }
88 }
89}
90
91#[cfg(all(feature = "async-custom", feature = "_async-tokio-internal"))]
92compile_error!("Only one async executor feature can be enabled at a time.");
93
94pub fn main_async(fut: impl Future<Output = ()> + 'static + Send) {
98 #[cfg(not(any(feature = "async-custom", feature = "_async-tokio-internal")))]
99 polling::async_executor(fut, true);
100 #[cfg(feature = "async-custom")]
101 custom_async::async_executor(fut, true);
102 #[cfg(feature = "_async-tokio-internal")]
103 tokio_event::async_executor(fut, true);
104}
105
106pub fn main_async_manual(fut: impl Future<Output = ()> + 'static + Send) {
109 #[cfg(not(any(feature = "async-custom", feature = "_async-tokio-internal")))]
110 polling::async_executor(fut, false);
111 #[cfg(feature = "async-custom")]
112 custom_async::async_executor(fut, false);
113 #[cfg(feature = "_async-tokio-internal")]
114 tokio_event::async_executor(fut, false);
115}
116
117pub async fn next_frame() {
119 #[cfg(not(any(feature = "async-custom", feature = "_async-tokio-internal")))]
120 return polling::next_frame().await;
121 #[cfg(feature = "async-custom")]
122 return custom_async::next_frame().await;
123 #[cfg(feature = "_async-tokio-internal")]
124 return tokio_event::next_frame().await;
125}
126
127pub async fn async_yield() {
130 #[cfg(feature = "async-custom")]
131 return custom_async::async_yield().await;
132 #[cfg(feature = "_async-tokio-internal")]
133 return tokio_event::async_yield().await;
134}
135
136pub fn spawn(task: impl Future<Output = ()> + 'static + Send) {
140 #[cfg(not(any(feature = "async-custom", feature = "_async-tokio-internal")))]
141 panic!("The polling/null executor does not support spawning multiple tasks.");
142 #[cfg(feature = "async-custom")]
143 return custom_async::spawn(task);
144 #[cfg(feature = "_async-tokio-internal")]
145 return tokio_event::spawn(task);
146}
147
148pub fn handle_event(ev: Event) {
151 match ev.data {
152 EventData::KeyEvent { key, pressed } => crate::keyboard::process_key_event(key, pressed),
153 EventData::MouseMoved { position } => crate::mouse::process_mouse_moved_event(position),
154 EventData::MouseClick { button, pressed } => {
155 crate::mouse::process_mouse_click_event(button, pressed)
156 }
157 }
158}