summaryrefslogtreecommitdiff
path: root/engine/src/util.rs
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2026-05-25 19:49:15 +0200
committerHampusM <hampus@hampusmat.com>2026-05-25 19:49:15 +0200
commitf8b7c0cfc73eaeb7ef8dfb3151f93879c97b220a (patch)
tree5ff078443f5d64e4f99fd0487b3a2e72ef961540 /engine/src/util.rs
parent8a41f5aeb3ac143d731928d1c343cd9338190f0a (diff)
fix(engine): prevent dropped cursor motion input on Windows
Diffstat (limited to 'engine/src/util.rs')
-rw-r--r--engine/src/util.rs96
1 files changed, 96 insertions, 0 deletions
diff --git a/engine/src/util.rs b/engine/src/util.rs
index 439fe9a..454a776 100644
--- a/engine/src/util.rs
+++ b/engine/src/util.rs
@@ -1,3 +1,9 @@
+use std::fmt::Debug;
+use std::mem::transmute;
+use std::sync::atomic::Ordering;
+
+use portable_atomic::AtomicU128;
+
use crate::ecs::util::VecExt;
#[derive(Debug)]
@@ -94,6 +100,96 @@ 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 {