#![recursion_limit = "72"]
#![deny(missing_docs)]
#![allow(dead_code)]
pub mod window;
pub mod graphics;
pub mod resources;
pub mod input;
pub mod ui;
use log::debug;
#[derive(PartialEq, Eq, Debug)]
pub enum EngineSignal {
Continue,
Halt,
}
impl EngineSignal {
fn update(&mut self, c: EngineSignal) {
if c == EngineSignal::Halt {
*self = EngineSignal::Halt
}
}
}
pub struct Engine<D>
where
D: Driver,
{
window: window::Window,
driver: D,
}
impl<D> Engine<D>
where
D: Driver + 'static,
{
pub fn new(
window_builder: window::WindowBuilder,
driver: D,
) -> Result<Self, window::WindowError> {
Ok(Engine {
window: window_builder.build()?,
driver: driver,
})
}
pub fn run(self) -> ! {
let (window, mut driver) = (self.window, self.driver);
window.window.set_visible(true);
let (width, height, mut renderer, winit_window, event_loop) = (
window.width,
window.height,
window.renderer,
window.window,
window.event_loop,
);
let winit_window_id = winit_window.id();
event_loop.run(move |event, _, control_flow| {
match event {
winit::event::Event::RedrawRequested(_) => {
renderer.render_frame().unwrap();
}
winit::event::Event::WindowEvent {
ref event,
window_id,
} => {
if window_id == winit_window_id {
match event {
winit::event::WindowEvent::Resized(physical_size) => {
renderer.resize(*physical_size);
}
winit::event::WindowEvent::ScaleFactorChanged {
new_inner_size,
..
} => {
renderer.resize(**new_inner_size);
}
winit::event::WindowEvent::CursorMoved { position, .. } => {
let (ax, ay) = renderer.aspect_ratio;
let winit::dpi::PhysicalPosition { x: xf, y: yf } = position;
let (x, y) = (*xf as u32, *yf as u32);
let winit::dpi::PhysicalSize {
width: screen_w,
height: screen_h,
} = winit_window.inner_size();
let target_w = std::cmp::min(screen_w, (screen_h * ax) / ay);
let target_h = std::cmp::min(screen_h, (screen_w * ay) / ax);
let offs_x;
let offs_y;
if target_w < screen_w {
offs_x = (screen_w - target_w) / 2;
offs_y = 0;
} else {
offs_x = 0;
offs_y = (screen_h - target_h) / 2;
}
if x > offs_x
&& y > offs_y
&& x < offs_x + target_w
&& y < offs_y + target_h
{
let xp = (x - offs_x) as f32;
let yp = (y - offs_y) as f32;
let sx = target_w as f32 / width as f32;
let sy = target_h as f32 / height as f32;
let xs = (xp / sx) as u32;
let ys = (yp / sy) as u32;
let e = input::Event::Mouse(input::MouseEvent::CursorMoved {
sprite_position: (xs, ys),
absolute_position: (*xf, *yf),
});
debug!("{:?}", e);
if driver.handle_input(e) == EngineSignal::Halt {
*control_flow = winit::event_loop::ControlFlow::Exit;
}
}
}
_ => {}
}
}
}
winit::event::Event::MainEventsCleared => {
if driver.process_frame(&mut renderer) == EngineSignal::Halt {
*control_flow = winit::event_loop::ControlFlow::Exit;
}
winit_window.request_redraw();
}
_ => {}
}
if let Ok(e) = std::convert::TryInto::<input::Event>::try_into(event) {
debug!("{:?}", e);
if driver.handle_input(e) == EngineSignal::Halt {
*control_flow = winit::event_loop::ControlFlow::Exit;
}
}
})
}
}
pub trait Driver {
#[must_use]
fn handle_input(&mut self, event: input::Event) -> EngineSignal;
#[must_use]
fn process_frame<R>(&mut self, renderer: &mut R) -> EngineSignal
where
R: graphics::render::RenderInterface;
}