256 lines
8.6 KiB
Rust
256 lines
8.6 KiB
Rust
use std::collections::BTreeMap;
|
|
|
|
use renderer::Renderer;
|
|
use tracing::info;
|
|
use tracing_subscriber::EnvFilter;
|
|
use winit::{
|
|
application::ApplicationHandler,
|
|
dpi::{LogicalSize, PhysicalSize},
|
|
event::ElementState,
|
|
event_loop::EventLoop,
|
|
raw_window_handle::{DisplayHandle, HasDisplayHandle, HasWindowHandle},
|
|
window::{Window, WindowAttributes, WindowId},
|
|
};
|
|
|
|
struct WindowState {
|
|
window: Window,
|
|
egui_platform: egui_winit_platform::Platform,
|
|
demo_app: egui_demo_lib::DemoWindows,
|
|
scale_factor: f64,
|
|
}
|
|
|
|
struct WinitState {
|
|
last_resize_events: BTreeMap<WindowId, PhysicalSize<u32>>,
|
|
window_attrs: WindowAttributes,
|
|
windows2: BTreeMap<WindowId, WindowState>,
|
|
renderer: Renderer<WindowId>,
|
|
last_redraw: std::time::Instant,
|
|
}
|
|
|
|
impl WinitState {
|
|
const BASE_WIDTH: u32 = 800;
|
|
const BASE_HEIGHT: u32 = 600;
|
|
fn new(window_title: String, display: DisplayHandle) -> WinitState {
|
|
Self {
|
|
windows2: BTreeMap::new(),
|
|
last_resize_events: BTreeMap::new(),
|
|
window_attrs: WindowAttributes::default()
|
|
.with_title(window_title)
|
|
.with_resizable(true)
|
|
.with_inner_size(LogicalSize::new(Self::BASE_WIDTH, Self::BASE_HEIGHT)),
|
|
// TODO: pass down this error and add some kind of error handling UI or dump
|
|
renderer: Renderer::new(display.as_raw()).expect("renderer"),
|
|
last_redraw: std::time::Instant::now(),
|
|
}
|
|
}
|
|
|
|
fn handle_final_resize(&mut self, window_id: WindowId, new_size: PhysicalSize<u32>) {
|
|
_ = (window_id, new_size);
|
|
info!("TODO: implement resize events");
|
|
if let Some(ctx) = self.renderer.window_contexts.get_mut(&window_id) {
|
|
ctx.recreate_with(Some(renderer::Extent2D {
|
|
width: new_size.width,
|
|
height: new_size.height,
|
|
}))
|
|
.expect("swapchain recreation");
|
|
}
|
|
}
|
|
|
|
fn handle_draw_request(&mut self, window_id: WindowId) {
|
|
_ = window_id;
|
|
tracing::debug!(
|
|
window_id = u64::from(window_id),
|
|
"TODO: implement draw request {}ms",
|
|
self.last_redraw.elapsed().as_millis()
|
|
);
|
|
self.last_redraw = std::time::Instant::now();
|
|
if let Some(window) = self.windows2.get_mut(&window_id) {
|
|
// egui
|
|
|
|
window.egui_platform.begin_pass();
|
|
window.demo_app.ui(&window.egui_platform.context());
|
|
let output = window.egui_platform.end_pass(Some(&window.window));
|
|
|
|
// self.renderer
|
|
// .draw_egui(&window.egui_platform.context(), output)
|
|
// .unwrap();
|
|
|
|
// rendering
|
|
self.renderer
|
|
.debug_draw_egui(&window_id, &window.egui_platform.context(), output, || {
|
|
window.window.pre_present_notify();
|
|
})
|
|
.inspect_err(|err| {
|
|
tracing::error!("error encountered while drawing: {err}");
|
|
})
|
|
.expect("drawing");
|
|
window.window.request_redraw();
|
|
}
|
|
}
|
|
|
|
fn remove_window(&mut self, window_id: WindowId) {
|
|
tracing::info!(window = u64::from(window_id), "window close requested");
|
|
|
|
self.windows2.remove(&window_id);
|
|
self.renderer.window_contexts.remove(&window_id);
|
|
}
|
|
|
|
fn create_window(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) {
|
|
let window = event_loop
|
|
.create_window(
|
|
self.window_attrs
|
|
.clone()
|
|
.with_window_level(winit::window::WindowLevel::AlwaysOnTop),
|
|
)
|
|
.expect("new window");
|
|
let window_id = window.id();
|
|
tracing::info!(window = u64::from(window_id), "created new window");
|
|
|
|
let size = self
|
|
.window_attrs
|
|
.inner_size
|
|
.map(|size| size.to_physical(1.0))
|
|
.unwrap_or(PhysicalSize::new(0, 0));
|
|
let extent = renderer::Extent2D {
|
|
width: size.width,
|
|
height: size.height,
|
|
};
|
|
|
|
let _ = self.renderer.new_window_context(
|
|
extent,
|
|
window_id,
|
|
window.window_handle().expect("window handle"),
|
|
);
|
|
|
|
let scale_factor = window.scale_factor();
|
|
self.windows2.insert(
|
|
window_id,
|
|
WindowState {
|
|
window,
|
|
scale_factor,
|
|
demo_app: egui_demo_lib::DemoWindows::default(),
|
|
egui_platform: egui_winit_platform::Platform::new(
|
|
egui_winit_platform::PlatformDescriptor {
|
|
physical_width: size.width,
|
|
physical_height: size.height,
|
|
scale_factor,
|
|
..Default::default()
|
|
},
|
|
),
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
impl ApplicationHandler for WinitState {
|
|
fn resumed(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) {
|
|
tracing::debug!("winit::resumed");
|
|
|
|
self.create_window(event_loop);
|
|
}
|
|
|
|
fn about_to_wait(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) {
|
|
tracing::trace!("winit::about_to_wait");
|
|
for (&window, &resize) in self.last_resize_events.clone().iter() {
|
|
self.handle_final_resize(window, resize);
|
|
}
|
|
|
|
self.last_resize_events.clear();
|
|
|
|
if self.windows2.is_empty() {
|
|
event_loop.exit();
|
|
}
|
|
}
|
|
|
|
fn window_event(
|
|
&mut self,
|
|
event_loop: &winit::event_loop::ActiveEventLoop,
|
|
window_id: winit::window::WindowId,
|
|
event: winit::event::WindowEvent,
|
|
) {
|
|
// if !matches!(event, winit::event::WindowEvent::Resized(_)) {
|
|
// if let Some(resize) = self.last_resize_events.remove(&window_id) {
|
|
// self.handle_final_resize(window_id, resize);
|
|
// }
|
|
// }
|
|
|
|
if let Some(window) = self.windows2.get_mut(&window_id) {
|
|
window.egui_platform.handle_event(&event);
|
|
}
|
|
|
|
match event {
|
|
winit::event::WindowEvent::Resized(physical_size) => {
|
|
_ = self.last_resize_events.insert(window_id, physical_size);
|
|
}
|
|
winit::event::WindowEvent::CloseRequested
|
|
| winit::event::WindowEvent::KeyboardInput {
|
|
event:
|
|
winit::event::KeyEvent {
|
|
physical_key:
|
|
winit::keyboard::PhysicalKey::Code(winit::keyboard::KeyCode::KeyQ),
|
|
state: ElementState::Pressed,
|
|
repeat: false,
|
|
..
|
|
},
|
|
..
|
|
} => {
|
|
self.remove_window(window_id);
|
|
}
|
|
winit::event::WindowEvent::KeyboardInput {
|
|
event:
|
|
winit::event::KeyEvent {
|
|
physical_key:
|
|
winit::keyboard::PhysicalKey::Code(winit::keyboard::KeyCode::Space),
|
|
state: ElementState::Pressed,
|
|
repeat: false,
|
|
..
|
|
},
|
|
..
|
|
} => {
|
|
self.create_window(event_loop);
|
|
}
|
|
winit::event::WindowEvent::KeyboardInput {
|
|
device_id,
|
|
event,
|
|
is_synthetic,
|
|
} => {
|
|
_ = (device_id, event, is_synthetic);
|
|
}
|
|
winit::event::WindowEvent::CursorMoved {
|
|
device_id,
|
|
position,
|
|
} => {
|
|
_ = (device_id, position);
|
|
}
|
|
winit::event::WindowEvent::MouseInput {
|
|
device_id,
|
|
state,
|
|
button,
|
|
} => {
|
|
_ = (device_id, state, button);
|
|
}
|
|
winit::event::WindowEvent::RedrawRequested => {
|
|
self.handle_draw_request(window_id);
|
|
}
|
|
winit::event::WindowEvent::ScaleFactorChanged { scale_factor, .. } => {
|
|
if let Some(window) = self.windows2.get_mut(&window_id) {
|
|
window.scale_factor = scale_factor;
|
|
}
|
|
}
|
|
_ => {} // unhandled event
|
|
}
|
|
}
|
|
}
|
|
|
|
fn main() {
|
|
let _ = tracing_subscriber::fmt()
|
|
.with_env_filter(EnvFilter::from_default_env())
|
|
.init();
|
|
let ev = EventLoop::new().unwrap();
|
|
ev.set_control_flow(winit::event_loop::ControlFlow::Poll);
|
|
|
|
let display = ev.display_handle().expect("display handle");
|
|
let mut game = WinitState::new("Vidya".to_owned(), display);
|
|
ev.run_app(&mut game).unwrap();
|
|
}
|