diff --git a/Cargo.toml b/Cargo.toml index 57e3f75ce3..248f7b5f46 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -228,6 +228,10 @@ path = "examples/app/return_after_run.rs" name = "thread_pool_resources" path = "examples/app/thread_pool_resources.rs" +[[example]] +name = "without_winit" +path = "examples/app/without_winit.rs" + # Assets [[example]] name = "asset_loading" diff --git a/crates/bevy_core_pipeline/src/main_pass_3d.rs b/crates/bevy_core_pipeline/src/main_pass_3d.rs index 61a571b794..bd1e491fe8 100644 --- a/crates/bevy_core_pipeline/src/main_pass_3d.rs +++ b/crates/bevy_core_pipeline/src/main_pass_3d.rs @@ -47,10 +47,11 @@ impl Node for MainPass3dNode { world: &World, ) -> Result<(), NodeRunError> { let view_entity = graph.get_input_entity(Self::IN_VIEW)?; - let (opaque_phase, alpha_mask_phase, transparent_phase, target, depth) = self - .query - .get_manual(world, view_entity) - .expect("view entity should exist"); + let (opaque_phase, alpha_mask_phase, transparent_phase, target, depth) = + match self.query.get_manual(world, view_entity) { + Ok(query) => query, + Err(_) => return Ok(()), // No window + }; { // Run the opaque pass, sorted front-to-back diff --git a/crates/bevy_pbr/src/light.rs b/crates/bevy_pbr/src/light.rs index b80f4fe8b7..54e2aabcee 100644 --- a/crates/bevy_pbr/src/light.rs +++ b/crates/bevy_pbr/src/light.rs @@ -341,7 +341,10 @@ pub fn add_clusters( cameras: Query<(Entity, &Camera), Without>, ) { for (entity, camera) in cameras.iter() { - let window = windows.get(camera.window).unwrap(); + let window = match windows.get(camera.window) { + Some(window) => window, + None => continue, + }; let clusters = Clusters::from_screen_size_and_z_slices( UVec2::new(window.physical_width(), window.physical_height()), Z_SLICES, diff --git a/examples/README.md b/examples/README.md index 189dfede11..67506edc2b 100644 --- a/examples/README.md +++ b/examples/README.md @@ -122,6 +122,7 @@ Example | File | Description `plugin_group` | [`app/plugin_group.rs`](./app/plugin_group.rs) | Demonstrates the creation and registration of a custom plugin group `return_after_run` | [`app/return_after_run.rs`](./app/return_after_run.rs) | Show how to return to main after the Bevy app has exited `thread_pool_resources` | [`app/thread_pool_resources.rs`](./app/thread_pool_resources.rs) | Creates and customizes the internal thread pool +`without_winit` | [`app/without_winit.rs`](./app/without_winit.rs) | Create an application without winit (runs single time, no event loop) ## Assets diff --git a/examples/app/without_winit.rs b/examples/app/without_winit.rs new file mode 100644 index 0000000000..50aaa3880a --- /dev/null +++ b/examples/app/without_winit.rs @@ -0,0 +1,13 @@ +use bevy::prelude::*; +use bevy::winit::WinitPlugin; + +fn main() { + App::new() + .add_plugins_with(DefaultPlugins, |group| group.disable::()) + .add_system(setup_system) + .run(); +} + +fn setup_system(mut commands: Commands) { + commands.spawn_bundle(PerspectiveCameraBundle::default()); +}