From ac91b19118bc0284c8c4ad4471b305c6dd966f04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lu=C3=ADs=20Figueiredo?= Date: Sat, 6 Apr 2024 03:22:50 +0100 Subject: [PATCH] =?UTF-8?q?Fixes=20#12000:=20When=20viewport=20is=20set=20?= =?UTF-8?q?to=20camera=20and=20switched=20to=20SizedFul=E2=80=A6=20(#12861?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # 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. --- --- crates/bevy_render/src/camera/camera.rs | 14 +++++++ tests/window/change_window_mode.rs | 50 +++++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 tests/window/change_window_mode.rs diff --git a/crates/bevy_render/src/camera/camera.rs b/crates/bevy_render/src/camera/camera.rs index 728a863b70..691d27d6d7 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 0000000000..e1fb856b46 --- /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