From 33f507e169b8cfef38bc08890577e1dc2c1ab0ce Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Thu, 26 May 2022 10:40:10 +0200 Subject: [PATCH 01/22] Use custom type for screen position This is a step towards extracting the Winit-using parts from `fj-viewer` into their own crate. --- crates/fj-viewer/src/camera.rs | 7 +++---- crates/fj-viewer/src/input/handler.rs | 7 ++++--- crates/fj-viewer/src/input/movement.rs | 12 ++++-------- crates/fj-viewer/src/lib.rs | 1 + crates/fj-viewer/src/run.rs | 10 +++++++--- crates/fj-viewer/src/screen.rs | 11 +++++++++++ 6 files changed, 30 insertions(+), 18 deletions(-) create mode 100644 crates/fj-viewer/src/screen.rs diff --git a/crates/fj-viewer/src/camera.rs b/crates/fj-viewer/src/camera.rs index 54481ae6a..4174150e5 100644 --- a/crates/fj-viewer/src/camera.rs +++ b/crates/fj-viewer/src/camera.rs @@ -3,9 +3,8 @@ use std::f64::consts::FRAC_PI_2; use fj_interop::mesh::Mesh; use fj_math::{Aabb, Point, Scalar, Transform, Triangle, Vector}; -use winit::dpi::PhysicalPosition; -use crate::window::Window; +use crate::{screen::Position, window::Window}; /// The camera abstraction /// @@ -108,7 +107,7 @@ impl Camera { /// Transform the position of the cursor on the near plane to model space. pub fn cursor_to_model_space( &self, - cursor: PhysicalPosition, + cursor: Position, window: &Window, ) -> Point<3> { let width = window.width() as f64; @@ -132,7 +131,7 @@ impl Camera { pub fn focus_point( &self, window: &Window, - cursor: Option>, + cursor: Option, mesh: &Mesh>, ) -> FocusPoint { let cursor = match cursor { diff --git a/crates/fj-viewer/src/input/handler.rs b/crates/fj-viewer/src/input/handler.rs index 883ff195f..3901c3e6a 100644 --- a/crates/fj-viewer/src/input/handler.rs +++ b/crates/fj-viewer/src/input/handler.rs @@ -12,6 +12,7 @@ use winit::{ use crate::{ camera::{Camera, FocusPoint}, + screen::Position, window::Window, }; @@ -21,7 +22,7 @@ use super::{movement::Movement, rotation::Rotation, zoom::Zoom}; /// /// Takes user input and applies them to application state. pub struct Handler { - cursor: Option>, + cursor: Option, movement: Movement, rotation: Rotation, @@ -48,7 +49,7 @@ impl Handler { } /// Returns the state of the cursor position. - pub fn cursor(&self) -> Option> { + pub fn cursor(&self) -> Option { self.cursor } @@ -79,7 +80,7 @@ impl Handler { /// Applies cursor movement to `camera`. pub fn handle_cursor_moved( &mut self, - cursor: PhysicalPosition, + cursor: Position, camera: &mut Camera, window: &Window, ) { diff --git a/crates/fj-viewer/src/input/movement.rs b/crates/fj-viewer/src/input/movement.rs index c71f76160..10cc9cb8a 100644 --- a/crates/fj-viewer/src/input/movement.rs +++ b/crates/fj-viewer/src/input/movement.rs @@ -1,14 +1,14 @@ use fj_math::{Point, Scalar, Transform, Vector}; -use winit::dpi::PhysicalPosition; use crate::{ camera::{Camera, FocusPoint}, + screen::Position, window::Window, }; pub struct Movement { focus_point: FocusPoint, - cursor: Option>, + cursor: Option, } impl Movement { @@ -19,11 +19,7 @@ impl Movement { } } - pub fn start( - &mut self, - focus_point: FocusPoint, - cursor: Option>, - ) { + pub fn start(&mut self, focus_point: FocusPoint, cursor: Option) { self.focus_point = focus_point; self.cursor = cursor; } @@ -34,7 +30,7 @@ impl Movement { pub fn apply( &mut self, - cursor: Option>, + cursor: Option, camera: &mut Camera, window: &Window, ) { diff --git a/crates/fj-viewer/src/lib.rs b/crates/fj-viewer/src/lib.rs index 5c2d045f9..7f09ba3b7 100644 --- a/crates/fj-viewer/src/lib.rs +++ b/crates/fj-viewer/src/lib.rs @@ -18,4 +18,5 @@ pub mod camera; pub mod graphics; pub mod input; pub mod run; +pub mod screen; pub mod window; diff --git a/crates/fj-viewer/src/run.rs b/crates/fj-viewer/src/run.rs index 77bd1c944..e0a3c596e 100644 --- a/crates/fj-viewer/src/run.rs +++ b/crates/fj-viewer/src/run.rs @@ -17,7 +17,8 @@ use winit::{ use crate::{ camera::Camera, graphics::{self, DrawConfig, Renderer}, - input, + input::{self}, + screen::Position, window::{self, Window}, }; @@ -103,8 +104,11 @@ pub fn run( .. } => { if let Some(camera) = &mut camera { - input_handler - .handle_cursor_moved(position, camera, &window); + let cursor = Position { + x: position.x, + y: position.y, + }; + input_handler.handle_cursor_moved(cursor, camera, &window); } } Event::WindowEvent { diff --git a/crates/fj-viewer/src/screen.rs b/crates/fj-viewer/src/screen.rs new file mode 100644 index 000000000..34ae6bde7 --- /dev/null +++ b/crates/fj-viewer/src/screen.rs @@ -0,0 +1,11 @@ +//! Types that describe aspects of the screen + +/// A position on the screen +#[derive(Clone, Copy, Debug)] +pub struct Position { + /// The x coordinate of the position + pub x: f64, + + /// The y coordinate of the position + pub y: f64, +} From 557ccb61059e701b13efd604c9781fb6c598769f Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Thu, 26 May 2022 10:47:50 +0200 Subject: [PATCH 02/22] Use custom type for screen size --- crates/fj-viewer/src/graphics/renderer.rs | 5 ++--- crates/fj-viewer/src/run.rs | 6 +++++- crates/fj-viewer/src/screen.rs | 10 ++++++++++ 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/crates/fj-viewer/src/graphics/renderer.rs b/crates/fj-viewer/src/graphics/renderer.rs index 670bc76ae..3a2e656b5 100644 --- a/crates/fj-viewer/src/graphics/renderer.rs +++ b/crates/fj-viewer/src/graphics/renderer.rs @@ -5,9 +5,8 @@ use thiserror::Error; use tracing::debug; use wgpu::util::DeviceExt as _; use wgpu_glyph::ab_glyph::InvalidFont; -use winit::dpi::PhysicalSize; -use crate::{camera::Camera, window::Window}; +use crate::{camera::Camera, screen::Size, window::Window}; use super::{ config_ui::ConfigUi, draw_config::DrawConfig, drawables::Drawables, @@ -182,7 +181,7 @@ impl Renderer { /// /// # Arguments /// - `size`: The target size for the render surface. - pub fn handle_resize(&mut self, size: PhysicalSize) { + pub fn handle_resize(&mut self, size: Size) { self.surface_config.width = size.width; self.surface_config.height = size.height; diff --git a/crates/fj-viewer/src/run.rs b/crates/fj-viewer/src/run.rs index e0a3c596e..4c9727896 100644 --- a/crates/fj-viewer/src/run.rs +++ b/crates/fj-viewer/src/run.rs @@ -18,7 +18,7 @@ use crate::{ camera::Camera, graphics::{self, DrawConfig, Renderer}, input::{self}, - screen::Position, + screen::{Position, Size}, window::{self, Window}, }; @@ -91,6 +91,10 @@ pub fn run( event: WindowEvent::Resized(size), .. } => { + let size = Size { + width: size.width, + height: size.height, + }; renderer.handle_resize(size); } Event::WindowEvent { diff --git a/crates/fj-viewer/src/screen.rs b/crates/fj-viewer/src/screen.rs index 34ae6bde7..02d5ee596 100644 --- a/crates/fj-viewer/src/screen.rs +++ b/crates/fj-viewer/src/screen.rs @@ -9,3 +9,13 @@ pub struct Position { /// The y coordinate of the position pub y: f64, } + +/// The size of the screen +#[derive(Clone, Copy, Debug)] +pub struct Size { + /// The width of the screen + pub width: u32, + + /// The height of the screen + pub height: u32, +} From ad31754275a3b73a8d2c047058098b88bdda996f Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Thu, 26 May 2022 10:54:33 +0200 Subject: [PATCH 03/22] Replace separate size methods with `Window::size` --- crates/fj-viewer/src/camera.rs | 10 +++++++--- crates/fj-viewer/src/graphics/renderer.rs | 5 +++-- crates/fj-viewer/src/window.rs | 16 +++++++++------- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/crates/fj-viewer/src/camera.rs b/crates/fj-viewer/src/camera.rs index 4174150e5..b22c057d4 100644 --- a/crates/fj-viewer/src/camera.rs +++ b/crates/fj-viewer/src/camera.rs @@ -4,7 +4,10 @@ use std::f64::consts::FRAC_PI_2; use fj_interop::mesh::Mesh; use fj_math::{Aabb, Point, Scalar, Transform, Triangle, Vector}; -use crate::{screen::Position, window::Window}; +use crate::{ + screen::{Position, Size}, + window::Window, +}; /// The camera abstraction /// @@ -110,8 +113,9 @@ impl Camera { cursor: Position, window: &Window, ) -> Point<3> { - let width = window.width() as f64; - let height = window.height() as f64; + let Size { width, height } = window.size(); + let width = width as f64; + let height = height as f64; let aspect_ratio = width / height; // Cursor position in normalized coordinates (-1 to +1) with diff --git a/crates/fj-viewer/src/graphics/renderer.rs b/crates/fj-viewer/src/graphics/renderer.rs index 3a2e656b5..2a0121728 100644 --- a/crates/fj-viewer/src/graphics/renderer.rs +++ b/crates/fj-viewer/src/graphics/renderer.rs @@ -86,11 +86,12 @@ impl Renderer { .get_preferred_format(&adapter) .expect("Error determining preferred color format"); + let Size { width, height } = window.size(); let surface_config = wgpu::SurfaceConfiguration { usage: wgpu::TextureUsages::RENDER_ATTACHMENT, format: color_format, - width: window.width(), - height: window.height(), + width, + height, present_mode: wgpu::PresentMode::Mailbox, }; surface.configure(&device, &surface_config); diff --git a/crates/fj-viewer/src/window.rs b/crates/fj-viewer/src/window.rs index b65e09415..ea40f1cdc 100644 --- a/crates/fj-viewer/src/window.rs +++ b/crates/fj-viewer/src/window.rs @@ -2,6 +2,8 @@ use winit::{event_loop::EventLoop, window::WindowBuilder}; +use crate::screen::Size; + /// Window abstraction providing details such as the width or height and easing initialization. pub struct Window(winit::window::Window); @@ -29,14 +31,14 @@ impl Window { &self.0 } - /// Returns the width of the window - pub fn width(&self) -> u32 { - self.0.inner_size().width - } + /// Returns the size of the window + pub fn size(&self) -> Size { + let size = self.0.inner_size(); - /// Returns the height of the window - pub fn height(&self) -> u32 { - self.0.inner_size().height + Size { + width: size.width, + height: size.height, + } } } From 372cdbfd5a27f447cc6af3e7c12d1a3a58b27817 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Thu, 26 May 2022 10:57:33 +0200 Subject: [PATCH 04/22] Add `Size::as_f64` --- crates/fj-viewer/src/camera.rs | 9 ++------- crates/fj-viewer/src/screen.rs | 7 +++++++ 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/crates/fj-viewer/src/camera.rs b/crates/fj-viewer/src/camera.rs index b22c057d4..796805d40 100644 --- a/crates/fj-viewer/src/camera.rs +++ b/crates/fj-viewer/src/camera.rs @@ -4,10 +4,7 @@ use std::f64::consts::FRAC_PI_2; use fj_interop::mesh::Mesh; use fj_math::{Aabb, Point, Scalar, Transform, Triangle, Vector}; -use crate::{ - screen::{Position, Size}, - window::Window, -}; +use crate::{screen::Position, window::Window}; /// The camera abstraction /// @@ -113,9 +110,7 @@ impl Camera { cursor: Position, window: &Window, ) -> Point<3> { - let Size { width, height } = window.size(); - let width = width as f64; - let height = height as f64; + let [width, height] = window.size().as_f64(); let aspect_ratio = width / height; // Cursor position in normalized coordinates (-1 to +1) with diff --git a/crates/fj-viewer/src/screen.rs b/crates/fj-viewer/src/screen.rs index 02d5ee596..884741398 100644 --- a/crates/fj-viewer/src/screen.rs +++ b/crates/fj-viewer/src/screen.rs @@ -19,3 +19,10 @@ pub struct Size { /// The height of the screen pub height: u32, } + +impl Size { + /// Convert size to `f64` + pub fn as_f64(&self) -> [f64; 2] { + [self.width, self.height].map(Into::into) + } +} From 369982aaa85722715c92a320b46230eeeb490f17 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Thu, 26 May 2022 11:02:52 +0200 Subject: [PATCH 05/22] Add dependency on `raw-window-handle` --- Cargo.lock | 1 + crates/fj-viewer/Cargo.toml | 1 + 2 files changed, 2 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 3ff66621d..12496c304 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -809,6 +809,7 @@ dependencies = [ "fj-math", "fj-operations", "futures", + "raw-window-handle", "thiserror", "tracing", "wgpu", diff --git a/crates/fj-viewer/Cargo.toml b/crates/fj-viewer/Cargo.toml index 76746d747..ace7092de 100644 --- a/crates/fj-viewer/Cargo.toml +++ b/crates/fj-viewer/Cargo.toml @@ -15,6 +15,7 @@ categories = ["encoding", "mathematics", "rendering"] [dependencies] bytemuck = "1.9.1" futures = "0.3.21" +raw-window-handle = "0.4.3" thiserror = "1.0.31" tracing = "0.1.34" wgpu = "0.12.0" From d4c49bcf4d8d283edbd7bc40e7c99812140e2f29 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Thu, 26 May 2022 11:04:32 +0200 Subject: [PATCH 06/22] Add `Screen` trait --- crates/fj-viewer/src/screen.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/crates/fj-viewer/src/screen.rs b/crates/fj-viewer/src/screen.rs index 884741398..5b3e8678e 100644 --- a/crates/fj-viewer/src/screen.rs +++ b/crates/fj-viewer/src/screen.rs @@ -1,5 +1,19 @@ //! Types that describe aspects of the screen +pub use raw_window_handle::HasRawWindowHandle; + +/// Needs to be implemented by types that can serve as a screen to render to +pub trait Screen { + /// The window + type Window: HasRawWindowHandle; + + /// Access the size of the screen + fn size(&self) -> Size; + + /// Access the window + fn window(&self) -> &Self::Window; +} + /// A position on the screen #[derive(Clone, Copy, Debug)] pub struct Position { From 8ff13800a716a3575a1aa6ec0808327e80f05073 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Thu, 26 May 2022 11:07:29 +0200 Subject: [PATCH 07/22] Don't expect `Window` where `Size` is required --- crates/fj-viewer/src/camera.rs | 10 +++++----- crates/fj-viewer/src/input/handler.rs | 11 +++++------ crates/fj-viewer/src/input/movement.rs | 9 ++++----- crates/fj-viewer/src/run.rs | 10 +++++++--- 4 files changed, 21 insertions(+), 19 deletions(-) diff --git a/crates/fj-viewer/src/camera.rs b/crates/fj-viewer/src/camera.rs index 796805d40..0a3d5f8a3 100644 --- a/crates/fj-viewer/src/camera.rs +++ b/crates/fj-viewer/src/camera.rs @@ -4,7 +4,7 @@ use std::f64::consts::FRAC_PI_2; use fj_interop::mesh::Mesh; use fj_math::{Aabb, Point, Scalar, Transform, Triangle, Vector}; -use crate::{screen::Position, window::Window}; +use crate::screen::{Position, Size}; /// The camera abstraction /// @@ -108,9 +108,9 @@ impl Camera { pub fn cursor_to_model_space( &self, cursor: Position, - window: &Window, + size: Size, ) -> Point<3> { - let [width, height] = window.size().as_f64(); + let [width, height] = size.as_f64(); let aspect_ratio = width / height; // Cursor position in normalized coordinates (-1 to +1) with @@ -129,7 +129,7 @@ impl Camera { /// Compute the point on the model, that the cursor currently points to. pub fn focus_point( &self, - window: &Window, + size: Size, cursor: Option, mesh: &Mesh>, ) -> FocusPoint { @@ -140,7 +140,7 @@ impl Camera { // Transform camera and cursor positions to model space. let origin = self.position(); - let cursor = self.cursor_to_model_space(cursor, window); + let cursor = self.cursor_to_model_space(cursor, size); let dir = (cursor - origin).normalize(); let mut min_t = None; diff --git a/crates/fj-viewer/src/input/handler.rs b/crates/fj-viewer/src/input/handler.rs index 3901c3e6a..04f204bfc 100644 --- a/crates/fj-viewer/src/input/handler.rs +++ b/crates/fj-viewer/src/input/handler.rs @@ -12,8 +12,7 @@ use winit::{ use crate::{ camera::{Camera, FocusPoint}, - screen::Position, - window::Window, + screen::{Position, Size}, }; use super::{movement::Movement, rotation::Rotation, zoom::Zoom}; @@ -82,13 +81,13 @@ impl Handler { &mut self, cursor: Position, camera: &mut Camera, - window: &Window, + size: Size, ) { if let Some(previous) = self.cursor { let diff_x = cursor.x - previous.x; let diff_y = cursor.y - previous.y; - self.movement.apply(self.cursor, camera, window); + self.movement.apply(self.cursor, camera, size); self.rotation.apply(diff_x, diff_y, camera); } @@ -139,10 +138,10 @@ impl Handler { delta_t: f64, now: Instant, camera: &mut Camera, - window: &Window, + size: Size, mesh: &Mesh>, ) { - let focus_point = camera.focus_point(window, self.cursor, mesh); + let focus_point = camera.focus_point(size, self.cursor, mesh); self.zoom.discard_old_events(now); self.zoom.update_speed(now, delta_t, focus_point, camera); diff --git a/crates/fj-viewer/src/input/movement.rs b/crates/fj-viewer/src/input/movement.rs index 10cc9cb8a..b1e4aeba8 100644 --- a/crates/fj-viewer/src/input/movement.rs +++ b/crates/fj-viewer/src/input/movement.rs @@ -2,8 +2,7 @@ use fj_math::{Point, Scalar, Transform, Vector}; use crate::{ camera::{Camera, FocusPoint}, - screen::Position, - window::Window, + screen::{Position, Size}, }; pub struct Movement { @@ -32,11 +31,11 @@ impl Movement { &mut self, cursor: Option, camera: &mut Camera, - window: &Window, + size: Size, ) { if let (Some(previous), Some(cursor)) = (self.cursor, cursor) { - let previous = camera.cursor_to_model_space(previous, window); - let cursor = camera.cursor_to_model_space(cursor, window); + let previous = camera.cursor_to_model_space(previous, size); + let cursor = camera.cursor_to_model_space(cursor, size); if let Some(focus_point) = self.focus_point.0 { let d1 = Point::distance(&camera.position(), &cursor); diff --git a/crates/fj-viewer/src/run.rs b/crates/fj-viewer/src/run.rs index 4c9727896..6b37a4e97 100644 --- a/crates/fj-viewer/src/run.rs +++ b/crates/fj-viewer/src/run.rs @@ -112,7 +112,11 @@ pub fn run( x: position.x, y: position.y, }; - input_handler.handle_cursor_moved(cursor, camera, &window); + input_handler.handle_cursor_moved( + cursor, + camera, + window.size(), + ); } } Event::WindowEvent { @@ -121,7 +125,7 @@ pub fn run( } => { if let (Some(shape), Some(camera)) = (&shape, &camera) { let focus_point = camera.focus_point( - &window, + window.size(), input_handler.cursor(), &shape.mesh, ); @@ -148,7 +152,7 @@ pub fn run( delta_t.as_secs_f64(), now, camera, - &window, + window.size(), &shape.mesh, ); } From 5e395432c1de65242f71d7142724b3556fa36290 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Thu, 26 May 2022 11:14:26 +0200 Subject: [PATCH 08/22] Implement `Screen` for `Window` --- crates/fj-viewer/src/graphics/renderer.rs | 8 ++++++-- crates/fj-viewer/src/run.rs | 4 ++-- crates/fj-viewer/src/window.rs | 16 +++++++++------- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/crates/fj-viewer/src/graphics/renderer.rs b/crates/fj-viewer/src/graphics/renderer.rs index 2a0121728..c910fbefd 100644 --- a/crates/fj-viewer/src/graphics/renderer.rs +++ b/crates/fj-viewer/src/graphics/renderer.rs @@ -6,7 +6,11 @@ use tracing::debug; use wgpu::util::DeviceExt as _; use wgpu_glyph::ab_glyph::InvalidFont; -use crate::{camera::Camera, screen::Size, window::Window}; +use crate::{ + camera::Camera, + screen::{Screen as _, Size}, + window::Window, +}; use super::{ config_ui::ConfigUi, draw_config::DrawConfig, drawables::Drawables, @@ -54,7 +58,7 @@ impl Renderer { let instance = wgpu::Instance::new(wgpu::Backends::PRIMARY); // This is sound, as `window` is an object to create a surface upon. - let surface = unsafe { instance.create_surface(window.inner()) }; + let surface = unsafe { instance.create_surface(window.window()) }; let adapter = instance .request_adapter(&wgpu::RequestAdapterOptions { diff --git a/crates/fj-viewer/src/run.rs b/crates/fj-viewer/src/run.rs index 6b37a4e97..cb3f0e4b9 100644 --- a/crates/fj-viewer/src/run.rs +++ b/crates/fj-viewer/src/run.rs @@ -18,7 +18,7 @@ use crate::{ camera::Camera, graphics::{self, DrawConfig, Renderer}, input::{self}, - screen::{Position, Size}, + screen::{Position, Screen as _, Size}, window::{self, Window}, }; @@ -157,7 +157,7 @@ pub fn run( ); } - window.inner().request_redraw(); + window.window().request_redraw(); } Event::RedrawRequested(_) => { if let (Some(shape), Some(camera)) = (&shape, &mut camera) { diff --git a/crates/fj-viewer/src/window.rs b/crates/fj-viewer/src/window.rs index ea40f1cdc..c267fb383 100644 --- a/crates/fj-viewer/src/window.rs +++ b/crates/fj-viewer/src/window.rs @@ -2,7 +2,7 @@ use winit::{event_loop::EventLoop, window::WindowBuilder}; -use crate::screen::Size; +use crate::screen::{Screen, Size}; /// Window abstraction providing details such as the width or height and easing initialization. pub struct Window(winit::window::Window); @@ -25,14 +25,12 @@ impl Window { Ok(Self(window)) } +} - /// Returns a shared reference to the wrapped window - pub fn inner(&self) -> &winit::window::Window { - &self.0 - } +impl Screen for Window { + type Window = winit::window::Window; - /// Returns the size of the window - pub fn size(&self) -> Size { + fn size(&self) -> Size { let size = self.0.inner_size(); Size { @@ -40,6 +38,10 @@ impl Window { height: size.height, } } + + fn window(&self) -> &winit::window::Window { + &self.0 + } } /// Error initializing window From c28b169b3572f30b3fd16a206fc525131c90ac08 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Thu, 26 May 2022 11:15:19 +0200 Subject: [PATCH 09/22] Remove dependency of `Renderer` on `Window` --- crates/fj-viewer/src/graphics/renderer.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/crates/fj-viewer/src/graphics/renderer.rs b/crates/fj-viewer/src/graphics/renderer.rs index c910fbefd..b4cf2318d 100644 --- a/crates/fj-viewer/src/graphics/renderer.rs +++ b/crates/fj-viewer/src/graphics/renderer.rs @@ -8,8 +8,7 @@ use wgpu_glyph::ab_glyph::InvalidFont; use crate::{ camera::Camera, - screen::{Screen as _, Size}, - window::Window, + screen::{Screen, Size}, }; use super::{ @@ -54,7 +53,7 @@ impl Renderer { /// // Attach renderer to the window /// let mut renderer = graphics::Renderer::new(&window); /// ``` - pub async fn new(window: &Window) -> Result { + pub async fn new(window: &impl Screen) -> Result { let instance = wgpu::Instance::new(wgpu::Backends::PRIMARY); // This is sound, as `window` is an object to create a surface upon. From 8b8062ac6141b4bb2cebd5b70bd0aebb78407a9b Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Thu, 26 May 2022 11:15:53 +0200 Subject: [PATCH 10/22] Update parameter name --- crates/fj-viewer/src/graphics/renderer.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/fj-viewer/src/graphics/renderer.rs b/crates/fj-viewer/src/graphics/renderer.rs index b4cf2318d..24ce343b2 100644 --- a/crates/fj-viewer/src/graphics/renderer.rs +++ b/crates/fj-viewer/src/graphics/renderer.rs @@ -53,11 +53,11 @@ impl Renderer { /// // Attach renderer to the window /// let mut renderer = graphics::Renderer::new(&window); /// ``` - pub async fn new(window: &impl Screen) -> Result { + pub async fn new(screen: &impl Screen) -> Result { let instance = wgpu::Instance::new(wgpu::Backends::PRIMARY); // This is sound, as `window` is an object to create a surface upon. - let surface = unsafe { instance.create_surface(window.window()) }; + let surface = unsafe { instance.create_surface(screen.window()) }; let adapter = instance .request_adapter(&wgpu::RequestAdapterOptions { @@ -89,7 +89,7 @@ impl Renderer { .get_preferred_format(&adapter) .expect("Error determining preferred color format"); - let Size { width, height } = window.size(); + let Size { width, height } = screen.size(); let surface_config = wgpu::SurfaceConfiguration { usage: wgpu::TextureUsages::RENDER_ATTACHMENT, format: color_format, From 5d2eb27d6fde85a9c486b2bc9b15f43cf74971c7 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Thu, 26 May 2022 11:16:03 +0200 Subject: [PATCH 11/22] Remove outdated part of doc comment --- crates/fj-viewer/src/graphics/renderer.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/crates/fj-viewer/src/graphics/renderer.rs b/crates/fj-viewer/src/graphics/renderer.rs index 24ce343b2..a964ebdb9 100644 --- a/crates/fj-viewer/src/graphics/renderer.rs +++ b/crates/fj-viewer/src/graphics/renderer.rs @@ -39,9 +39,6 @@ pub struct Renderer { impl Renderer { /// Returns a new `Renderer`. /// - /// # Arguments - /// - `window` - a `crate::window::Window` with a surface to render onto. - /// /// # Examples /// ```rust no_run /// use fj_viewer::{graphics, window}; From b3a2ee6f90bf068bb9e64cdbfadd88188ac51546 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Thu, 26 May 2022 11:30:40 +0200 Subject: [PATCH 12/22] Handle keyboard input through new `Event` enum This is another step towards decoupling the input code from Winit. --- crates/fj-viewer/src/input/event.rs | 20 ++++++++++++++ crates/fj-viewer/src/input/handler.rs | 38 +++++++++------------------ crates/fj-viewer/src/input/mod.rs | 6 ++++- crates/fj-viewer/src/run.rs | 34 +++++++++++++++++++++--- 4 files changed, 68 insertions(+), 30 deletions(-) create mode 100644 crates/fj-viewer/src/input/event.rs diff --git a/crates/fj-viewer/src/input/event.rs b/crates/fj-viewer/src/input/event.rs new file mode 100644 index 000000000..453ab2083 --- /dev/null +++ b/crates/fj-viewer/src/input/event.rs @@ -0,0 +1,20 @@ +/// An input event +pub enum Event { + /// A key has been pressed + KeyPressed(Key), +} + +/// A keyboard or mouse key +pub enum Key { + /// The escape key + Escape, + + /// The numerical key `1` + Key1, + + /// The numerical key `2` + Key2, + + /// The numerical key `3` + Key3, +} diff --git a/crates/fj-viewer/src/input/handler.rs b/crates/fj-viewer/src/input/handler.rs index 04f204bfc..33f1f8347 100644 --- a/crates/fj-viewer/src/input/handler.rs +++ b/crates/fj-viewer/src/input/handler.rs @@ -4,10 +4,7 @@ use fj_interop::mesh::Mesh; use fj_math::{Point, Transform, Vector}; use winit::{ dpi::PhysicalPosition, - event::{ - ElementState, KeyboardInput, MouseButton, MouseScrollDelta, - VirtualKeyCode, - }, + event::{ElementState, MouseButton, MouseScrollDelta}, }; use crate::{ @@ -15,7 +12,7 @@ use crate::{ screen::{Position, Size}, }; -use super::{movement::Movement, rotation::Rotation, zoom::Zoom}; +use super::{movement::Movement, rotation::Rotation, zoom::Zoom, Event, Key}; /// Input handling abstraction /// @@ -52,27 +49,16 @@ impl Handler { self.cursor } - /// Applies user input to `actions`. - pub fn handle_keyboard_input( - &mut self, - input: KeyboardInput, - actions: &mut Actions, - ) { - if let KeyboardInput { - state: ElementState::Pressed, - virtual_keycode: Some(virtual_key_code), - .. - } = input - { - match virtual_key_code { - VirtualKeyCode::Escape => actions.exit = true, - - VirtualKeyCode::Key1 => actions.toggle_model = true, - VirtualKeyCode::Key2 => actions.toggle_mesh = true, - VirtualKeyCode::Key3 => actions.toggle_debug = true, - - _ => (), - } + /// Handle an input event + pub fn handle_event(&mut self, event: Event, actions: &mut Actions) { + match event { + Event::KeyPressed(key) => match key { + Key::Escape => actions.exit = true, + + Key::Key1 => actions.toggle_model = true, + Key::Key2 => actions.toggle_mesh = true, + Key::Key3 => actions.toggle_debug = true, + }, } } diff --git a/crates/fj-viewer/src/input/mod.rs b/crates/fj-viewer/src/input/mod.rs index 38c18673f..21cee1df0 100644 --- a/crates/fj-viewer/src/input/mod.rs +++ b/crates/fj-viewer/src/input/mod.rs @@ -1,8 +1,12 @@ //! User input parsing and propagation. +mod event; mod handler; mod movement; mod rotation; mod zoom; -pub use self::handler::{Actions, Handler}; +pub use self::{ + event::{Event, Key}, + handler::{Actions, Handler}, +}; diff --git a/crates/fj-viewer/src/run.rs b/crates/fj-viewer/src/run.rs index cb3f0e4b9..88bf28123 100644 --- a/crates/fj-viewer/src/run.rs +++ b/crates/fj-viewer/src/run.rs @@ -10,7 +10,7 @@ use fj_operations::shape_processor::ShapeProcessor; use futures::executor::block_on; use tracing::{trace, warn}; use winit::{ - event::{Event, WindowEvent}, + event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent}, event_loop::{ControlFlow, EventLoop}, }; @@ -98,10 +98,38 @@ pub fn run( renderer.handle_resize(size); } Event::WindowEvent { - event: WindowEvent::KeyboardInput { input, .. }, + event: + WindowEvent::KeyboardInput { + input: + KeyboardInput { + state: ElementState::Pressed, + virtual_keycode: Some(virtual_key_code), + .. + }, + .. + }, .. } => { - input_handler.handle_keyboard_input(input, &mut actions); + let event = match virtual_key_code { + VirtualKeyCode::Escape => { + Some(input::Event::KeyPressed(input::Key::Escape)) + } + VirtualKeyCode::Key1 => { + Some(input::Event::KeyPressed(input::Key::Key1)) + } + VirtualKeyCode::Key2 => { + Some(input::Event::KeyPressed(input::Key::Key2)) + } + VirtualKeyCode::Key3 => { + Some(input::Event::KeyPressed(input::Key::Key3)) + } + + _ => None, + }; + + if let Some(event) = event { + input_handler.handle_event(event, &mut actions); + } } Event::WindowEvent { event: WindowEvent::CursorMoved { position, .. }, From 650ded7e8b4949058cac985840814694cf1f87e1 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Thu, 26 May 2022 11:34:19 +0200 Subject: [PATCH 13/22] Update argument name --- crates/fj-viewer/src/input/handler.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/fj-viewer/src/input/handler.rs b/crates/fj-viewer/src/input/handler.rs index 33f1f8347..980c8de66 100644 --- a/crates/fj-viewer/src/input/handler.rs +++ b/crates/fj-viewer/src/input/handler.rs @@ -65,19 +65,19 @@ impl Handler { /// Applies cursor movement to `camera`. pub fn handle_cursor_moved( &mut self, - cursor: Position, + position: Position, camera: &mut Camera, size: Size, ) { if let Some(previous) = self.cursor { - let diff_x = cursor.x - previous.x; - let diff_y = cursor.y - previous.y; + let diff_x = position.x - previous.x; + let diff_y = position.y - previous.y; self.movement.apply(self.cursor, camera, size); self.rotation.apply(diff_x, diff_y, camera); } - self.cursor = Some(cursor); + self.cursor = Some(position); } /// Updates `state` and `focus_point` when mouse is clicked. From e46e2fbee79238ddc88dc350fd4b0bca66a97b0b Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Thu, 26 May 2022 11:36:31 +0200 Subject: [PATCH 14/22] Make argument name more explicit --- crates/fj-viewer/src/input/handler.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/fj-viewer/src/input/handler.rs b/crates/fj-viewer/src/input/handler.rs index 980c8de66..17d0fd3ae 100644 --- a/crates/fj-viewer/src/input/handler.rs +++ b/crates/fj-viewer/src/input/handler.rs @@ -67,13 +67,13 @@ impl Handler { &mut self, position: Position, camera: &mut Camera, - size: Size, + screen_size: Size, ) { if let Some(previous) = self.cursor { let diff_x = position.x - previous.x; let diff_y = position.y - previous.y; - self.movement.apply(self.cursor, camera, size); + self.movement.apply(self.cursor, camera, screen_size); self.rotation.apply(diff_x, diff_y, camera); } From b77bead9668262b0a1fa686efaf74d9aee40a573 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Thu, 26 May 2022 11:40:03 +0200 Subject: [PATCH 15/22] Prepare event handling for extended use of `Event` --- crates/fj-viewer/src/run.rs | 56 ++++++++++++++++++++++--------------- 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/crates/fj-viewer/src/run.rs b/crates/fj-viewer/src/run.rs index 88bf28123..54e9d04ba 100644 --- a/crates/fj-viewer/src/run.rs +++ b/crates/fj-viewer/src/run.rs @@ -80,12 +80,13 @@ pub fn run( } } - match event { + let event = match event { Event::WindowEvent { event: WindowEvent::CloseRequested, .. } => { *control_flow = ControlFlow::Exit; + None } Event::WindowEvent { event: WindowEvent::Resized(size), @@ -96,6 +97,8 @@ pub fn run( height: size.height, }; renderer.handle_resize(size); + + None } Event::WindowEvent { event: @@ -109,28 +112,22 @@ pub fn run( .. }, .. - } => { - let event = match virtual_key_code { - VirtualKeyCode::Escape => { - Some(input::Event::KeyPressed(input::Key::Escape)) - } - VirtualKeyCode::Key1 => { - Some(input::Event::KeyPressed(input::Key::Key1)) - } - VirtualKeyCode::Key2 => { - Some(input::Event::KeyPressed(input::Key::Key2)) - } - VirtualKeyCode::Key3 => { - Some(input::Event::KeyPressed(input::Key::Key3)) - } - - _ => None, - }; - - if let Some(event) = event { - input_handler.handle_event(event, &mut actions); + } => match virtual_key_code { + VirtualKeyCode::Escape => { + Some(input::Event::KeyPressed(input::Key::Escape)) } - } + VirtualKeyCode::Key1 => { + Some(input::Event::KeyPressed(input::Key::Key1)) + } + VirtualKeyCode::Key2 => { + Some(input::Event::KeyPressed(input::Key::Key2)) + } + VirtualKeyCode::Key3 => { + Some(input::Event::KeyPressed(input::Key::Key3)) + } + + _ => None, + }, Event::WindowEvent { event: WindowEvent::CursorMoved { position, .. }, .. @@ -146,6 +143,8 @@ pub fn run( window.size(), ); } + + None } Event::WindowEvent { event: WindowEvent::MouseInput { state, button, .. }, @@ -164,12 +163,15 @@ pub fn run( focus_point, ); } + + None } Event::WindowEvent { event: WindowEvent::MouseWheel { delta, .. }, .. } => { input_handler.handle_mouse_wheel(delta, now); + None } Event::MainEventsCleared => { let delta_t = now.duration_since(previous_time); @@ -186,6 +188,8 @@ pub fn run( } window.window().request_redraw(); + + None } Event::RedrawRequested(_) => { if let (Some(shape), Some(camera)) = (&shape, &mut camera) { @@ -195,8 +199,14 @@ pub fn run( warn!("Draw error: {}", err); } } + + None } - _ => {} + _ => None, + }; + + if let Some(event) = event { + input_handler.handle_event(event, &mut actions); } if actions.exit { From 5b496a8f947b8b0a70a0268edda67f280c982607 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Thu, 26 May 2022 11:43:26 +0200 Subject: [PATCH 16/22] Update variable name --- crates/fj-viewer/src/run.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/fj-viewer/src/run.rs b/crates/fj-viewer/src/run.rs index 54e9d04ba..ab7708b30 100644 --- a/crates/fj-viewer/src/run.rs +++ b/crates/fj-viewer/src/run.rs @@ -133,12 +133,12 @@ pub fn run( .. } => { if let Some(camera) = &mut camera { - let cursor = Position { + let position = Position { x: position.x, y: position.y, }; input_handler.handle_cursor_moved( - cursor, + position, camera, window.size(), ); From 6f615e5d8beedefc4311845facf62b5d5e8bcbc6 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Thu, 26 May 2022 11:44:27 +0200 Subject: [PATCH 17/22] Handle cursor move through `Event` --- crates/fj-viewer/src/input/event.rs | 5 ++++ crates/fj-viewer/src/input/handler.rs | 37 +++++++++++++-------------- crates/fj-viewer/src/run.rs | 27 +++++++++---------- 3 files changed, 35 insertions(+), 34 deletions(-) diff --git a/crates/fj-viewer/src/input/event.rs b/crates/fj-viewer/src/input/event.rs index 453ab2083..3fb7a752d 100644 --- a/crates/fj-viewer/src/input/event.rs +++ b/crates/fj-viewer/src/input/event.rs @@ -1,5 +1,10 @@ +use crate::screen::Position; + /// An input event pub enum Event { + /// The cursor has moved to another position + CursorMoved(Position), + /// A key has been pressed KeyPressed(Key), } diff --git a/crates/fj-viewer/src/input/handler.rs b/crates/fj-viewer/src/input/handler.rs index 17d0fd3ae..a77c31c41 100644 --- a/crates/fj-viewer/src/input/handler.rs +++ b/crates/fj-viewer/src/input/handler.rs @@ -50,8 +50,25 @@ impl Handler { } /// Handle an input event - pub fn handle_event(&mut self, event: Event, actions: &mut Actions) { + pub fn handle_event( + &mut self, + event: Event, + screen_size: Size, + camera: &mut Camera, + actions: &mut Actions, + ) { match event { + Event::CursorMoved(position) => { + if let Some(previous) = self.cursor { + let diff_x = position.x - previous.x; + let diff_y = position.y - previous.y; + + self.movement.apply(self.cursor, camera, screen_size); + self.rotation.apply(diff_x, diff_y, camera); + } + + self.cursor = Some(position); + } Event::KeyPressed(key) => match key { Key::Escape => actions.exit = true, @@ -62,24 +79,6 @@ impl Handler { } } - /// Applies cursor movement to `camera`. - pub fn handle_cursor_moved( - &mut self, - position: Position, - camera: &mut Camera, - screen_size: Size, - ) { - if let Some(previous) = self.cursor { - let diff_x = position.x - previous.x; - let diff_y = position.y - previous.y; - - self.movement.apply(self.cursor, camera, screen_size); - self.rotation.apply(diff_x, diff_y, camera); - } - - self.cursor = Some(position); - } - /// Updates `state` and `focus_point` when mouse is clicked. pub fn handle_mouse_input( &mut self, diff --git a/crates/fj-viewer/src/run.rs b/crates/fj-viewer/src/run.rs index ab7708b30..25aac00d3 100644 --- a/crates/fj-viewer/src/run.rs +++ b/crates/fj-viewer/src/run.rs @@ -132,19 +132,11 @@ pub fn run( event: WindowEvent::CursorMoved { position, .. }, .. } => { - if let Some(camera) = &mut camera { - let position = Position { - x: position.x, - y: position.y, - }; - input_handler.handle_cursor_moved( - position, - camera, - window.size(), - ); - } - - None + let position = Position { + x: position.x, + y: position.y, + }; + Some(input::Event::CursorMoved(position)) } Event::WindowEvent { event: WindowEvent::MouseInput { state, button, .. }, @@ -205,8 +197,13 @@ pub fn run( _ => None, }; - if let Some(event) = event { - input_handler.handle_event(event, &mut actions); + if let (Some(event), Some(camera)) = (event, &mut camera) { + input_handler.handle_event( + event, + window.size(), + camera, + &mut actions, + ); } if actions.exit { From 340b06129d302b0b202e30893373f51c2d2244e1 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Thu, 26 May 2022 11:48:23 +0200 Subject: [PATCH 18/22] Add support for releasing keys to `Event` --- crates/fj-viewer/src/input/event.rs | 13 +++++++++++-- crates/fj-viewer/src/input/handler.rs | 23 ++++++++++++++++------- crates/fj-viewer/src/input/mod.rs | 2 +- crates/fj-viewer/src/run.rs | 15 ++++++++------- 4 files changed, 36 insertions(+), 17 deletions(-) diff --git a/crates/fj-viewer/src/input/event.rs b/crates/fj-viewer/src/input/event.rs index 3fb7a752d..c5ff2820d 100644 --- a/crates/fj-viewer/src/input/event.rs +++ b/crates/fj-viewer/src/input/event.rs @@ -5,8 +5,8 @@ pub enum Event { /// The cursor has moved to another position CursorMoved(Position), - /// A key has been pressed - KeyPressed(Key), + /// A key has been pressed or released + Key(Key, KeyState), } /// A keyboard or mouse key @@ -23,3 +23,12 @@ pub enum Key { /// The numerical key `3` Key3, } + +/// Defines the meaning of a key event +pub enum KeyState { + /// A key was pressed + Pressed, + + /// A key was released + Released, +} diff --git a/crates/fj-viewer/src/input/handler.rs b/crates/fj-viewer/src/input/handler.rs index a77c31c41..8fce2e562 100644 --- a/crates/fj-viewer/src/input/handler.rs +++ b/crates/fj-viewer/src/input/handler.rs @@ -12,7 +12,10 @@ use crate::{ screen::{Position, Size}, }; -use super::{movement::Movement, rotation::Rotation, zoom::Zoom, Event, Key}; +use super::{ + event::KeyState, movement::Movement, rotation::Rotation, zoom::Zoom, Event, + Key, +}; /// Input handling abstraction /// @@ -69,13 +72,19 @@ impl Handler { self.cursor = Some(position); } - Event::KeyPressed(key) => match key { - Key::Escape => actions.exit = true, + Event::Key(Key::Escape, KeyState::Pressed) => actions.exit = true, + + Event::Key(Key::Key1, KeyState::Pressed) => { + actions.toggle_model = true + } + Event::Key(Key::Key2, KeyState::Pressed) => { + actions.toggle_mesh = true + } + Event::Key(Key::Key3, KeyState::Pressed) => { + actions.toggle_debug = true + } - Key::Key1 => actions.toggle_model = true, - Key::Key2 => actions.toggle_mesh = true, - Key::Key3 => actions.toggle_debug = true, - }, + _ => {} } } diff --git a/crates/fj-viewer/src/input/mod.rs b/crates/fj-viewer/src/input/mod.rs index 21cee1df0..3de606fe4 100644 --- a/crates/fj-viewer/src/input/mod.rs +++ b/crates/fj-viewer/src/input/mod.rs @@ -7,6 +7,6 @@ mod rotation; mod zoom; pub use self::{ - event::{Event, Key}, + event::{Event, Key, KeyState}, handler::{Actions, Handler}, }; diff --git a/crates/fj-viewer/src/run.rs b/crates/fj-viewer/src/run.rs index 25aac00d3..c1e3d759e 100644 --- a/crates/fj-viewer/src/run.rs +++ b/crates/fj-viewer/src/run.rs @@ -17,7 +17,7 @@ use winit::{ use crate::{ camera::Camera, graphics::{self, DrawConfig, Renderer}, - input::{self}, + input::{self, KeyState}, screen::{Position, Screen as _, Size}, window::{self, Window}, }; @@ -113,17 +113,18 @@ pub fn run( }, .. } => match virtual_key_code { - VirtualKeyCode::Escape => { - Some(input::Event::KeyPressed(input::Key::Escape)) - } + VirtualKeyCode::Escape => Some(input::Event::Key( + input::Key::Escape, + KeyState::Pressed, + )), VirtualKeyCode::Key1 => { - Some(input::Event::KeyPressed(input::Key::Key1)) + Some(input::Event::Key(input::Key::Key1, KeyState::Pressed)) } VirtualKeyCode::Key2 => { - Some(input::Event::KeyPressed(input::Key::Key2)) + Some(input::Event::Key(input::Key::Key2, KeyState::Pressed)) } VirtualKeyCode::Key3 => { - Some(input::Event::KeyPressed(input::Key::Key3)) + Some(input::Event::Key(input::Key::Key3, KeyState::Pressed)) } _ => None, From ddb34577ba255e7f868b2dc0e0a0f8d2b9ad0ed6 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Thu, 26 May 2022 11:58:52 +0200 Subject: [PATCH 19/22] Handle mouse buttons through `Event` --- crates/fj-viewer/src/input/event.rs | 6 ++++ crates/fj-viewer/src/input/handler.rs | 27 +++++------------- crates/fj-viewer/src/run.rs | 41 +++++++++++++++++---------- 3 files changed, 39 insertions(+), 35 deletions(-) diff --git a/crates/fj-viewer/src/input/event.rs b/crates/fj-viewer/src/input/event.rs index c5ff2820d..4b8a54c29 100644 --- a/crates/fj-viewer/src/input/event.rs +++ b/crates/fj-viewer/src/input/event.rs @@ -22,6 +22,12 @@ pub enum Key { /// The numerical key `3` Key3, + + /// The left mouse key + MouseLeft, + + /// The right mouse key + MouseRight, } /// Defines the meaning of a key event diff --git a/crates/fj-viewer/src/input/handler.rs b/crates/fj-viewer/src/input/handler.rs index 8fce2e562..d8ef1ddf0 100644 --- a/crates/fj-viewer/src/input/handler.rs +++ b/crates/fj-viewer/src/input/handler.rs @@ -2,10 +2,7 @@ use std::time::Instant; use fj_interop::mesh::Mesh; use fj_math::{Point, Transform, Vector}; -use winit::{ - dpi::PhysicalPosition, - event::{ElementState, MouseButton, MouseScrollDelta}, -}; +use winit::{dpi::PhysicalPosition, event::MouseScrollDelta}; use crate::{ camera::{Camera, FocusPoint}, @@ -57,6 +54,7 @@ impl Handler { &mut self, event: Event, screen_size: Size, + focus_point: FocusPoint, camera: &mut Camera, actions: &mut Actions, ) { @@ -84,30 +82,19 @@ impl Handler { actions.toggle_debug = true } - _ => {} - } - } - - /// Updates `state` and `focus_point` when mouse is clicked. - pub fn handle_mouse_input( - &mut self, - button: MouseButton, - state: ElementState, - focus_point: FocusPoint, - ) { - match (button, state) { - (MouseButton::Left, ElementState::Pressed) => { + Event::Key(Key::MouseLeft, KeyState::Pressed) => { self.rotation.start(focus_point); } - (MouseButton::Left, ElementState::Released) => { + Event::Key(Key::MouseLeft, KeyState::Released) => { self.rotation.stop(); } - (MouseButton::Right, ElementState::Pressed) => { + Event::Key(Key::MouseRight, KeyState::Pressed) => { self.movement.start(focus_point, self.cursor); } - (MouseButton::Right, ElementState::Released) => { + Event::Key(Key::MouseRight, KeyState::Released) => { self.movement.stop(); } + _ => {} } } diff --git a/crates/fj-viewer/src/run.rs b/crates/fj-viewer/src/run.rs index c1e3d759e..3dfcdde7e 100644 --- a/crates/fj-viewer/src/run.rs +++ b/crates/fj-viewer/src/run.rs @@ -10,7 +10,10 @@ use fj_operations::shape_processor::ShapeProcessor; use futures::executor::block_on; use tracing::{trace, warn}; use winit::{ - event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent}, + event::{ + ElementState, Event, KeyboardInput, MouseButton, VirtualKeyCode, + WindowEvent, + }, event_loop::{ControlFlow, EventLoop}, }; @@ -143,21 +146,20 @@ pub fn run( event: WindowEvent::MouseInput { state, button, .. }, .. } => { - if let (Some(shape), Some(camera)) = (&shape, &camera) { - let focus_point = camera.focus_point( - window.size(), - input_handler.cursor(), - &shape.mesh, - ); + let state = match state { + ElementState::Pressed => input::KeyState::Pressed, + ElementState::Released => input::KeyState::Released, + }; - input_handler.handle_mouse_input( - button, - state, - focus_point, - ); + match button { + MouseButton::Left => { + Some(input::Event::Key(input::Key::MouseLeft, state)) + } + MouseButton::Right => { + Some(input::Event::Key(input::Key::MouseRight, state)) + } + _ => None, } - - None } Event::WindowEvent { event: WindowEvent::MouseWheel { delta, .. }, @@ -198,10 +200,19 @@ pub fn run( _ => None, }; - if let (Some(event), Some(camera)) = (event, &mut camera) { + if let (Some(event), Some(shape), Some(camera)) = + (event, &shape, &mut camera) + { + let focus_point = camera.focus_point( + window.size(), + input_handler.cursor(), + &shape.mesh, + ); + input_handler.handle_event( event, window.size(), + focus_point, camera, &mut actions, ); From be9966d99f542a2580c42231135912821a88408a Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Thu, 26 May 2022 12:03:39 +0200 Subject: [PATCH 20/22] Handle scrolling through `Event` --- crates/fj-viewer/src/input/event.rs | 3 +++ crates/fj-viewer/src/input/handler.rs | 20 +++++--------------- crates/fj-viewer/src/run.rs | 16 ++++++++++++---- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/crates/fj-viewer/src/input/event.rs b/crates/fj-viewer/src/input/event.rs index 4b8a54c29..48542fc4d 100644 --- a/crates/fj-viewer/src/input/event.rs +++ b/crates/fj-viewer/src/input/event.rs @@ -7,6 +7,9 @@ pub enum Event { /// A key has been pressed or released Key(Key, KeyState), + + /// The user scrolled + Scroll(f64), } /// A keyboard or mouse key diff --git a/crates/fj-viewer/src/input/handler.rs b/crates/fj-viewer/src/input/handler.rs index d8ef1ddf0..7b7987ac8 100644 --- a/crates/fj-viewer/src/input/handler.rs +++ b/crates/fj-viewer/src/input/handler.rs @@ -2,7 +2,6 @@ use std::time::Instant; use fj_interop::mesh::Mesh; use fj_math::{Point, Transform, Vector}; -use winit::{dpi::PhysicalPosition, event::MouseScrollDelta}; use crate::{ camera::{Camera, FocusPoint}, @@ -55,6 +54,7 @@ impl Handler { event: Event, screen_size: Size, focus_point: FocusPoint, + now: Instant, camera: &mut Camera, actions: &mut Actions, ) { @@ -95,24 +95,14 @@ impl Handler { self.movement.stop(); } + Event::Scroll(delta) => { + self.zoom.push_input_delta(delta, now); + } + _ => {} } } - /// Updates zoom state from the scroll wheel. - pub fn handle_mouse_wheel( - &mut self, - delta: MouseScrollDelta, - now: Instant, - ) { - let delta = match delta { - MouseScrollDelta::LineDelta(_, y) => y as f64 * 10.0, - MouseScrollDelta::PixelDelta(PhysicalPosition { y, .. }) => y, - }; - - self.zoom.push_input_delta(delta, now); - } - /// Update application state from user input. pub fn update( &mut self, diff --git a/crates/fj-viewer/src/run.rs b/crates/fj-viewer/src/run.rs index 3dfcdde7e..c7eb8cf0b 100644 --- a/crates/fj-viewer/src/run.rs +++ b/crates/fj-viewer/src/run.rs @@ -10,9 +10,10 @@ use fj_operations::shape_processor::ShapeProcessor; use futures::executor::block_on; use tracing::{trace, warn}; use winit::{ + dpi::PhysicalPosition, event::{ - ElementState, Event, KeyboardInput, MouseButton, VirtualKeyCode, - WindowEvent, + ElementState, Event, KeyboardInput, MouseButton, MouseScrollDelta, + VirtualKeyCode, WindowEvent, }, event_loop::{ControlFlow, EventLoop}, }; @@ -165,8 +166,14 @@ pub fn run( event: WindowEvent::MouseWheel { delta, .. }, .. } => { - input_handler.handle_mouse_wheel(delta, now); - None + let delta = match delta { + MouseScrollDelta::LineDelta(_, y) => y as f64 * 10.0, + MouseScrollDelta::PixelDelta(PhysicalPosition { + y, + .. + }) => y, + }; + Some(input::Event::Scroll(delta)) } Event::MainEventsCleared => { let delta_t = now.duration_since(previous_time); @@ -213,6 +220,7 @@ pub fn run( event, window.size(), focus_point, + now, camera, &mut actions, ); From 4fd2ce5355b8d23d70d0379db6e4595ab7f139f9 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Thu, 26 May 2022 12:19:18 +0200 Subject: [PATCH 21/22] Extract `fj-window` from `fj-viewer` --- Cargo.lock | 16 ++++++++-- Cargo.toml | 2 ++ crates/fj-app/Cargo.toml | 4 +++ crates/fj-app/src/main.rs | 2 +- crates/fj-viewer/Cargo.toml | 10 ------ crates/fj-viewer/src/graphics/renderer.rs | 12 ------- crates/fj-viewer/src/lib.rs | 2 -- crates/fj-window/Cargo.toml | 31 +++++++++++++++++++ crates/fj-window/src/lib.rs | 17 ++++++++++ crates/{fj-viewer => fj-window}/src/run.rs | 14 ++++----- crates/{fj-viewer => fj-window}/src/window.rs | 9 +----- 11 files changed, 76 insertions(+), 43 deletions(-) create mode 100644 crates/fj-window/Cargo.toml create mode 100644 crates/fj-window/src/lib.rs rename crates/{fj-viewer => fj-window}/src/run.rs (99%) rename crates/{fj-viewer => fj-window}/src/window.rs (82%) diff --git a/Cargo.lock b/Cargo.lock index 12496c304..d54934b39 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -728,6 +728,7 @@ dependencies = [ "fj-math", "fj-operations", "fj-viewer", + "fj-window", "serde", "tracing-subscriber", ] @@ -804,16 +805,25 @@ name = "fj-viewer" version = "0.6.0" dependencies = [ "bytemuck", - "fj-host", "fj-interop", "fj-math", - "fj-operations", - "futures", "raw-window-handle", "thiserror", "tracing", "wgpu", "wgpu_glyph", +] + +[[package]] +name = "fj-window" +version = "0.6.0" +dependencies = [ + "fj-host", + "fj-operations", + "fj-viewer", + "futures", + "thiserror", + "tracing", "winit", ] diff --git a/Cargo.toml b/Cargo.toml index 4acbafbe6..192258230 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ members = [ "crates/fj-math", "crates/fj-operations", "crates/fj-viewer", + "crates/fj-window", "models/cuboid", "models/spacer", @@ -28,4 +29,5 @@ default-members = [ "crates/fj-math", "crates/fj-operations", "crates/fj-viewer", + "crates/fj-window", ] diff --git a/crates/fj-app/Cargo.toml b/crates/fj-app/Cargo.toml index 05410ea6b..6c13a0eba 100644 --- a/crates/fj-app/Cargo.toml +++ b/crates/fj-app/Cargo.toml @@ -51,6 +51,10 @@ path = "../fj-operations" version = "0.6.0" path = "../fj-viewer" +[dependencies.fj-window] +version = "0.6.0" +path = "../fj-window" + [dependencies.serde] version = "1.0.137" features = ["derive"] diff --git a/crates/fj-app/src/main.rs b/crates/fj-app/src/main.rs index 0788d887b..34c62a675 100644 --- a/crates/fj-app/src/main.rs +++ b/crates/fj-app/src/main.rs @@ -21,7 +21,7 @@ use anyhow::{anyhow, Context as _}; use fj_export::export; use fj_host::{Model, Parameters}; use fj_operations::shape_processor::ShapeProcessor; -use fj_viewer::run::run; +use fj_window::run::run; use tracing_subscriber::fmt::format; use tracing_subscriber::EnvFilter; diff --git a/crates/fj-viewer/Cargo.toml b/crates/fj-viewer/Cargo.toml index ace7092de..d35a4eaf7 100644 --- a/crates/fj-viewer/Cargo.toml +++ b/crates/fj-viewer/Cargo.toml @@ -14,17 +14,11 @@ categories = ["encoding", "mathematics", "rendering"] [dependencies] bytemuck = "1.9.1" -futures = "0.3.21" raw-window-handle = "0.4.3" thiserror = "1.0.31" tracing = "0.1.34" wgpu = "0.12.0" wgpu_glyph = "0.16.0" -winit = "0.26.1" - -[dependencies.fj-host] -version = "0.6.0" -path = "../fj-host" [dependencies.fj-interop] version = "0.6.0" @@ -33,7 +27,3 @@ path = "../fj-interop" [dependencies.fj-math] version = "0.6.0" path = "../fj-math" - -[dependencies.fj-operations] -version = "0.6.0" -path = "../fj-operations" diff --git a/crates/fj-viewer/src/graphics/renderer.rs b/crates/fj-viewer/src/graphics/renderer.rs index a964ebdb9..636b96601 100644 --- a/crates/fj-viewer/src/graphics/renderer.rs +++ b/crates/fj-viewer/src/graphics/renderer.rs @@ -38,18 +38,6 @@ pub struct Renderer { impl Renderer { /// Returns a new `Renderer`. - /// - /// # Examples - /// ```rust no_run - /// use fj_viewer::{graphics, window}; - /// - /// // Create window - /// let event_loop = winit::event_loop::EventLoop::new(); - /// let window = window::Window::new(&event_loop).unwrap(); - /// - /// // Attach renderer to the window - /// let mut renderer = graphics::Renderer::new(&window); - /// ``` pub async fn new(screen: &impl Screen) -> Result { let instance = wgpu::Instance::new(wgpu::Backends::PRIMARY); diff --git a/crates/fj-viewer/src/lib.rs b/crates/fj-viewer/src/lib.rs index 7f09ba3b7..b6b4be702 100644 --- a/crates/fj-viewer/src/lib.rs +++ b/crates/fj-viewer/src/lib.rs @@ -17,6 +17,4 @@ pub mod camera; pub mod graphics; pub mod input; -pub mod run; pub mod screen; -pub mod window; diff --git a/crates/fj-window/Cargo.toml b/crates/fj-window/Cargo.toml new file mode 100644 index 000000000..954b354ce --- /dev/null +++ b/crates/fj-window/Cargo.toml @@ -0,0 +1,31 @@ +[package] +name = "fj-window" +version = "0.6.0" +edition = "2021" + +description = "The world needs another CAD program." +readme = "../../README.md" +homepage = "https://www.fornjot.app/" +repository = "https://github.com/hannobraun/fornjot" +license = "0BSD" +keywords = ["cad", "programmatic", "code-cad"] +categories = ["encoding", "mathematics", "rendering"] + + +[dependencies] +futures = "0.3.21" +thiserror = "1.0.31" +tracing = "0.1.34" +winit = "0.26.1" + +[dependencies.fj-host] +version = "0.6.0" +path = "../fj-host" + +[dependencies.fj-operations] +version = "0.6.0" +path = "../fj-operations" + +[dependencies.fj-viewer] +version = "0.6.0" +path = "../fj-viewer" diff --git a/crates/fj-window/src/lib.rs b/crates/fj-window/src/lib.rs new file mode 100644 index 000000000..b67bc34ac --- /dev/null +++ b/crates/fj-window/src/lib.rs @@ -0,0 +1,17 @@ +//! # Fornjot Window Abstraction +//! +//! This library is part of the [Fornjot] ecosystem. Fornjot is an open-source, +//! code-first CAD application; and collection of libraries that make up the CAD +//! application, but can be used independently. +//! +//! This library is an internal component of Fornjot. It is not relevant to end +//! users that just want to create CAD models. +//! +//! This library provides a window abstraction based on Winit. +//! +//! [Fornjot]: https://www.fornjot.app/ + +#![warn(missing_docs)] + +pub mod run; +pub mod window; diff --git a/crates/fj-viewer/src/run.rs b/crates/fj-window/src/run.rs similarity index 99% rename from crates/fj-viewer/src/run.rs rename to crates/fj-window/src/run.rs index c7eb8cf0b..9e801c274 100644 --- a/crates/fj-viewer/src/run.rs +++ b/crates/fj-window/src/run.rs @@ -7,6 +7,12 @@ use std::{error, time::Instant}; use fj_host::Watcher; use fj_operations::shape_processor::ShapeProcessor; +use fj_viewer::{ + camera::Camera, + graphics::{self, DrawConfig, Renderer}, + input::{self, KeyState}, + screen::{Position, Screen as _, Size}, +}; use futures::executor::block_on; use tracing::{trace, warn}; use winit::{ @@ -18,13 +24,7 @@ use winit::{ event_loop::{ControlFlow, EventLoop}, }; -use crate::{ - camera::Camera, - graphics::{self, DrawConfig, Renderer}, - input::{self, KeyState}, - screen::{Position, Screen as _, Size}, - window::{self, Window}, -}; +use crate::window::{self, Window}; /// Initializes a model viewer for a given model and enters its process loop. pub fn run( diff --git a/crates/fj-viewer/src/window.rs b/crates/fj-window/src/window.rs similarity index 82% rename from crates/fj-viewer/src/window.rs rename to crates/fj-window/src/window.rs index c267fb383..3f28b1169 100644 --- a/crates/fj-viewer/src/window.rs +++ b/crates/fj-window/src/window.rs @@ -1,20 +1,13 @@ //! CAD viewer utility windowing abstraction +use fj_viewer::screen::{Screen, Size}; use winit::{event_loop::EventLoop, window::WindowBuilder}; -use crate::screen::{Screen, Size}; - /// Window abstraction providing details such as the width or height and easing initialization. pub struct Window(winit::window::Window); impl Window { /// Returns a new window with the given `EventLoop`. - /// - /// # Examples - /// ```rust no_run - /// let event_loop = winit::event_loop::EventLoop::new(); - /// let window = fj_viewer::window::Window::new(&event_loop); - /// ``` pub fn new(event_loop: &EventLoop<()>) -> Result { let window = WindowBuilder::new() .with_title("Fornjot") From 29685806ce5dcec5d9b2e0a03195207ff60424a6 Mon Sep 17 00:00:00 2001 From: Hanno Braun Date: Thu, 26 May 2022 12:20:52 +0200 Subject: [PATCH 22/22] Mention `fj-window` in README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 5ca2a40df..3c4ecb037 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,7 @@ Here's an overview over all of the crates, with a short description of what they - `fj-export`: Exports Fornjot models to external data formats. - `fj-host`: Loads Fornjot models and watches them for changes. - `fj-viewer`: Displays Fornjot models. +- `fj-window`: Embed `fj-viewer` in a Winit-based window. - `fj-app`: The Fornjot CAD application. - `fj`: End-user API for defining Fornjot models.