macroquad/math/
rect.rs

1use glam::*;
2
3/// A 2D rectangle, defined by its top-left corner, width and height.
4#[derive(Clone, Copy, Debug, Default, PartialEq)]
5pub struct Rect {
6    pub x: f32,
7    pub y: f32,
8    pub w: f32,
9    pub h: f32,
10}
11
12impl Rect {
13    /// Creates a new rectangle from its top-left corner, width and height.
14    ///
15    /// # Arguments:
16    ///   * `x` - x-coordinate of the top-left corner.
17    ///   * `y` - y-coordinate of the top-left corner.
18    ///   * `w` - width of the `Rect`, going to the right.
19    ///   * `h` - height of the `Rect`, going down.
20    pub const fn new(x: f32, y: f32, w: f32, h: f32) -> Rect {
21        Rect { x, y, w, h }
22    }
23
24    /// Returns the top-left corner of the `Rect`.
25    pub const fn point(&self) -> Vec2 {
26        vec2(self.x, self.y)
27    }
28
29    /// Returns the size (width and height) of the `Rect`.
30    pub const fn size(&self) -> Vec2 {
31        vec2(self.w, self.h)
32    }
33
34    /// Returns the center position of the `Rect`.
35    pub fn center(&self) -> Vec2 {
36        vec2(self.x + self.w * 0.5f32, self.y + self.h * 0.5f32)
37    }
38
39    /// Returns the left edge of the `Rect`
40    pub const fn left(&self) -> f32 {
41        self.x
42    }
43
44    /// Returns the right edge of the `Rect`
45    pub fn right(&self) -> f32 {
46        self.x + self.w
47    }
48
49    /// Returns the top edge of the `Rect`
50    pub const fn top(&self) -> f32 {
51        self.y
52    }
53
54    /// Returns the bottom edge of the `Rect`
55    pub fn bottom(&self) -> f32 {
56        self.y + self.h
57    }
58
59    /// Moves the `Rect`'s origin to (x, y)
60    pub fn move_to(&mut self, destination: Vec2) {
61        self.x = destination.x;
62        self.y = destination.y;
63    }
64
65    /// Scales the `Rect` by a factor of (sx, sy),
66    /// growing towards the bottom-left
67    pub fn scale(&mut self, sx: f32, sy: f32) {
68        self.w *= sx;
69        self.h *= sy;
70    }
71
72    /// Checks whether the `Rect` contains a `Point`
73    pub fn contains(&self, point: Vec2) -> bool {
74        point.x >= self.left()
75            && point.x < self.right()
76            && point.y < self.bottom()
77            && point.y >= self.top()
78    }
79
80    /// Checks whether the `Rect` overlaps another `Rect`
81    pub fn overlaps(&self, other: &Rect) -> bool {
82        self.left() <= other.right()
83            && self.right() >= other.left()
84            && self.top() <= other.bottom()
85            && self.bottom() >= other.top()
86    }
87
88    /// Returns a new `Rect` that includes all points of these two `Rect`s.
89    pub fn combine_with(self, other: Rect) -> Rect {
90        let x = f32::min(self.x, other.x);
91        let y = f32::min(self.y, other.y);
92        let w = f32::max(self.right(), other.right()) - x;
93        let h = f32::max(self.bottom(), other.bottom()) - y;
94        Rect { x, y, w, h }
95    }
96
97    /// Returns an intersection rect there is any intersection
98    pub fn intersect(&self, other: Rect) -> Option<Rect> {
99        let left = self.x.max(other.x);
100        let top = self.y.max(other.y);
101        let right = self.right().min(other.right());
102        let bottom = self.bottom().min(other.bottom());
103
104        if right < left || bottom < top {
105            return None;
106        }
107
108        Some(Rect {
109            x: left,
110            y: top,
111            w: right - left,
112            h: bottom - top,
113        })
114    }
115
116    /// Translate rect origin be `offset` vector
117    pub fn offset(self, offset: Vec2) -> Rect {
118        Rect::new(self.x + offset.x, self.y + offset.y, self.w, self.h)
119    }
120}
121
122#[derive(Clone, Copy, Debug, Default, PartialEq)]
123pub struct RectOffset {
124    pub left: f32,
125    pub right: f32,
126    pub bottom: f32,
127    pub top: f32,
128}
129
130impl RectOffset {
131    pub const fn new(left: f32, right: f32, top: f32, bottom: f32) -> RectOffset {
132        RectOffset {
133            left,
134            right,
135            top,
136            bottom,
137        }
138    }
139}