summaryrefslogtreecommitdiff
path: root/engine/src
diff options
context:
space:
mode:
Diffstat (limited to 'engine/src')
-rw-r--r--engine/src/util.rs94
-rw-r--r--engine/src/windowing.rs139
-rw-r--r--engine/src/windowing/mouse.rs2
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)]