Skip to content

Initialize Window by observer instead of by plugin fields #20018

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 23 additions & 23 deletions crates/bevy_window/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ extern crate alloc;

use alloc::sync::Arc;

use bevy_ecs::system::Commands;
use bevy_platform::sync::Mutex;

mod event;
Expand Down Expand Up @@ -56,8 +57,7 @@ use bevy_app::prelude::*;
impl Default for WindowPlugin {
fn default() -> Self {
WindowPlugin {
primary_window: Some(Window::default()),
primary_cursor_options: Some(CursorOptions::default()),
spawn_primary_window: true,
exit_condition: ExitCondition::OnAllClosed,
close_when_requested: true,
}
Expand All @@ -66,23 +66,28 @@ impl Default for WindowPlugin {

/// A [`Plugin`] that defines an interface for windowing support in Bevy.
pub struct WindowPlugin {
/// Settings for the primary window.
/// Whether or not to spawn a [`PrimaryWindow`] and its associated required components.
/// If you want to customize the primary window when it spawns, you can use an observer:
///
/// `Some(custom_window)` will spawn an entity with `custom_window` and [`PrimaryWindow`] as components.
/// `None` will not spawn a primary window.
/// ```
/// # use bevy_window::{CursorOptions, PresentMode, PrimaryWindow, Window, PresentMode};
/// # use bevy_ecs::prelude::*;
/// fn configure_window(
/// trigger: On<Add, PrimaryWindow>,
/// mut window: Query<(&mut CursorOptions, &mut PresentMode)>,
/// ) {
/// // This unwrap is guaranteed to succeed because the queried components are required on any [`Window`]
/// let (mut cursor_options, mut present_mode) = window.get_mut(trigger.target()).unwrap();
/// cursor_options.visible = false;
/// present_mode = PresentMode::AutoNoVsync;
/// }
/// ```
///
/// Defaults to `Some(Window::default())`.
/// Defaults to `true`.
///
/// Note that if there are no windows the App will exit (by default) due to
/// [`exit_on_all_closed`].
pub primary_window: Option<Window>,

/// Settings for the cursor on the primary window.
///
/// Defaults to `Some(CursorOptions::default())`.
///
/// Has no effect if [`WindowPlugin::primary_window`] is `None`.
pub primary_cursor_options: Option<CursorOptions>,
pub spawn_primary_window: bool,

/// Whether to exit the app when there are no open windows.
///
Expand Down Expand Up @@ -129,15 +134,10 @@ impl Plugin for WindowPlugin {
.add_event::<WindowThemeChanged>()
.add_event::<AppLifecycle>();

if let Some(primary_window) = &self.primary_window {
let mut entity_commands = app.world_mut().spawn(primary_window.clone());
entity_commands.insert((
PrimaryWindow,
RawHandleWrapperHolder(Arc::new(Mutex::new(None))),
));
if let Some(primary_cursor_options) = &self.primary_cursor_options {
entity_commands.insert(primary_cursor_options.clone());
}
if self.spawn_primary_window {
app.add_systems(PreStartup, |mut commands: Commands| {
commands.spawn(PrimaryWindow);
});
}

match self.exit_condition {
Expand Down
2 changes: 1 addition & 1 deletion crates/bevy_window/src/raw_handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -162,5 +162,5 @@ impl HasDisplayHandle for ThreadLockedRawWindowHandleWrapper {
}

/// Holder of the [`RawHandleWrapper`] with wrappers, to allow use in asynchronous context
#[derive(Debug, Clone, Component)]
#[derive(Debug, Clone, Component, Default)]
pub struct RawHandleWrapperHolder(pub Arc<Mutex<Option<RawHandleWrapper>>>);
5 changes: 3 additions & 2 deletions crates/bevy_window/src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use {
#[cfg(all(feature = "serialize", feature = "bevy_reflect"))]
use bevy_reflect::{ReflectDeserialize, ReflectSerialize};

use crate::VideoMode;
use crate::{RawHandleWrapperHolder, VideoMode};

/// Default string used for the window title.
///
Expand Down Expand Up @@ -53,6 +53,7 @@ static DEFAULT_WINDOW_TITLE: LazyLock<String> = LazyLock::new(|| {
derive(Reflect),
reflect(Component, Debug, Default, PartialEq, Clone)
)]
#[require(Window, RawHandleWrapperHolder)]
pub struct PrimaryWindow;

/// Reference to a [`Window`], whether it be a direct link to a specific entity or
Expand Down Expand Up @@ -469,8 +470,8 @@ impl Default for Window {
fn default() -> Self {
Self {
title: DEFAULT_WINDOW_TITLE.to_owned(),
present_mode: PresentMode::default(),
name: None,
present_mode: Default::default(),
mode: Default::default(),
position: Default::default(),
resolution: Default::default(),
Expand Down
8 changes: 1 addition & 7 deletions examples/3d/anisotropy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,7 @@ impl Display for Scene {
fn main() {
App::new()
.init_resource::<AppStatus>()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
title: "Bevy Anisotropy Example".into(),
..default()
}),
..default()
}))
.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.add_systems(Update, create_material_variants)
.add_systems(Update, animate_light)
Expand Down
8 changes: 1 addition & 7 deletions examples/3d/clustered_decals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,7 @@ impl MaterialExtension for CustomDecalExtension {
/// Entry point.
fn main() {
App::new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
title: "Bevy Clustered Decals Example".into(),
..default()
}),
..default()
}))
.add_plugins(DefaultPlugin)
.add_plugins(MaterialPlugin::<
ExtendedMaterial<StandardMaterial, CustomDecalExtension>,
>::default())
Expand Down
8 changes: 1 addition & 7 deletions examples/3d/depth_of_field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,7 @@ struct AppSettings {
fn main() {
App::new()
.init_resource::<AppSettings>()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
title: "Bevy Depth of Field Example".to_string(),
..default()
}),
..default()
}))
.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.add_systems(Update, tweak_scene)
.add_systems(
Expand Down
8 changes: 1 addition & 7 deletions examples/3d/fog_volumes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,7 @@ use bevy::{
/// Entry point.
fn main() {
App::new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
title: "Bevy Fog Volumes Example".into(),
..default()
}),
..default()
}))
.add_plugins(DefaultPlugins)
.insert_resource(AmbientLight::NONE)
.add_systems(Startup, setup)
.add_systems(Update, rotate_camera)
Expand Down
8 changes: 1 addition & 7 deletions examples/3d/irradiance_volumes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,13 +147,7 @@ struct VoxelVisualizationIrradianceVolumeInfo {
fn main() {
// Create the example app.
App::new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
title: "Bevy Irradiance Volumes Example".into(),
..default()
}),
..default()
}))
.add_plugins(DefaultPlugins)
.add_plugins(MaterialPlugin::<VoxelVisualizationMaterial>::default())
.init_resource::<AppStatus>()
.init_resource::<ExampleAssets>()
Expand Down
8 changes: 1 addition & 7 deletions examples/3d/light_textures.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,7 @@ struct HelpText;
/// Entry point.
fn main() {
App::new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
title: "Bevy Light Textures Example".into(),
..default()
}),
..default()
}))
.add_plugins(DefaultPlugins)
.init_resource::<AppStatus>()
.add_event::<WidgetClickEvent<Selection>>()
.add_event::<WidgetClickEvent<Visibility>>()
Expand Down
8 changes: 1 addition & 7 deletions examples/3d/mixed_lighting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,7 @@ const INITIAL_SPHERE_POSITION: Vec3 = vec3(0.0, 0.5233223, 0.0);

