break feedback loop when moving cursor (#7298)

# Objective

- Fixes #7294

## Solution

- Do not trigger change detection when setting the cursor position from winit

When moving the cursor continuously, Winit sends events:
- CursorMoved(0)
- CursorMoved(1)
- => start of Bevy schedule execution
- CursorMoved(2)
- CursorMoved(3)
- <= End of Bevy schedule execution

if Bevy schedule runs after the event 1, events 2 and 3 would happen during the execution but would be read only on the next system run. During the execution, the system would detect a change on cursor position, and send back an order to winit to move it back to 1, so event 2 and 3 would be ignored. By bypassing change detection when setting the cursor from winit event, it doesn't trigger sending back that change to winit out of order.
This commit is contained in:
François 2023-01-21 00:01:28 +00:00
parent 1be3b6d592
commit a94830f0c9
2 changed files with 12 additions and 3 deletions

View file

@ -396,7 +396,11 @@ pub fn winit_runner(mut app: App) {
window.resolution.physical_height() as f64 - position.y,
);
window.set_physical_cursor_position(Some(physical_position));
// bypassing change detection to not trigger feedback loop with system `changed_window`
// this system change the cursor position in winit
window
.bypass_change_detection()
.set_physical_cursor_position(Some(physical_position));
cursor_events.cursor_moved.send(CursorMoved {
window: window_entity,
@ -412,7 +416,11 @@ pub fn winit_runner(mut app: App) {
WindowEvent::CursorLeft { .. } => {
// Component
if let Ok((mut window, _)) = window_query.get_mut(window_entity) {
window.set_physical_cursor_position(None);
// bypassing change detection to not trigger feedback loop with system `changed_window`
// this system change the cursor position in winit
window
.bypass_change_detection()
.set_physical_cursor_position(None);
}
cursor_events.cursor_left.send(CursorLeft {

View file

@ -177,7 +177,8 @@ fn camera_controller(
for mouse_event in mouse_events.iter() {
mouse_delta += mouse_event.delta;
}
} else {
}
if mouse_button_input.just_released(options.mouse_key_enable_mouse) {
for mut window in &mut windows {
window.cursor.grab_mode = CursorGrabMode::None;
window.cursor.visible = true;