diff options
Diffstat (limited to 'engine/src')
| -rw-r--r-- | engine/src/util.rs | 94 | ||||
| -rw-r--r-- | engine/src/windowing.rs | 139 | ||||
| -rw-r--r-- | engine/src/windowing/mouse.rs | 2 |
3 files changed, 61 insertions, 174 deletions
diff --git a/engine/src/util.rs b/engine/src/util.rs index 819b2da..08e2227 100644 --- a/engine/src/util.rs +++ b/engine/src/util.rs @@ -1,8 +1,4 @@ use std::fmt::Debug; -use std::mem::transmute; -use std::sync::atomic::Ordering; - -use portable_atomic::AtomicU128; use crate::ecs::util::VecExt; @@ -114,96 +110,6 @@ impl<T> OptionExt<T> for Option<T> } } -pub struct AtomicTwoF64 -{ - inner: AtomicU128, -} - -impl AtomicTwoF64 -{ - pub const fn new((first, second): (f64, f64)) -> Self - { - let mut bytes = [0u8; size_of::<u128>()]; - - bytes.copy_from_slice([first.to_ne_bytes(), second.to_ne_bytes()].as_flattened()); - - Self { - inner: AtomicU128::new(u128::from_ne_bytes(bytes)), - } - } - - pub fn load(&self, order: Ordering) -> (f64, f64) - { - u128_to_two_f64(self.inner.load(order)) - } - - pub fn store(&self, values: (f64, f64), order: Ordering) - { - self.inner.store(two_f64_to_u128(values), order); - } - - pub fn swap(&self, values: (f64, f64), order: Ordering) -> (f64, f64) - { - u128_to_two_f64(self.inner.swap(two_f64_to_u128(values), order)) - } - - pub fn compare_exchange( - &self, - current: (f64, f64), - new: (f64, f64), - success_order: Ordering, - failure_order: Ordering, - ) -> Result<(f64, f64), (f64, f64)> - { - self.inner - .compare_exchange( - two_f64_to_u128(current), - two_f64_to_u128(new), - success_order, - failure_order, - ) - .map(|stored| u128_to_two_f64(stored)) - .map_err(|stored| u128_to_two_f64(stored)) - } -} - -impl Debug for AtomicTwoF64 -{ - fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result - { - let (first, second) = self.load(Ordering::Relaxed); - - formatter - .debug_tuple("AtomicTwoF64") - .field(&first) - .field(&second) - .finish() - } -} - -fn two_f64_to_u128((first, second): (f64, f64)) -> u128 -{ - let mut bytes = [0u8; size_of::<u128>()]; - - bytes.copy_from_slice([first.to_ne_bytes(), second.to_ne_bytes()].as_flattened()); - - u128::from_ne_bytes(bytes) -} - -fn u128_to_two_f64(src: u128) -> (f64, f64) -{ - let [first_bytes, second_bytes] = unsafe { - transmute::<[u8; size_of::<u128>()], [[u8; size_of::<f64>()]; 2]>( - src.to_ne_bytes(), - ) - }; - - ( - f64::from_ne_bytes(first_bytes), - f64::from_ne_bytes(second_bytes), - ) -} - macro_rules! try_option { ($expr: expr) => { match $expr { diff --git a/engine/src/windowing.rs b/engine/src/windowing.rs index be8dc39..dc378fa 100644 --- a/engine/src/windowing.rs +++ b/engine/src/windowing.rs @@ -1,14 +1,15 @@ use std::hint::cold_path; -use std::panic::catch_unwind; +use std::panic::{catch_unwind, AssertUnwindSafe}; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, Condvar, Mutex, Weak}; use std::thread::Builder as ThreadBuilder; +use std::time::Duration; use crossbeam_queue::ArrayQueue; use raw_window_handle::{DisplayHandle, HandleError, HasDisplayHandle, WindowHandle}; use winit::application::ApplicationHandler; use winit::error::EventLoopError; -use winit::event::{DeviceEvent, DeviceId, MouseScrollDelta, StartCause, WindowEvent}; +use winit::event::{DeviceEvent, DeviceId, StartCause, WindowEvent}; use winit::event_loop::{ ActiveEventLoop, ControlFlow as EventLoopControlFlow, @@ -29,7 +30,8 @@ use crate::ecs::sole::Single; use crate::ecs::system::observer::Observe; use crate::ecs::uid::Uid; use crate::ecs::{declare_entity, Query, Sole}; -use crate::util::{AtomicTwoF64, MapVec}; +use crate::util::MapVec; +use crate::vector::Vec2; use crate::windowing::dpi::{PhysicalPosition, PhysicalSize, Position}; use crate::windowing::keyboard::{Key, KeyState, Keyboard, UnknownKeyCodeError}; use crate::windowing::monitor::Handle as MonitorHandle; @@ -38,6 +40,7 @@ use crate::windowing::mouse::{ ButtonState as MouseButtonState, Buttons as MouseButtons, Mouse, + ScrollDelta as MouseScrollDelta, }; use crate::windowing::window::{ Closed as WindowClosed, @@ -156,29 +159,22 @@ fn update_stuff( keyboard.make_key_states_previous(); mouse_buttons.make_states_previous(); - mouse.curr_tick_position_delta = context - .shared_state - .relative_mouse_pos_delta - .swap((0.0, 0.0), Ordering::Relaxed) - .into(); - - let absolute_mouse_pos = context - .shared_state - .absolute_mouse_pos - .load(Ordering::Relaxed); + let input = { + 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.position = PhysicalPosition { - x: absolute_mouse_pos.0, - y: absolute_mouse_pos.1, + std::mem::take(&mut *input) }; - let mouse_scroll_delta = context - .shared_state - .mouse_scroll_delta - .swap((0.0, 0.0), Ordering::Relaxed); - - mouse.scroll_delta.hor_lines = mouse_scroll_delta.0 as f32; - mouse.scroll_delta.vert_lines = mouse_scroll_delta.1 as f32; + 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; keyboard.set_text_keys(iter_array_queue(&context.shared_state.text_keys)); @@ -655,9 +651,7 @@ struct SharedState { message_from_app_queue: ArrayQueue<MessageFromApp>, message_to_app_queue: ArrayQueue<MessageToApp>, - relative_mouse_pos_delta: AtomicTwoF64, - absolute_mouse_pos: AtomicTwoF64, - mouse_scroll_delta: AtomicTwoF64, + input: AssertUnwindSafe<parking_lot::Mutex<Input>>, text_keys: ArrayQueue<char>, is_dropped: AtomicBool, thread_panicked: AtomicBool, @@ -674,9 +668,7 @@ impl Default for SharedState Self { message_from_app_queue: ArrayQueue::new(MESSAGE_FROM_APP_QUEUE_SIZE), message_to_app_queue: ArrayQueue::new(MESSAGE_TO_APP_QUEUE_SIZE), - relative_mouse_pos_delta: AtomicTwoF64::new((0.0, 0.0)), - absolute_mouse_pos: AtomicTwoF64::new((0.0, 0.0)), - mouse_scroll_delta: AtomicTwoF64::new((0.0, 0.0)), + input: AssertUnwindSafe(parking_lot::Mutex::default()), text_keys: ArrayQueue::new(TEXT_KEY_QUEUE_SIZE), is_dropped: AtomicBool::new(false), thread_panicked: AtomicBool::new(false), @@ -688,6 +680,14 @@ impl Default for SharedState } } +#[derive(Debug, Default, Clone)] +struct Input +{ + relative_mouse_pos_delta: Vec2<f64>, + absolute_mouse_pos: PhysicalPosition<f64>, + mouse_scroll_delta: MouseScrollDelta, +} + #[derive(Debug)] struct InitData { @@ -774,6 +774,13 @@ impl App self.shared_state.message_from_app_queue.force_push(message); } + + fn lock_input(&self) -> Option<parking_lot::MutexGuard<'_, Input>> + { + self.shared_state + .input + .try_lock_for(Duration::from_millis(100)) + } } impl ApplicationHandler for App @@ -900,9 +907,14 @@ impl ApplicationHandler for App )); } WindowEvent::CursorMoved { device_id: _, position } => { - self.shared_state - .absolute_mouse_pos - .store((position.x, position.y), Ordering::Relaxed); + { + 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)) @@ -965,36 +977,19 @@ impl ApplicationHandler for App { match device_event { DeviceEvent::MouseMotion { delta } => { - let curr_mouse_pos_delta = self - .shared_state - .relative_mouse_pos_delta - .load(Ordering::Relaxed); - - if self - .shared_state - .relative_mouse_pos_delta - .compare_exchange( - curr_mouse_pos_delta, - ( - curr_mouse_pos_delta.0 + delta.0, - curr_mouse_pos_delta.1 + delta.1, - ), - Ordering::Relaxed, - Ordering::Relaxed, - ) - .is_err() - { - self.shared_state - .relative_mouse_pos_delta - .store(delta, Ordering::Relaxed); - } + 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); } DeviceEvent::MouseWheel { delta } => { - let line_delta = match delta { - MouseScrollDelta::LineDelta(hor_lines, vert_lines) => { - (hor_lines as f64, vert_lines as f64) + let (hor_lines, vert_lines) = match delta { + winit::event::MouseScrollDelta::LineDelta(hor_lines, vert_lines) => { + (hor_lines, vert_lines) } - MouseScrollDelta::PixelDelta(pos_delta) => { + 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, @@ -1011,27 +1006,13 @@ impl ApplicationHandler for App } }; - let curr_mouse_scroll_delta = - self.shared_state.mouse_scroll_delta.load(Ordering::Relaxed); + let Some(mut input) = self.lock_input() else { + tracing::error!("Locking input mutex timed out after 100ms"); + return; + }; - if self - .shared_state - .mouse_scroll_delta - .compare_exchange( - curr_mouse_scroll_delta, - ( - curr_mouse_scroll_delta.0 + line_delta.0, - curr_mouse_scroll_delta.1 + line_delta.1, - ), - Ordering::Relaxed, - Ordering::Relaxed, - ) - .is_err() - { - self.shared_state - .mouse_scroll_delta - .store(line_delta, Ordering::Relaxed); - } + input.mouse_scroll_delta.hor_lines += hor_lines; + input.mouse_scroll_delta.vert_lines += vert_lines; } _ => {} } diff --git a/engine/src/windowing/mouse.rs b/engine/src/windowing/mouse.rs index abe2ab7..3145a17 100644 --- a/engine/src/windowing/mouse.rs +++ b/engine/src/windowing/mouse.rs @@ -18,7 +18,7 @@ pub struct Mouse /// been affected by cursor acceleration pub position: PhysicalPosition<f64>, - pub scroll_delta: ScrollDelta, + pub curr_tick_scroll_delta: ScrollDelta, } #[derive(Debug, Clone, Default)] |
