diff options
Diffstat (limited to 'engine/src/windowing.rs')
| -rw-r--r-- | engine/src/windowing.rs | 731 |
1 files changed, 386 insertions, 345 deletions
diff --git a/engine/src/windowing.rs b/engine/src/windowing.rs index 2493851..3e27075 100644 --- a/engine/src/windowing.rs +++ b/engine/src/windowing.rs @@ -24,7 +24,6 @@ use winit::window::{Window as WinitWindow, WindowId as WinitWindowId}; use crate::ecs::actions::Actions; use crate::ecs::component::Component; -use crate::ecs::entity::obtainer::Obtainer as EntityObtainer; use crate::ecs::event::component::{Added, Changed, EventMatchExt, Removed}; use crate::ecs::pair::{ChildOf, Pair}; use crate::ecs::phase::{Phase, PRE_UPDATE as PRE_UPDATE_PHASE}; @@ -32,11 +31,11 @@ use crate::ecs::sole::Single; use crate::ecs::system::observer::Observe; use crate::ecs::uid::Uid; use crate::ecs::util::StreamingIterator; -use crate::ecs::{declare_entity, pair, Query, Sole}; +use crate::ecs::{declare_entity, pair, Query, Sole, World}; use crate::util::BitArray; use crate::vector::Vec2; -use crate::windowing::dpi::{PhysicalPosition, PhysicalSize, Position}; -use crate::windowing::keyboard::{Key, KeyState, Keyboard, UnknownKeyCodeError}; +use crate::windowing::dpi::{LogicalPosition, PhysicalPosition, PhysicalSize, Position}; +use crate::windowing::keyboard::{Key, KeyState, Keyboard}; use crate::windowing::monitor::Handle as MonitorHandle; use crate::windowing::mouse::{ Button as MouseButton, @@ -82,7 +81,7 @@ impl crate::ecs::extension::Extension for Extension fn collect(self, mut collector: crate::ecs::extension::Collector<'_>) { if !CONTEXT_CREATED.load(Ordering::Relaxed) { - collector.add_sole(Context::new()).ok(); + collector.add_sole(Context::new_global()).ok(); } collector.add_sole(Keyboard::default()).ok(); @@ -135,118 +134,55 @@ fn update_stuff( mut mouse: Single<Mouse>, mut mouse_buttons: Single<MouseButtons>, mut actions: Actions, - entity_obtainer: EntityObtainer, + world: &World, ) -> Result<(), EngineError> { let Ok(context) = context.get_mut() else { unreachable!(); }; - let keyboard = keyboard.get_mut()?; - let mouse = mouse.get_mut()?; - let mouse_buttons = mouse_buttons.get_mut()?; - if context.display_handle.is_none() { cold_path(); actions.stop(); return Ok(()); } - keyboard.make_key_states_previous(); - - { - let Some(mut input) = context - .shared_state - .input - .try_lock_for(Duration::from_millis(100)) - else { - tracing::error!("Locking input mutex timed out after 100ms"); - return Ok(()); - }; - - mouse.curr_tick_position_delta = input.relative_mouse_pos_delta; - mouse.position = input.absolute_mouse_pos.clone(); - mouse.curr_tick_scroll_delta = input.mouse_scroll_delta.clone(); - - for (mouse_button, mouse_button_input) in input.mouse_buttons.iter_mut() { - mouse_buttons.set_previous_to_current(mouse_button); - - if mouse_button_input.flags.is_all() { - match mouse_buttons.get_previous(mouse_button) { - MouseButtonState::Pressed => { - mouse_buttons.set(mouse_button, MouseButtonState::Released); - - mouse_button_input.flags.remove(MouseButtonFlags::RELEASED); - } - MouseButtonState::Released => { - mouse_buttons.set(mouse_button, MouseButtonState::Pressed); - - mouse_button_input.flags.remove(MouseButtonFlags::PRESSED); - } - } - - continue; - } - - let mouse_button_state = if mouse_button_input.flags.is_empty() { - let Some(mouse_button_state) = mouse_button_input.lagged.pop_front() - else { - continue; - }; - - mouse_button_state - } else { - bitflags_match!(mouse_button_input.flags, { - MouseButtonFlags::PRESSED => MouseButtonState::Pressed, - MouseButtonFlags::RELEASED => MouseButtonState::Released, - _ => unreachable!() - }) - }; - - mouse_buttons.set(mouse_button, mouse_button_state); - - mouse_button_input.flags.clear(); - } - - let mut key_updates = input.keys.iter_occupied_mut(); - - while let Some(mut key_item) = key_updates.streaming_next() { - let key = Key::KEYS[key_item.index]; - - if key_item.bits == KEY_PRESSED_BITS | KEY_RELEASED_BITS { - match keyboard.get_key_state(key) { - KeyState::Pressed => { - keyboard.set_key_state(key, KeyState::Released); + let keyboard = keyboard.get_mut()?; + let mouse = mouse.get_mut()?; + let mouse_buttons = mouse_buttons.get_mut()?; - key_item.clear_and_set(KEY_PRESSED_BITS, u8::MAX); - } - KeyState::Released => { - keyboard.set_key_state(key, KeyState::Pressed); + update_inputs(context, keyboard, mouse, mouse_buttons); - key_item.clear_and_set(KEY_RELEASED_BITS, u8::MAX); - } - } + receive_app_messages(context, &mut actions, world); - continue; - } + if context.shared_state.thread_panicked.load(Ordering::Relaxed) { + cold_path(); + return Err(error!("Windowing app thread panicked")); + } - let key_state = match key_item.bits { - KEY_PRESSED_BITS => KeyState::Pressed, - KEY_RELEASED_BITS => KeyState::Released, - _ => unreachable!(), - }; + if context.shared_state.has_thread_err.load(Ordering::Relaxed) { + cold_path(); - keyboard.set_key_state(key, key_state); + let Ok(mut err) = context.shared_state.thread_err.try_lock() else { + // The windowing app thread always unlocks the thread_err mutex before + // setting the has_thread_err atomic + unreachable!(); + }; - key_item.clear_and_set(0, u8::MAX); - } + let Some(err) = err.take() else { + // The has_thread_err atomic is set to true so this option is always + // Some + unreachable!(); + }; - input.relative_mouse_pos_delta = Vec2 { x: 0.0, y: 0.0 }; - input.mouse_scroll_delta = MouseScrollDelta { vert_lines: 0.0, hor_lines: 0.0 }; - }; + return Err(err.into()); + } - keyboard.set_text_keys(iter_array_queue(&context.shared_state.text_keys)); + Ok(()) +} +fn receive_app_messages(context: &mut Context, actions: &mut Actions, world: &World) +{ let Context { ref mut windows, ref shared_state, .. } = *context; @@ -255,11 +191,11 @@ fn update_stuff( tracing::trace!(message=?message, "Received message from app"); match message { - MessageFromApp::WindowCreated( + MessageFromApp::Window(WindowMessage::Created( window_ent_id, winit_window, window_creation_attrs, - ) => { + )) => { actions.add_components( window_ent_id, (Window::new(&winit_window, &window_creation_attrs),), @@ -277,7 +213,10 @@ fn update_stuff( "Window creation completed" ); } - MessageFromApp::WindowResized(window_id, new_window_size) => { + MessageFromApp::Window(WindowMessage::Resized( + window_id, + new_window_size, + )) => { tracing::trace!( window_id = ?window_id, "Received window resized message" @@ -293,7 +232,7 @@ fn update_stuff( continue; }; - let Some(window_ent) = entity_obtainer.get_entity(*window_ent_id) else { + let Some(window_ent) = world.get_entity(*window_ent_id) else { continue; }; @@ -305,7 +244,7 @@ fn update_stuff( window.set_changed(); } - MessageFromApp::WindowCloseRequested(window_id) => { + MessageFromApp::Window(WindowMessage::CloseRequested(window_id)) => { let Some(window_ent_id) = windows.get(window_id).map(|(_, ent_id)| ent_id) else { @@ -318,7 +257,10 @@ fn update_stuff( actions.remove_comps::<(Window,)>(*window_ent_id); } - MessageFromApp::WindowScaleFactorChanged(window_id, scale_factor) => { + MessageFromApp::Window(WindowMessage::ScaleFactorChanged( + window_id, + scale_factor, + )) => { let Some(window_ent_id) = windows.get(window_id).map(|(_, ent_id)| ent_id) else { @@ -329,7 +271,7 @@ fn update_stuff( continue; }; - let Some(window_ent) = entity_obtainer.get_entity(*window_ent_id) else { + let Some(window_ent) = world.get_entity(*window_ent_id) else { continue; }; @@ -343,31 +285,109 @@ fn update_stuff( } } } +} - if shared_state.thread_panicked.load(Ordering::Relaxed) { - cold_path(); - return Err(error!("Windowing app thread panicked")); - } - - if shared_state.has_thread_err.load(Ordering::Relaxed) { - cold_path(); +fn update_inputs( + context: &Context, + keyboard: &mut Keyboard, + mouse: &mut Mouse, + mouse_buttons: &mut MouseButtons, +) +{ + keyboard.make_key_states_previous(); - let Ok(mut err) = shared_state.thread_err.try_lock() else { - // The windowing app thread always unlocks the thread_err mutex before - // setting the has_thread_err atomic - unreachable!(); + { + let Some(mut input) = context + .shared_state + .input + .try_lock_for(Duration::from_millis(100)) + else { + tracing::error!("Locking input mutex timed out after 100ms"); + return; }; - let Some(err) = err.take() else { - // The has_thread_err atomic is set to true so this option is always - // Some - unreachable!(); - }; + mouse.curr_tick_position_delta = input.relative_mouse_pos_delta; + mouse.position = input.absolute_mouse_pos; + mouse.curr_tick_scroll_delta = input.mouse_scroll_delta.clone(); - return Err(err.into()); - } + for (mouse_button, mouse_button_input) in &mut input.mouse_buttons { + mouse_buttons.set_previous_to_current(mouse_button); - Ok(()) + if mouse_button_input.flags.is_all() { + match mouse_buttons.get_previous(mouse_button) { + MouseButtonState::Pressed => { + mouse_buttons.set(mouse_button, MouseButtonState::Released); + + mouse_button_input.flags.remove(MouseButtonFlags::RELEASED); + } + MouseButtonState::Released => { + mouse_buttons.set(mouse_button, MouseButtonState::Pressed); + + mouse_button_input.flags.remove(MouseButtonFlags::PRESSED); + } + } + + continue; + } + + let mouse_button_state = if mouse_button_input.flags.is_empty() { + let Some(mouse_button_state) = mouse_button_input.lagged.pop_front() + else { + continue; + }; + + mouse_button_state + } else { + bitflags_match!(mouse_button_input.flags, { + MouseButtonFlags::PRESSED => MouseButtonState::Pressed, + MouseButtonFlags::RELEASED => MouseButtonState::Released, + _ => unreachable!() + }) + }; + + mouse_buttons.set(mouse_button, mouse_button_state); + + mouse_button_input.flags.clear(); + } + + let mut key_updates = input.keys.iter_occupied_mut(); + + while let Some(mut key_item) = key_updates.streaming_next() { + let key = Key::KEYS[key_item.index]; + + if key_item.bits == KEY_PRESSED_BITS | KEY_RELEASED_BITS { + match keyboard.get_key_state(key) { + KeyState::Pressed => { + keyboard.set_key_state(key, KeyState::Released); + + key_item.clear_and_set(KEY_PRESSED_BITS, u8::MAX); + } + KeyState::Released => { + keyboard.set_key_state(key, KeyState::Pressed); + + key_item.clear_and_set(KEY_RELEASED_BITS, u8::MAX); + } + } + + continue; + } + + let key_state = match key_item.bits { + KEY_PRESSED_BITS => KeyState::Pressed, + KEY_RELEASED_BITS => KeyState::Released, + _ => unreachable!(), + }; + + keyboard.set_key_state(key, key_state); + + key_item.clear_and_set(0, u8::MAX); + } + + input.relative_mouse_pos_delta = Vec2 { x: 0.0, y: 0.0 }; + input.mouse_scroll_delta = MouseScrollDelta { vert_lines: 0.0, hor_lines: 0.0 }; + }; + + keyboard.set_text_keys(iter_array_queue(&context.shared_state.text_keys)); } fn handle_window_changed( @@ -442,6 +462,7 @@ pub struct Context impl Context { + #[must_use] pub fn display_handle(&self) -> Option<DisplayHandle<'_>> { self.display_handle.as_ref()?.display_handle().ok() @@ -451,6 +472,7 @@ impl Context /// /// # Safety /// The Window handle must only be used with thread safe APIs. + #[must_use] pub unsafe fn get_window_as_handle( &self, window_id: &WindowId, @@ -476,6 +498,7 @@ impl Context /// Returns the last known primary monitor. This monitor may or may not exist any /// longer and it may or may not be the primary monitor any longer. + #[must_use] pub fn get_primary_monitor(&self) -> Option<&MonitorHandle> { self.primary_monitor.as_ref() @@ -509,11 +532,12 @@ impl Context /// /// # Panics /// Will panic if a windowing context have already been created. - pub fn new() -> Self + pub fn new_global() -> Self { - if CONTEXT_CREATED.swap(true, Ordering::Relaxed) { - panic!("A windowing context have already been created"); - } + assert!( + !CONTEXT_CREATED.swap(true, Ordering::Relaxed), + "A windowing context have already been created" + ); let shared_state = Arc::new(SharedState::default()); let shared_state_b = shared_state.clone(); @@ -521,58 +545,7 @@ impl Context if let Err(err) = ThreadBuilder::new() .name("windowing app".to_string()) .spawn(move || { - let shared_state_c = shared_state_b.clone(); - - match catch_unwind(move || { - let mut app = App { - shared_state: shared_state_b, - windows: IntMap::with_capacity(1), - }; - - let event_loop = match create_event_loop() { - Ok(event_loop) => event_loop, - Err(err) => { - return Err((app, AppThreadError::CreateEventLoop(err))); - } - }; - - event_loop.set_control_flow(EventLoopControlFlow::Poll); - - event_loop - .run_app(&mut app) - .map_err(|err| (app, AppThreadError::StartEventLoop(err)))?; - - Ok(()) - }) { - Ok(Ok(())) => {} - Ok(Err((app, err))) => { - { - let Ok(mut thread_err) = - app.shared_state.thread_err.try_lock() - else { - // The thread_err mutex is only locked by the main thread - // when the has_thread_err atomic is set to true, which - // it can not be set to yet - unreachable!(); - }; - - *thread_err = Some(err); - } - - app.shared_state - .has_thread_err - .store(true, Ordering::Relaxed); - - app.shared_state.init_data_cond.notify_one(); - } - Err(_) => { - shared_state_c - .thread_panicked - .store(true, Ordering::Relaxed); - - shared_state_c.init_data_cond.notify_one(); - } - }; + app_thread_main(shared_state_b); }) { tracing::error!( @@ -664,6 +637,58 @@ impl Drop for Context } } +fn app_thread_main(shared_state: Arc<SharedState>) +{ + let shared_state_c = shared_state.clone(); + + match catch_unwind(move || { + let mut app = App { + shared_state, + windows: IntMap::with_capacity(1), + }; + + let event_loop = match create_event_loop() { + Ok(event_loop) => event_loop, + Err(err) => { + return Err(AppThreadError::CreateEventLoop(err)); + } + }; + + event_loop.set_control_flow(EventLoopControlFlow::Poll); + + event_loop + .run_app(&mut app) + .map_err(AppThreadError::StartEventLoop)?; + + Ok(()) + }) { + Ok(Ok(())) => {} + Ok(Err(err)) => { + { + let Ok(mut thread_err) = shared_state_c.thread_err.try_lock() else { + // The thread_err mutex is only locked by the main thread + // when the has_thread_err atomic is set to true, which + // it can not be set to yet + unreachable!(); + }; + + *thread_err = Some(err); + } + + shared_state_c.has_thread_err.store(true, Ordering::Relaxed); + + shared_state_c.init_data_cond.notify_one(); + } + Err(_) => { + shared_state_c + .thread_panicked + .store(true, Ordering::Relaxed); + + shared_state_c.init_data_cond.notify_one(); + } + }; +} + fn create_event_loop() -> Result<EventLoop<()>, EventLoopError> { let mut event_loop_builder = EventLoop::builder(); @@ -702,10 +727,16 @@ enum AppThreadError #[derive(Debug)] enum MessageFromApp { - WindowCreated(Uid, Arc<WinitWindow>, WindowCreationAttributes), - WindowResized(WindowId, PhysicalSize<u32>), - WindowCloseRequested(WindowId), - WindowScaleFactorChanged(WindowId, f64), + Window(WindowMessage), +} + +#[derive(Debug)] +enum WindowMessage +{ + Created(Uid, Arc<WinitWindow>, WindowCreationAttributes), + Resized(WindowId, PhysicalSize<u32>), + CloseRequested(WindowId), + ScaleFactorChanged(WindowId, f64), } #[derive(Debug)] @@ -855,11 +886,11 @@ impl App ), ); - self.send_message(MessageFromApp::WindowCreated( + self.send_message(MessageFromApp::Window(WindowMessage::Created( window_ent_id, winit_window, window_creation_attrs, - )); + ))); } MessageToApp::SetWindowCursorGrabMode(window_id, cursor_grab_mode) => { let Some((_, window_settings)) = self.windows.get_mut(window_id) @@ -896,6 +927,153 @@ impl App .input .try_lock_for(Duration::from_millis(100)) } + + fn handle_keyboard_input(&self, keyboard_event: winit::event::KeyEvent) + { + if let Some(key_text) = keyboard_event + .text + .filter(|_| keyboard_event.state.is_pressed()) + { + for character in key_text.chars() { + if self.shared_state.text_keys.is_full() { + cold_path(); + tracing::warn!("Text key queue is full. Dropping oldest character"); + } + + self.shared_state.text_keys.force_push(character); + } + } + + if keyboard_event.repeat { + return; + } + + let key_code = match keyboard_event.physical_key { + PhysicalKey::Code(key_code) => key_code, + PhysicalKey::Unidentified(native_key) => { + tracing::warn!("Ignoring unidentified key: {native_key:?}"); + return; + } + }; + + let key: Key = if let Ok(key) = key_code.try_into() { + key + } else { + tracing::warn!("Ignoring key with unknown key code {key_code:?}"); + return; + }; + + let Some(mut input) = self.lock_input() else { + tracing::error!("Locking input mutex timed out after 100ms"); + return; + }; + + let key_state_bits = match keyboard_event.state.into() { + KeyState::Pressed => KEY_PRESSED_BITS, + KeyState::Released => KEY_RELEASED_BITS, + }; + + input.keys.clear_and_set(key as usize, key_state_bits, 0); + } + + fn handle_cursor_moved(&self, position: PhysicalPosition<f64>, window_id: WindowId) + { + { + let Some(mut input) = self.lock_input() else { + tracing::error!("Locking input mutex timed out after 100ms"); + return; + }; + + input.absolute_mouse_pos = position; + } + + let Some((window, window_settings)) = self.windows.get(window_id) else { + cold_path(); + return; + }; + + if window_settings.cursor_grab_mode != CursorGrabMode::Locked { + return; + } + + let Some(window) = window.upgrade() else { + cold_path(); + return; + }; + + if !window.has_focus() { + return; + } + + let window_size = window.inner_size().to_logical::<f64>(window.scale_factor()); + + if let Err(err) = window.set_cursor_position(Position::Logical(LogicalPosition { + x: window_size.width / 2.0, + y: window_size.height / 2.0, + })) { + cold_path(); + tracing::error!( + window_id=?window_id, + "Failed to lock cursor position: {:#}", + crate::Error::new(err) + ); + } + } + + fn handle_mouse_wheel(&self, delta: winit::event::MouseScrollDelta) + { + let (hor_lines, vert_lines) = match delta { + winit::event::MouseScrollDelta::LineDelta(hor_lines, vert_lines) => { + (hor_lines, vert_lines) + } + winit::event::MouseScrollDelta::PixelDelta(pos_delta) => { + let hor_lines = match pos_delta.x.partial_cmp(&0.0) { + Some(std::cmp::Ordering::Greater) => 1.0, + Some(std::cmp::Ordering::Less) => -1.0, + _ => 0.0, + }; + + let vert_lines = match pos_delta.y.partial_cmp(&0.0) { + Some(std::cmp::Ordering::Greater) => 1.0, + Some(std::cmp::Ordering::Less) => -1.0, + _ => 0.0, + }; + + (hor_lines, vert_lines) + } + }; + + let Some(mut input) = self.lock_input() else { + tracing::error!("Locking input mutex timed out after 100ms"); + return; + }; + + input.mouse_scroll_delta.hor_lines += hor_lines; + input.mouse_scroll_delta.vert_lines += vert_lines; + } + + fn handle_mouse_input(&self, button: MouseButton, button_state: MouseButtonState) + { + let Some(mut input) = self.lock_input() else { + tracing::error!("Locking input mutex timed out after 100ms"); + return; + }; + + let button_input = input + .mouse_buttons + .entry(button) + .or_insert_with(MouseButtonInput::default); + + if button_input.flags.is_all() || !button_input.lagged.is_empty() { + button_input.lagged.push_back(button_state); + return; + } + + button_input.flags.insert(match button_state { + MouseButtonState::Pressed => MouseButtonFlags::PRESSED, + MouseButtonState::Released => MouseButtonFlags::RELEASED, + }); + } } impl ApplicationHandler for App @@ -917,10 +1095,10 @@ impl ApplicationHandler for App *init_data = Some(InitData { display: event_loop.owned_display_handle(), - available_monitors: available_monitors, + available_monitors, primary_monitor: event_loop .primary_monitor() - .map(|monitor| MonitorHandle::from_winit_monitor_handle(monitor)), + .map(MonitorHandle::from_winit_monitor_handle), }); self.shared_state.init_data_cond.notify_one(); @@ -960,173 +1138,39 @@ impl ApplicationHandler for App { match event { WindowEvent::Resized(new_window_size) => { - self.send_message(MessageFromApp::WindowResized( + self.send_message(MessageFromApp::Window(WindowMessage::Resized( WindowId::from_inner(window_id), new_window_size.into(), - )); + ))); } WindowEvent::CloseRequested => { - self.send_message(MessageFromApp::WindowCloseRequested( + self.send_message(MessageFromApp::Window(WindowMessage::CloseRequested( WindowId::from_inner(window_id), - )); + ))); } WindowEvent::KeyboardInput { device_id: _, event: keyboard_event, is_synthetic: _, - } => { - if let Some(key_text) = keyboard_event - .text - .filter(|_| keyboard_event.state.is_pressed()) - { - for character in key_text.chars() { - if self.shared_state.text_keys.is_full() { - cold_path(); - tracing::warn!( - "Text key queue is full. Dropping oldest character" - ); - } - - self.shared_state.text_keys.force_push(character); - } - } - - if keyboard_event.repeat { - return; - } - - let key_code = match keyboard_event.physical_key { - PhysicalKey::Code(key_code) => key_code, - PhysicalKey::Unidentified(native_key) => { - tracing::warn!("Ignoring unidentified key: {native_key:?}"); - return; - } - }; - - let key: Key = match key_code.try_into() { - Ok(key) => key, - Err(UnknownKeyCodeError) => { - tracing::warn!("Ignoring key with unknown key code {key_code:?}"); - return; - } - }; - - let Some(mut input) = self.lock_input() else { - tracing::error!("Locking input mutex timed out after 100ms"); - return; - }; - - let key_state_bits = match keyboard_event.state.into() { - KeyState::Pressed => KEY_PRESSED_BITS, - KeyState::Released => KEY_RELEASED_BITS, - }; - - input.keys.clear_and_set(key as usize, key_state_bits, 0); - } + } => self.handle_keyboard_input(keyboard_event), WindowEvent::CursorMoved { device_id: _, position } => { - { - let Some(mut input) = self.lock_input() else { - tracing::error!("Locking input mutex timed out after 100ms"); - return; - }; - - input.absolute_mouse_pos = position.into(); - } - - let Some((window, window_settings)) = - self.windows.get(WindowId::from_inner(window_id)) - else { - cold_path(); - return; - }; - - if window_settings.cursor_grab_mode != CursorGrabMode::Locked { - return; - } - - let Some(window) = window.upgrade() else { - cold_path(); - return; - }; - - if !window.has_focus() { - return; - } - - let window_size = window.inner_size(); - - if let Err(err) = - window.set_cursor_position(Position::Physical(PhysicalPosition { - x: window_size.width as i32 / 2, - y: window_size.height as i32 / 2, - })) - { - cold_path(); - tracing::error!( - window_id=?window_id, - "Failed to lock cursor position: {:#}", - crate::Error::new(err) - ); - }; + self.handle_cursor_moved( + position.into(), + WindowId::from_inner(window_id), + ); } WindowEvent::MouseWheel { device_id: _, delta, phase: _ } => { - let (hor_lines, vert_lines) = match delta { - winit::event::MouseScrollDelta::LineDelta(hor_lines, vert_lines) => { - (hor_lines, vert_lines) - } - winit::event::MouseScrollDelta::PixelDelta(pos_delta) => { - let hor_lines = match pos_delta.x.partial_cmp(&0.0) { - Some(std::cmp::Ordering::Greater) => 1.0, - Some(std::cmp::Ordering::Less) => -1.0, - _ => 0.0, - }; - - let vert_lines = match pos_delta.y.partial_cmp(&0.0) { - Some(std::cmp::Ordering::Greater) => 1.0, - Some(std::cmp::Ordering::Less) => -1.0, - _ => 0.0, - }; - - (hor_lines, vert_lines) - } - }; - - let Some(mut input) = self.lock_input() else { - tracing::error!("Locking input mutex timed out after 100ms"); - return; - }; - - input.mouse_scroll_delta.hor_lines += hor_lines; - input.mouse_scroll_delta.vert_lines += vert_lines; + self.handle_mouse_wheel(delta); } WindowEvent::MouseInput { device_id: _, state, button } => { - let Some(mut input) = self.lock_input() else { - tracing::error!("Locking input mutex timed out after 100ms"); - return; - }; - - let button = MouseButton::from(button); - let button_state = MouseButtonState::from(state); - - let button_input = input - .mouse_buttons - .entry(button) - .or_insert_with(|| MouseButtonInput::default()); - - if button_input.flags.is_all() || !button_input.lagged.is_empty() { - button_input.lagged.push_back(button_state); - return; - } - - button_input.flags.insert(match button_state { - MouseButtonState::Pressed => MouseButtonFlags::PRESSED, - MouseButtonState::Released => MouseButtonFlags::RELEASED, - }); + self.handle_mouse_input(button.into(), state.into()); } WindowEvent::ScaleFactorChanged { scale_factor, inner_size_writer: _ } => { - self.send_message(MessageFromApp::WindowScaleFactorChanged( - WindowId::from_inner(window_id), - scale_factor, + self.send_message(MessageFromApp::Window( + WindowMessage::ScaleFactorChanged( + WindowId::from_inner(window_id), + scale_factor, + ), )); } _ => {} @@ -1141,16 +1185,13 @@ impl ApplicationHandler for App device_event: DeviceEvent, ) { - match device_event { - DeviceEvent::MouseMotion { delta } => { - let Some(mut input) = self.lock_input() else { - tracing::error!("Locking input mutex timed out after 100ms"); - return; - }; + if let DeviceEvent::MouseMotion { delta } = device_event { + let Some(mut input) = self.lock_input() else { + tracing::error!("Locking input mutex timed out after 100ms"); + return; + }; - input.relative_mouse_pos_delta += Vec2::from(delta); - } - _ => {} + input.relative_mouse_pos_delta += Vec2::from(delta); } } } |
