bevy_math/
aspect_ratio.rs

1//! Provides a simple aspect ratio struct to help with calculations.
2
3use crate::Vec2;
4use derive_more::derive::{Display, Error, Into};
5
6#[cfg(feature = "bevy_reflect")]
7use bevy_reflect::Reflect;
8
9/// An `AspectRatio` is the ratio of width to height.
10#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Into)]
11#[cfg_attr(feature = "bevy_reflect", derive(Reflect), reflect(Debug, PartialEq))]
12pub struct AspectRatio(f32);
13
14impl AspectRatio {
15    /// Standard 16:9 aspect ratio
16    pub const SIXTEEN_NINE: Self = Self(16.0 / 9.0);
17    /// Standard 4:3 aspect ratio
18    pub const FOUR_THREE: Self = Self(4.0 / 3.0);
19    /// Standard 21:9 ultrawide aspect ratio
20    pub const ULTRAWIDE: Self = Self(21.0 / 9.0);
21
22    /// Attempts to create a new [`AspectRatio`] from a given width and height.
23    ///
24    /// # Errors
25    ///
26    /// Returns an `Err` with `AspectRatioError` if:
27    /// - Either width or height is zero (`AspectRatioError::Zero`)
28    /// - Either width or height is infinite (`AspectRatioError::Infinite`)
29    /// - Either width or height is NaN (`AspectRatioError::NaN`)
30    #[inline]
31    pub fn try_new(width: f32, height: f32) -> Result<Self, AspectRatioError> {
32        match (width, height) {
33            (w, h) if w == 0.0 || h == 0.0 => Err(AspectRatioError::Zero),
34            (w, h) if w.is_infinite() || h.is_infinite() => Err(AspectRatioError::Infinite),
35            (w, h) if w.is_nan() || h.is_nan() => Err(AspectRatioError::NaN),
36            _ => Ok(Self(width / height)),
37        }
38    }
39
40    /// Attempts to create a new [`AspectRatio`] from a given amount of x pixels and y pixels.
41    #[inline]
42    pub fn try_from_pixels(x: u32, y: u32) -> Result<Self, AspectRatioError> {
43        Self::try_new(x as f32, y as f32)
44    }
45
46    /// Returns the aspect ratio as a f32 value.
47    #[inline]
48    pub fn ratio(&self) -> f32 {
49        self.0
50    }
51
52    /// Returns the inverse of this aspect ratio (height/width).
53    #[inline]
54    pub fn inverse(&self) -> Self {
55        Self(1.0 / self.0)
56    }
57
58    /// Returns true if the aspect ratio represents a landscape orientation.
59    #[inline]
60    pub fn is_landscape(&self) -> bool {
61        self.0 > 1.0
62    }
63
64    /// Returns true if the aspect ratio represents a portrait orientation.
65    #[inline]
66    pub fn is_portrait(&self) -> bool {
67        self.0 < 1.0
68    }
69
70    /// Returns true if the aspect ratio is exactly square.
71    #[inline]
72    pub fn is_square(&self) -> bool {
73        self.0 == 1.0
74    }
75}
76
77impl TryFrom<Vec2> for AspectRatio {
78    type Error = AspectRatioError;
79
80    #[inline]
81    fn try_from(value: Vec2) -> Result<Self, Self::Error> {
82        Self::try_new(value.x, value.y)
83    }
84}
85
86/// An Error type for when [`super::AspectRatio`] is provided invalid width or height values
87#[derive(Error, Display, Debug, PartialEq, Eq, Clone, Copy)]
88pub enum AspectRatioError {
89    /// Error due to width or height having zero as a value.
90    #[display("AspectRatio error: width or height is zero")]
91    Zero,
92    /// Error due towidth or height being infinite.
93    #[display("AspectRatio error: width or height is infinite")]
94    Infinite,
95    /// Error due to width or height being Not a Number (NaN).
96    #[display("AspectRatio error: width or height is NaN")]
97    NaN,
98}