Fixes #12000: When viewport is set to camera and switched to SizedFul… (#12861)

# Objective

- When viewport is set to the same size as the window on creation, when
adjusting to SizedFullscreen, the window may be smaller than the
viewport for a moment, which caused the arguments to be invalid and
panic.
- Fixes #12000.

## Solution

- The fix consists of matching the size of the viewport to the lower
size of the window ( if the x value of the window is lower, I update
only the x value of the viewport, same for the y value). Also added a
test to show that it does not panic anymore.

---
This commit is contained in:
Luís Figueiredo 2024-04-06 03:22:50 +01:00 committed by GitHub
parent a27ce270d0
commit ac91b19118
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 64 additions and 0 deletions

View file

@ -755,6 +755,20 @@ pub fn camera_system<T: CameraProjection + Component>(
} }
} }
} }
// 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; camera.computed.target_info = new_computed_target_info;
if let Some(size) = camera.logical_viewport_size() { if let Some(size) = camera.logical_viewport_size() {
camera_projection.update(size.x, size.y); camera_projection.update(size.x, size.y);

View file

@ -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
},
};
}