diff --git a/crates/bevy_render/src/camera/camera.rs b/crates/bevy_render/src/camera/camera.rs index 728a863b703cf..691d27d6d7685 100644 --- a/crates/bevy_render/src/camera/camera.rs +++ b/crates/bevy_render/src/camera/camera.rs @@ -755,6 +755,20 @@ pub fn camera_system( } } } + // This check is needed because when changing WindowMode to SizedFullscreen, the viewport may have invalid + // arguments due to a sudden change on the window size to a lower value. + // If the size of the window is lower, the viewport will match that lower value. + if let Some(viewport) = &mut camera.viewport { + let target_info = &new_computed_target_info; + if let Some(target) = target_info { + if viewport.physical_size.x > target.physical_size.x { + viewport.physical_size.x = target.physical_size.x; + } + if viewport.physical_size.y > target.physical_size.y { + viewport.physical_size.y = target.physical_size.y; + } + } + } camera.computed.target_info = new_computed_target_info; if let Some(size) = camera.logical_viewport_size() { camera_projection.update(size.x, size.y); diff --git a/tests/window/change_window_mode.rs b/tests/window/change_window_mode.rs new file mode 100644 index 0000000000000..e1fb856b469b0 --- /dev/null +++ b/tests/window/change_window_mode.rs @@ -0,0 +1,50 @@ +//! a test that confirms that 'bevy' does not panic while changing from Windowed to SizedFullscreen when viewport is set + +use bevy:: +{ prelude::*, + render::camera::Viewport, + window::WindowMode, +}; + +//Having a viewport set to the same size as a window used to cause panic on some occasions when switching to SizedFullscreen +const WINDOW_WIDTH : f32 = 1366.0; +const WINDOW_HEIGHT: f32 = 768.0; + +fn main() +{ //Specify Window Size. + let window = Window { resolution: ( WINDOW_WIDTH, WINDOW_HEIGHT ).into(), ..default() }; + let primary_window = Some ( window ); + + App::new() + .add_plugins( DefaultPlugins.set( WindowPlugin { primary_window, ..default() } ) ) + .add_systems( Startup, startup ) + .add_systems( Update, toggle_window_mode ) + .run(); +} + +fn startup( mut cmds: Commands ) +{ //Match viewport to Window size. + let physical_position = UVec2::new( 0, 0 ); + let physical_size = Vec2::new( WINDOW_WIDTH, WINDOW_HEIGHT ).as_uvec2(); + let viewport = Some ( Viewport { physical_position, physical_size, ..default() } ); + + cmds.spawn( Camera2dBundle::default() ).insert( Camera { viewport, ..default() } ); +} + +fn toggle_window_mode +( mut qry_window: Query<&mut Window>, +) +{ let Ok( mut window ) = qry_window.get_single_mut() else { return }; + + window.mode = match window.mode { + WindowMode::Windowed => { + //it takes a while for the window to change from windowed to sizedfullscreen and back + std::thread::sleep(std::time::Duration::from_secs(4)); + WindowMode::SizedFullscreen + }, + _ => { + std::thread::sleep(std::time::Duration::from_secs(4)); + WindowMode::Windowed + }, + }; +} \ No newline at end of file