Migrate all examples to observer

This commit is contained in:
Jan Hohenheim 2025-07-07 21:59:15 +02:00
parent e015555f63
commit 157b67b511
No known key found for this signature in database
31 changed files with 193 additions and 246 deletions

View File

@ -56,7 +56,7 @@ use bevy_app::prelude::*;
impl Default for WindowPlugin {
fn default() -> Self {
WindowPlugin {
primary_window: Some(Window::default()),
spawn_primary_window: true,
exit_condition: ExitCondition::OnAllClosed,
close_when_requested: true,
}
@ -65,16 +65,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>,
pub spawn_primary_window: bool,
/// Whether to exit the app when there are no open windows.
///
@ -121,9 +133,8 @@ 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((
if self.spawn_primary_window {
app.world_mut().spawn((
PrimaryWindow,
RawHandleWrapperHolder(Arc::new(Mutex::new(None))),
));

View File

@ -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>>>);

View File

@ -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.
///
@ -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

View File

@ -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(

View File

@ -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)

View File

@ -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>()

View File

@ -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()

View File

@ -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(

View File

@ -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)

View File

@ -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)

View File

@ -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(

View File

@ -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(

View File

@ -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)

View File

@ -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()

View File

@ -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,
// Dont automatically exit due to having no windows.
// Instead, the code in `update()` will explicitly produce an `AppExit` event.
exit_condition: bevy::window::ExitCondition::DontExit,

View File

@ -5,23 +5,23 @@
//! - `App::run()` will never return on iOS and Web.
//! - It is not possible to recreate a window after the event loop has been terminated.
use bevy::prelude::*;
use bevy::{prelude::*, window::PrimaryWindow};
fn main() {
println!("Running Bevy App");
App::new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
title: "Close the window to return to the main function".into(),
..default()
}),
..default()
}))
.add_plugins(DefaultPlugins)
.add_observer(configure_window)
.add_systems(Update, system)
.run();
println!("Bevy App has exited. We are back in our main function.");
}
fn configure_window(trigger: On<Add, PrimaryWindow>, mut window: Query<&mut Window>) {
let mut window = window.get_mut(trigger.target()).unwrap();
window.title = "Close the window to return to the main function".into();
}
fn system() {
info!("Logging from Bevy App");
}

View File

