From 07eabd5287f00a6fc663d8a66cfd654f3fa4809c Mon Sep 17 00:00:00 2001 From: Daniikk1012 Date: Tue, 14 Dec 2021 20:48:15 +0600 Subject: [PATCH 1/6] Make ScalingMode more flexible Add additional fields to existing modes and add an additional Auto mode --- crates/bevy_render/src/camera/bundle.rs | 2 +- crates/bevy_render/src/camera/projection.rs | 85 +++++++++++---------- 2 files changed, 44 insertions(+), 43 deletions(-) diff --git a/crates/bevy_render/src/camera/bundle.rs b/crates/bevy_render/src/camera/bundle.rs index 8f61527345954..6e23f2046cd10 100644 --- a/crates/bevy_render/src/camera/bundle.rs +++ b/crates/bevy_render/src/camera/bundle.rs @@ -110,7 +110,7 @@ impl OrthographicCameraBundle { pub fn new_3d() -> Self { let orthographic_projection = OrthographicProjection { - scaling_mode: ScalingMode::FixedVertical, + scaling_mode: ScalingMode::FixedVertical(1.0), depth_calculation: DepthCalculation::Distance, ..Default::default() }; diff --git a/crates/bevy_render/src/camera/projection.rs b/crates/bevy_render/src/camera/projection.rs index b0ea170c75f6e..208a77a49ab58 100644 --- a/crates/bevy_render/src/camera/projection.rs +++ b/crates/bevy_render/src/camera/projection.rs @@ -63,12 +63,17 @@ pub enum ScalingMode { /// Manually specify left/right/top/bottom values. /// Ignore window resizing; the image will stretch. None, - /// Match the window size. 1 world unit = 1 pixel. - WindowSize, + /// Match the window size. + /// The argument is the amount of world units per pixel. + WindowSize(f32), + /// Use minimal possible viewport size while keeping the aspect ratio. + Auto { min_width: f32, min_height: f32 }, /// Keep vertical axis constant; resize horizontal with aspect ratio. - FixedVertical, + /// The argument is the height of the viewport. + FixedVertical(f32), /// Keep horizontal axis constant; resize vertical with aspect ratio. - FixedHorizontal, + /// The argument is the width of the viewport. + FixedHorizontal(f32), } #[derive(Component, Debug, Clone, Reflect)] @@ -101,50 +106,46 @@ impl CameraProjection for OrthographicProjection { } fn update(&mut self, width: f32, height: f32) { - match (&self.scaling_mode, &self.window_origin) { - (ScalingMode::WindowSize, WindowOrigin::Center) => { - let half_width = width / 2.0; - let half_height = height / 2.0; - self.left = -half_width; - self.right = half_width; - self.top = half_height; - self.bottom = -half_height; - } - (ScalingMode::WindowSize, WindowOrigin::BottomLeft) => { - self.left = 0.0; - self.right = width; - self.top = height; - self.bottom = 0.0; + if let ScalingMode::None = self.scaling_mode { + return; + } + + let (viewport_width, viewport_height) = match self.scaling_mode { + ScalingMode::WindowSize(scale) => (width * scale, height * scale), + ScalingMode::Auto { + min_width, + min_height, + } => { + if width * min_height > min_width * height { + (width * min_height / height, min_height) + } else { + (min_width, height * min_width / width) + } } - (ScalingMode::FixedVertical, WindowOrigin::Center) => { - let aspect_ratio = width / height; - self.left = -aspect_ratio; - self.right = aspect_ratio; - self.top = 1.0; - self.bottom = -1.0; + ScalingMode::FixedVertical(viewport_height) => { + (width * viewport_height / height, viewport_height) } - (ScalingMode::FixedVertical, WindowOrigin::BottomLeft) => { - let aspect_ratio = width / height; - self.left = 0.0; - self.right = aspect_ratio; - self.top = 1.0; - self.bottom = 0.0; + ScalingMode::FixedHorizontal(viewport_width) => { + (viewport_width, height * viewport_width / width) } - (ScalingMode::FixedHorizontal, WindowOrigin::Center) => { - let aspect_ratio = height / width; - self.left = -1.0; - self.right = 1.0; - self.top = aspect_ratio; - self.bottom = -aspect_ratio; + ScalingMode::None => unreachable!(), + }; + + match self.window_origin { + WindowOrigin::Center => { + let half_width = viewport_width / 2.0; + let half_height = viewport_height / 2.0; + self.left = -half_width; + self.bottom = -half_height; + self.right = half_width; + self.top = half_height; } - (ScalingMode::FixedHorizontal, WindowOrigin::BottomLeft) => { - let aspect_ratio = height / width; + WindowOrigin::BottomLeft => { self.left = 0.0; - self.right = 1.0; - self.top = aspect_ratio; self.bottom = 0.0; + self.right = viewport_width; + self.top = viewport_height; } - (ScalingMode::None, _) => {} } } @@ -167,7 +168,7 @@ impl Default for OrthographicProjection { near: 0.0, far: 1000.0, window_origin: WindowOrigin::Center, - scaling_mode: ScalingMode::WindowSize, + scaling_mode: ScalingMode::WindowSize(1.0), scale: 1.0, depth_calculation: DepthCalculation::Distance, } From 7c436479fd0812effe628d1adaa370e89df4c45f Mon Sep 17 00:00:00 2001 From: Daniikk1012 Date: Tue, 17 May 2022 17:00:24 +0600 Subject: [PATCH 2/6] Remove parameter from ScalingMode::WindowSize --- crates/bevy_render/src/camera/projection.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/crates/bevy_render/src/camera/projection.rs b/crates/bevy_render/src/camera/projection.rs index 208a77a49ab58..820c9047e9888 100644 --- a/crates/bevy_render/src/camera/projection.rs +++ b/crates/bevy_render/src/camera/projection.rs @@ -63,9 +63,8 @@ pub enum ScalingMode { /// Manually specify left/right/top/bottom values. /// Ignore window resizing; the image will stretch. None, - /// Match the window size. - /// The argument is the amount of world units per pixel. - WindowSize(f32), + /// Match the window size. 1 world unit = 1 pixel. + WindowSize, /// Use minimal possible viewport size while keeping the aspect ratio. Auto { min_width: f32, min_height: f32 }, /// Keep vertical axis constant; resize horizontal with aspect ratio. @@ -111,7 +110,7 @@ impl CameraProjection for OrthographicProjection { } let (viewport_width, viewport_height) = match self.scaling_mode { - ScalingMode::WindowSize(scale) => (width * scale, height * scale), + ScalingMode::WindowSize => (width, height), ScalingMode::Auto { min_width, min_height, @@ -168,7 +167,7 @@ impl Default for OrthographicProjection { near: 0.0, far: 1000.0, window_origin: WindowOrigin::Center, - scaling_mode: ScalingMode::WindowSize(1.0), + scaling_mode: ScalingMode::WindowSize, scale: 1.0, depth_calculation: DepthCalculation::Distance, } From 323923a66fac7a5618eec2a944dcf742d7059127 Mon Sep 17 00:00:00 2001 From: Daniikk1012 Date: Tue, 17 May 2022 17:26:17 +0600 Subject: [PATCH 3/6] Fix uses of FixedHorizontal and FixedVertical --- crates/bevy_gltf/src/loader.rs | 4 ++-- crates/bevy_render/src/camera/bundle.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/crates/bevy_gltf/src/loader.rs b/crates/bevy_gltf/src/loader.rs index 5965109062947..bac852305210f 100644 --- a/crates/bevy_gltf/src/loader.rs +++ b/crates/bevy_gltf/src/loader.rs @@ -726,8 +726,8 @@ fn load_node( let orthographic_projection: OrthographicProjection = OrthographicProjection { far: orthographic.zfar(), near: orthographic.znear(), - scaling_mode: ScalingMode::FixedHorizontal, - scale: xmag / 2.0, + scaling_mode: ScalingMode::FixedHorizontal(1.0), + scale: xmag, ..Default::default() }; diff --git a/crates/bevy_render/src/camera/bundle.rs b/crates/bevy_render/src/camera/bundle.rs index 3e3b31e9f9105..ee2363fd7e6bf 100644 --- a/crates/bevy_render/src/camera/bundle.rs +++ b/crates/bevy_render/src/camera/bundle.rs @@ -83,7 +83,7 @@ pub struct OrthographicCameraBundle { impl OrthographicCameraBundle { pub fn new_3d() -> Self { let orthographic_projection = OrthographicProjection { - scaling_mode: ScalingMode::FixedVertical(1.0), + scaling_mode: ScalingMode::FixedVertical(2.0), depth_calculation: DepthCalculation::Distance, ..Default::default() }; From c0c8af73a7a3e5231c96ff9b7256dbe5cdfdeda5 Mon Sep 17 00:00:00 2001 From: Daniikk1012 Date: Tue, 17 May 2022 23:45:39 +0600 Subject: [PATCH 4/6] Specify units in the comments --- crates/bevy_render/src/camera/projection.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/crates/bevy_render/src/camera/projection.rs b/crates/bevy_render/src/camera/projection.rs index 9a959ee455dfa..9166d95e13315 100644 --- a/crates/bevy_render/src/camera/projection.rs +++ b/crates/bevy_render/src/camera/projection.rs @@ -67,12 +67,13 @@ pub enum ScalingMode { /// Match the window size. 1 world unit = 1 pixel. WindowSize, /// Use minimal possible viewport size while keeping the aspect ratio. + /// Arguments are in world units. Auto { min_width: f32, min_height: f32 }, /// Keep vertical axis constant; resize horizontal with aspect ratio. - /// The argument is the height of the viewport. + /// The argument is the desired height of the viewport in world units. FixedVertical(f32), /// Keep horizontal axis constant; resize vertical with aspect ratio. - /// The argument is the width of the viewport. + /// The argument is the desired width of the viewport in world units. FixedHorizontal(f32), } From 0a2375572b3fc020636e9e6a2376637f44876958 Mon Sep 17 00:00:00 2001 From: Daniikk1012 Date: Wed, 18 May 2022 21:02:36 +0600 Subject: [PATCH 5/6] Replace early return with match arm --- crates/bevy_render/src/camera/projection.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/crates/bevy_render/src/camera/projection.rs b/crates/bevy_render/src/camera/projection.rs index 9166d95e13315..c9ecf874809be 100644 --- a/crates/bevy_render/src/camera/projection.rs +++ b/crates/bevy_render/src/camera/projection.rs @@ -107,10 +107,6 @@ impl CameraProjection for OrthographicProjection { } fn update(&mut self, width: f32, height: f32) { - if let ScalingMode::None = self.scaling_mode { - return; - } - let (viewport_width, viewport_height) = match self.scaling_mode { ScalingMode::WindowSize => (width, height), ScalingMode::Auto { @@ -129,7 +125,7 @@ impl CameraProjection for OrthographicProjection { ScalingMode::FixedHorizontal(viewport_width) => { (viewport_width, height * viewport_width / width) } - ScalingMode::None => unreachable!(), + ScalingMode::None => return, }; match self.window_origin { From 070c4804bda7eb0215300f83d135a753931e3493 Mon Sep 17 00:00:00 2001 From: Daniikk1012 Date: Wed, 18 May 2022 21:14:11 +0600 Subject: [PATCH 6/6] Round viewport size when WindowSize is used --- crates/bevy_render/src/camera/projection.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/crates/bevy_render/src/camera/projection.rs b/crates/bevy_render/src/camera/projection.rs index c9ecf874809be..86fba6a3d4b3a 100644 --- a/crates/bevy_render/src/camera/projection.rs +++ b/crates/bevy_render/src/camera/projection.rs @@ -136,6 +136,15 @@ impl CameraProjection for OrthographicProjection { self.bottom = -half_height; self.right = half_width; self.top = half_height; + + if let ScalingMode::WindowSize = self.scaling_mode { + if self.scale == 1.0 { + self.left = self.left.floor(); + self.bottom = self.bottom.floor(); + self.right = self.right.floor(); + self.top = self.top.floor(); + } + } } WindowOrigin::BottomLeft => { self.left = 0.0;