1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
use glam::Vec2;
/// A rectangle on the screen.
#[derive(Copy, Clone)]
pub struct ScreenRect(Vec2, Vec2);
impl ScreenRect {
pub fn full() -> Self {
Self(-Vec2::ONE, Vec2::ONE)
}
/// Creates a new screen rectangle from two arbitrary points which lie
/// between [-1, -1] and [1, 1].
///
/// See [`Self::new`].
pub fn from_points(a: Vec2, b: Vec2) -> Self {
Self::new(a.min(b), a.max(b))
}
/// # Arguments
///
/// * `bottom_left` - coordinates of the bottom left corner of the rectangle.
/// Bottom-left corner has coordinates [-1, -1] and top-right corner has
/// coordinates [1, 1].
///
/// * `top_right` - see `bottom_left`
///
/// # Panics
///
/// * If one of the corners is outside of screen space boundaries.
///
/// * If `bottom_left` corner is to the right or to the top from
/// `top_right` corner.
pub fn new(bottom_left: Vec2, top_right: Vec2) -> Self {
if bottom_left.cmpgt(top_right).any() {
panic!(
"Bottom left corner is greater than top right corner: {bottom_left:?} > {top_right:?}"
);
}
if bottom_left.abs().cmpgt(Vec2::ONE).any() {
panic!("Bottom left corner is not within screen range: {bottom_left:?}");
}
if top_right.abs().cmpgt(Vec2::ONE).any() {
panic!("Top right corner is not within screen range: {top_right:?}");
}
Self(bottom_left, top_right)
}
/// Returns array of edge coordinates corresponding to (in order):
///
/// * X coordinate of the left edge.
/// * X coordinate of the right edge.
/// * Y coordinate of the bottom edge.
/// * Y coordinate of the top edge.
pub fn as_array(&self) -> [f32; 4] {
[self.left(), self.right(), self.bottom(), self.top()]
}
/// X coordinate of the left edge.
pub fn left(&self) -> f32 {
self.0.x
}
/// X coordinate of the right edge.
pub fn right(&self) -> f32 {
self.1.x
}
/// Y coordinate of the bottom edge.
pub fn bottom(&self) -> f32 {
self.0.y
}
/// Y coordinate of the top edge.
pub fn top(&self) -> f32 {
self.1.y
}
/// Returns size of the rectangle. Full screen size is [2., 2.].
pub fn size(&self) -> Vec2 {
self.1 - self.0
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_from_points() {
let rect = ScreenRect::from_points(Vec2::new(0.1, 0.2), Vec2::new(-0.15, 0.3));
assert_eq!(rect.left(), -0.15);
assert_eq!(rect.right(), 0.1);
assert_eq!(rect.bottom(), 0.2);
assert_eq!(rect.top(), 0.3);
}
}