Repository: sburris0/bevy_flycam (language: rust)

Issue:
Panics when window closes
Working on the Bevy 0.8 release of [bevy_atmosphere](https://github.com/JonahPlusPlus/bevy_atmosphere/tree/9ee5a6f9b60371aaed7503a1ac002a4a7c468677) (link to current commit tree). I noticed that when I run my example (`cargo run --example cycle --feature dynamic`) and close the window, it actually crashes. I get the following error log:
```
2022-08-03T00:13:27.505579Z  INFO bevy_winit: Skipped event for closed window: WindowId(00000000-0000-0000-0000-000000000000)
2022-08-03T00:13:27.506219Z  INFO bevy_winit: Skipped event for closed window: WindowId(00000000-0000-0000-0000-000000000000)
2022-08-03T00:13:27.509384Z  INFO bevy_winit: Skipped event for closed window: WindowId(00000000-0000-0000-0000-000000000000)
thread 'Compute Task Pool (1)' panicked at 'called `Option::unwrap()` on a `None` value', C:\Users\jonah\.cargo\registry\src\github.com-1ecc6299db9ec823\bevy_flycam-0.8.0\src\lib.rs:118:44
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread 'main' panicked at 'task has failed', C:\Users\jonah\.cargo\registry\src\github.com-1ecc6299db9ec823\async-task-4.3.0\src\task.rs:426:45
```
The error comes from the following code:
```rust
fn cursor_grab(keys: Res<Input<KeyCode>>, mut windows: ResMut<Windows>) {
    let window = windows.get_primary_mut().unwrap();
    if keys.just_pressed(KeyCode::Escape) {
        toggle_grab_cursor(window);
    }
}
```

I believe changing this to something like the following will fix this:
```rust
fn cursor_grab(keys: Res<Input<KeyCode>>, mut windows: ResMut<Windows>) {
    if let Some(window) = windows.get_primary_mut() {
        if keys.just_pressed(KeyCode::Escape) {
            toggle_grab_cursor(window);
        }
    }
}
```

I can fork and create a PR later, just figured it would be good to make an issue first.


Discussion / hints:

Fix patch:
diff --git a/src/lib.rs b/src/lib.rs
index d3d11ec..160a2ed 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -37,7 +37,11 @@ fn toggle_grab_cursor(window: &mut Window) {
 
 /// Grabs the cursor when game first starts
 fn initial_grab_cursor(mut windows: ResMut<Windows>) {
-    toggle_grab_cursor(windows.get_primary_mut().unwrap());
+    if let Some(window) = windows.get_primary_mut() {
+        toggle_grab_cursor(window);
+    } else {
+        warn!("Primary window not found for `initial_grab_cursor`!");
+    }
 }
 
 /// Spawns the `Camera3dBundle` to be controlled
@@ -58,30 +62,33 @@ fn player_move(
     settings: Res<MovementSettings>,
     mut query: Query<&mut Transform, With<FlyCam>>,
 ) {
-    let window = windows.get_primary().unwrap();
-    for mut transform in query.iter_mut() {
-        let mut velocity = Vec3::ZERO;
-        let local_z = transform.local_z();
-        let forward = -Vec3::new(local_z.x, 0., local_z.z);
-        let right = Vec3::new(local_z.z, 0., -local_z.x);
-
-        for key in keys.get_pressed() {
-            if window.cursor_locked() {
-                match key {
-                    KeyCode::W => velocity += forward,
-                    KeyCode::S => velocity -= forward,
-                    KeyCode::A => velocity -= right,
-                    KeyCode::D => velocity += right,
-                    KeyCode::Space => velocity += Vec3::Y,
-                    KeyCode::LShift => velocity -= Vec3::Y,
-                    _ => (),
+    if let Some(window) = windows.get_primary() {
+        for mut transform in query.iter_mut() {
+            let mut velocity = Vec3::ZERO;
+            let local_z = transform.local_z();
+            let forward = -Vec3::new(local_z.x, 0., local_z.z);
+            let right = Vec3::new(local_z.z, 0., -local_z.x);
+
+            for key in keys.get_pressed() {
+                if window.cursor_locked() {
+                    match key {
+                        KeyCode::W => velocity += forward,
+                        KeyCode::S => velocity -= forward,
+                        KeyCode::A => velocity -= right,
+                        KeyCode::D => velocity += right,
+                        KeyCode::Space => velocity += Vec3::Y,
+                        KeyCode::LShift => velocity -= Vec3::Y,
+                        _ => (),
+                    }
                 }
             }
-        }
 
-        velocity = velocity.normalize_or_zero();
+            velocity = velocity.normalize_or_zero();
 
-        transform.translation += velocity * time.delta_seconds() * settings.speed
+            transform.translation += velocity * time.delta_seconds() * settings.speed
+        }
+    } else {
+        warn!("Primary window not found for `player_move`!");
     }
 }
 
@@ -93,31 +100,38 @@ fn player_look(
     motion: Res<Events<MouseMotion>>,
     mut query: Query<&mut Transform, With<FlyCam>>,
 ) {
-    let window = windows.get_primary().unwrap();
-    let mut delta_state = state.as_mut();
-    for mut transform in query.iter_mut() {
-        for ev in delta_state.reader_motion.iter(&motion) {
-            if window.cursor_locked() {
-                // Using smallest of height or width ensures equal vertical and horizontal sensitivity
-                let window_scale = window.height().min(window.width());
-                delta_state.pitch -=
-                    (settings.sensitivity * ev.delta.y * window_scale).to_radians();
-                delta_state.yaw -= (settings.sensitivity * ev.delta.x * window_scale).to_radians();
-            }
+    if let Some(window) = windows.get_primary() {
+        let mut delta_state = state.as_mut();
+        for mut transform in query.iter_mut() {
+            for ev in delta_state.reader_motion.iter(&motion) {
+                if window.cursor_locked() {
+                    // Using smallest of height or width ensures equal vertical and horizontal sensitivity
+                    let window_scale = window.height().min(window.width());
+                    delta_state.pitch -=
+                        (settings.sensitivity * ev.delta.y * window_scale).to_radians();
+                    delta_state.yaw -=
+                        (settings.sensitivity * ev.delta.x * window_scale).to_radians();
+                }
 
-            delta_state.pitch = delta_state.pitch.clamp(-1.54, 1.54);
+                delta_state.pitch = delta_state.pitch.clamp(-1.54, 1.54);
 
-            // Order is important to prevent unintended roll
-            transform.rotation = Quat::from_axis_angle(Vec3::Y, delta_state.yaw)
-                * Quat::from_axis_angle(Vec3::X, delta_state.pitch);
+                // Order is important to prevent unintended roll
+                transform.rotation = Quat::from_axis_angle(Vec3::Y, delta_state.yaw)
+                    * Quat::from_axis_angle(Vec3::X, delta_state.pitch);
+            }
         }
+    } else {
+        warn!("Primary window not found for `player_look`!");
     }
 }
 
 fn cursor_grab(keys: Res<Input<KeyCode>>, mut windows: ResMut<Windows>) {
-    let window = windows.get_primary_mut().unwrap();
-    if keys.just_pressed(KeyCode::Escape) {
-        toggle_grab_cursor(window);
+    if let Some(window) = windows.get_primary_mut() {
+        if keys.just_pressed(KeyCode::Escape) {
+            toggle_grab_cursor(window);
+        }
+    } else {
+        warn!("Primary window not found for `cursor_grab`!");
     }
 }
 


Test patch: