resizing/
resizing.rs

1//! A test to confirm that `bevy` allows setting the window to arbitrary small sizes
2//! This is run in CI to ensure that this doesn't regress again.
3
4use bevy::{prelude::*, window::WindowResolution};
5
6// The smallest size reached is 1x1, as X11 doesn't support windows with a 0 dimension
7// TODO: Add a check for platforms other than X11 for 0xk and kx0, despite those currently unsupported on CI.
8const MAX_WIDTH: u16 = 401;
9const MAX_HEIGHT: u16 = 401;
10const MIN_WIDTH: u16 = 1;
11const MIN_HEIGHT: u16 = 1;
12const RESIZE_STEP: u16 = 4;
13
14#[derive(Resource)]
15struct Dimensions {
16    width: u16,
17    height: u16,
18}
19
20fn main() {
21    App::new()
22        .add_plugins(
23            DefaultPlugins.set(WindowPlugin {
24                primary_window: Some(Window {
25                    resolution: WindowResolution::new(MAX_WIDTH as f32, MAX_HEIGHT as f32)
26                        .with_scale_factor_override(1.0),
27                    title: "Resizing".into(),
28                    ..default()
29                }),
30                ..default()
31            }),
32        )
33        .insert_resource(Dimensions {
34            width: MAX_WIDTH,
35            height: MAX_HEIGHT,
36        })
37        .insert_resource(ContractingY)
38        .add_systems(Startup, (setup_3d, setup_2d))
39        .add_systems(Update, (change_window_size, sync_dimensions))
40        .run();
41}
42
43#[derive(Resource)]
44enum Phase {
45    ContractingY,
46    ContractingX,
47    ExpandingY,
48    ExpandingX,
49}
50
51use Phase::*;
52
53fn change_window_size(
54    mut windows: ResMut<Dimensions>,
55    mut phase: ResMut<Phase>,
56    mut first_complete: Local<bool>,
57) {
58    // Put off rendering for one frame, as currently for a frame where
59    // resizing happens, nothing is presented.
60    // TODO: Debug and fix this if feasible
61    if !*first_complete {
62        *first_complete = true;
63        return;
64    }
65    let height = windows.height;
66    let width = windows.width;
67    match *phase {
68        ContractingY => {
69            if height <= MIN_HEIGHT {
70                *phase = ContractingX;
71            } else {
72                windows.height -= RESIZE_STEP;
73            }
74        }
75        ContractingX => {
76            if width <= MIN_WIDTH {
77                *phase = ExpandingY;
78            } else {
79                windows.width -= RESIZE_STEP;
80            }
81        }
82        ExpandingY => {
83            if height >= MAX_HEIGHT {
84                *phase = ExpandingX;
85            } else {
86                windows.height += RESIZE_STEP;
87            }
88        }
89        ExpandingX => {
90            if width >= MAX_WIDTH {
91                *phase = ContractingY;
92            } else {
93                windows.width += RESIZE_STEP;
94            }
95        }
96    }
97}
98
99fn sync_dimensions(dim: Res<Dimensions>, mut window: Single<&mut Window>) {
100    if dim.is_changed() {
101        window.resolution.set(dim.width as f32, dim.height as f32);
102    }
103}
104
105/// A simple 3d scene, taken from the `3d_scene` example
106fn setup_3d(
107    mut commands: Commands,
108    mut meshes: ResMut<Assets<Mesh>>,
109    mut materials: ResMut<Assets<StandardMaterial>>,
110) {
111    // plane
112    commands.spawn((
113        Mesh3d(meshes.add(Plane3d::default().mesh().size(5.0, 5.0))),
114        MeshMaterial3d(materials.add(Color::srgb(0.3, 0.5, 0.3))),
115    ));
116    // cube
117    commands.spawn((
118        Mesh3d(meshes.add(Cuboid::default())),
119        MeshMaterial3d(materials.add(Color::srgb(0.8, 0.7, 0.6))),
120        Transform::from_xyz(0.0, 0.5, 0.0),
121    ));
122    // light
123    commands.spawn((
124        PointLight {
125            shadows_enabled: true,
126            ..default()
127        },
128        Transform::from_xyz(4.0, 8.0, 4.0),
129    ));
130    // camera
131    commands.spawn((
132        Camera3d::default(),
133        Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
134    ));
135}
136
137/// A simple 2d scene, taken from the `rect` example
138fn setup_2d(mut commands: Commands) {
139    commands.spawn((
140        Camera2d,
141        Camera {
142            // render the 2d camera after the 3d camera
143            order: 1,
144            // do not use a clear color
145            clear_color: ClearColorConfig::None,
146            ..default()
147        },
148    ));
149    commands.spawn(Sprite::from_color(
150        Color::srgb(0.25, 0.25, 0.75),
151        Vec2::new(50.0, 50.0),
152    ));
153}