@ -18,19 +18,11 @@ use bevy::window::CompositeAlphaMode;
fn main() {
App::new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
title: "Bevy Desk Toy".into(),
transparent: true,
#[cfg(target_os = "macos")]
composite_alpha_mode: CompositeAlphaMode::PostMultiplied,
..default()
}),
..default()
}))
.add_plugins(DefaultPlugins)
.insert_resource(ClearColor(WINDOW_CLEAR_COLOR))
.insert_resource(WindowTransparency(false))
.insert_resource(CursorWorldPos(None))
.add_observer(configure_window)
.add_systems(Startup, setup)
.add_systems(
Update,
@ -51,6 +43,16 @@ fn main() {
.run();
}
fn configure_window(trigger: On<Add, PrimaryWindow>, mut window: Query<&mut Window>) {
let mut window = window.get_mut(trigger.target()).unwrap();
window.title = "Bevy Desk Toy".into();
window.transparent = true;
#[cfg(target_os = "macos")]
{
window.composite_alpha_mode = CompositeAlphaMode::PostMultiplied;
}
}
/// Whether the window is transparent
#[derive(Resource)]
struct WindowTransparency(bool);

View File

@ -14,6 +14,7 @@ use bevy::{
texture::GpuImage,
Render, RenderApp, RenderSystems,
},
window::PrimaryWindow,
};
use std::borrow::Cow;
@ -28,28 +29,25 @@ fn main() {
App::new()
.insert_resource(ClearColor(Color::BLACK))
.add_plugins((
DefaultPlugins
.set(WindowPlugin {
primary_window: Some(Window {
resolution: (
(SIZE.0 * DISPLAY_FACTOR) as f32,
(SIZE.1 * DISPLAY_FACTOR) as f32,
)
.into(),
// uncomment for unthrottled FPS
// present_mode: bevy::window::PresentMode::AutoNoVsync,
..default()
}),
..default()
})
.set(ImagePlugin::default_nearest()),
DefaultPlugins.set(ImagePlugin::default_nearest()),
GameOfLifeComputePlugin,
))
.add_observer(configure_window)
.add_systems(Startup, setup)
.add_systems(Update, switch_textures)
.run();
}
fn configure_window(trigger: On<Add, PrimaryWindow>, mut window: Query<&mut Window>) {
let mut window = window.get_mut(trigger.target()).unwrap();
window.resolution = (
(SIZE.0 * DISPLAY_FACTOR) as f32,
(SIZE.1 * DISPLAY_FACTOR) as f32,
)
.into();
// Optional: set the present mode to AutoNoVsync for unthrottled FPS
}
fn setup(mut commands: Commands, mut images: ResMut<Assets<Image>>) {
let mut image = Image::new_fill(
Extent3d {

View File

@ -189,7 +189,7 @@ fn main() {
.insert_resource(cfg)
.add_plugins((
DefaultPlugins.set(WindowPlugin {
primary_window: None,
spawn_primary_window: false,
exit_condition: ExitCondition::DontExit,
..default()
}),

View File

@ -18,6 +18,7 @@ use bevy::{
experimental::occlusion_culling::OcclusionCulling,
primitives::{Aabb, Sphere},
},
window::PrimaryWindow,
};
#[path = "../../helpers/camera_controller.rs"]
@ -65,25 +66,18 @@ fn main() {
let mut app = App::new();
app.add_plugins((
DefaultPlugins
.set(WindowPlugin {
primary_window: Some(Window {
title: "bevy scene viewer".to_string(),
..default()
}),
..default()
})
.set(AssetPlugin {
file_path: std::env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".to_string()),
// Allow scenes to be loaded from anywhere on disk
unapproved_path_mode: UnapprovedPathMode::Allow,
..default()
}),
DefaultPlugins.set(AssetPlugin {
file_path: std::env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| ".".to_string()),
// Allow scenes to be loaded from anywhere on disk
unapproved_path_mode: UnapprovedPathMode::Allow,
..default()
}),
CameraControllerPlugin,
SceneViewerPlugin,
MorphViewerPlugin,
))
.insert_resource(args)
.add_observer(configure_window)
.add_systems(Startup, setup)
.add_systems(PreUpdate, setup_scene_after_load);
@ -98,6 +92,11 @@ fn main() {
app.run();
}
fn configure_window(trigger: On<Add, PrimaryWindow>, mut window: Query<&mut Window>) {
let mut window = window.get_mut(trigger.target()).unwrap();
window.title = "Bevy Scene Viewer".to_string();
}
fn parse_scene(scene_path: String) -> (String, usize) {
if scene_path.contains('#') {
let gltf_and_scene = scene_path.split('#').collect::<Vec<_>>();

View File

@ -7,13 +7,7 @@ const MARGIN: Val = Val::Px(12.);
fn main() {
App::new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
title: "Bevy Flex Layout Example".to_string(),
..Default::default()
}),
..Default::default()
}))
.add_plugins(DefaultPlugins)
.add_systems(Startup, spawn_layout)
.run();
}

View File

@ -1,20 +1,20 @@
//! Demonstrates how CSS Grid layout can be used to lay items out in a 2D grid
use bevy::{color::palettes::css::*, prelude::*};
use bevy::{color::palettes::css::*, prelude::*, window::PrimaryWindow};
fn main() {
App::new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
resolution: [800., 600.].into(),
title: "Bevy CSS Grid Layout Example".to_string(),
..default()
}),
..default()
}))
.add_plugins(DefaultPlugins)
.add_observer(configure_window)
.add_systems(Startup, spawn_layout)
.run();
}
fn configure_window(trigger: On<Add, PrimaryWindow>, mut window: Query<&mut Window>) {
let mut window = window.get_mut(trigger.target()).unwrap();
window.title = "Bevy CSS Grid Layout Example".to_string();
window.resolution = [800., 600.].into();
}
fn spawn_layout(mut commands: Commands, asset_server: Res<AssetServer>) {
let font = asset_server.load("fonts/FiraSans-Bold.ttf");
commands.spawn(Camera2d);

View File

@ -1,7 +1,12 @@
//! This example demonstrates text wrapping and use of the `LineBreakOn` property.
use argh::FromArgs;
use bevy::{prelude::*, text::LineBreak, window::WindowResolution, winit::WinitSettings};
use bevy::{
prelude::*,
text::LineBreak,
window::{PrimaryWindow, WindowResolution},
winit::WinitSettings,
};
#[derive(FromArgs, Resource)]
/// `text_wrap_debug` demonstrates text wrapping and use of the `LineBreakOn` property
@ -16,30 +21,30 @@ struct Args {
}
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.insert_resource(WinitSettings::desktop_app())
.add_observer(configure_window)
.add_systems(Startup, spawn)
.run();
}
fn configure_window(
trigger: On<Add, PrimaryWindow>,
mut window: Query<&mut Window>,
mut commands: Commands,
) {
let mut window = window.get_mut(trigger.target()).unwrap();
// `from_env` panics on the web
#[cfg(not(target_arch = "wasm32"))]
let args: Args = argh::from_env();
#[cfg(target_arch = "wasm32")]
let args = Args::from_args(&[], &[]).unwrap();
let window = if let Some(scale_factor) = args.scale_factor {
Window {
resolution: WindowResolution::default().with_scale_factor_override(scale_factor),
..Default::default()
}
} else {
Window::default()
};
App::new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(window),
..Default::default()
}))
.insert_resource(WinitSettings::desktop_app())
.insert_resource(UiScale(args.ui_scale))
.add_systems(Startup, spawn)
.run();
if let Some(scale_factor) = args.scale_factor {
window.resolution = WindowResolution::default().with_scale_factor_override(scale_factor);
}
commands.insert_resource(UiScale(args.ui_scale));
}
fn spawn(mut commands: Commands, asset_server: Res<AssetServer>) {

View File

@ -4,7 +4,7 @@
//! and then switches between them once per second using the `Display` style property.
//! If there are no problems both layouts should be identical, except for the color of the margin changing which is used to signal that the displayed UI node tree has changed
//! (red for viewport, yellow for pixel).
use bevy::{color::palettes::css::*, prelude::*};
use bevy::{color::palettes::css::*, prelude::*, window::PrimaryWindow};
const PALETTE: [Srgba; 10] = [
RED, YELLOW, WHITE, BEIGE, AQUA, CRIMSON, NAVY, AZURE, LIME, BLACK,
@ -20,22 +20,20 @@ enum Coords {
fn main() {
App::new()
.insert_resource(UiScale(2.0))
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
title: "Viewport Coordinates Debug".to_string(),
// This example relies on these specific viewport dimensions, so let's explicitly
// define them.
resolution: [1280., 720.].into(),
resizable: false,
..Default::default()
}),
..Default::default()
}))
.add_plugins(DefaultPlugins)
.add_observer(configure_window)
.add_systems(Startup, setup)
.add_systems(Update, update)
.run();
}
fn configure_window(trigger: On<Add, PrimaryWindow>, mut window: Query<&mut Window>) {
let mut window = window.get_mut(trigger.target()).unwrap();
window.title = "Viewport Coordinates Debug".to_string();
window.resolution = [1280., 720.].into();
window.resizable = false;
}
fn update(
mut timer: Local<f32>,
mut visible_tree: Local<Coords>,

View File

@ -2,26 +2,28 @@
//! If you build this, and hit 'P' it should toggle on/off the mouse's passthrough.
//! Note: this example will not work on following platforms: iOS / Android / Web / X11. Window fall through is not supported there.
use bevy::{prelude::*, window::CursorOptions};
use bevy::{
prelude::*,
window::{CursorOptions, PrimaryWindow, WindowLevel},
};
fn main() {
App::new()
.insert_resource(ClearColor(Color::NONE)) // Use a transparent window, to make effects obvious.
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
// Set the window's parameters, note we're setting the window to always be on top.
transparent: true,
decorations: true,
window_level: bevy::window::WindowLevel::AlwaysOnTop,
..default()
}),
..default()
}))
.add_plugins(DefaultPlugins)
.add_observer(configure_window)
.add_systems(Startup, setup)
.add_systems(Update, toggle_mouse_passthrough) // This allows us to hit 'P' to toggle on/off the mouse's passthrough
.run();
}
fn configure_window(trigger: On<Add, PrimaryWindow>, mut window: Query<&mut Window>) {
let mut window = window.get_mut(trigger.target()).unwrap();
window.transparent = true;
window.decorations = true;
window.window_level = WindowLevel::AlwaysOnTop;
}
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
// UI camera
commands.spawn(Camera2d);

