use eframe::{egui, egui::Key};
use std::{
collections::HashSet,
time::{Duration, Instant},
};
pub trait MainFunction: FnMut(Context, &mut egui::Ui) {}
impl<T: FnMut(Context, &mut egui::Ui)> MainFunction for T {}
pub struct Context {
pub dt: Duration,
pub key_map: HashSet<Key>,
pub painter: egui::Painter,
pub drawable_area: egui::Rect,
}
struct Gui<F: MainFunction> {
main_function: F,
last_update: Instant,
}
impl<F: MainFunction> Gui<F> {
fn new(main_function: F) -> Self {
Self {
main_function,
last_update: Instant::now(),
}
}
}
pub fn run<F>(options: eframe::NativeOptions, app_name: &str, main_function: F) -> eframe::Result
where
F: MainFunction,
{
eframe::run_native(
app_name,
options,
Box::new(|_cc| {
#[cfg(feature = "images")]
egui_extras::install_image_loaders(&_cc.egui_ctx);
Ok(Box::new(Gui::new(main_function)))
}),
)
}
pub fn __test_run<F>(
_options: eframe::NativeOptions,
_app_name: &str,
_main_function: F,
) -> eframe::Result
where
F: MainFunction,
{
Ok(())
}
impl<F: MainFunction> eframe::App for Gui<F> {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
let dt = self.last_update.elapsed();
self.last_update = Instant::now();
egui::CentralPanel::default()
.frame(egui::Frame::none())
.show(ctx, |ui| {
let (response, painter) =
ui.allocate_painter(ui.available_size(), egui::Sense::hover());
let key_map = ctx.input(|i| i.keys_down.clone());
(self.main_function)(
Context {
dt,
key_map,
drawable_area: response.rect,
painter,
},
ui,
);
});
ctx.request_repaint_after_secs(1.0 / 30.0);
}
}