diff --git a/examples/src/cube_camera/main.rs b/examples/src/cube_camera/main.rs index f0bcf96..ecb8d6c 100644 --- a/examples/src/cube_camera/main.rs +++ b/examples/src/cube_camera/main.rs @@ -8,22 +8,31 @@ use sursface::wgpu; use wgpu::{util::DeviceExt, Color, RenderPipeline}; use sursface::cgmath::{Deg, Matrix4, Point3, Vector3, perspective}; use sursface::cgmath::SquareMatrix; +use sursface::{app::AppHandlers, winit::dpi::PhysicalSize}; #[cfg(target_arch = "wasm32")] use sursface::wasm_bindgen; #[cfg(not(target_arch = "wasm32"))] fn main() { - use sursface::winit::dpi::PhysicalSize; - sursface::start::create_window_desktop(PhysicalSize::new(1280, 720), &init, &render, &event); + sursface::start::create_window_desktop(PhysicalSize::new(1280, 720), AppHandlers { + init, + render, + event, + ..Default::default() + }); } #[cfg(target_arch = "wasm32")] #[wasm_bindgen::prelude::wasm_bindgen] pub fn start_browser(canvas: sursface::wgpu::web_sys::HtmlCanvasElement) { - use sursface::start; - start::create_window_browser(canvas, &init, &render, &event); + sursface::start::create_window_browser(canvas, AppHandlers { + init, + render, + event, + ..Default::default() + }); } #[cfg(target_arch = "wasm32")] diff --git a/examples/src/hello_triangle/main.rs b/examples/src/hello_triangle/main.rs index 414cb2c..012475d 100644 --- a/examples/src/hello_triangle/main.rs +++ b/examples/src/hello_triangle/main.rs @@ -1,9 +1,14 @@ use sursface::{display::Display, std::{clear_screen, create_render_pipeline, create_shader, get_framebuffer}, wgpu::{self, Color, RenderPipeline}, winit::event::WindowEvent}; +use sursface::{app::AppHandlers, winit::dpi::PhysicalSize}; #[cfg(not(target_arch = "wasm32"))] fn main() { - use sursface::winit::dpi::PhysicalSize; - sursface::start::create_window_desktop(PhysicalSize::new(1280, 720), &init, &render, &event); + sursface::start::create_window_desktop(PhysicalSize::new(1280, 720), AppHandlers { + init, + render, + event, + ..Default::default() + }); } #[cfg(target_arch = "wasm32")] @@ -13,9 +18,12 @@ fn main() {} #[cfg(target_arch = "wasm32")] #[wasm_bindgen::prelude::wasm_bindgen] pub fn start_browser(canvas: sursface::wgpu::web_sys::HtmlCanvasElement) { - use sursface::start; - - start::create_window_browser(canvas, &init, &render, &event); + sursface::start::create_window_browser(canvas, AppHandlers { + init, + render, + event, + ..Default::default() + }); } struct TriangleState { diff --git a/examples/src/hello_window/main.rs b/examples/src/hello_window/main.rs index 352baba..09e7cd2 100644 --- a/examples/src/hello_window/main.rs +++ b/examples/src/hello_window/main.rs @@ -1,18 +1,28 @@ use sursface::{display::Display, wgpu::{self, TextureView}, winit::event::WindowEvent}; +use sursface::{app::AppHandlers, winit::dpi::PhysicalSize}; + #[cfg(target_arch = "wasm32")] use sursface::wasm_bindgen; #[cfg(not(target_arch = "wasm32"))] fn main() { - use sursface::winit::dpi::PhysicalSize; - sursface::start::create_window_desktop(PhysicalSize::new(1280, 720), &init, &render, &event); + sursface::start::create_window_desktop(PhysicalSize::new(1280, 720),AppHandlers { + init, + render, + event, + ..Default::default() + }); } #[cfg(target_arch = "wasm32")] #[wasm_bindgen::prelude::wasm_bindgen] pub fn start_browser(canvas: sursface::wgpu::web_sys::HtmlCanvasElement) { - use sursface::start; - start::create_window_browser(canvas, &init, &render, &event); + sursface::start::create_window_browser(canvas, AppHandlers { + init, + render, + event, + ..Default::default() + }); } #[cfg(target_arch = "wasm32")] diff --git a/examples/src/mandelbrot/main.rs b/examples/src/mandelbrot/main.rs index 7825b82..ee7585c 100644 --- a/examples/src/mandelbrot/main.rs +++ b/examples/src/mandelbrot/main.rs @@ -10,22 +10,31 @@ use sursface::{log, wgpu}; use sursface::cgmath::{Vector2, Zero}; use bytemuck::{Pod,Zeroable}; use std::fmt::Display as FmtDisplay; +use sursface::{app::AppHandlers, winit::dpi::PhysicalSize}; #[cfg(target_arch = "wasm32")] use sursface::wasm_bindgen; #[cfg(not(target_arch = "wasm32"))] fn main() { - use sursface::winit::dpi::PhysicalSize; - sursface::start::create_window_desktop(PhysicalSize::new(720, 720), &init, &render, &event); + sursface::start::create_window_desktop(PhysicalSize::new(720, 720), AppHandlers { + init, + render, + event, + ..Default::default() + }); } #[cfg(target_arch = "wasm32")] #[wasm_bindgen::prelude::wasm_bindgen] pub fn start_browser(canvas: sursface::wgpu::web_sys::HtmlCanvasElement) { - use sursface::start; - start::create_window_browser(canvas, &init, &render, &event); + sursface::start::create_window_browser(canvas, AppHandlers { + init, + render, + event, + ..Default::default() + }); } #[cfg(target_arch = "wasm32")] diff --git a/sursface/src/app.rs b/sursface/src/app.rs index a6f2553..7eeb110 100644 --- a/sursface/src/app.rs +++ b/sursface/src/app.rs @@ -1,7 +1,7 @@ use std::sync::{Arc, Mutex}; use winit::application::ApplicationHandler; use winit::dpi::PhysicalSize; -use winit::event::{ElementState, KeyEvent, WindowEvent}; +use winit::event::{DeviceEvent, ElementState, KeyEvent, WindowEvent}; use winit::event_loop::ActiveEventLoop; use winit::keyboard::{KeyCode, PhysicalKey}; use winit::window::WindowId; @@ -17,9 +17,25 @@ pub struct App<'a, State> { #[cfg(target_arch = "wasm32")] pub canvas: wgpu::web_sys::HtmlCanvasElement, pub state: Option>>, - pub init: Arc State>, - pub render: Arc, - pub event: Arc, + pub handlers: AppHandlers +} + +pub struct AppHandlers { + pub init: fn(&mut Display) -> State, + pub render: fn(&mut Display, &mut State), + pub event: fn(&mut Display, &mut State, WindowEvent), + pub device_event: fn(&mut Display, &mut State, DeviceEvent), +} + +impl Default for AppHandlers { + fn default() -> Self { + AppHandlers { + init: |_display: &mut Display| panic!("init handler not provided"), + render: |_display: &mut Display, _state: &mut State| {}, + event: |_display: &mut Display, _state: &mut State, _event: WindowEvent| {}, + device_event: |_display: &mut Display, _state: &mut State, _event: DeviceEvent| {}, + } + } } @@ -62,27 +78,23 @@ impl<'a, State> App<'a, State> { #[cfg(not(target_arch = "wasm32"))] pub fn from_window_size( size: PhysicalSize, - init_func: &'static dyn Fn(&mut Display) -> State, - render_func: &'static dyn Fn(&mut Display, &mut State), - event_func: &'static dyn Fn(&mut Display, &mut State, WindowEvent)) -> Self + handlers: AppHandlers) -> Self { + log::debug!("Setting window size"); App { initial_size: size, display: None, state: None, - init: Arc::new(init_func), - render: Arc::new(render_func), - event: Arc::new(event_func) + handlers } } + #[cfg(target_arch = "wasm32")] pub fn from_canvas( canvas: wgpu::web_sys::HtmlCanvasElement, - init_func: &'static dyn Fn(&mut Display) -> State, - render_func: &'static dyn Fn(&mut Display, &mut State), - event_func: &'static dyn Fn(&mut Display, &mut State, WindowEvent)) -> Self + handlers: AppHandlers) -> Self { log::debug!("Setting canvas size"); App { @@ -90,9 +102,7 @@ impl<'a, State> App<'a, State> { canvas, display: None, state: None, - init: Arc::new(init_func), - render: Arc::new(render_func), - event: Arc::new(event_func) + handlers } } } @@ -110,18 +120,13 @@ impl<'a, State> ApplicationHandler for App<'a, State> { self.display = Some(Arc::new(Mutex::new(Display::from_canvas(event_loop, self.canvas.clone())))); } - let new_state = { - let init_fn = Arc::clone(&self.init); - init_fn(&mut self.display.clone().unwrap().lock().unwrap()) - }; - - // Now, set the state with a mutable borrow + let new_state = (&self.handlers.init)(&mut self.display.clone().unwrap().lock().unwrap()); self.state = Some(Arc::new(Mutex::new(new_state))); } fn window_event(&mut self, event_loop: &ActiveEventLoop, _id: WindowId, event: WindowEvent) { let mut display = self.display.as_ref().clone().unwrap().lock().unwrap(); - (Arc::clone(&self.event))(&mut display, &mut self.state.clone().unwrap().lock().unwrap(), event.clone()); + (&self.handlers.event)(&mut display, &mut self.state.clone().unwrap().lock().unwrap(), event.clone()); match event { WindowEvent::CloseRequested @@ -141,10 +146,15 @@ impl<'a, State> ApplicationHandler for App<'a, State> { display.resize(physical_size); } WindowEvent::RedrawRequested => { - (Arc::clone(&self.render))(&mut display, &mut self.state.clone().unwrap().lock().unwrap()); + (self.handlers.render)(&mut display, &mut self.state.clone().unwrap().lock().unwrap()); display.window.as_ref().request_redraw(); } _ => () }; } + + fn device_event(&mut self, event_loop: &ActiveEventLoop, device_id: winit::event::DeviceId, event: winit::event::DeviceEvent) { + let mut display = self.display.as_ref().clone().unwrap().lock().unwrap(); + (self.handlers.device_event)(&mut display, &mut self.state.clone().unwrap().lock().unwrap(), event.clone()); + } } \ No newline at end of file diff --git a/sursface/src/start.rs b/sursface/src/start.rs index ad591f3..155b73b 100644 --- a/sursface/src/start.rs +++ b/sursface/src/start.rs @@ -4,7 +4,7 @@ use winit::event_loop::{ControlFlow, EventLoop}; use wgpu::web_sys::HtmlCanvasElement; use crate::app::App; -use crate::display::Display; +use crate::app::AppHandlers; #[cfg(target_arch = "wasm32")] extern crate console_error_panic_hook; @@ -12,29 +12,23 @@ extern crate console_error_panic_hook; #[cfg(not(target_arch = "wasm32"))] pub fn create_window_desktop( window_size: winit::dpi::PhysicalSize, - init: &'static (dyn Fn(&mut Display) -> State), - render: &'static dyn Fn(&mut Display, &mut State), - event: &'static dyn Fn(&mut Display, &mut State, winit::event::WindowEvent)) + handlers: AppHandlers) { - let event_loop = EventLoop::new().unwrap(); event_loop.set_control_flow(ControlFlow::Poll); - let mut app = App::from_window_size(window_size, init, render, event); + let mut app = App::from_window_size(window_size, handlers); event_loop.run_app(&mut app).unwrap(); } - #[cfg(target_arch = "wasm32")] pub fn create_window_browser( canvas: HtmlCanvasElement, - init: &'static (dyn Fn(&mut Display) -> State), - render: &'static dyn Fn(&mut Display, &mut State), - event: &'static dyn Fn(&mut Display, &mut State, winit::event::WindowEvent)) + handlers: AppHandlers) { let event_loop = EventLoop::new().unwrap(); event_loop.set_control_flow(ControlFlow::Poll); - let mut app = App::from_canvas(canvas, init, render, event); + let mut app = App::from_canvas(canvas, handlers); event_loop.run_app(&mut app).unwrap(); } \ No newline at end of file