View File

@ -9,7 +9,7 @@ use bevy::{
fn main() {
App::new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: None,
spawn_primary_window: false,
exit_condition: ExitCondition::DontExit,
..default()
}))

View File

@ -1,20 +1,18 @@
//! This example illustrates how to override the window scale factor imposed by the
//! operating system.
use bevy::{prelude::*, window::WindowResolution};
use bevy::{
prelude::*,
window::{PrimaryWindow, WindowResolution},
};
#[derive(Component)]
struct CustomText;
fn main() {
App::new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
resolution: WindowResolution::new(500., 300.).with_scale_factor_override(1.0),
..default()
}),
..default()
}))
.add_plugins(DefaultPlugins)
.add_observer(configure_window)
.add_systems(Startup, setup)
.add_systems(
Update,
@ -23,6 +21,11 @@ fn main() {
.run();
}
fn configure_window(trigger: On<Add, PrimaryWindow>, mut window: Query<&mut Window>) {
let mut window = window.get_mut(trigger.target()).unwrap();
window.resolution = WindowResolution::new(1920.0, 1080.0).with_scale_factor_override(1.0);
}
fn setup(mut commands: Commands) {
// camera
commands.spawn(Camera2d);

View File

@ -4,32 +4,38 @@
//! [documentation](https://docs.rs/bevy/latest/bevy/prelude/struct.Window.html#structfield.transparent)
//! for more details.
use bevy::prelude::*;
#[cfg(any(target_os = "macos", target_os = "linux"))]
use bevy::window::CompositeAlphaMode;
use bevy::{prelude::*, window::PrimaryWindow};
fn main() {
App::new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
// Setting `transparent` allows the `ClearColor`'s alpha value to take effect
transparent: true,
// Disabling window decorations to make it feel more like a widget than a window
decorations: false,
#[cfg(target_os = "macos")]
composite_alpha_mode: CompositeAlphaMode::PostMultiplied,
#[cfg(target_os = "linux")]
composite_alpha_mode: CompositeAlphaMode::PreMultiplied,
..default()
}),
..default()
}))
.add_plugins(DefaultPlugins)
// ClearColor must have 0 alpha, otherwise some color will bleed through
.insert_resource(ClearColor(Color::NONE))
.add_observer(configure_window)
.add_systems(Startup, setup)
.run();
}
fn configure_window(trigger: On<Add, PrimaryWindow>, mut window: Query<&mut Window>) {
let mut window = window.get_mut(trigger.target()).unwrap();
// Setting `transparent` allows the `ClearColor`'s alpha value to take effect
window.transparent = true;
// Disabling window decorations to make it feel more like a widget than a window
window.decorations = false;
#[cfg(target_os = "macos")]
{
window.composite_alpha_mode = CompositeAlphaMode::PostMultiplied;
}
#[cfg(target_os = "linux")]
{
window.composite_alpha_mode = CompositeAlphaMode::PreMultiplied;
}
}
fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
commands.spawn(Camera2d);
commands.spawn(Sprite::from_image(asset_server.load("branding/icon.png")));

