refactor renderer into smaller functions
This commit is contained in:
parent
cc428055f1
commit
aec264653f
3 changed files with 341 additions and 119 deletions
|
@ -1,19 +1,29 @@
|
|||
use std::collections::HashMap;
|
||||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
|
||||
use ctx::WgpuCtx;
|
||||
use tracing::{debug, error, info, trace, warn};
|
||||
use wgpu::rwh::HasWindowHandle;
|
||||
use winit::application::ApplicationHandler;
|
||||
use winit::event::WindowEvent;
|
||||
use winit::event_loop::ControlFlow;
|
||||
use winit::event_loop::{ActiveEventLoop, EventLoop};
|
||||
use winit::window::{Window, WindowId};
|
||||
use winit::event::{KeyEvent, WindowEvent};
|
||||
use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop};
|
||||
use winit::window::Window;
|
||||
use winit::window::WindowId;
|
||||
|
||||
pub mod ctx;
|
||||
|
||||
struct WindowContext<'window> {
|
||||
window: Arc<Window>,
|
||||
ctx: WgpuCtx<'window>,
|
||||
main_window: bool
|
||||
main_window: bool,
|
||||
}
|
||||
impl Deref for WindowContext<'_> {
|
||||
type Target = winit::window::Window;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
self.window.as_ref()
|
||||
}
|
||||
}
|
||||
impl WindowContext<'_> {
|
||||
pub fn is_main_window(&self) -> bool {
|
||||
|
@ -26,25 +36,155 @@ pub struct App<'window> {
|
|||
windows: HashMap<WindowId, WindowContext<'window>>,
|
||||
}
|
||||
|
||||
impl App<'_> {
|
||||
fn create_main_window(&mut self, event_loop: &ActiveEventLoop) {
|
||||
let win_attr = Window::default_attributes().with_title("Zenyx");
|
||||
match event_loop.create_window(win_attr) {
|
||||
Ok(window) => {
|
||||
let window = Arc::new(window);
|
||||
let window_id = window.id();
|
||||
match WgpuCtx::new_blocking(window.clone()) {
|
||||
Ok(wgpu_ctx) => {
|
||||
self.windows.insert(
|
||||
window_id,
|
||||
WindowContext {
|
||||
window,
|
||||
ctx: wgpu_ctx,
|
||||
main_window: true,
|
||||
},
|
||||
);
|
||||
info!("Main window created: {:?}", window_id);
|
||||
}
|
||||
Err(e) => error!("Failed to create WGPU context: {:?}", e),
|
||||
}
|
||||
}
|
||||
Err(e) => error!("Failed to create main window: {:?}", e),
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_close_requested(&mut self, window_id: WindowId) {
|
||||
if self.windows.remove(&window_id).is_some() {
|
||||
debug!("Window {:?} closed", window_id);
|
||||
} else {
|
||||
warn!("Tried to close non-existent window {:?}", window_id);
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_keyboard_input(
|
||||
&mut self,
|
||||
event_loop: &ActiveEventLoop,
|
||||
window_id: WindowId,
|
||||
key_event: KeyEvent,
|
||||
) {
|
||||
if !key_event.state.is_pressed() {
|
||||
return;
|
||||
}
|
||||
match key_event.physical_key {
|
||||
winit::keyboard::PhysicalKey::Code(code) => match code {
|
||||
winit::keyboard::KeyCode::Space => {
|
||||
self.toggle_background(window_id);
|
||||
}
|
||||
winit::keyboard::KeyCode::Escape => {
|
||||
self.spawn_child_window(event_loop);
|
||||
}
|
||||
other => error!("Unimplemented keycode: {:?}", other),
|
||||
},
|
||||
_ => debug!("Received a keyboard event with no physical key"),
|
||||
}
|
||||
}
|
||||
|
||||
fn toggle_background(&mut self, window_id: WindowId) {
|
||||
if let Some(window_context) = self.windows.get_mut(&window_id) {
|
||||
let current_color = window_context.ctx.bg_color();
|
||||
let new_color = match current_color {
|
||||
wgpu::Color::WHITE => wgpu::Color::BLACK,
|
||||
wgpu::Color::BLACK => wgpu::Color::WHITE,
|
||||
_ => wgpu::Color::WHITE,
|
||||
};
|
||||
window_context.ctx.change_bg_color(new_color);
|
||||
debug!("Toggled background color for window {:?}", window_id);
|
||||
} else {
|
||||
warn!("No window context for toggling background: {:?}", window_id);
|
||||
}
|
||||
}
|
||||
|
||||
fn spawn_child_window(&mut self, event_loop: &ActiveEventLoop) {
|
||||
if let Some(main_ctx) = self.windows.values().find(|ctx| ctx.is_main_window()) {
|
||||
let title = format!("Zenyx - New Window {}", self.windows.len());
|
||||
//TODO: Verify that this is safe instead of matching on it
|
||||
let win_attr = unsafe {
|
||||
let base = Window::default_attributes().with_title(title);
|
||||
match main_ctx.window_handle() {
|
||||
Ok(handle) => base.with_parent_window(Some(handle.as_raw())),
|
||||
Err(_) => base,
|
||||
}
|
||||
};
|
||||
match event_loop.create_window(win_attr) {
|
||||
Ok(window) => {
|
||||
let window = Arc::new(window);
|
||||
let window_id = window.id();
|
||||
match WgpuCtx::new_blocking(window.clone()) {
|
||||
Ok(wgpu_ctx) => {
|
||||
self.windows.insert(
|
||||
window_id,
|
||||
WindowContext {
|
||||
window,
|
||||
ctx: wgpu_ctx,
|
||||
main_window: false,
|
||||
},
|
||||
);
|
||||
debug!("Spawned new child window: {:?}", window_id);
|
||||
}
|
||||
Err(e) => error!("Failed to create WGPU context for child window: {:?}", e),
|
||||
}
|
||||
}
|
||||
Err(e) => error!("Failed to create child window: {:?}", e),
|
||||
}
|
||||
} else {
|
||||
error!("No main window found. Cannot spawn a child window.");
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_redraw_requested(&mut self, window_id: WindowId) {
|
||||
if let Some(window_context) = self.windows.get_mut(&window_id) {
|
||||
window_context.ctx.draw();
|
||||
window_context.request_redraw();
|
||||
trace!(
|
||||
"Redrew window {:?} with title: {}",
|
||||
window_id,
|
||||
window_context.window.title()
|
||||
);
|
||||
} else {
|
||||
warn!("Received redraw for unknown window {:?}", window_id);
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_resize(&mut self, window_id: WindowId, new_size: winit::dpi::PhysicalSize<u32>) {
|
||||
if let Some(window_context) = self.windows.get_mut(&window_id) {
|
||||
window_context.ctx.resize(new_size.into());
|
||||
window_context.window.request_redraw();
|
||||
debug!(
|
||||
"Resized window {:?} to {}x{}",
|
||||
window_id, new_size.width, new_size.height
|
||||
);
|
||||
} else {
|
||||
warn!("Received resize for unknown window {:?}", window_id);
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_destroyed(&mut self, event_loop: &ActiveEventLoop) {
|
||||
if self.windows.is_empty() || !self.windows.iter().any(|(_, ctx)| ctx.is_main_window()) {
|
||||
self.windows.clear();
|
||||
debug!("All main windows are closed. Exiting event loop.");
|
||||
event_loop.exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ApplicationHandler for App<'_> {
|
||||
fn resumed(&mut self, event_loop: &ActiveEventLoop) {
|
||||
if self.windows.is_empty() {
|
||||
let win_attr = Window::default_attributes().with_title("Zenyx");
|
||||
let window = Arc::new(
|
||||
event_loop
|
||||
.create_window(win_attr)
|
||||
.expect("create window err."),
|
||||
);
|
||||
let window_id = window.id();
|
||||
let wgpu_ctx = WgpuCtx::new_blocking(window.clone()).unwrap();
|
||||
self.windows.insert(
|
||||
window_id,
|
||||
WindowContext {
|
||||
window,
|
||||
ctx: wgpu_ctx,
|
||||
main_window: true,
|
||||
},
|
||||
);
|
||||
self.create_main_window(event_loop);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,88 +196,31 @@ impl ApplicationHandler for App<'_> {
|
|||
) {
|
||||
match event {
|
||||
WindowEvent::CloseRequested => {
|
||||
if let Some(window_context) = self.windows.remove(&window_id) {
|
||||
|
||||
drop(window_context);
|
||||
debug!("Window: {:?} closed, exiting", window_id);
|
||||
}
|
||||
self.handle_close_requested(window_id);
|
||||
}
|
||||
WindowEvent::KeyboardInput {
|
||||
device_id,
|
||||
event,
|
||||
is_synthetic,
|
||||
} => match event.physical_key {
|
||||
winit::keyboard::PhysicalKey::Code(code) => {
|
||||
if event.state.is_pressed() == false {
|
||||
return;
|
||||
}
|
||||
match code {
|
||||
winit::keyboard::KeyCode::Space => {
|
||||
debug!("Space key pressed");
|
||||
if let Some(window_context) = self.windows.get_mut(&window_id){
|
||||
match window_context.ctx.bg_color() {
|
||||
wgpu::Color::WHITE => {
|
||||
window_context.ctx.change_bg_color(wgpu::Color::BLACK)
|
||||
}
|
||||
wgpu::Color::BLACK => {
|
||||
window_context.ctx.change_bg_color(wgpu::Color::WHITE)
|
||||
}
|
||||
_ => window_context.ctx.change_bg_color(wgpu::Color::WHITE),
|
||||
}
|
||||
}
|
||||
}
|
||||
winit::keyboard::KeyCode::Escape => {
|
||||
debug!("Escape key pressed, spawning new window");
|
||||
let win_attr = Window::default_attributes()
|
||||
.with_title(format!("Zenyx - New Window {}", self.windows.len()));
|
||||
let new_window = Arc::new(
|
||||
event_loop
|
||||
.create_window(win_attr)
|
||||
.expect("create window err."),
|
||||
);
|
||||
let window_id = new_window.id();
|
||||
let wgpu_ctx = WgpuCtx::new_blocking(new_window.clone()).unwrap();
|
||||
self.windows.insert(
|
||||
window_id,
|
||||
WindowContext {
|
||||
window: new_window,
|
||||
ctx: wgpu_ctx,
|
||||
main_window: false,
|
||||
},
|
||||
);
|
||||
}
|
||||
_ => info!("Unimplemented keycode: {:?}", code),
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
WindowEvent::RedrawRequested => {
|
||||
if let Some(window_context) = self.windows.get_mut(&window_id) {
|
||||
window_context.ctx.draw();
|
||||
window_context.window.request_redraw();
|
||||
}
|
||||
event: key_event, ..
|
||||
} => {
|
||||
self.handle_keyboard_input(event_loop, window_id, key_event);
|
||||
}
|
||||
WindowEvent::Resized(size) => {
|
||||
if let Some(window_context) = self.windows.get_mut(&window_id) {
|
||||
window_context.ctx.resize(size.into());
|
||||
window_context.window.request_redraw();
|
||||
let size_str: String = size.height.to_string() + "x" + &size.width.to_string();
|
||||
debug!("Window resized to {:?}", size_str);
|
||||
}
|
||||
WindowEvent::RedrawRequested => {
|
||||
self.handle_redraw_requested(window_id);
|
||||
}
|
||||
WindowEvent::Resized(new_size) => {
|
||||
self.handle_resize(window_id, new_size);
|
||||
}
|
||||
WindowEvent::Destroyed => {
|
||||
if !self.windows.iter().any(|(_,ctx)| ctx.is_main_window()) || self.windows.is_empty() {
|
||||
self.windows.clear();
|
||||
event_loop.exit();
|
||||
}
|
||||
self.handle_destroyed(event_loop);
|
||||
}
|
||||
_ => trace!("Unhandled window event"),
|
||||
_ => trace!("Unhandled window event for window {:?}", window_id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init_renderer(event_loop: EventLoop<()>) {
|
||||
event_loop.set_control_flow(ControlFlow::Poll);
|
||||
event_loop.set_control_flow(ControlFlow::Wait);
|
||||
let mut app = App::default();
|
||||
event_loop.run_app(&mut app).unwrap();
|
||||
if let Err(e) = event_loop.run_app(&mut app) {
|
||||
error!("Failed to run application: {:?}", e);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue