Skip to content

Commit cbf0324

Browse files
committed
Refactor Camera methods and add viewport rect (#4948)
While working on a refactor of `bevy_mod_picking` to include viewport-awareness, I found myself writing these functions to test if a cursor coordinate was inside the camera's rendered area. # Objective - Simplify conversion from physical to logical pixels - Add methods that returns the dimensions of the viewport as a min-max rect --- ## Changelog - Added `Camera::to_logical` - Added `Camera::physical_viewport_rect` - Added `Camera::logical_viewport_rect`
1 parent d51a87c commit cbf0324

File tree

1 file changed

+35
-16
lines changed

1 file changed

+35
-16
lines changed

crates/bevy_render/src/camera/camera.rs

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -104,21 +104,42 @@ impl Default for Camera {
104104
}
105105

106106
impl Camera {
107+
/// Converts a physical size in this `Camera` to a logical size.
108+
#[inline]
109+
pub fn to_logical(&self, physical_size: UVec2) -> Option<Vec2> {
110+
let scale = self.computed.target_info.as_ref()?.scale_factor;
111+
Some((physical_size.as_dvec2() / scale).as_vec2())
112+
}
113+
114+
/// The rendered physical bounds (minimum, maximum) of the camera. If the `viewport` field is
115+
/// set to [`Some`], this will be the rect of that custom viewport. Otherwise it will default to
116+
/// the full physical rect of the current [`RenderTarget`].
117+
#[inline]
118+
pub fn physical_viewport_rect(&self) -> Option<(UVec2, UVec2)> {
119+
let min = self.viewport.as_ref()?.physical_position;
120+
let max = min + self.physical_viewport_size()?;
121+
Some((min, max))
122+
}
123+
124+
/// The rendered logical bounds (minimum, maximum) of the camera. If the `viewport` field is set
125+
/// to [`Some`], this will be the rect of that custom viewport. Otherwise it will default to the
126+
/// full logical rect of the current [`RenderTarget`].
127+
#[inline]
128+
pub fn logical_viewport_rect(&self) -> Option<(Vec2, Vec2)> {
129+
let (min, max) = self.physical_viewport_rect()?;
130+
Some((self.to_logical(min)?, self.to_logical(max)?))
131+
}
132+
107133
/// The logical size of this camera's viewport. If the `viewport` field is set to [`Some`], this
108-
/// will be the size of that custom viewport. Otherwise it will default to the full logical size of
109-
/// the current [`RenderTarget`].
110-
/// For logic that requires the full logical size of the [`RenderTarget`], prefer [`Camera::logical_target_size`].
134+
/// will be the size of that custom viewport. Otherwise it will default to the full logical size
135+
/// of the current [`RenderTarget`].
136+
/// For logic that requires the full logical size of the
137+
/// [`RenderTarget`], prefer [`Camera::logical_target_size`].
111138
#[inline]
112139
pub fn logical_viewport_size(&self) -> Option<Vec2> {
113-
let target_info = self.computed.target_info.as_ref()?;
114140
self.viewport
115141
.as_ref()
116-
.map(|v| {
117-
Vec2::new(
118-
(v.physical_size.x as f64 / target_info.scale_factor) as f32,
119-
(v.physical_size.y as f64 / target_info.scale_factor) as f32,
120-
)
121-
})
142+
.and_then(|v| self.to_logical(v.physical_size))
122143
.or_else(|| self.logical_target_size())
123144
}
124145

@@ -139,12 +160,10 @@ impl Camera {
139160
/// For logic that requires the size of the actually rendered area, prefer [`Camera::logical_viewport_size`].
140161
#[inline]
141162
pub fn logical_target_size(&self) -> Option<Vec2> {
142-
self.computed.target_info.as_ref().map(|t| {
143-
Vec2::new(
144-
(t.physical_size.x as f64 / t.scale_factor) as f32,
145-
(t.physical_size.y as f64 / t.scale_factor) as f32,
146-
)
147-
})
163+
self.computed
164+
.target_info
165+
.as_ref()
166+
.and_then(|t| self.to_logical(t.physical_size))
148167
}
149168

150169
/// The full physical size of this camera's [`RenderTarget`], ignoring custom `viewport` configuration.

0 commit comments

Comments
 (0)