fn main() {
App::new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
title: "Bevy Mixed Lighting Example".into(),
..default()
}),
..default()
}))
.add_plugins(DefaultPlugins)
.add_plugins(MeshPickingPlugin)
.insert_resource(AmbientLight {
color: ClearColor::default().0,
Expand Down
7 changes: 0 additions & 7 deletions examples/3d/occlusion_culling.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,13 +182,6 @@ fn main() {
App::new()
.add_plugins(
DefaultPlugins
.set(WindowPlugin {
primary_window: Some(Window {
title: "Bevy Occlusion Culling Example".into(),
..default()
}),
..default()
})
.set(RenderPlugin {
debug_flags: render_debug_flags,
..default()
Expand Down
8 changes: 1 addition & 7 deletions examples/3d/pcss.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,7 @@ enum AppSetting {
fn main() {
App::new()
.init_resource::<AppStatus>()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
title: "Bevy Percentage Closer Soft Shadows Example".into(),
..default()
}),
..default()
}))
.add_plugins(DefaultPlugins)
.add_event::<WidgetClickEvent<AppSetting>>()
.add_systems(Startup, setup)
.add_systems(Update, widgets::handle_ui_interactions::<AppSetting>)
Expand Down
8 changes: 1 addition & 7 deletions examples/3d/post_processing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,7 @@ struct AppSettings {
fn main() {
App::new()
.init_resource::<AppSettings>()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
title: "Bevy Chromatic Aberration Example".into(),
..default()
}),
..default()
}))
.add_plugins(DefaultPlugins)
.add_systems(Startup, setup)
.add_systems(Update, handle_keyboard_input)
.add_systems(
Expand Down
8 changes: 1 addition & 7 deletions examples/3d/scrolling_fog.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,7 @@ use bevy::{
/// Initializes the example.
fn main() {
App::new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
title: "Bevy Scrolling Fog".into(),
..default()
}),
..default()
}))
.add_plugins(DefaultPlugins)
.insert_resource(DirectionalLightShadowMap { size: 4096 })
.add_systems(Startup, setup)
.add_systems(Update, scroll_fog)
Expand Down
8 changes: 1 addition & 7 deletions examples/3d/specular_tint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,7 @@ enum TintType {
/// The entry point.
fn main() {
App::new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
title: "Bevy Specular Tint Example".into(),
..default()
}),
..default()
}))
.add_plugins(DefaultPlugins)
.init_resource::<AppAssets>()
.init_resource::<AppStatus>()
.insert_resource(AmbientLight {
Expand Down
8 changes: 1 addition & 7 deletions examples/3d/ssr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,13 +101,7 @@ fn main() {
App::new()
.insert_resource(DefaultOpaqueRendererMethod::deferred())
.init_resource::<AppSettings>()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
title: "Bevy Screen Space Reflections Example".into(),
..default()
}),
..default()
}))
.add_plugins(DefaultPlugins)
.add_plugins(MaterialPlugin::<ExtendedMaterial<StandardMaterial, Water>>::default())
.add_systems(Startup, setup)
.add_systems(Update, rotate_model)
Expand Down
8 changes: 1 addition & 7 deletions examples/3d/visibility_range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,7 @@ struct AppStatus {
// Sets up the app.
fn main() {
App::new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
title: "Bevy Visibility Range Example".into(),
..default()
}),
..default()
}))
.add_plugins(DefaultPlugins)
.init_resource::<AppStatus>()
.add_systems(Startup, setup)
.add_systems(
Expand Down
8 changes: 1 addition & 7 deletions examples/animation/animation_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,7 @@ fn main() {
let args = Args::from_args(&[], &[]).unwrap();

App::new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
title: "Bevy Animation Graph Example".into(),
..default()
}),
..default()
}))
.add_plugins(DefaultPlugins)
.add_systems(Startup, (setup_assets, setup_scene, setup_ui))
.add_systems(Update, init_animations)
.add_systems(
Expand Down
8 changes: 1 addition & 7 deletions examples/animation/animation_masks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,13 +94,7 @@ struct MaskGroupState {
// The application entry point.
fn main() {
App::new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
title: "Bevy Animation Masks Example".into(),
..default()
}),
..default()
}))
.add_plugins(DefaultPlugins)
.add_systems(Startup, (setup_scene, setup_ui))
.add_systems(Update, setup_animation_graph_once_loaded)
.add_systems(Update, handle_button_toggles)
Expand Down
8 changes: 1 addition & 7 deletions examples/animation/morph_targets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,7 @@ use std::f32::consts::PI;

fn main() {
App::new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
title: "morph targets".to_string(),
..default()
}),
..default()
}))
.add_plugins(DefaultPlugins)
.insert_resource(AmbientLight {
brightness: 150.0,
..default()
Expand Down
2 changes: 1 addition & 1 deletion examples/app/headless_renderer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ fn main() {
// Not strictly necessary, as the inclusion of ScheduleRunnerPlugin below
// replaces the bevy_winit app runner and so a window is never created.
.set(WindowPlugin {
primary_window: None,
spawn_primary_window: false,
// Don’t automatically exit due to having no windows.
// Instead, the code in `update()` will explicitly produce an `AppExit` event.
exit_condition: bevy::window::ExitCondition::DontExit,
Expand Down
Loading
Loading