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.rs173
1 files changed, 97 insertions, 76 deletions
diff --git a/engine/src/windowing.rs b/engine/src/windowing.rs
index ea5a692..096a23f 100644
--- a/engine/src/windowing.rs
+++ b/engine/src/windowing.rs
@@ -1,3 +1,4 @@
+use std::hint::cold_path;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::{Arc, Weak};
use std::thread::{Builder as ThreadBuilder, JoinHandle as ThreadJoinHandle};
@@ -33,8 +34,7 @@ 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::MapVec;
-use crate::vector::Vec2;
+use crate::util::{AtomicTwoF64, MapVec};
use crate::windowing::keyboard::{Key, KeyState, Keyboard, UnknownKeyCodeError};
use crate::windowing::mouse::{
Button as MouseButton,
@@ -130,7 +130,18 @@ fn update_stuff(
{
keyboard.make_key_states_previous();
mouse_buttons.make_states_previous();
- mouse.curr_tick_position_delta = Vec2::default();
+
+ mouse.curr_tick_position_delta = context
+ .shared_state
+ .relative_mouse_pos_delta
+ .swap((0.0, 0.0), Ordering::Relaxed)
+ .into();
+
+ mouse.position = context
+ .shared_state
+ .absolute_mouse_pos
+ .load(Ordering::Relaxed)
+ .into();
let Context {
ref message_from_app_receiver,
@@ -235,12 +246,6 @@ fn update_stuff(
MessageFromApp::KeyboardKeyStateChanged(key, key_state) => {
keyboard.set_key_state(key, key_state);
}
- MessageFromApp::MouseMovedTo { position } => {
- mouse.position = position;
- }
- MessageFromApp::MouseMoved { position_delta } => {
- mouse.curr_tick_position_delta += position_delta;
- }
MessageFromApp::MouseButtonStateChanged(mouse_button, mouse_button_state) => {
mouse_buttons.set(mouse_button, mouse_button_state);
}
@@ -300,9 +305,9 @@ fn handle_window_removed(
pub struct Context
{
_thread: ThreadJoinHandle<()>,
- is_dropped: Arc<AtomicBool>,
message_from_app_receiver: ChannelReceiver<MessageFromApp>,
message_to_app_sender: ChannelSender<MessageToApp>,
+ shared_state: Arc<SharedState>,
display_handle: Option<OwnedDisplayHandle>,
windows: MapVec<WindowId, (Arc<winit::window::Window>, Uid)>,
}
@@ -362,10 +367,6 @@ impl Default for Context
{
fn default() -> Self
{
- let is_dropped = Arc::new(AtomicBool::new(false));
-
- let is_dropped_b = is_dropped.clone();
-
let (message_from_app_sender, message_from_app_receiver) =
bounded_channel::<MessageFromApp>(MESSAGE_FROM_APP_CHANNEL_CAP);
@@ -374,6 +375,9 @@ impl Default for Context
let (message_to_app_sender, message_to_app_receiver) =
bounded_channel::<MessageToApp>(MESSAGE_TO_APP_CHANNEL_CAP);
+ let shared_state = Arc::new(SharedState::default());
+ let shared_state_b = shared_state.clone();
+
Self {
_thread: ThreadBuilder::new()
.name("windowing".to_string())
@@ -382,9 +386,8 @@ impl Default for Context
message_from_app_sender,
message_from_app_receiver: message_from_app_receiver_b,
message_to_app_receiver,
- is_dropped: is_dropped_b,
+ shared_state: shared_state_b,
windows: MapVec::default(),
- focused_window_id: None,
};
let event_loop = match create_event_loop() {
@@ -402,9 +405,9 @@ impl Default for Context
}
})
.expect("Failed to create windowing thread"),
- is_dropped,
message_from_app_receiver,
message_to_app_sender,
+ shared_state,
display_handle: None,
windows: MapVec::default(),
}
@@ -415,7 +418,7 @@ impl Drop for Context
{
fn drop(&mut self)
{
- self.is_dropped.store(true, Ordering::Relaxed);
+ self.shared_state.is_dropped.store(true, Ordering::Relaxed);
}
}
@@ -450,14 +453,6 @@ enum MessageFromApp
WindowCloseRequested(WindowId),
WindowScaleFactorChanged(WindowId, f64),
KeyboardKeyStateChanged(Key, KeyState),
- MouseMovedTo
- {
- position: Vec2<f64>,
- },
- MouseMoved
- {
- position_delta: Vec2<f64>,
- },
MouseButtonStateChanged(MouseButton, MouseButtonState),
}
@@ -469,14 +464,33 @@ enum MessageToApp
}
#[derive(Debug)]
+struct SharedState
+{
+ relative_mouse_pos_delta: AtomicTwoF64,
+ absolute_mouse_pos: AtomicTwoF64,
+ is_dropped: AtomicBool,
+}
+
+impl Default for SharedState
+{
+ fn default() -> Self
+ {
+ Self {
+ relative_mouse_pos_delta: AtomicTwoF64::new((0.0, 0.0)),
+ absolute_mouse_pos: AtomicTwoF64::new((0.0, 0.0)),
+ is_dropped: AtomicBool::new(false),
+ }
+ }
+}
+
+#[derive(Debug)]
struct App
{
message_from_app_sender: ChannelSender<MessageFromApp>,
message_from_app_receiver: ChannelReceiver<MessageFromApp>,
message_to_app_receiver: ChannelReceiver<MessageToApp>,
- is_dropped: Arc<AtomicBool>,
+ shared_state: Arc<SharedState>,
windows: MapVec<WindowId, (Weak<WinitWindow>, WindowSettings)>,
- focused_window_id: Option<WindowId>,
}
impl App
@@ -567,7 +581,7 @@ impl ApplicationHandler for App
));
}
StartCause::Poll => {
- if self.is_dropped.load(Ordering::Relaxed) {
+ if self.shared_state.is_dropped.load(Ordering::Relaxed) {
event_loop.exit();
return;
}
@@ -642,9 +656,38 @@ impl ApplicationHandler for App
));
}
WindowEvent::CursorMoved { device_id: _, position } => {
- self.send_message(MessageFromApp::MouseMovedTo {
- position: Vec2 { x: position.x, y: position.y },
- });
+ self.shared_state
+ .absolute_mouse_pos
+ .store((position.x, position.y), Ordering::Relaxed);
+
+ let Some((window, window_settings)) =
+ self.windows.get(&WindowId::from_inner(window_id))
+ else {
+ cold_path();
+ return;
+ };
+
+ if window_settings.cursor_grab_mode != CursorGrabMode::Locked {
+ return;
+ }
+
+ let Some(window) = window.upgrade() else {
+ cold_path();
+ return;
+ };
+
+ let window_size = window.inner_size();
+
+ if let Err(err) = window.set_cursor_position(PhysicalPosition {
+ x: window_size.width / 2,
+ y: window_size.height / 2,
+ }) {
+ cold_path();
+ tracing::error!(
+ window_id=?window_id,
+ "Failed to lock cursor position: {err}"
+ );
+ };
}
WindowEvent::MouseInput { device_id: _, state, button } => {
self.send_message(MessageFromApp::MouseButtonStateChanged(
@@ -652,13 +695,6 @@ impl ApplicationHandler for App
state.into(),
));
}
- WindowEvent::Focused(is_focused) => {
- if is_focused {
- self.focused_window_id = Some(WindowId::from_inner(window_id));
- } else {
- self.focused_window_id = None;
- }
- }
WindowEvent::ScaleFactorChanged { scale_factor, inner_size_writer: _ } => {
self.send_message(MessageFromApp::WindowScaleFactorChanged(
WindowId::from_inner(window_id),
@@ -679,44 +715,29 @@ impl ApplicationHandler for App
{
match device_event {
DeviceEvent::MouseMotion { delta } => {
- self.send_message(MessageFromApp::MouseMoved {
- position_delta: Vec2 { x: delta.0, y: delta.1 },
- });
-
- let Some(focused_window_id) = self.focused_window_id else {
- return;
- };
-
- let Some((focused_window, focused_window_settings)) =
- self.windows.get(&focused_window_id)
- else {
- tracing::error!(
- window_id=?focused_window_id,
- "Focused window not found"
- );
- return;
- };
-
- if focused_window_settings.cursor_grab_mode != CursorGrabMode::Locked {
- return;
+ 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);
}
-
- // TODO: This might need to be optimized
- let Some(focused_window) = focused_window.upgrade() else {
- return;
- };
-
- let focused_window_size = focused_window.inner_size();
-
- if let Err(err) = focused_window.set_cursor_position(PhysicalPosition {
- x: focused_window_size.width / 2,
- y: focused_window_size.height / 2,
- }) {
- tracing::error!(
- window_id=?focused_window_id,
- "Failed to set cursor position in focused window: {err}"
- );
- };
}
_ => {}
}