summaryrefslogtreecommitdiff
path: root/engine/src/windowing.rs
diff options
context:
space:
mode:
Diffstat (limited to 'engine/src/windowing.rs')
-rw-r--r--engine/src/windowing.rs128
1 files changed, 107 insertions, 21 deletions
diff --git a/engine/src/windowing.rs b/engine/src/windowing.rs
index cca8e9a..808e85e 100644
--- a/engine/src/windowing.rs
+++ b/engine/src/windowing.rs
@@ -1,3 +1,4 @@
+use std::collections::VecDeque;
use std::hint::cold_path;
use std::panic::{catch_unwind, AssertUnwindSafe};
use std::sync::atomic::{AtomicBool, Ordering};
@@ -5,6 +6,7 @@ use std::sync::{Arc, Condvar, Mutex, Weak};
use std::thread::Builder as ThreadBuilder;
use std::time::Duration;
+use bitflags::{bitflags, bitflags_match, Flags};
use crossbeam_queue::ArrayQueue;
use raw_window_handle::{DisplayHandle, HandleError, HasDisplayHandle, WindowHandle};
use winit::application::ApplicationHandler;
@@ -150,9 +152,8 @@ fn update_stuff(
}
keyboard.make_key_states_previous();
- mouse_buttons.make_states_previous();
- let input = {
+ {
let Some(mut input) = context
.shared_state
.input
@@ -162,18 +163,53 @@ fn update_stuff(
return Ok(());
};
- let new_input = Input {
- relative_mouse_pos_delta: Vec2 { x: 0.0, y: 0.0 },
- absolute_mouse_pos: input.absolute_mouse_pos.clone(),
- mouse_scroll_delta: MouseScrollDelta { vert_lines: 0.0, hor_lines: 0.0 },
- };
+ 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();
- std::mem::replace(&mut *input, new_input)
- };
+ 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);
+ }
+ }
- 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;
+ 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();
+ }
+
+ 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));
@@ -274,9 +310,6 @@ fn update_stuff(
MessageFromApp::KeyboardKeyStateChanged(key, key_state) => {
keyboard.set_key_state(key, key_state);
}
- MessageFromApp::MouseButtonStateChanged(mouse_button, mouse_button_state) => {
- mouse_buttons.set(mouse_button, mouse_button_state);
- }
}
}
@@ -641,7 +674,6 @@ enum MessageFromApp
WindowCloseRequested(WindowId),
WindowScaleFactorChanged(WindowId, f64),
KeyboardKeyStateChanged(Key, KeyState),
- MouseButtonStateChanged(MouseButton, MouseButtonState),
}
#[derive(Debug)]
@@ -685,12 +717,48 @@ impl Default for SharedState
}
}
-#[derive(Debug, Default, Clone)]
+#[derive(Debug)]
struct Input
{
relative_mouse_pos_delta: Vec2<f64>,
absolute_mouse_pos: PhysicalPosition<f64>,
mouse_scroll_delta: MouseScrollDelta,
+ mouse_buttons: MapVec<MouseButton, MouseButtonInput>,
+}
+
+impl Default for Input
+{
+ fn default() -> Self
+ {
+ Self {
+ relative_mouse_pos_delta: Vec2::default(),
+ absolute_mouse_pos: PhysicalPosition::default(),
+ mouse_scroll_delta: MouseScrollDelta::default(),
+ mouse_buttons: MapVec::from_iter([
+ (MouseButton::Left, MouseButtonInput::default()),
+ (MouseButton::Right, MouseButtonInput::default()),
+ (MouseButton::Middle, MouseButtonInput::default()),
+ (MouseButton::Back, MouseButtonInput::default()),
+ (MouseButton::Forward, MouseButtonInput::default()),
+ ]),
+ }
+ }
+}
+
+#[derive(Debug, Default)]
+struct MouseButtonInput
+{
+ flags: MouseButtonFlags,
+ lagged: VecDeque<MouseButtonState>,
+}
+
+bitflags! {
+#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
+struct MouseButtonFlags: u8
+{
+ const PRESSED = 1 << 0;
+ const RELEASED = 1 << 1;
+}
}
#[derive(Debug)]
@@ -991,10 +1059,28 @@ impl ApplicationHandler for App
input.mouse_scroll_delta.vert_lines += vert_lines;
}
WindowEvent::MouseInput { device_id: _, state, button } => {
- self.send_message(MessageFromApp::MouseButtonStateChanged(
- button.into(),
- state.into(),
- ));
+ 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,
+ });
}
WindowEvent::ScaleFactorChanged { scale_factor, inner_size_writer: _ } => {
self.send_message(MessageFromApp::WindowScaleFactorChanged(