diff options
Diffstat (limited to 'engine/src/windowing.rs')
| -rw-r--r-- | engine/src/windowing.rs | 128 |
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( |