View File

@ -10,7 +10,7 @@
//!
//! The `start_drag_resize()` function behaves similarly but permits a window to
//! be resized.
use bevy::{math::CompassOctant, prelude::*};
use bevy::{math::CompassOctant, prelude::*, window::PrimaryWindow};
/// Determine what do on left click.
#[derive(Resource, Debug)]
@ -41,20 +41,20 @@ const DIRECTIONS: [CompassOctant; 8] = [
fn main() {
App::new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
decorations: false,
..default()
}),
..default()
}))
.add_plugins(DefaultPlugins)
.insert_resource(ResizeDir(7))
.insert_resource(LeftClickAction::Move)
.add_observer(configure_window)
.add_systems(Startup, setup)
.add_systems(Update, (handle_input, move_or_resize_windows))
.run();
}
fn configure_window(trigger: On<Add, PrimaryWindow>, mut window: Query<&mut Window>) {
let mut window = window.get_mut(trigger.target()).unwrap();
window.decorations = false;
}
fn setup(mut commands: Commands) {
// Camera
commands.spawn(Camera3d::default());

View File

@ -6,13 +6,7 @@ fn main() {
// TODO: Combine this with `resizing` once multiple_windows is simpler than
// it is currently.
App::new()
.add_plugins(DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
title: "Minimizing".into(),
..default()
}),
..default()
}))
.add_plugins(DefaultPlugins)
.add_systems(Startup, (setup_3d, setup_2d))
.add_systems(Update, minimize_automatically)
.run();

View File

@ -1,7 +1,10 @@
//! A test to confirm that `bevy` allows setting the window to arbitrary small sizes
//! This is run in CI to ensure that this doesn't regress again.
use bevy::{prelude::*, window::WindowResolution};
use bevy::{
prelude::*,
window::{PrimaryWindow, WindowResolution},
};
// The smallest size reached is 1x1, as X11 doesn't support windows with a 0 dimension
// TODO: Add a check for platforms other than X11 for 0xk and kx0, despite those currently unsupported on CI.
@ -19,27 +22,25 @@ struct Dimensions {
fn main() {
App::new()
.add_plugins(
DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
resolution: WindowResolution::new(MAX_WIDTH as f32, MAX_HEIGHT as f32)
.with_scale_factor_override(1.0),
title: "Resizing".into(),
..default()
}),
..default()
}),
)
.add_plugins(DefaultPlugins)
.insert_resource(Dimensions {
width: MAX_WIDTH,
height: MAX_HEIGHT,
})
.insert_resource(ContractingY)
.add_observer(configure_window)
.add_systems(Startup, (setup_3d, setup_2d))
.add_systems(Update, (change_window_size, sync_dimensions))
.run();
}
fn configure_window(trigger: On<Add, PrimaryWindow>, mut window: Query<&mut Window>) {
let mut window = window.get_mut(trigger.target()).unwrap();
window.resolution =
WindowResolution::new(MAX_WIDTH as f32, MAX_HEIGHT as f32).with_scale_factor_override(1.0);
window.title = "Resizing".into();
}
#[derive(Resource)]
enum Phase {
ContractingY,