From 4451972f6ca7ea11264c3aa02f744468c1e1d98b Mon Sep 17 00:00:00 2001 From: vmarcella Date: Sat, 4 Feb 2023 12:58:55 -0800 Subject: [PATCH 01/21] [add] egui to lambda-rs-platform. --- Cargo.lock | 99 +++++++++++++++++++++++++++- crates/lambda-rs-platform/Cargo.toml | 3 +- 2 files changed, 98 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fc499c1b..95d03687 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,22 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "ab_glyph" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe21446ad43aa56417a767f3e2f3d7c4ca522904de1dd640529a76e9c5c3b33c" +dependencies = [ + "ab_glyph_rasterizer", + "owned_ttf_parser", +] + +[[package]] +name = "ab_glyph_rasterizer" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046" + [[package]] name = "abscissa_core" version = "0.5.2" @@ -65,6 +81,17 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" +[[package]] +name = "ahash" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f" +dependencies = [ + "cfg-if 1.0.0", + "once_cell", + "version_check", +] + [[package]] name = "aho-corasick" version = "0.7.18" @@ -113,6 +140,12 @@ dependencies = [ "libloading", ] +[[package]] +name = "atomic_refcell" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "857253367827bd9d0fd973f0ef15506a96e79e41b0ad7aa691203a4e3214f6c8" + [[package]] name = "atty" version = "0.2.14" @@ -735,12 +768,50 @@ dependencies = [ "wio", ] +[[package]] +name = "ecolor" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b601108bca3af7650440ace4ca55b2daf52c36f2635be3587d77b16efd8d0691" + +[[package]] +name = "egui" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65a5e883a316e53866977450eecfbcac9c48109c2ab3394af29feb83fcde4ea9" +dependencies = [ + "ahash", + "epaint", + "nohash-hasher", +] + [[package]] name = "either" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" +[[package]] +name = "emath" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5277249c8c3430e7127e4f2c40a77485e7baf11ae132ce9b3253a8ed710df0a0" + +[[package]] +name = "epaint" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de14b65fe5e423e0058f77a8beb2c863b056d0566d6c4ce0d097aa5814cb705a" +dependencies = [ + "ab_glyph", + "ahash", + "atomic_refcell", + "ecolor", + "emath", + "nohash-hasher", + "parking_lot 0.12.1", +] + [[package]] name = "expat-sys" version = "2.1.6" @@ -1328,9 +1399,10 @@ version = "2023.1.30" [[package]] name = "lambda-rs-platform" -version = "2023.1.30" +version = "2023.2.4" dependencies = [ "cfg-if 1.0.0", + "egui", "gfx-backend-dx11", "gfx-backend-dx12", "gfx-backend-empty", @@ -1674,6 +1746,12 @@ dependencies = [ "memoffset", ] +[[package]] +name = "nohash-hasher" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bf50223579dc7cdcfb3bfcacf7069ff68243f8c363f62ffa99cf000a6b9c451" + [[package]] name = "nom" version = "7.1.0" @@ -1815,6 +1893,15 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "owned_ttf_parser" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e25e9fb15717794fae58ab55c26e044103aad13186fbb625893f9a3bbcc24228" +dependencies = [ + "ttf-parser", +] + [[package]] name = "owning_ref" version = "0.4.1" @@ -2718,6 +2805,12 @@ dependencies = [ "tracing-log", ] +[[package]] +name = "ttf-parser" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0609f771ad9c6155384897e1df4d948e692667cc0588548b68eb44d052b27633" + [[package]] name = "unicode-bidi" version = "0.3.7" @@ -2778,9 +2871,9 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "version_check" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "wait-timeout" diff --git a/crates/lambda-rs-platform/Cargo.toml b/crates/lambda-rs-platform/Cargo.toml index f398d13d..581e4322 100644 --- a/crates/lambda-rs-platform/Cargo.toml +++ b/crates/lambda-rs-platform/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "lambda-rs-platform" description = "Platform implementations for lambda-rs" -version = "2023.1.30" +version = "2023.2.4" edition = "2021" resolver = "2" license = "MIT" @@ -18,6 +18,7 @@ cfg-if = "=1.0.0" rand = "=0.8.5" obj-rs = "=0.7.0" gfx-backend-empty = "=0.9.0" +egui = "0.20.1" lambda-rs-logging = { path = "../lambda-rs-logging", version = "2023.1.30" } From b34b843c7c0c1de22dd6a56ff9708c6fd3d56445 Mon Sep 17 00:00:00 2001 From: vmarcella Date: Sat, 4 Feb 2023 14:14:15 -0800 Subject: [PATCH 02/21] [update] readme for lambda-rs-platform, simplify Runtime, and prepare eguiContext for handling winit events. --- crates/lambda-rs-platform/README.md | 25 +++--- crates/lambda-rs-platform/src/egui/mod.rs | 11 +++ crates/lambda-rs-platform/src/egui/winit.rs | 95 ++++++++++++++++++++ crates/lambda-rs-platform/src/lib.rs | 1 + crates/lambda-rs/src/runtime.rs | 24 +++-- crates/lambda-rs/src/runtimes/application.rs | 6 +- 6 files changed, 140 insertions(+), 22 deletions(-) create mode 100644 crates/lambda-rs-platform/src/egui/mod.rs create mode 100644 crates/lambda-rs-platform/src/egui/winit.rs diff --git a/crates/lambda-rs-platform/README.md b/crates/lambda-rs-platform/README.md index 097d8d88..91924d81 100644 --- a/crates/lambda-rs-platform/README.md +++ b/crates/lambda-rs-platform/README.md @@ -6,13 +6,18 @@ Platform implementations for lambda-rs. This crate is not intended to be used di ## Platforms The following platforms are currently supported: -* Windows - * Vulkan - * DirectX 11 - * DirectX 12 -* Linux - * Vulkan - * OpenGL -* MacOS - * Metal - * Vulkan +* Rendering & Compute support + * Windows + * Vulkan + * DirectX 11 + * DirectX 12 + * Linux + * Vulkan + * OpenGL + * MacOS + * Metal + * Vulkan +* Window support + * winit +* UI support + * egui (via winit) diff --git a/crates/lambda-rs-platform/src/egui/mod.rs b/crates/lambda-rs-platform/src/egui/mod.rs new file mode 100644 index 00000000..91eb57b4 --- /dev/null +++ b/crates/lambda-rs-platform/src/egui/mod.rs @@ -0,0 +1,11 @@ +use egui::{ + Context, + RawInput, +}; + +pub mod winit; + +pub struct EguiContext { + internal_egui_input: RawInput, + internal_egui_context: Context, +} diff --git a/crates/lambda-rs-platform/src/egui/winit.rs b/crates/lambda-rs-platform/src/egui/winit.rs new file mode 100644 index 00000000..0fce1fcd --- /dev/null +++ b/crates/lambda-rs-platform/src/egui/winit.rs @@ -0,0 +1,95 @@ +//! Custom integration between [egui](https://crates.io/crates/egui) +//! and [winit](https://crates.io/crates/winit). + +use egui::{ + Context, + RawInput, +}; +use winit::event::{ + ElementState, + MouseButton, +}; + +impl super::EguiContext { + /// Create a new input manager prepped for winit usage. + pub fn new() -> Self { + Self { + internal_egui_input: RawInput { + has_focus: false, + ..Default::default() + }, + internal_egui_context: Context::default(), + } + } + + pub fn on_event( + &self, + event: &winit::event::Event, + ) { + match event { + winit::event::Event::NewEvents(_) => todo!(), + winit::event::Event::WindowEvent { window_id, event } => match event { + winit::event::WindowEvent::Resized(_) => todo!(), + winit::event::WindowEvent::Moved(_) => todo!(), + winit::event::WindowEvent::CloseRequested => todo!(), + winit::event::WindowEvent::Destroyed => todo!(), + winit::event::WindowEvent::DroppedFile(_) => todo!(), + winit::event::WindowEvent::HoveredFile(_) => todo!(), + winit::event::WindowEvent::HoveredFileCancelled => todo!(), + winit::event::WindowEvent::ReceivedCharacter(_) => todo!(), + winit::event::WindowEvent::Focused(_) => todo!(), + winit::event::WindowEvent::KeyboardInput { + device_id, + input, + is_synthetic, + } => todo!(), + winit::event::WindowEvent::ModifiersChanged(_) => todo!(), + winit::event::WindowEvent::Ime(_) => todo!(), + winit::event::WindowEvent::CursorMoved { + device_id, + position, + modifiers, + } => todo!(), + winit::event::WindowEvent::CursorEntered { device_id } => todo!(), + winit::event::WindowEvent::CursorLeft { device_id } => todo!(), + winit::event::WindowEvent::MouseWheel { + device_id, + delta, + phase, + modifiers, + } => todo!(), + winit::event::WindowEvent::MouseInput { + device_id, + state, + button, + modifiers, + } => todo!(), + winit::event::WindowEvent::TouchpadPressure { + device_id, + pressure, + stage, + } => todo!(), + winit::event::WindowEvent::AxisMotion { + device_id, + axis, + value, + } => todo!(), + winit::event::WindowEvent::Touch(_) => todo!(), + winit::event::WindowEvent::ScaleFactorChanged { + scale_factor, + new_inner_size, + } => todo!(), + winit::event::WindowEvent::ThemeChanged(_) => todo!(), + winit::event::WindowEvent::Occluded(_) => todo!(), + }, + winit::event::Event::DeviceEvent { device_id, event } => todo!(), + winit::event::Event::UserEvent(_) => todo!(), + winit::event::Event::Suspended => todo!(), + winit::event::Event::Resumed => todo!(), + winit::event::Event::MainEventsCleared => todo!(), + winit::event::Event::RedrawRequested(_) => todo!(), + winit::event::Event::RedrawEventsCleared => todo!(), + winit::event::Event::LoopDestroyed => todo!(), + } + } +} diff --git a/crates/lambda-rs-platform/src/lib.rs b/crates/lambda-rs-platform/src/lib.rs index ab1667f1..465b3ca8 100644 --- a/crates/lambda-rs-platform/src/lib.rs +++ b/crates/lambda-rs-platform/src/lib.rs @@ -1,3 +1,4 @@ +pub mod egui; pub mod gfx; pub mod obj; pub mod rand; diff --git a/crates/lambda-rs/src/runtime.rs b/crates/lambda-rs/src/runtime.rs index 8e680c6b..4d149216 100644 --- a/crates/lambda-rs/src/runtime.rs +++ b/crates/lambda-rs/src/runtime.rs @@ -13,19 +13,29 @@ where RuntimeError: Sized + Debug, { type Component; - fn on_start(&mut self); - fn on_stop(&mut self); + fn before_start(&mut self); fn run(self) -> Result; } -/// Simple function for starting any prebuilt Runnable. -pub fn start_runtime>( - runtime: T, +/// Starts a runtime and waits for it to finish. This function will not return +/// until the runtime has finished executing. +/// +/// The type `ImplementedRuntime` represents any struct which implements the +/// `Runtime` trait with valid `RuntimeResult` & `RuntimeError` parameters. +pub fn start_runtime< + RuntimeResult: Sized + Debug, + RuntimeError: Sized + Debug, + ImplementedRuntime: Runtime, +>( + runtime: ImplementedRuntime, ) { let runtime_result = runtime.run(); match runtime_result { - Ok(_) => { - logging::info!("Runtime finished successfully."); + Ok(result) => { + logging::info!( + "Runtime finished successfully with the result: {:?}", + result + ); } Err(e) => { logging::fatal!("Runtime panicked because: {:?}", e); diff --git a/crates/lambda-rs/src/runtimes/application.rs b/crates/lambda-rs/src/runtimes/application.rs index 5bd3dbb4..395da2e5 100644 --- a/crates/lambda-rs/src/runtimes/application.rs +++ b/crates/lambda-rs/src/runtimes/application.rs @@ -421,11 +421,7 @@ impl Runtime<(), String> for ApplicationRuntime { /// When an application runtime starts, it will attach all of the components that /// have been added during the construction phase in the users code. - fn on_start(&mut self) { + fn before_start(&mut self) { logging::info!("Starting the runtime: {}", self.name); } - - fn on_stop(&mut self) { - logging::info!("Stopping the runtime: {}", self.name); - } } From 5982be0e172e9fdb245e593b414335c02761ffb1 Mon Sep 17 00:00:00 2001 From: vmarcella Date: Sat, 4 Feb 2023 15:39:06 -0800 Subject: [PATCH 03/21] [update] winit event qualification. --- crates/lambda-rs-platform/src/egui/winit.rs | 80 +++++++++++---------- 1 file changed, 44 insertions(+), 36 deletions(-) diff --git a/crates/lambda-rs-platform/src/egui/winit.rs b/crates/lambda-rs-platform/src/egui/winit.rs index 0fce1fcd..30e394fb 100644 --- a/crates/lambda-rs-platform/src/egui/winit.rs +++ b/crates/lambda-rs-platform/src/egui/winit.rs @@ -7,7 +7,9 @@ use egui::{ }; use winit::event::{ ElementState, + Event, MouseButton, + WindowEvent, }; impl super::EguiContext { @@ -23,73 +25,79 @@ impl super::EguiContext { } pub fn on_event( - &self, - event: &winit::event::Event, + &mut self, + event: &Event, ) { match event { - winit::event::Event::NewEvents(_) => todo!(), - winit::event::Event::WindowEvent { window_id, event } => match event { - winit::event::WindowEvent::Resized(_) => todo!(), - winit::event::WindowEvent::Moved(_) => todo!(), - winit::event::WindowEvent::CloseRequested => todo!(), - winit::event::WindowEvent::Destroyed => todo!(), - winit::event::WindowEvent::DroppedFile(_) => todo!(), - winit::event::WindowEvent::HoveredFile(_) => todo!(), - winit::event::WindowEvent::HoveredFileCancelled => todo!(), - winit::event::WindowEvent::ReceivedCharacter(_) => todo!(), - winit::event::WindowEvent::Focused(_) => todo!(), - winit::event::WindowEvent::KeyboardInput { + Event::NewEvents(_) => todo!(), + Event::WindowEvent { window_id, event } => match event { + WindowEvent::Resized(_) => todo!(), + WindowEvent::Moved(_) => todo!(), + WindowEvent::CloseRequested => todo!(), + WindowEvent::Destroyed => todo!(), + WindowEvent::DroppedFile(_) => todo!(), + WindowEvent::HoveredFile(_) => todo!(), + WindowEvent::HoveredFileCancelled => todo!(), + WindowEvent::ReceivedCharacter(_) => todo!(), + WindowEvent::Focused(_) => todo!(), + WindowEvent::KeyboardInput { device_id, input, is_synthetic, } => todo!(), - winit::event::WindowEvent::ModifiersChanged(_) => todo!(), - winit::event::WindowEvent::Ime(_) => todo!(), - winit::event::WindowEvent::CursorMoved { + WindowEvent::ModifiersChanged(_) => todo!(), + WindowEvent::Ime(_) => todo!(), + WindowEvent::CursorMoved { device_id, position, modifiers, } => todo!(), - winit::event::WindowEvent::CursorEntered { device_id } => todo!(), - winit::event::WindowEvent::CursorLeft { device_id } => todo!(), - winit::event::WindowEvent::MouseWheel { + WindowEvent::CursorEntered { device_id } => todo!(), + WindowEvent::CursorLeft { device_id } => todo!(), + WindowEvent::MouseWheel { device_id, delta, phase, modifiers, } => todo!(), - winit::event::WindowEvent::MouseInput { + WindowEvent::MouseInput { device_id, state, button, modifiers, } => todo!(), - winit::event::WindowEvent::TouchpadPressure { + WindowEvent::TouchpadPressure { device_id, pressure, stage, } => todo!(), - winit::event::WindowEvent::AxisMotion { + WindowEvent::AxisMotion { device_id, axis, value, } => todo!(), - winit::event::WindowEvent::Touch(_) => todo!(), - winit::event::WindowEvent::ScaleFactorChanged { + WindowEvent::Touch(_) => todo!(), + WindowEvent::ScaleFactorChanged { scale_factor, new_inner_size, - } => todo!(), - winit::event::WindowEvent::ThemeChanged(_) => todo!(), - winit::event::WindowEvent::Occluded(_) => todo!(), + } => { + let pixels_per_point = *scale_factor as f32; + self.internal_egui_input.pixels_per_point = Some(pixels_per_point); + self + .internal_egui_context + .set_pixels_per_point(pixels_per_point); + } + WindowEvent::ThemeChanged(_) => todo!(), + WindowEvent::Occluded(_) => todo!(), }, - winit::event::Event::DeviceEvent { device_id, event } => todo!(), - winit::event::Event::UserEvent(_) => todo!(), - winit::event::Event::Suspended => todo!(), - winit::event::Event::Resumed => todo!(), - winit::event::Event::MainEventsCleared => todo!(), - winit::event::Event::RedrawRequested(_) => todo!(), - winit::event::Event::RedrawEventsCleared => todo!(), - winit::event::Event::LoopDestroyed => todo!(), + Event::DeviceEvent { device_id, event } => todo!(), + Event::UserEvent(_) => todo!(), + Event::Suspended => todo!(), + Event::Resumed => todo!(), + Event::MainEventsCleared => todo!(), + Event::RedrawRequested(_) => todo!(), + Event::RedrawEventsCleared => todo!(), + Event::LoopDestroyed => todo!(), } } } From d8cf2738619ebda10897afd45b235e56709a79b0 Mon Sep 17 00:00:00 2001 From: vmarcella Date: Sat, 4 Feb 2023 16:03:46 -0800 Subject: [PATCH 04/21] [update] mouse input event handler, add cursor position to egui context. --- crates/lambda-rs-platform/src/egui/mod.rs | 3 +++ crates/lambda-rs-platform/src/egui/winit.rs | 25 +++++++++++++++++---- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/crates/lambda-rs-platform/src/egui/mod.rs b/crates/lambda-rs-platform/src/egui/mod.rs index 91eb57b4..d3efa281 100644 --- a/crates/lambda-rs-platform/src/egui/mod.rs +++ b/crates/lambda-rs-platform/src/egui/mod.rs @@ -1,11 +1,14 @@ use egui::{ Context, + Pos2, RawInput, }; pub mod winit; +/// A context for managing egui input & rendering. pub struct EguiContext { internal_egui_input: RawInput, internal_egui_context: Context, + internal_cursor_position: Option, } diff --git a/crates/lambda-rs-platform/src/egui/winit.rs b/crates/lambda-rs-platform/src/egui/winit.rs index 30e394fb..d8866a77 100644 --- a/crates/lambda-rs-platform/src/egui/winit.rs +++ b/crates/lambda-rs-platform/src/egui/winit.rs @@ -11,6 +11,10 @@ use winit::event::{ MouseButton, WindowEvent, }; +pub struct EventResult { + pub consumed: bool, + pub redraw: bool, +} impl super::EguiContext { /// Create a new input manager prepped for winit usage. @@ -21,14 +25,17 @@ impl super::EguiContext { ..Default::default() }, internal_egui_context: Context::default(), + internal_cursor_position: None, } } + fn process_mouse_input(&mut self, state: ElementState, button: MouseButton) {} + pub fn on_event( &mut self, event: &Event, - ) { - match event { + ) -> EventResult { + return match event { Event::NewEvents(_) => todo!(), Event::WindowEvent { window_id, event } => match event { WindowEvent::Resized(_) => todo!(), @@ -65,7 +72,13 @@ impl super::EguiContext { state, button, modifiers, - } => todo!(), + } => { + self.process_mouse_input(state.clone(), button.clone()); + EventResult { + consumed: self.internal_egui_context.wants_pointer_input(), + redraw: true, + } + } WindowEvent::TouchpadPressure { device_id, pressure, @@ -86,6 +99,10 @@ impl super::EguiContext { self .internal_egui_context .set_pixels_per_point(pixels_per_point); + EventResult { + consumed: false, + redraw: true, + } } WindowEvent::ThemeChanged(_) => todo!(), WindowEvent::Occluded(_) => todo!(), @@ -98,6 +115,6 @@ impl super::EguiContext { Event::RedrawRequested(_) => todo!(), Event::RedrawEventsCleared => todo!(), Event::LoopDestroyed => todo!(), - } + }; } } From a8fa01e91e1aab5182823590cc830851e9a56e2e Mon Sep 17 00:00:00 2001 From: vmarcella Date: Sat, 4 Feb 2023 16:26:51 -0800 Subject: [PATCH 05/21] [fix] constructor & update event implementations for egui. --- crates/lambda-rs-platform/src/egui/mod.rs | 5 +- crates/lambda-rs-platform/src/egui/winit.rs | 61 ++++++++++++--------- 2 files changed, 39 insertions(+), 27 deletions(-) diff --git a/crates/lambda-rs-platform/src/egui/mod.rs b/crates/lambda-rs-platform/src/egui/mod.rs index d3efa281..5323b196 100644 --- a/crates/lambda-rs-platform/src/egui/mod.rs +++ b/crates/lambda-rs-platform/src/egui/mod.rs @@ -10,5 +10,8 @@ pub mod winit; pub struct EguiContext { internal_egui_input: RawInput, internal_egui_context: Context, - internal_cursor_position: Option, + cursor_position: Option, + cursor_button_active: bool, + current_pixels_per_point: f32, + emulate_touch_screen: bool, } diff --git a/crates/lambda-rs-platform/src/egui/winit.rs b/crates/lambda-rs-platform/src/egui/winit.rs index d8866a77..7808ee54 100644 --- a/crates/lambda-rs-platform/src/egui/winit.rs +++ b/crates/lambda-rs-platform/src/egui/winit.rs @@ -12,7 +12,7 @@ use winit::event::{ WindowEvent, }; pub struct EventResult { - pub consumed: bool, + pub processed: bool, pub redraw: bool, } @@ -25,11 +25,16 @@ impl super::EguiContext { ..Default::default() }, internal_egui_context: Context::default(), - internal_cursor_position: None, + cursor_position: None, + cursor_button_active: false, + current_pixels_per_point: 1.0, + emulate_touch_screen: false, } } - fn process_mouse_input(&mut self, state: ElementState, button: MouseButton) {} + fn process_mouse_input(&mut self, state: ElementState, button: MouseButton) { + if let Some(position) = self.cursor_position {} + } pub fn on_event( &mut self, @@ -38,10 +43,6 @@ impl super::EguiContext { return match event { Event::NewEvents(_) => todo!(), Event::WindowEvent { window_id, event } => match event { - WindowEvent::Resized(_) => todo!(), - WindowEvent::Moved(_) => todo!(), - WindowEvent::CloseRequested => todo!(), - WindowEvent::Destroyed => todo!(), WindowEvent::DroppedFile(_) => todo!(), WindowEvent::HoveredFile(_) => todo!(), WindowEvent::HoveredFileCancelled => todo!(), @@ -59,14 +60,8 @@ impl super::EguiContext { position, modifiers, } => todo!(), - WindowEvent::CursorEntered { device_id } => todo!(), WindowEvent::CursorLeft { device_id } => todo!(), - WindowEvent::MouseWheel { - device_id, - delta, - phase, - modifiers, - } => todo!(), + // Mouse input events WindowEvent::MouseInput { device_id, state, @@ -75,21 +70,37 @@ impl super::EguiContext { } => { self.process_mouse_input(state.clone(), button.clone()); EventResult { - consumed: self.internal_egui_context.wants_pointer_input(), + processed: self.internal_egui_context.wants_pointer_input(), redraw: true, } } - WindowEvent::TouchpadPressure { - device_id, - pressure, - stage, - } => todo!(), - WindowEvent::AxisMotion { + WindowEvent::MouseWheel { device_id, - axis, - value, + delta, + phase, + modifiers, } => todo!(), + + // Repaint events + WindowEvent::CloseRequested + | WindowEvent::CursorEntered { .. } + | WindowEvent::Destroyed + | WindowEvent::ThemeChanged(_) + | WindowEvent::Occluded(_) + | WindowEvent::Resized(_) + | WindowEvent::TouchpadPressure { .. } => EventResult { + processed: false, + redraw: true, + }, + + // Noop events + WindowEvent::Moved(_) | WindowEvent::AxisMotion { .. } => EventResult { + processed: false, + redraw: false, + }, WindowEvent::Touch(_) => todo!(), + + // Window Events WindowEvent::ScaleFactorChanged { scale_factor, new_inner_size, @@ -100,12 +111,10 @@ impl super::EguiContext { .internal_egui_context .set_pixels_per_point(pixels_per_point); EventResult { - consumed: false, + processed: false, redraw: true, } } - WindowEvent::ThemeChanged(_) => todo!(), - WindowEvent::Occluded(_) => todo!(), }, Event::DeviceEvent { device_id, event } => todo!(), Event::UserEvent(_) => todo!(), From 7efa007ee85431c30a58266744e45ac167e1d215 Mon Sep 17 00:00:00 2001 From: vmarcella Date: Sat, 4 Feb 2023 16:37:16 -0800 Subject: [PATCH 06/21] [add] event handling for window focusing. --- crates/lambda-rs-platform/src/egui/winit.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/crates/lambda-rs-platform/src/egui/winit.rs b/crates/lambda-rs-platform/src/egui/winit.rs index 7808ee54..ade8dabc 100644 --- a/crates/lambda-rs-platform/src/egui/winit.rs +++ b/crates/lambda-rs-platform/src/egui/winit.rs @@ -3,6 +3,7 @@ use egui::{ Context, + Modifiers, RawInput, }; use winit::event::{ @@ -43,11 +44,12 @@ impl super::EguiContext { return match event { Event::NewEvents(_) => todo!(), Event::WindowEvent { window_id, event } => match event { + // File events. WindowEvent::DroppedFile(_) => todo!(), WindowEvent::HoveredFile(_) => todo!(), WindowEvent::HoveredFileCancelled => todo!(), + // Keyboard events. WindowEvent::ReceivedCharacter(_) => todo!(), - WindowEvent::Focused(_) => todo!(), WindowEvent::KeyboardInput { device_id, input, @@ -115,6 +117,17 @@ impl super::EguiContext { redraw: true, } } + WindowEvent::Focused(focused) => { + self.internal_egui_input.has_focus = *focused; + match focused { + false => self.internal_egui_input.modifiers = Modifiers::default(), + _ => {} + } + EventResult { + processed: false, + redraw: true, + } + } }, Event::DeviceEvent { device_id, event } => todo!(), Event::UserEvent(_) => todo!(), From 6fd55b3d1dd18e26e0ace5949ecbd2deb688f85d Mon Sep 17 00:00:00 2001 From: vmarcella Date: Sat, 4 Feb 2023 16:39:29 -0800 Subject: [PATCH 07/21] [update] mouse input. --- crates/lambda-rs-platform/src/egui/winit.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/lambda-rs-platform/src/egui/winit.rs b/crates/lambda-rs-platform/src/egui/winit.rs index ade8dabc..66e14cbe 100644 --- a/crates/lambda-rs-platform/src/egui/winit.rs +++ b/crates/lambda-rs-platform/src/egui/winit.rs @@ -71,8 +71,9 @@ impl super::EguiContext { modifiers, } => { self.process_mouse_input(state.clone(), button.clone()); + let processed = self.internal_egui_context.wants_pointer_input(); EventResult { - processed: self.internal_egui_context.wants_pointer_input(), + processed, redraw: true, } } From 532e8d7eb646650cbcaee550ee87565ccf596e4c Mon Sep 17 00:00:00 2001 From: vmarcella Date: Sat, 4 Feb 2023 16:42:31 -0800 Subject: [PATCH 08/21] [add] logic for cursor leaving the window. --- crates/lambda-rs-platform/src/egui/winit.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/crates/lambda-rs-platform/src/egui/winit.rs b/crates/lambda-rs-platform/src/egui/winit.rs index 66e14cbe..68bc5786 100644 --- a/crates/lambda-rs-platform/src/egui/winit.rs +++ b/crates/lambda-rs-platform/src/egui/winit.rs @@ -62,7 +62,7 @@ impl super::EguiContext { position, modifiers, } => todo!(), - WindowEvent::CursorLeft { device_id } => todo!(), + // Mouse input events WindowEvent::MouseInput { device_id, @@ -83,6 +83,17 @@ impl super::EguiContext { phase, modifiers, } => todo!(), + WindowEvent::CursorLeft { .. } => { + self.cursor_position = None; + self + .internal_egui_input + .events + .push(egui::Event::PointerGone); + EventResult { + processed: false, + redraw: true, + } + } // Repaint events WindowEvent::CloseRequested From 092ffcf8c91bee0fb69a2255a54e410ef3155141 Mon Sep 17 00:00:00 2001 From: vmarcella Date: Sat, 4 Feb 2023 19:08:56 -0800 Subject: [PATCH 09/21] [add] input translations for egui/winit. --- crates/lambda-rs-platform/src/egui/mod.rs | 2 +- .../src/egui/winit/input.rs | 214 ++++++++++++++++++ .../src/egui/{winit.rs => winit/mod.rs} | 38 +++- 3 files changed, 245 insertions(+), 9 deletions(-) create mode 100644 crates/lambda-rs-platform/src/egui/winit/input.rs rename crates/lambda-rs-platform/src/egui/{winit.rs => winit/mod.rs} (85%) diff --git a/crates/lambda-rs-platform/src/egui/mod.rs b/crates/lambda-rs-platform/src/egui/mod.rs index 5323b196..54543a57 100644 --- a/crates/lambda-rs-platform/src/egui/mod.rs +++ b/crates/lambda-rs-platform/src/egui/mod.rs @@ -10,7 +10,7 @@ pub mod winit; pub struct EguiContext { internal_egui_input: RawInput, internal_egui_context: Context, - cursor_position: Option, + mouse_position: Option, cursor_button_active: bool, current_pixels_per_point: f32, emulate_touch_screen: bool, diff --git a/crates/lambda-rs-platform/src/egui/winit/input.rs b/crates/lambda-rs-platform/src/egui/winit/input.rs new file mode 100644 index 00000000..5e03f4fb --- /dev/null +++ b/crates/lambda-rs-platform/src/egui/winit/input.rs @@ -0,0 +1,214 @@ +//! This module contains the code to convert winit input events to egui +//! input events. + +use egui::PointerButton; +use winit::event::{ + MouseButton, + VirtualKeyCode, +}; + +/// Convert a winit mouse button to an egui mouse button. +pub fn winit_to_egui_button(button: MouseButton) -> Option { + return match button { + MouseButton::Left => Some(PointerButton::Primary), + MouseButton::Right => Some(PointerButton::Secondary), + MouseButton::Middle => Some(PointerButton::Middle), + MouseButton::Other(1) => Some(PointerButton::Extra1), + MouseButton::Other(2) => Some(PointerButton::Extra2), + MouseButton::Other(_) => None, + }; +} + +/// Convert a winit virtual key code to an egui key code. +pub fn winit_to_egui_key(key: VirtualKeyCode) -> Option { + return Some(match key { + VirtualKeyCode::Down => egui::Key::ArrowDown, + VirtualKeyCode::Left => egui::Key::ArrowLeft, + VirtualKeyCode::Right => egui::Key::ArrowRight, + VirtualKeyCode::Up => egui::Key::ArrowUp, + VirtualKeyCode::Escape => egui::Key::Escape, + VirtualKeyCode::Tab => egui::Key::Tab, + VirtualKeyCode::Back => egui::Key::Backspace, + VirtualKeyCode::Return => egui::Key::Enter, + VirtualKeyCode::Space => egui::Key::Space, + VirtualKeyCode::Insert => egui::Key::Insert, + VirtualKeyCode::Delete => egui::Key::Delete, + VirtualKeyCode::Home => egui::Key::Home, + VirtualKeyCode::End => egui::Key::End, + VirtualKeyCode::PageUp => egui::Key::PageUp, + VirtualKeyCode::PageDown => egui::Key::PageDown, + VirtualKeyCode::Minus => egui::Key::Minus, + VirtualKeyCode::Equals => egui::Key::PlusEquals, + VirtualKeyCode::Key0 | VirtualKeyCode::Numpad0 => egui::Key::Num0, + VirtualKeyCode::Key1 | VirtualKeyCode::Numpad1 => egui::Key::Num1, + VirtualKeyCode::Key2 | VirtualKeyCode::Numpad2 => egui::Key::Num2, + VirtualKeyCode::Key3 | VirtualKeyCode::Numpad3 => egui::Key::Num3, + VirtualKeyCode::Key4 | VirtualKeyCode::Numpad4 => egui::Key::Num4, + VirtualKeyCode::Key5 | VirtualKeyCode::Numpad5 => egui::Key::Num5, + VirtualKeyCode::Key6 | VirtualKeyCode::Numpad6 => egui::Key::Num6, + VirtualKeyCode::Key7 | VirtualKeyCode::Numpad7 => egui::Key::Num7, + VirtualKeyCode::Key8 | VirtualKeyCode::Numpad8 => egui::Key::Num8, + VirtualKeyCode::Key9 | VirtualKeyCode::Numpad9 => egui::Key::Num9, + VirtualKeyCode::A => egui::Key::A, + VirtualKeyCode::B => egui::Key::B, + VirtualKeyCode::C => egui::Key::C, + VirtualKeyCode::D => egui::Key::D, + VirtualKeyCode::E => egui::Key::E, + VirtualKeyCode::F => egui::Key::F, + VirtualKeyCode::G => egui::Key::G, + VirtualKeyCode::H => egui::Key::H, + VirtualKeyCode::I => egui::Key::I, + VirtualKeyCode::J => egui::Key::J, + VirtualKeyCode::K => egui::Key::K, + VirtualKeyCode::L => egui::Key::L, + VirtualKeyCode::M => egui::Key::M, + VirtualKeyCode::N => egui::Key::N, + VirtualKeyCode::O => egui::Key::O, + VirtualKeyCode::P => egui::Key::P, + VirtualKeyCode::Q => egui::Key::Q, + VirtualKeyCode::R => egui::Key::R, + VirtualKeyCode::S => egui::Key::S, + VirtualKeyCode::T => egui::Key::T, + VirtualKeyCode::U => egui::Key::U, + VirtualKeyCode::V => egui::Key::V, + VirtualKeyCode::W => egui::Key::W, + VirtualKeyCode::X => egui::Key::X, + VirtualKeyCode::Y => egui::Key::Y, + VirtualKeyCode::Z => egui::Key::Z, + VirtualKeyCode::F1 => egui::Key::F1, + VirtualKeyCode::F2 => egui::Key::F2, + VirtualKeyCode::F3 => egui::Key::F3, + VirtualKeyCode::F4 => egui::Key::F4, + VirtualKeyCode::F5 => egui::Key::F5, + VirtualKeyCode::F6 => egui::Key::F6, + VirtualKeyCode::F7 => egui::Key::F7, + VirtualKeyCode::F8 => egui::Key::F8, + VirtualKeyCode::F9 => egui::Key::F9, + VirtualKeyCode::F10 => egui::Key::F10, + VirtualKeyCode::F11 => egui::Key::F11, + VirtualKeyCode::F12 => egui::Key::F12, + VirtualKeyCode::F13 => egui::Key::F13, + VirtualKeyCode::F14 => egui::Key::F14, + VirtualKeyCode::F15 => egui::Key::F15, + VirtualKeyCode::F16 => egui::Key::F16, + VirtualKeyCode::F17 => egui::Key::F17, + VirtualKeyCode::F18 => egui::Key::F18, + VirtualKeyCode::F19 => egui::Key::F19, + VirtualKeyCode::F20 => egui::Key::F20, + _ => { + return None; + } + }); +} + +/// Convert an egui mouse cursor icon to a winit mouse cursor icon. +pub fn egui_to_winit_mouse_cursor_icon( + mouse_cursor_icon: egui::CursorIcon, +) -> Option { + return match mouse_cursor_icon { + egui::CursorIcon::None => None, + egui::CursorIcon::Alias => Some(winit::window::CursorIcon::Alias), + egui::CursorIcon::AllScroll => Some(winit::window::CursorIcon::AllScroll), + egui::CursorIcon::Cell => Some(winit::window::CursorIcon::Cell), + egui::CursorIcon::ContextMenu => { + Some(winit::window::CursorIcon::ContextMenu) + } + egui::CursorIcon::Copy => Some(winit::window::CursorIcon::Copy), + egui::CursorIcon::Crosshair => Some(winit::window::CursorIcon::Crosshair), + egui::CursorIcon::Default => Some(winit::window::CursorIcon::Default), + egui::CursorIcon::Grab => Some(winit::window::CursorIcon::Grab), + egui::CursorIcon::Grabbing => Some(winit::window::CursorIcon::Grabbing), + egui::CursorIcon::Help => Some(winit::window::CursorIcon::Help), + egui::CursorIcon::Move => Some(winit::window::CursorIcon::Move), + egui::CursorIcon::NoDrop => Some(winit::window::CursorIcon::NoDrop), + egui::CursorIcon::NotAllowed => Some(winit::window::CursorIcon::NotAllowed), + egui::CursorIcon::PointingHand => Some(winit::window::CursorIcon::Hand), + egui::CursorIcon::Progress => Some(winit::window::CursorIcon::Progress), + egui::CursorIcon::ResizeHorizontal => { + Some(winit::window::CursorIcon::EwResize) + } + egui::CursorIcon::ResizeNeSw => Some(winit::window::CursorIcon::NeswResize), + egui::CursorIcon::ResizeNwSe => Some(winit::window::CursorIcon::NwseResize), + egui::CursorIcon::ResizeVertical => { + Some(winit::window::CursorIcon::NsResize) + } + egui::CursorIcon::ResizeEast => Some(winit::window::CursorIcon::EResize), + egui::CursorIcon::ResizeSouthEast => { + Some(winit::window::CursorIcon::SeResize) + } + egui::CursorIcon::ResizeSouth => Some(winit::window::CursorIcon::SResize), + egui::CursorIcon::ResizeSouthWest => { + Some(winit::window::CursorIcon::SwResize) + } + egui::CursorIcon::ResizeWest => Some(winit::window::CursorIcon::WResize), + egui::CursorIcon::ResizeNorthWest => { + Some(winit::window::CursorIcon::NwResize) + } + egui::CursorIcon::ResizeNorth => Some(winit::window::CursorIcon::NResize), + egui::CursorIcon::ResizeNorthEast => { + Some(winit::window::CursorIcon::NeResize) + } + egui::CursorIcon::ResizeColumn => { + Some(winit::window::CursorIcon::ColResize) + } + egui::CursorIcon::ResizeRow => Some(winit::window::CursorIcon::RowResize), + + egui::CursorIcon::Text => Some(winit::window::CursorIcon::Text), + egui::CursorIcon::VerticalText => { + Some(winit::window::CursorIcon::VerticalText) + } + egui::CursorIcon::Wait => Some(winit::window::CursorIcon::Wait), + egui::CursorIcon::ZoomIn => Some(winit::window::CursorIcon::ZoomIn), + egui::CursorIcon::ZoomOut => Some(winit::window::CursorIcon::ZoomOut), + }; +} + +/// Check if the keyboard event is a cut event. +pub fn is_keyboard_cut( + modifiers: egui::Modifiers, + key_code: winit::event::VirtualKeyCode, +) -> bool { + let is_cut = modifiers.command && key_code == winit::event::VirtualKeyCode::X; + + let is_cut_with_delete = cfg!(any( + target_os = "windows", + all(unix, not(target_os = "macos")) + )) && modifiers.ctrl + && key_code == winit::event::VirtualKeyCode::Delete; + + return is_cut || is_cut_with_delete; +} + +/// Check if the keyboard event is a copy event. +pub fn is_keyboard_copy( + modifiers: egui::Modifiers, + key_code: winit::event::VirtualKeyCode, +) -> bool { + let is_copy = + modifiers.command && key_code == winit::event::VirtualKeyCode::C; + + let is_copy_with_insert = cfg!(any( + target_os = "windows", + all(unix, not(target_os = "macos")) + )) && modifiers.ctrl + && key_code == winit::event::VirtualKeyCode::Insert; + + return is_copy || is_copy_with_insert; +} + +/// Check if the keyboard event is a paste event. +pub fn is_keyboard_paste( + modifiers: egui::Modifiers, + key_code: winit::event::VirtualKeyCode, +) -> bool { + let is_paste = + modifiers.command && key_code == winit::event::VirtualKeyCode::V; + + let is_paste_with_insert = cfg!(any( + target_os = "windows", + all(unix, not(target_os = "macos")) + )) && modifiers.shift + && key_code == winit::event::VirtualKeyCode::Insert; + + return is_paste || is_paste_with_insert; +} diff --git a/crates/lambda-rs-platform/src/egui/winit.rs b/crates/lambda-rs-platform/src/egui/winit/mod.rs similarity index 85% rename from crates/lambda-rs-platform/src/egui/winit.rs rename to crates/lambda-rs-platform/src/egui/winit/mod.rs index 68bc5786..1082c3c2 100644 --- a/crates/lambda-rs-platform/src/egui/winit.rs +++ b/crates/lambda-rs-platform/src/egui/winit/mod.rs @@ -1,16 +1,21 @@ //! Custom integration between [egui](https://crates.io/crates/egui) //! and [winit](https://crates.io/crates/winit). +pub mod input; + use egui::{ Context, Modifiers, RawInput, }; -use winit::event::{ - ElementState, - Event, - MouseButton, - WindowEvent, +use winit::{ + dpi::PhysicalPosition, + event::{ + ElementState, + Event, + MouseButton, + WindowEvent, + }, }; pub struct EventResult { pub processed: bool, @@ -26,7 +31,7 @@ impl super::EguiContext { ..Default::default() }, internal_egui_context: Context::default(), - cursor_position: None, + mouse_position: None, cursor_button_active: false, current_pixels_per_point: 1.0, emulate_touch_screen: false, @@ -34,7 +39,24 @@ impl super::EguiContext { } fn process_mouse_input(&mut self, state: ElementState, button: MouseButton) { - if let Some(position) = self.cursor_position {} + if let Some(position) = self.mouse_position {} + } + + fn process_mouse_movement( + &mut self, + physical_mouse_position: PhysicalPosition, + ) { + let normalized_position = egui::pos2( + physical_mouse_position.x as f32 / self.current_pixels_per_point, + physical_mouse_position.y as f32 / self.current_pixels_per_point, + ); + + self.mouse_position = Some(normalized_position); + + match self.emulate_touch_screen { + true => if self.cursor_button_active {}, + false => {} + } } pub fn on_event( @@ -84,7 +106,7 @@ impl super::EguiContext { modifiers, } => todo!(), WindowEvent::CursorLeft { .. } => { - self.cursor_position = None; + self.mouse_position = None; self .internal_egui_input .events From c6af41044d3aeb499abaaaffaeafae2caa2e3038 Mon Sep 17 00:00:00 2001 From: vmarcella Date: Sun, 5 Feb 2023 13:07:28 -0800 Subject: [PATCH 10/21] [add] egui file opeartions. --- .../lambda-rs-platform/src/egui/winit/mod.rs | 53 +++++++++++++++---- 1 file changed, 42 insertions(+), 11 deletions(-) diff --git a/crates/lambda-rs-platform/src/egui/winit/mod.rs b/crates/lambda-rs-platform/src/egui/winit/mod.rs index 1082c3c2..d77f1490 100644 --- a/crates/lambda-rs-platform/src/egui/winit/mod.rs +++ b/crates/lambda-rs-platform/src/egui/winit/mod.rs @@ -67,9 +67,40 @@ impl super::EguiContext { Event::NewEvents(_) => todo!(), Event::WindowEvent { window_id, event } => match event { // File events. - WindowEvent::DroppedFile(_) => todo!(), - WindowEvent::HoveredFile(_) => todo!(), - WindowEvent::HoveredFileCancelled => todo!(), + WindowEvent::DroppedFile(path) => { + self.internal_egui_input.dropped_files.clear(); + self + .internal_egui_input + .dropped_files + .push(egui::DroppedFile { + path: Some(path.clone()), + ..Default::default() + }); + return EventResult { + redraw: true, + processed: false, + }; + } + WindowEvent::HoveredFile(path) => { + self + .internal_egui_input + .hovered_files + .push(egui::HoveredFile { + path: Some(path.clone()), + ..Default::default() + }); + return EventResult { + redraw: true, + processed: false, + }; + } + WindowEvent::HoveredFileCancelled => { + self.internal_egui_input.hovered_files.clear(); + return EventResult { + redraw: true, + processed: false, + }; + } // Keyboard events. WindowEvent::ReceivedCharacter(_) => todo!(), WindowEvent::KeyboardInput { @@ -94,10 +125,10 @@ impl super::EguiContext { } => { self.process_mouse_input(state.clone(), button.clone()); let processed = self.internal_egui_context.wants_pointer_input(); - EventResult { + return EventResult { processed, redraw: true, - } + }; } WindowEvent::MouseWheel { device_id, @@ -111,10 +142,10 @@ impl super::EguiContext { .internal_egui_input .events .push(egui::Event::PointerGone); - EventResult { + return EventResult { processed: false, redraw: true, - } + }; } // Repaint events @@ -146,10 +177,10 @@ impl super::EguiContext { self .internal_egui_context .set_pixels_per_point(pixels_per_point); - EventResult { + return EventResult { processed: false, redraw: true, - } + }; } WindowEvent::Focused(focused) => { self.internal_egui_input.has_focus = *focused; @@ -157,10 +188,10 @@ impl super::EguiContext { false => self.internal_egui_input.modifiers = Modifiers::default(), _ => {} } - EventResult { + return EventResult { processed: false, redraw: true, - } + }; } }, Event::DeviceEvent { device_id, event } => todo!(), From 1cd12b0ae362c222d49d9d7169f6419ac9ff9e14 Mon Sep 17 00:00:00 2001 From: vmarcella Date: Sun, 5 Feb 2023 14:41:51 -0800 Subject: [PATCH 11/21] [update] process mouse input and refactor winit mouse button conversion function. --- .../src/egui/winit/input.rs | 4 ++- .../lambda-rs-platform/src/egui/winit/mod.rs | 36 +++++++++++++++++-- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/crates/lambda-rs-platform/src/egui/winit/input.rs b/crates/lambda-rs-platform/src/egui/winit/input.rs index 5e03f4fb..1b8d761a 100644 --- a/crates/lambda-rs-platform/src/egui/winit/input.rs +++ b/crates/lambda-rs-platform/src/egui/winit/input.rs @@ -8,7 +8,9 @@ use winit::event::{ }; /// Convert a winit mouse button to an egui mouse button. -pub fn winit_to_egui_button(button: MouseButton) -> Option { +pub fn winit_to_egui_mouse_button( + button: MouseButton, +) -> Option { return match button { MouseButton::Left => Some(PointerButton::Primary), MouseButton::Right => Some(PointerButton::Secondary), diff --git a/crates/lambda-rs-platform/src/egui/winit/mod.rs b/crates/lambda-rs-platform/src/egui/winit/mod.rs index d77f1490..fc274be0 100644 --- a/crates/lambda-rs-platform/src/egui/winit/mod.rs +++ b/crates/lambda-rs-platform/src/egui/winit/mod.rs @@ -17,6 +17,8 @@ use winit::{ WindowEvent, }, }; + +use self::input::winit_to_egui_mouse_button; pub struct EventResult { pub processed: bool, pub redraw: bool, @@ -39,7 +41,21 @@ impl super::EguiContext { } fn process_mouse_input(&mut self, state: ElementState, button: MouseButton) { - if let Some(position) = self.mouse_position {} + match self.mouse_position { + Some(position) => match winit_to_egui_mouse_button(button) { + Some(button) => { + let is_pressed = state == winit::event::ElementState::Pressed; + } + None => { + logging::warn!("Couldn't convert the winit mouse button to an egui mouse button. Ignoring input."); + } + }, + None => { + logging::debug!( + "Mouse position not within the bounds of the window. Ignoring input." + ); + } + } } fn process_mouse_movement( @@ -108,7 +124,23 @@ impl super::EguiContext { input, is_synthetic, } => todo!(), - WindowEvent::ModifiersChanged(_) => todo!(), + WindowEvent::ModifiersChanged(state) => { + self.internal_egui_input.modifiers.alt = state.alt(); + self.internal_egui_input.modifiers.ctrl = state.ctrl(); + self.internal_egui_input.modifiers.shift = state.shift(); + self.internal_egui_input.modifiers.mac_cmd = + cfg!(target_os = "macos") && state.logo(); + self.internal_egui_input.modifiers.command = + match cfg!(target_os = "macos") { + true => state.logo(), + false => state.ctrl(), + }; + + return EventResult { + redraw: true, + processed: false, + }; + } WindowEvent::Ime(_) => todo!(), WindowEvent::CursorMoved { device_id, From 03d75e498e7bc1df7bd2fc008efe8c26e0183ef6 Mon Sep 17 00:00:00 2001 From: vmarcella Date: Sun, 5 Feb 2023 15:54:34 -0800 Subject: [PATCH 12/21] [update] naming for egui input & context. --- crates/lambda-rs-platform/src/egui/mod.rs | 4 +- .../lambda-rs-platform/src/egui/winit/mod.rs | 80 +++++++++++++------ 2 files changed, 57 insertions(+), 27 deletions(-) diff --git a/crates/lambda-rs-platform/src/egui/mod.rs b/crates/lambda-rs-platform/src/egui/mod.rs index 54543a57..464c78bf 100644 --- a/crates/lambda-rs-platform/src/egui/mod.rs +++ b/crates/lambda-rs-platform/src/egui/mod.rs @@ -8,8 +8,8 @@ pub mod winit; /// A context for managing egui input & rendering. pub struct EguiContext { - internal_egui_input: RawInput, - internal_egui_context: Context, + internal_input_handler: RawInput, + internal_context: Context, mouse_position: Option, cursor_button_active: bool, current_pixels_per_point: f32, diff --git a/crates/lambda-rs-platform/src/egui/winit/mod.rs b/crates/lambda-rs-platform/src/egui/winit/mod.rs index fc274be0..daa0824e 100644 --- a/crates/lambda-rs-platform/src/egui/winit/mod.rs +++ b/crates/lambda-rs-platform/src/egui/winit/mod.rs @@ -11,6 +11,7 @@ use egui::{ use winit::{ dpi::PhysicalPosition, event::{ + DeviceId, ElementState, Event, MouseButton, @@ -28,11 +29,11 @@ impl super::EguiContext { /// Create a new input manager prepped for winit usage. pub fn new() -> Self { Self { - internal_egui_input: RawInput { + internal_input_handler: RawInput { has_focus: false, ..Default::default() }, - internal_egui_context: Context::default(), + internal_context: Context::default(), mouse_position: None, cursor_button_active: false, current_pixels_per_point: 1.0, @@ -40,7 +41,12 @@ impl super::EguiContext { } } - fn process_mouse_input(&mut self, state: ElementState, button: MouseButton) { + /// Process a winit mouse input event. + fn process_winit_mouse_input( + &mut self, + state: ElementState, + button: MouseButton, + ) { match self.mouse_position { Some(position) => match winit_to_egui_mouse_button(button) { Some(button) => { @@ -58,7 +64,8 @@ impl super::EguiContext { } } - fn process_mouse_movement( + /// Process a winit mouse movement event. + fn process_winit_mouse_movement( &mut self, physical_mouse_position: PhysicalPosition, ) { @@ -70,8 +77,25 @@ impl super::EguiContext { self.mouse_position = Some(normalized_position); match self.emulate_touch_screen { - true => if self.cursor_button_active {}, - false => {} + true => { + if self.cursor_button_active { + self + .internal_input_handler + .events + .push(egui::Event::PointerMoved(normalized_position)); + self.internal_input_handler.events.push(egui::Event::Touch { + device_id: egui::TouchDeviceId(0), + id: egui::TouchId(0), + phase: egui::TouchPhase::Move, + pos: normalized_position, + force: 0.0, + }) + } + } + false => self + .internal_input_handler + .events + .push(egui::Event::PointerMoved((normalized_position))), } } @@ -84,9 +108,9 @@ impl super::EguiContext { Event::WindowEvent { window_id, event } => match event { // File events. WindowEvent::DroppedFile(path) => { - self.internal_egui_input.dropped_files.clear(); + self.internal_input_handler.dropped_files.clear(); self - .internal_egui_input + .internal_input_handler .dropped_files .push(egui::DroppedFile { path: Some(path.clone()), @@ -99,7 +123,7 @@ impl super::EguiContext { } WindowEvent::HoveredFile(path) => { self - .internal_egui_input + .internal_input_handler .hovered_files .push(egui::HoveredFile { path: Some(path.clone()), @@ -111,7 +135,7 @@ impl super::EguiContext { }; } WindowEvent::HoveredFileCancelled => { - self.internal_egui_input.hovered_files.clear(); + self.internal_input_handler.hovered_files.clear(); return EventResult { redraw: true, processed: false, @@ -125,12 +149,12 @@ impl super::EguiContext { is_synthetic, } => todo!(), WindowEvent::ModifiersChanged(state) => { - self.internal_egui_input.modifiers.alt = state.alt(); - self.internal_egui_input.modifiers.ctrl = state.ctrl(); - self.internal_egui_input.modifiers.shift = state.shift(); - self.internal_egui_input.modifiers.mac_cmd = + self.internal_input_handler.modifiers.alt = state.alt(); + self.internal_input_handler.modifiers.ctrl = state.ctrl(); + self.internal_input_handler.modifiers.shift = state.shift(); + self.internal_input_handler.modifiers.mac_cmd = cfg!(target_os = "macos") && state.logo(); - self.internal_egui_input.modifiers.command = + self.internal_input_handler.modifiers.command = match cfg!(target_os = "macos") { true => state.logo(), false => state.ctrl(), @@ -146,7 +170,13 @@ impl super::EguiContext { device_id, position, modifiers, - } => todo!(), + } => { + self.process_winit_mouse_movement(*position); + return EventResult { + processed: self.internal_context.wants_pointer_input(), + redraw: true, + }; + } // Mouse input events WindowEvent::MouseInput { @@ -155,8 +185,8 @@ impl super::EguiContext { button, modifiers, } => { - self.process_mouse_input(state.clone(), button.clone()); - let processed = self.internal_egui_context.wants_pointer_input(); + self.process_winit_mouse_input(state.clone(), button.clone()); + let processed = self.internal_context.wants_pointer_input(); return EventResult { processed, redraw: true, @@ -171,7 +201,7 @@ impl super::EguiContext { WindowEvent::CursorLeft { .. } => { self.mouse_position = None; self - .internal_egui_input + .internal_input_handler .events .push(egui::Event::PointerGone); return EventResult { @@ -205,19 +235,19 @@ impl super::EguiContext { new_inner_size, } => { let pixels_per_point = *scale_factor as f32; - self.internal_egui_input.pixels_per_point = Some(pixels_per_point); - self - .internal_egui_context - .set_pixels_per_point(pixels_per_point); + self.internal_input_handler.pixels_per_point = Some(pixels_per_point); + self.internal_context.set_pixels_per_point(pixels_per_point); return EventResult { processed: false, redraw: true, }; } WindowEvent::Focused(focused) => { - self.internal_egui_input.has_focus = *focused; + self.internal_input_handler.has_focus = *focused; match focused { - false => self.internal_egui_input.modifiers = Modifiers::default(), + false => { + self.internal_input_handler.modifiers = Modifiers::default() + } _ => {} } return EventResult { From 3f0db012d6ee2592b6b943199d3b7c346efb4839 Mon Sep 17 00:00:00 2001 From: vmarcella Date: Sun, 5 Feb 2023 17:36:46 -0800 Subject: [PATCH 13/21] [update] winit cursor icon. --- crates/lambda-rs-platform/src/egui/mod.rs | 2 +- .../src/egui/winit/input.rs | 89 ++++++++----------- .../lambda-rs-platform/src/egui/winit/mod.rs | 40 +++++++-- 3 files changed, 70 insertions(+), 61 deletions(-) diff --git a/crates/lambda-rs-platform/src/egui/mod.rs b/crates/lambda-rs-platform/src/egui/mod.rs index 464c78bf..4eb5a93b 100644 --- a/crates/lambda-rs-platform/src/egui/mod.rs +++ b/crates/lambda-rs-platform/src/egui/mod.rs @@ -11,7 +11,7 @@ pub struct EguiContext { internal_input_handler: RawInput, internal_context: Context, mouse_position: Option, - cursor_button_active: bool, + mouse_button_active: bool, current_pixels_per_point: f32, emulate_touch_screen: bool, } diff --git a/crates/lambda-rs-platform/src/egui/winit/input.rs b/crates/lambda-rs-platform/src/egui/winit/input.rs index 1b8d761a..0cdd885c 100644 --- a/crates/lambda-rs-platform/src/egui/winit/input.rs +++ b/crates/lambda-rs-platform/src/egui/winit/input.rs @@ -103,65 +103,48 @@ pub fn winit_to_egui_key(key: VirtualKeyCode) -> Option { }); } +use winit::window::CursorIcon as WinitCursorIcon; + /// Convert an egui mouse cursor icon to a winit mouse cursor icon. pub fn egui_to_winit_mouse_cursor_icon( mouse_cursor_icon: egui::CursorIcon, ) -> Option { return match mouse_cursor_icon { egui::CursorIcon::None => None, - egui::CursorIcon::Alias => Some(winit::window::CursorIcon::Alias), - egui::CursorIcon::AllScroll => Some(winit::window::CursorIcon::AllScroll), - egui::CursorIcon::Cell => Some(winit::window::CursorIcon::Cell), - egui::CursorIcon::ContextMenu => { - Some(winit::window::CursorIcon::ContextMenu) - } - egui::CursorIcon::Copy => Some(winit::window::CursorIcon::Copy), - egui::CursorIcon::Crosshair => Some(winit::window::CursorIcon::Crosshair), - egui::CursorIcon::Default => Some(winit::window::CursorIcon::Default), - egui::CursorIcon::Grab => Some(winit::window::CursorIcon::Grab), - egui::CursorIcon::Grabbing => Some(winit::window::CursorIcon::Grabbing), - egui::CursorIcon::Help => Some(winit::window::CursorIcon::Help), - egui::CursorIcon::Move => Some(winit::window::CursorIcon::Move), - egui::CursorIcon::NoDrop => Some(winit::window::CursorIcon::NoDrop), - egui::CursorIcon::NotAllowed => Some(winit::window::CursorIcon::NotAllowed), - egui::CursorIcon::PointingHand => Some(winit::window::CursorIcon::Hand), - egui::CursorIcon::Progress => Some(winit::window::CursorIcon::Progress), - egui::CursorIcon::ResizeHorizontal => { - Some(winit::window::CursorIcon::EwResize) - } - egui::CursorIcon::ResizeNeSw => Some(winit::window::CursorIcon::NeswResize), - egui::CursorIcon::ResizeNwSe => Some(winit::window::CursorIcon::NwseResize), - egui::CursorIcon::ResizeVertical => { - Some(winit::window::CursorIcon::NsResize) - } - egui::CursorIcon::ResizeEast => Some(winit::window::CursorIcon::EResize), - egui::CursorIcon::ResizeSouthEast => { - Some(winit::window::CursorIcon::SeResize) - } - egui::CursorIcon::ResizeSouth => Some(winit::window::CursorIcon::SResize), - egui::CursorIcon::ResizeSouthWest => { - Some(winit::window::CursorIcon::SwResize) - } - egui::CursorIcon::ResizeWest => Some(winit::window::CursorIcon::WResize), - egui::CursorIcon::ResizeNorthWest => { - Some(winit::window::CursorIcon::NwResize) - } - egui::CursorIcon::ResizeNorth => Some(winit::window::CursorIcon::NResize), - egui::CursorIcon::ResizeNorthEast => { - Some(winit::window::CursorIcon::NeResize) - } - egui::CursorIcon::ResizeColumn => { - Some(winit::window::CursorIcon::ColResize) - } - egui::CursorIcon::ResizeRow => Some(winit::window::CursorIcon::RowResize), - - egui::CursorIcon::Text => Some(winit::window::CursorIcon::Text), - egui::CursorIcon::VerticalText => { - Some(winit::window::CursorIcon::VerticalText) - } - egui::CursorIcon::Wait => Some(winit::window::CursorIcon::Wait), - egui::CursorIcon::ZoomIn => Some(winit::window::CursorIcon::ZoomIn), - egui::CursorIcon::ZoomOut => Some(winit::window::CursorIcon::ZoomOut), + egui::CursorIcon::Alias => Some(WinitCursorIcon::Alias), + egui::CursorIcon::AllScroll => Some(WinitCursorIcon::AllScroll), + egui::CursorIcon::Cell => Some(WinitCursorIcon::Cell), + egui::CursorIcon::ContextMenu => Some(WinitCursorIcon::ContextMenu), + egui::CursorIcon::Copy => Some(WinitCursorIcon::Copy), + egui::CursorIcon::Crosshair => Some(WinitCursorIcon::Crosshair), + egui::CursorIcon::Default => Some(WinitCursorIcon::Default), + egui::CursorIcon::Grab => Some(WinitCursorIcon::Grab), + egui::CursorIcon::Grabbing => Some(WinitCursorIcon::Grabbing), + egui::CursorIcon::Help => Some(WinitCursorIcon::Help), + egui::CursorIcon::Move => Some(WinitCursorIcon::Move), + egui::CursorIcon::NoDrop => Some(WinitCursorIcon::NoDrop), + egui::CursorIcon::NotAllowed => Some(WinitCursorIcon::NotAllowed), + egui::CursorIcon::PointingHand => Some(WinitCursorIcon::Hand), + egui::CursorIcon::Progress => Some(WinitCursorIcon::Progress), + egui::CursorIcon::ResizeHorizontal => Some(WinitCursorIcon::EwResize), + egui::CursorIcon::ResizeNeSw => Some(WinitCursorIcon::NeswResize), + egui::CursorIcon::ResizeNwSe => Some(WinitCursorIcon::NwseResize), + egui::CursorIcon::ResizeVertical => Some(WinitCursorIcon::NsResize), + egui::CursorIcon::ResizeEast => Some(WinitCursorIcon::EResize), + egui::CursorIcon::ResizeSouthEast => Some(WinitCursorIcon::SeResize), + egui::CursorIcon::ResizeSouth => Some(WinitCursorIcon::SResize), + egui::CursorIcon::ResizeSouthWest => Some(WinitCursorIcon::SwResize), + egui::CursorIcon::ResizeWest => Some(WinitCursorIcon::WResize), + egui::CursorIcon::ResizeNorthWest => Some(WinitCursorIcon::NwResize), + egui::CursorIcon::ResizeNorth => Some(WinitCursorIcon::NResize), + egui::CursorIcon::ResizeNorthEast => Some(WinitCursorIcon::NeResize), + egui::CursorIcon::ResizeColumn => Some(WinitCursorIcon::ColResize), + egui::CursorIcon::ResizeRow => Some(WinitCursorIcon::RowResize), + egui::CursorIcon::Text => Some(WinitCursorIcon::Text), + egui::CursorIcon::VerticalText => Some(WinitCursorIcon::VerticalText), + egui::CursorIcon::Wait => Some(WinitCursorIcon::Wait), + egui::CursorIcon::ZoomIn => Some(WinitCursorIcon::ZoomIn), + egui::CursorIcon::ZoomOut => Some(WinitCursorIcon::ZoomOut), }; } diff --git a/crates/lambda-rs-platform/src/egui/winit/mod.rs b/crates/lambda-rs-platform/src/egui/winit/mod.rs index daa0824e..ed9deb37 100644 --- a/crates/lambda-rs-platform/src/egui/winit/mod.rs +++ b/crates/lambda-rs-platform/src/egui/winit/mod.rs @@ -35,14 +35,15 @@ impl super::EguiContext { }, internal_context: Context::default(), mouse_position: None, - cursor_button_active: false, + mouse_button_active: false, current_pixels_per_point: 1.0, emulate_touch_screen: false, } } - /// Process a winit mouse input event. - fn process_winit_mouse_input( + /// Process a winit mouse input event. First checks if the mouse position is on + /// the screen and then if a winit mouse button is pressed. + fn process_winit_mouse_button( &mut self, state: ElementState, button: MouseButton, @@ -51,9 +52,31 @@ impl super::EguiContext { Some(position) => match winit_to_egui_mouse_button(button) { Some(button) => { let is_pressed = state == winit::event::ElementState::Pressed; + + self + .internal_input_handler + .events + .push(egui::Event::PointerButton { + pos: position, + button, + pressed: is_pressed, + modifiers: self.internal_input_handler.modifiers, + }); + + match self.emulate_touch_screen { + false => {} + true => match is_pressed { + true => { + self.mouse_button_active = true; + } + false => { + self.mouse_button_active = false; + } + }, + } } None => { - logging::warn!("Couldn't convert the winit mouse button to an egui mouse button. Ignoring input."); + logging::debug!("Couldn't convert the winit mouse button to an egui mouse button. Ignoring input."); } }, None => { @@ -69,6 +92,7 @@ impl super::EguiContext { &mut self, physical_mouse_position: PhysicalPosition, ) { + // Normalize the mouse position by the current pixels per point. let normalized_position = egui::pos2( physical_mouse_position.x as f32 / self.current_pixels_per_point, physical_mouse_position.y as f32 / self.current_pixels_per_point, @@ -76,9 +100,11 @@ impl super::EguiContext { self.mouse_position = Some(normalized_position); + // If we are emulating a touch screen, we need to send a touch event. + // Otherwise, we send a mouse event. match self.emulate_touch_screen { true => { - if self.cursor_button_active { + if self.mouse_button_active { self .internal_input_handler .events @@ -95,7 +121,7 @@ impl super::EguiContext { false => self .internal_input_handler .events - .push(egui::Event::PointerMoved((normalized_position))), + .push(egui::Event::PointerMoved(normalized_position)), } } @@ -185,7 +211,7 @@ impl super::EguiContext { button, modifiers, } => { - self.process_winit_mouse_input(state.clone(), button.clone()); + self.process_winit_mouse_button(state.clone(), button.clone()); let processed = self.internal_context.wants_pointer_input(); return EventResult { processed, From 28ed67e4243fc5f005eb57a99d1670200b6acbf7 Mon Sep 17 00:00:00 2001 From: vmarcella Date: Sun, 5 Feb 2023 17:41:37 -0800 Subject: [PATCH 14/21] [update] virtual key code. --- .../src/egui/winit/input.rs | 173 +++++++++--------- 1 file changed, 84 insertions(+), 89 deletions(-) diff --git a/crates/lambda-rs-platform/src/egui/winit/input.rs b/crates/lambda-rs-platform/src/egui/winit/input.rs index 0cdd885c..b849d9f4 100644 --- a/crates/lambda-rs-platform/src/egui/winit/input.rs +++ b/crates/lambda-rs-platform/src/egui/winit/input.rs @@ -4,7 +4,7 @@ use egui::PointerButton; use winit::event::{ MouseButton, - VirtualKeyCode, + VirtualKeyCode as WinitKey, }; /// Convert a winit mouse button to an egui mouse button. @@ -22,81 +22,81 @@ pub fn winit_to_egui_mouse_button( } /// Convert a winit virtual key code to an egui key code. -pub fn winit_to_egui_key(key: VirtualKeyCode) -> Option { +pub fn winit_to_egui_key(key: WinitKey) -> Option { return Some(match key { - VirtualKeyCode::Down => egui::Key::ArrowDown, - VirtualKeyCode::Left => egui::Key::ArrowLeft, - VirtualKeyCode::Right => egui::Key::ArrowRight, - VirtualKeyCode::Up => egui::Key::ArrowUp, - VirtualKeyCode::Escape => egui::Key::Escape, - VirtualKeyCode::Tab => egui::Key::Tab, - VirtualKeyCode::Back => egui::Key::Backspace, - VirtualKeyCode::Return => egui::Key::Enter, - VirtualKeyCode::Space => egui::Key::Space, - VirtualKeyCode::Insert => egui::Key::Insert, - VirtualKeyCode::Delete => egui::Key::Delete, - VirtualKeyCode::Home => egui::Key::Home, - VirtualKeyCode::End => egui::Key::End, - VirtualKeyCode::PageUp => egui::Key::PageUp, - VirtualKeyCode::PageDown => egui::Key::PageDown, - VirtualKeyCode::Minus => egui::Key::Minus, - VirtualKeyCode::Equals => egui::Key::PlusEquals, - VirtualKeyCode::Key0 | VirtualKeyCode::Numpad0 => egui::Key::Num0, - VirtualKeyCode::Key1 | VirtualKeyCode::Numpad1 => egui::Key::Num1, - VirtualKeyCode::Key2 | VirtualKeyCode::Numpad2 => egui::Key::Num2, - VirtualKeyCode::Key3 | VirtualKeyCode::Numpad3 => egui::Key::Num3, - VirtualKeyCode::Key4 | VirtualKeyCode::Numpad4 => egui::Key::Num4, - VirtualKeyCode::Key5 | VirtualKeyCode::Numpad5 => egui::Key::Num5, - VirtualKeyCode::Key6 | VirtualKeyCode::Numpad6 => egui::Key::Num6, - VirtualKeyCode::Key7 | VirtualKeyCode::Numpad7 => egui::Key::Num7, - VirtualKeyCode::Key8 | VirtualKeyCode::Numpad8 => egui::Key::Num8, - VirtualKeyCode::Key9 | VirtualKeyCode::Numpad9 => egui::Key::Num9, - VirtualKeyCode::A => egui::Key::A, - VirtualKeyCode::B => egui::Key::B, - VirtualKeyCode::C => egui::Key::C, - VirtualKeyCode::D => egui::Key::D, - VirtualKeyCode::E => egui::Key::E, - VirtualKeyCode::F => egui::Key::F, - VirtualKeyCode::G => egui::Key::G, - VirtualKeyCode::H => egui::Key::H, - VirtualKeyCode::I => egui::Key::I, - VirtualKeyCode::J => egui::Key::J, - VirtualKeyCode::K => egui::Key::K, - VirtualKeyCode::L => egui::Key::L, - VirtualKeyCode::M => egui::Key::M, - VirtualKeyCode::N => egui::Key::N, - VirtualKeyCode::O => egui::Key::O, - VirtualKeyCode::P => egui::Key::P, - VirtualKeyCode::Q => egui::Key::Q, - VirtualKeyCode::R => egui::Key::R, - VirtualKeyCode::S => egui::Key::S, - VirtualKeyCode::T => egui::Key::T, - VirtualKeyCode::U => egui::Key::U, - VirtualKeyCode::V => egui::Key::V, - VirtualKeyCode::W => egui::Key::W, - VirtualKeyCode::X => egui::Key::X, - VirtualKeyCode::Y => egui::Key::Y, - VirtualKeyCode::Z => egui::Key::Z, - VirtualKeyCode::F1 => egui::Key::F1, - VirtualKeyCode::F2 => egui::Key::F2, - VirtualKeyCode::F3 => egui::Key::F3, - VirtualKeyCode::F4 => egui::Key::F4, - VirtualKeyCode::F5 => egui::Key::F5, - VirtualKeyCode::F6 => egui::Key::F6, - VirtualKeyCode::F7 => egui::Key::F7, - VirtualKeyCode::F8 => egui::Key::F8, - VirtualKeyCode::F9 => egui::Key::F9, - VirtualKeyCode::F10 => egui::Key::F10, - VirtualKeyCode::F11 => egui::Key::F11, - VirtualKeyCode::F12 => egui::Key::F12, - VirtualKeyCode::F13 => egui::Key::F13, - VirtualKeyCode::F14 => egui::Key::F14, - VirtualKeyCode::F15 => egui::Key::F15, - VirtualKeyCode::F16 => egui::Key::F16, - VirtualKeyCode::F17 => egui::Key::F17, - VirtualKeyCode::F18 => egui::Key::F18, - VirtualKeyCode::F19 => egui::Key::F19, - VirtualKeyCode::F20 => egui::Key::F20, + WinitKey::Down => egui::Key::ArrowDown, + WinitKey::Left => egui::Key::ArrowLeft, + WinitKey::Right => egui::Key::ArrowRight, + WinitKey::Up => egui::Key::ArrowUp, + WinitKey::Escape => egui::Key::Escape, + WinitKey::Tab => egui::Key::Tab, + WinitKey::Back => egui::Key::Backspace, + WinitKey::Return => egui::Key::Enter, + WinitKey::Space => egui::Key::Space, + WinitKey::Insert => egui::Key::Insert, + WinitKey::Delete => egui::Key::Delete, + WinitKey::Home => egui::Key::Home, + WinitKey::End => egui::Key::End, + WinitKey::PageUp => egui::Key::PageUp, + WinitKey::PageDown => egui::Key::PageDown, + WinitKey::Minus => egui::Key::Minus, + WinitKey::Equals => egui::Key::PlusEquals, + WinitKey::Key0 | WinitKey::Numpad0 => egui::Key::Num0, + WinitKey::Key1 | WinitKey::Numpad1 => egui::Key::Num1, + WinitKey::Key2 | WinitKey::Numpad2 => egui::Key::Num2, + WinitKey::Key3 | WinitKey::Numpad3 => egui::Key::Num3, + WinitKey::Key4 | WinitKey::Numpad4 => egui::Key::Num4, + WinitKey::Key5 | WinitKey::Numpad5 => egui::Key::Num5, + WinitKey::Key6 | WinitKey::Numpad6 => egui::Key::Num6, + WinitKey::Key7 | WinitKey::Numpad7 => egui::Key::Num7, + WinitKey::Key8 | WinitKey::Numpad8 => egui::Key::Num8, + WinitKey::Key9 | WinitKey::Numpad9 => egui::Key::Num9, + WinitKey::A => egui::Key::A, + WinitKey::B => egui::Key::B, + WinitKey::C => egui::Key::C, + WinitKey::D => egui::Key::D, + WinitKey::E => egui::Key::E, + WinitKey::F => egui::Key::F, + WinitKey::G => egui::Key::G, + WinitKey::H => egui::Key::H, + WinitKey::I => egui::Key::I, + WinitKey::J => egui::Key::J, + WinitKey::K => egui::Key::K, + WinitKey::L => egui::Key::L, + WinitKey::M => egui::Key::M, + WinitKey::N => egui::Key::N, + WinitKey::O => egui::Key::O, + WinitKey::P => egui::Key::P, + WinitKey::Q => egui::Key::Q, + WinitKey::R => egui::Key::R, + WinitKey::S => egui::Key::S, + WinitKey::T => egui::Key::T, + WinitKey::U => egui::Key::U, + WinitKey::V => egui::Key::V, + WinitKey::W => egui::Key::W, + WinitKey::X => egui::Key::X, + WinitKey::Y => egui::Key::Y, + WinitKey::Z => egui::Key::Z, + WinitKey::F1 => egui::Key::F1, + WinitKey::F2 => egui::Key::F2, + WinitKey::F3 => egui::Key::F3, + WinitKey::F4 => egui::Key::F4, + WinitKey::F5 => egui::Key::F5, + WinitKey::F6 => egui::Key::F6, + WinitKey::F7 => egui::Key::F7, + WinitKey::F8 => egui::Key::F8, + WinitKey::F9 => egui::Key::F9, + WinitKey::F10 => egui::Key::F10, + WinitKey::F11 => egui::Key::F11, + WinitKey::F12 => egui::Key::F12, + WinitKey::F13 => egui::Key::F13, + WinitKey::F14 => egui::Key::F14, + WinitKey::F15 => egui::Key::F15, + WinitKey::F16 => egui::Key::F16, + WinitKey::F17 => egui::Key::F17, + WinitKey::F18 => egui::Key::F18, + WinitKey::F19 => egui::Key::F19, + WinitKey::F20 => egui::Key::F20, _ => { return None; } @@ -149,17 +149,14 @@ pub fn egui_to_winit_mouse_cursor_icon( } /// Check if the keyboard event is a cut event. -pub fn is_keyboard_cut( - modifiers: egui::Modifiers, - key_code: winit::event::VirtualKeyCode, -) -> bool { - let is_cut = modifiers.command && key_code == winit::event::VirtualKeyCode::X; +pub fn is_keyboard_cut(modifiers: egui::Modifiers, key_code: WinitKey) -> bool { + let is_cut = modifiers.command && key_code == WinitKey::X; let is_cut_with_delete = cfg!(any( target_os = "windows", all(unix, not(target_os = "macos")) )) && modifiers.ctrl - && key_code == winit::event::VirtualKeyCode::Delete; + && key_code == WinitKey::Delete; return is_cut || is_cut_with_delete; } @@ -167,16 +164,15 @@ pub fn is_keyboard_cut( /// Check if the keyboard event is a copy event. pub fn is_keyboard_copy( modifiers: egui::Modifiers, - key_code: winit::event::VirtualKeyCode, + key_code: WinitKey, ) -> bool { - let is_copy = - modifiers.command && key_code == winit::event::VirtualKeyCode::C; + let is_copy = modifiers.command && key_code == WinitKey::C; let is_copy_with_insert = cfg!(any( target_os = "windows", all(unix, not(target_os = "macos")) )) && modifiers.ctrl - && key_code == winit::event::VirtualKeyCode::Insert; + && key_code == WinitKey::Insert; return is_copy || is_copy_with_insert; } @@ -184,16 +180,15 @@ pub fn is_keyboard_copy( /// Check if the keyboard event is a paste event. pub fn is_keyboard_paste( modifiers: egui::Modifiers, - key_code: winit::event::VirtualKeyCode, + key_code: WinitKey, ) -> bool { - let is_paste = - modifiers.command && key_code == winit::event::VirtualKeyCode::V; + let is_paste = modifiers.command && key_code == WinitKey::V; let is_paste_with_insert = cfg!(any( target_os = "windows", all(unix, not(target_os = "macos")) )) && modifiers.shift - && key_code == winit::event::VirtualKeyCode::Insert; + && key_code == WinitKey::Insert; return is_paste || is_paste_with_insert; } From c26be1673689a055b7d8a26a33b5cc2908f051a3 Mon Sep 17 00:00:00 2001 From: vmarcella Date: Sun, 5 Feb 2023 18:05:14 -0800 Subject: [PATCH 15/21] [update] input handler references. --- crates/lambda-rs-platform/src/egui/mod.rs | 2 +- .../lambda-rs-platform/src/egui/winit/mod.rs | 80 ++++++++----------- 2 files changed, 34 insertions(+), 48 deletions(-) diff --git a/crates/lambda-rs-platform/src/egui/mod.rs b/crates/lambda-rs-platform/src/egui/mod.rs index 4eb5a93b..72ab98fa 100644 --- a/crates/lambda-rs-platform/src/egui/mod.rs +++ b/crates/lambda-rs-platform/src/egui/mod.rs @@ -8,7 +8,7 @@ pub mod winit; /// A context for managing egui input & rendering. pub struct EguiContext { - internal_input_handler: RawInput, + input_handler: RawInput, internal_context: Context, mouse_position: Option, mouse_button_active: bool, diff --git a/crates/lambda-rs-platform/src/egui/winit/mod.rs b/crates/lambda-rs-platform/src/egui/winit/mod.rs index ed9deb37..95717a04 100644 --- a/crates/lambda-rs-platform/src/egui/winit/mod.rs +++ b/crates/lambda-rs-platform/src/egui/winit/mod.rs @@ -29,7 +29,7 @@ impl super::EguiContext { /// Create a new input manager prepped for winit usage. pub fn new() -> Self { Self { - internal_input_handler: RawInput { + input_handler: RawInput { has_focus: false, ..Default::default() }, @@ -53,15 +53,12 @@ impl super::EguiContext { Some(button) => { let is_pressed = state == winit::event::ElementState::Pressed; - self - .internal_input_handler - .events - .push(egui::Event::PointerButton { - pos: position, - button, - pressed: is_pressed, - modifiers: self.internal_input_handler.modifiers, - }); + self.input_handler.events.push(egui::Event::PointerButton { + pos: position, + button, + pressed: is_pressed, + modifiers: self.input_handler.modifiers, + }); match self.emulate_touch_screen { false => {} @@ -106,10 +103,10 @@ impl super::EguiContext { true => { if self.mouse_button_active { self - .internal_input_handler + .input_handler .events .push(egui::Event::PointerMoved(normalized_position)); - self.internal_input_handler.events.push(egui::Event::Touch { + self.input_handler.events.push(egui::Event::Touch { device_id: egui::TouchDeviceId(0), id: egui::TouchId(0), phase: egui::TouchPhase::Move, @@ -119,7 +116,7 @@ impl super::EguiContext { } } false => self - .internal_input_handler + .input_handler .events .push(egui::Event::PointerMoved(normalized_position)), } @@ -134,34 +131,28 @@ impl super::EguiContext { Event::WindowEvent { window_id, event } => match event { // File events. WindowEvent::DroppedFile(path) => { - self.internal_input_handler.dropped_files.clear(); - self - .internal_input_handler - .dropped_files - .push(egui::DroppedFile { - path: Some(path.clone()), - ..Default::default() - }); + self.input_handler.dropped_files.clear(); + self.input_handler.dropped_files.push(egui::DroppedFile { + path: Some(path.clone()), + ..Default::default() + }); return EventResult { redraw: true, processed: false, }; } WindowEvent::HoveredFile(path) => { - self - .internal_input_handler - .hovered_files - .push(egui::HoveredFile { - path: Some(path.clone()), - ..Default::default() - }); + self.input_handler.hovered_files.push(egui::HoveredFile { + path: Some(path.clone()), + ..Default::default() + }); return EventResult { redraw: true, processed: false, }; } WindowEvent::HoveredFileCancelled => { - self.internal_input_handler.hovered_files.clear(); + self.input_handler.hovered_files.clear(); return EventResult { redraw: true, processed: false, @@ -175,16 +166,16 @@ impl super::EguiContext { is_synthetic, } => todo!(), WindowEvent::ModifiersChanged(state) => { - self.internal_input_handler.modifiers.alt = state.alt(); - self.internal_input_handler.modifiers.ctrl = state.ctrl(); - self.internal_input_handler.modifiers.shift = state.shift(); - self.internal_input_handler.modifiers.mac_cmd = + self.input_handler.modifiers.alt = state.alt(); + self.input_handler.modifiers.ctrl = state.ctrl(); + self.input_handler.modifiers.shift = state.shift(); + self.input_handler.modifiers.mac_cmd = cfg!(target_os = "macos") && state.logo(); - self.internal_input_handler.modifiers.command = - match cfg!(target_os = "macos") { - true => state.logo(), - false => state.ctrl(), - }; + self.input_handler.modifiers.command = match cfg!(target_os = "macos") + { + true => state.logo(), + false => state.ctrl(), + }; return EventResult { redraw: true, @@ -226,10 +217,7 @@ impl super::EguiContext { } => todo!(), WindowEvent::CursorLeft { .. } => { self.mouse_position = None; - self - .internal_input_handler - .events - .push(egui::Event::PointerGone); + self.input_handler.events.push(egui::Event::PointerGone); return EventResult { processed: false, redraw: true, @@ -261,7 +249,7 @@ impl super::EguiContext { new_inner_size, } => { let pixels_per_point = *scale_factor as f32; - self.internal_input_handler.pixels_per_point = Some(pixels_per_point); + self.input_handler.pixels_per_point = Some(pixels_per_point); self.internal_context.set_pixels_per_point(pixels_per_point); return EventResult { processed: false, @@ -269,11 +257,9 @@ impl super::EguiContext { }; } WindowEvent::Focused(focused) => { - self.internal_input_handler.has_focus = *focused; + self.input_handler.has_focus = *focused; match focused { - false => { - self.internal_input_handler.modifiers = Modifiers::default() - } + false => self.input_handler.modifiers = Modifiers::default(), _ => {} } return EventResult { From 81b77355bbe32aa7f7fef6fb72cf306a84650925 Mon Sep 17 00:00:00 2001 From: vmarcella Date: Sun, 5 Feb 2023 18:05:56 -0800 Subject: [PATCH 16/21] [update] context references. --- crates/lambda-rs-platform/src/egui/mod.rs | 2 +- crates/lambda-rs-platform/src/egui/winit/mod.rs | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/crates/lambda-rs-platform/src/egui/mod.rs b/crates/lambda-rs-platform/src/egui/mod.rs index 72ab98fa..a2fdc493 100644 --- a/crates/lambda-rs-platform/src/egui/mod.rs +++ b/crates/lambda-rs-platform/src/egui/mod.rs @@ -9,7 +9,7 @@ pub mod winit; /// A context for managing egui input & rendering. pub struct EguiContext { input_handler: RawInput, - internal_context: Context, + context: Context, mouse_position: Option, mouse_button_active: bool, current_pixels_per_point: f32, diff --git a/crates/lambda-rs-platform/src/egui/winit/mod.rs b/crates/lambda-rs-platform/src/egui/winit/mod.rs index 95717a04..10832dd1 100644 --- a/crates/lambda-rs-platform/src/egui/winit/mod.rs +++ b/crates/lambda-rs-platform/src/egui/winit/mod.rs @@ -33,7 +33,7 @@ impl super::EguiContext { has_focus: false, ..Default::default() }, - internal_context: Context::default(), + context: Context::default(), mouse_position: None, mouse_button_active: false, current_pixels_per_point: 1.0, @@ -190,7 +190,7 @@ impl super::EguiContext { } => { self.process_winit_mouse_movement(*position); return EventResult { - processed: self.internal_context.wants_pointer_input(), + processed: self.context.wants_pointer_input(), redraw: true, }; } @@ -203,7 +203,7 @@ impl super::EguiContext { modifiers, } => { self.process_winit_mouse_button(state.clone(), button.clone()); - let processed = self.internal_context.wants_pointer_input(); + let processed = self.context.wants_pointer_input(); return EventResult { processed, redraw: true, @@ -250,7 +250,7 @@ impl super::EguiContext { } => { let pixels_per_point = *scale_factor as f32; self.input_handler.pixels_per_point = Some(pixels_per_point); - self.internal_context.set_pixels_per_point(pixels_per_point); + self.context.set_pixels_per_point(pixels_per_point); return EventResult { processed: false, redraw: true, From 1b8bdf715779376d6635e134ff8a625e02813182 Mon Sep 17 00:00:00 2001 From: vmarcella Date: Sat, 11 Feb 2023 23:43:59 -0800 Subject: [PATCH 17/21] [fix] references for internal variables. --- crates/lambda-rs-platform/src/egui/winit/mod.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crates/lambda-rs-platform/src/egui/winit/mod.rs b/crates/lambda-rs-platform/src/egui/winit/mod.rs index 10832dd1..303ea2e8 100644 --- a/crates/lambda-rs-platform/src/egui/winit/mod.rs +++ b/crates/lambda-rs-platform/src/egui/winit/mod.rs @@ -1,5 +1,10 @@ //! Custom integration between [egui](https://crates.io/crates/egui) //! and [winit](https://crates.io/crates/winit). +//! +//! This module implements the following for winit / egui compatibility: +//! * Mouse support +//! * Touch support +//! * File support pub mod input; From 0235873a92a9660303245e05fc521fb38ab0a9a1 Mon Sep 17 00:00:00 2001 From: vmarcella Date: Sat, 11 Feb 2023 23:46:19 -0800 Subject: [PATCH 18/21] [update] pipeline to not manually call the webhook. --- .github/workflows/compile_lambda_rs.yml | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/.github/workflows/compile_lambda_rs.yml b/.github/workflows/compile_lambda_rs.yml index fc6851d2..44dbf3fa 100644 --- a/.github/workflows/compile_lambda_rs.yml +++ b/.github/workflows/compile_lambda_rs.yml @@ -66,19 +66,5 @@ jobs: rustup toolchain install ${{ matrix.rustup-toolchain }} rustup default ${{ matrix.rustup-toolchain }} - - name: Build Lambda & other default workspace members. + - name: Build Lambda using platform specific features. run: cargo test --all --features ${{ matrix.features }} --no-default-features - - - uses: actions/setup-ruby@v1 - - name: Send Webhook Notification for build status. - if: ${{ github.ref == 'refs/heads/main' }} - env: - JOB_STATUS: ${{ job.status }} - WEBHOOK_URL: ${{ secrets.LAMBDA_BUILD_WEBHOOK }} - HOOK_OS_NAME: ${{ runner.os }} - WORKFLOW_NAME: ${{ github.workflow }} - JOB_ID: ${{ github.job }} - run: | - git clone https://github.com/dhinakg/github-actions-discord-webhook.git webhook - bash webhook/send.sh $JOB_STATUS $WEBHOOK_URL - shell: bash From f3a05760d2e5e429856c594dc9e1704f258bb93b Mon Sep 17 00:00:00 2001 From: vmarcella Date: Sat, 18 Feb 2023 13:14:35 -0800 Subject: [PATCH 19/21] [add] high level ui context & elements to use for rendering from user applications. --- .../lambda-rs-platform/src/egui/winit/mod.rs | 2 + crates/lambda-rs/src/render/mod.rs | 1 + crates/lambda-rs/src/render/ui/mod.rs | 51 +++++++++++++++++++ 3 files changed, 54 insertions(+) create mode 100644 crates/lambda-rs/src/render/ui/mod.rs diff --git a/crates/lambda-rs-platform/src/egui/winit/mod.rs b/crates/lambda-rs-platform/src/egui/winit/mod.rs index 303ea2e8..1a016463 100644 --- a/crates/lambda-rs-platform/src/egui/winit/mod.rs +++ b/crates/lambda-rs-platform/src/egui/winit/mod.rs @@ -65,6 +65,8 @@ impl super::EguiContext { modifiers: self.input_handler.modifiers, }); + // If we emulate a touch screen & a mouse button is being pressed, + // we set the mouse button as active to send touch events. match self.emulate_touch_screen { false => {} true => match is_pressed { diff --git a/crates/lambda-rs/src/render/mod.rs b/crates/lambda-rs/src/render/mod.rs index 27cd0c22..e22da4d8 100644 --- a/crates/lambda-rs/src/render/mod.rs +++ b/crates/lambda-rs/src/render/mod.rs @@ -8,6 +8,7 @@ pub mod mesh; pub mod pipeline; pub mod render_pass; pub mod shader; +pub mod ui; pub mod vertex; pub mod viewport; pub mod window; diff --git a/crates/lambda-rs/src/render/ui/mod.rs b/crates/lambda-rs/src/render/ui/mod.rs new file mode 100644 index 00000000..66d401f1 --- /dev/null +++ b/crates/lambda-rs/src/render/ui/mod.rs @@ -0,0 +1,51 @@ +pub use lambda_platform::egui; + +pub enum GridDirection { + Horizontal, + Vertical, +} + +pub enum UIElement { + Button { + text: String, + width: f32, + height: f32, + on_click: Option, + }, + Grid { + rows: usize, + columns: usize, + width: f32, + height: f32, + direction: GridDirection, + children: Vec, + }, +} + +/// The context for managing UI state & rendering. +pub struct UIContext { + pub elements: Vec, + egui_context: egui::EguiContext, +} + +impl UIContext { + pub fn new() -> Self { + Self { + elements: Vec::new(), + egui_context: egui::EguiContext::new(), + } + } + + pub fn add_element(&mut self, element: UIElement) { + self.elements.push(element); + } + + /// Passes lower level winit events to egui for processing. + // TODO(vmarcella): Can we change this function signature? + pub(crate) fn on_winit_event( + &mut self, + event: &lambda_platform::winit::winit_exports::Event<()>, + ) -> egui::winit::EventResult { + self.egui_context.on_event(event) + } +} From a41934ab3c41307e658261ad4b459b3e82b4da0a Mon Sep 17 00:00:00 2001 From: vmarcella Date: Sat, 8 Apr 2023 22:53:13 -0700 Subject: [PATCH 20/21] [add] touch event processing for egui. --- crates/lambda-rs-platform/src/egui/gfx/mod.rs | 52 ++++++ crates/lambda-rs-platform/src/egui/mod.rs | 3 + .../lambda-rs-platform/src/egui/winit/mod.rs | 150 ++++++++++++++++-- crates/lambda-rs/src/render/ui/mod.rs | 23 +-- 4 files changed, 194 insertions(+), 34 deletions(-) create mode 100644 crates/lambda-rs-platform/src/egui/gfx/mod.rs diff --git a/crates/lambda-rs-platform/src/egui/gfx/mod.rs b/crates/lambda-rs-platform/src/egui/gfx/mod.rs new file mode 100644 index 00000000..a68852d7 --- /dev/null +++ b/crates/lambda-rs-platform/src/egui/gfx/mod.rs @@ -0,0 +1,52 @@ +//! Support module for rendering `egui` elements within our rendering +//! infrastructure. +pub enum GridDirection { + Horizontal, + Vertical, +} + +pub enum UIElement { + Button { + text: String, + width: f32, + height: f32, + on_click: Option, + }, + Grid { + rows: usize, + columns: usize, + width: f32, + height: f32, + direction: GridDirection, + children: Vec, + }, +} + +impl UIElement { + /// Renders the UI element + pub(crate) fn render(&mut self, ui_for_frame: &mut egui::Ui) { + match self { + UIElement::Button { + text, + width, + height, + on_click, + } => { + if ui_for_frame.button(text.as_str()).clicked() { + match on_click { + Some(on_click) => on_click(), + None => {} + } + } + } + UIElement::Grid { + rows, + columns, + width, + height, + direction, + children, + } => todo!(), + } + } +} diff --git a/crates/lambda-rs-platform/src/egui/mod.rs b/crates/lambda-rs-platform/src/egui/mod.rs index a2fdc493..9cdadb60 100644 --- a/crates/lambda-rs-platform/src/egui/mod.rs +++ b/crates/lambda-rs-platform/src/egui/mod.rs @@ -2,8 +2,10 @@ use egui::{ Context, Pos2, RawInput, + TouchDeviceId, }; +pub mod gfx; pub mod winit; /// A context for managing egui input & rendering. @@ -14,4 +16,5 @@ pub struct EguiContext { mouse_button_active: bool, current_pixels_per_point: f32, emulate_touch_screen: bool, + active_touch_device: Option, } diff --git a/crates/lambda-rs-platform/src/egui/winit/mod.rs b/crates/lambda-rs-platform/src/egui/winit/mod.rs index 1a016463..e84962ec 100644 --- a/crates/lambda-rs-platform/src/egui/winit/mod.rs +++ b/crates/lambda-rs-platform/src/egui/winit/mod.rs @@ -13,6 +13,10 @@ use egui::{ Modifiers, RawInput, }; +use logging::{ + debug, + Logger, +}; use winit::{ dpi::PhysicalPosition, event::{ @@ -20,11 +24,14 @@ use winit::{ ElementState, Event, MouseButton, + TouchPhase, + VirtualKeyCode, WindowEvent, }, }; use self::input::winit_to_egui_mouse_button; +use crate::egui::winit::input::winit_to_egui_key; pub struct EventResult { pub processed: bool, pub redraw: bool, @@ -43,6 +50,7 @@ impl super::EguiContext { mouse_button_active: false, current_pixels_per_point: 1.0, emulate_touch_screen: false, + active_touch_device: None, } } @@ -129,12 +137,98 @@ impl super::EguiContext { } } + fn process_winit_touch_event(&mut self, event: winit::event::Touch) { + let winit::event::Touch { + location, + phase, + device_id, + force, + id, + } = event; + let egui_phase = match phase { + TouchPhase::Started => { + self.mouse_button_active = true; + egui::TouchPhase::Start + } + TouchPhase::Moved => { + self.mouse_button_active = true; + egui::TouchPhase::Move + } + TouchPhase::Ended => { + self.mouse_button_active = false; + egui::TouchPhase::End + } + TouchPhase::Cancelled => { + self.mouse_button_active = false; + egui::TouchPhase::Cancel + } + }; + let touch_device_id = + egui::TouchDeviceId(egui::epaint::util::hash(device_id)); + self.input_handler.events.push(egui::Event::Touch { + device_id: touch_device_id, + id: egui::TouchId(id), + phase: egui_phase, + pos: egui::pos2( + location.x as f32 / self.current_pixels_per_point, + location.y as f32 / self.current_pixels_per_point, + ), + force: match force { + Some(winit::event::Force::Normalized(force)) => force as f32, + Some(winit::event::Force::Calibrated { + force, + max_possible_force, + altitude_angle, + }) => match altitude_angle { + // Applies the altitude angle to the force + Some(altitude_angle) => { + (force / max_possible_force) as f32 * (altitude_angle.cos() as f32) + } + None => (force / max_possible_force) as f32, + }, + None => 0.0 as f32, + }, + }); + let processing_touch = self.active_touch_device.is_none() + || self.active_touch_device == Some(touch_device_id); + + if processing_touch { + match phase { + TouchPhase::Started => { + self.active_touch_device = Some(touch_device_id); + self.process_winit_mouse_movement(location); + self.process_winit_mouse_button( + ElementState::Pressed, + MouseButton::Left, + ); + } + TouchPhase::Moved => { + self.process_winit_mouse_movement(location); + } + TouchPhase::Ended => { + self.active_touch_device = None; + self.process_winit_mouse_movement(location); + self.process_winit_mouse_button( + ElementState::Released, + MouseButton::Left, + ); + } + TouchPhase::Cancelled => { + self.process_winit_mouse_movement(location); + self.process_winit_mouse_button( + ElementState::Released, + MouseButton::Left, + ); + } + } + } + } + pub fn on_event( &mut self, event: &Event, ) -> EventResult { return match event { - Event::NewEvents(_) => todo!(), Event::WindowEvent { window_id, event } => match event { // File events. WindowEvent::DroppedFile(path) => { @@ -166,12 +260,40 @@ impl super::EguiContext { }; } // Keyboard events. - WindowEvent::ReceivedCharacter(_) => todo!(), + WindowEvent::ReceivedCharacter(character) => { + if !character.is_control() { + self + .input_handler + .events + .push(egui::Event::Text(character.to_string())); + } + return EventResult { + redraw: true, + processed: false, + }; + } + WindowEvent::KeyboardInput { device_id, input, is_synthetic, - } => todo!(), + } => { + let pressed = input.state == ElementState::Pressed; + + if let Some(key) = winit_to_egui_key( + input.virtual_keycode.expect("No virtual keycode"), + ) { + self.input_handler.events.push(egui::Event::Key { + key, + pressed, + modifiers: self.input_handler.modifiers, + }); + } + return EventResult { + redraw: true, + processed: false, + }; + } WindowEvent::ModifiersChanged(state) => { self.input_handler.modifiers.alt = state.alt(); self.input_handler.modifiers.ctrl = state.ctrl(); @@ -189,7 +311,13 @@ impl super::EguiContext { processed: false, }; } - WindowEvent::Ime(_) => todo!(), + WindowEvent::Ime(ime) => { + debug!("IME event received, but cannot be handled yet: {:?}", ime); + return EventResult { + redraw: false, + processed: false, + }; + } WindowEvent::CursorMoved { device_id, position, @@ -275,14 +403,12 @@ impl super::EguiContext { }; } }, - Event::DeviceEvent { device_id, event } => todo!(), - Event::UserEvent(_) => todo!(), - Event::Suspended => todo!(), - Event::Resumed => todo!(), - Event::MainEventsCleared => todo!(), - Event::RedrawRequested(_) => todo!(), - Event::RedrawEventsCleared => todo!(), - Event::LoopDestroyed => todo!(), + _ => { + return EventResult { + processed: false, + redraw: false, + }; + } }; } } diff --git a/crates/lambda-rs/src/render/ui/mod.rs b/crates/lambda-rs/src/render/ui/mod.rs index 66d401f1..a1e0375e 100644 --- a/crates/lambda-rs/src/render/ui/mod.rs +++ b/crates/lambda-rs/src/render/ui/mod.rs @@ -1,26 +1,5 @@ pub use lambda_platform::egui; - -pub enum GridDirection { - Horizontal, - Vertical, -} - -pub enum UIElement { - Button { - text: String, - width: f32, - height: f32, - on_click: Option, - }, - Grid { - rows: usize, - columns: usize, - width: f32, - height: f32, - direction: GridDirection, - children: Vec, - }, -} +use lambda_platform::egui::gfx::UIElement; /// The context for managing UI state & rendering. pub struct UIContext { From 2f2f7d97ab716fe1254956be50743236e01a99d4 Mon Sep 17 00:00:00 2001 From: vmarcella Date: Sat, 8 Apr 2023 22:59:45 -0700 Subject: [PATCH 21/21] [add] touch event handling to event loop. --- crates/lambda-rs-platform/src/egui/winit/mod.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/crates/lambda-rs-platform/src/egui/winit/mod.rs b/crates/lambda-rs-platform/src/egui/winit/mod.rs index e84962ec..3f3c713f 100644 --- a/crates/lambda-rs-platform/src/egui/winit/mod.rs +++ b/crates/lambda-rs-platform/src/egui/winit/mod.rs @@ -329,7 +329,6 @@ impl super::EguiContext { redraw: true, }; } - // Mouse input events WindowEvent::MouseInput { device_id, @@ -376,7 +375,13 @@ impl super::EguiContext { processed: false, redraw: false, }, - WindowEvent::Touch(_) => todo!(), + WindowEvent::Touch(event) => { + self.process_winit_touch_event(event.clone()); + return EventResult { + processed: self.context.wants_pointer_input(), + redraw: true, + }; + } // Window Events WindowEvent::ScaleFactorChanged {