@@ -8,7 +8,7 @@ use godot_ffi as sys;
8
8
use sys:: { ffi_methods, GodotFfi } ;
9
9
10
10
use crate :: builtin:: math:: ApproxEq ;
11
- use crate :: builtin:: { real, Rect2i , Vector2 } ;
11
+ use crate :: builtin:: { real, Rect2i , RectSide , Vector2 } ;
12
12
13
13
/// 2D axis-aligned bounding box.
14
14
///
@@ -35,6 +35,13 @@ impl Rect2 {
35
35
Self { position, size }
36
36
}
37
37
38
+ /// Create a new `Rect2` with the first corner at `position` and the opposite corner at `end`.
39
+ #[ inline]
40
+ pub fn from_corners ( position : Vector2 , end : Vector2 ) -> Self {
41
+ // Cannot use floating point arithmetic in const functions.
42
+ Self :: new ( position, end - position)
43
+ }
44
+
38
45
/// Create a new `Rect2` from four reals representing position `(x,y)` and size `(width,height)`.
39
46
///
40
47
/// _Godot equivalent: `Rect2(float x, float y, float width, float height)`_
@@ -57,33 +64,180 @@ impl Rect2 {
57
64
}
58
65
}
59
66
60
- /// Create a new `Rect2` with the first corner at `position` and the opposite corner at `end` .
67
+ /// Returns a rectangle with the same geometry, with top-left corner as `position` and non-negative size .
61
68
#[ inline]
62
- pub fn from_corners ( position : Vector2 , end : Vector2 ) -> Self {
69
+ pub fn abs ( & self ) -> Self {
63
70
Self {
64
- position,
65
- size : position + end ,
71
+ position : self . position + self . size . coord_min ( Vector2 :: ZERO ) ,
72
+ size : self . size . abs ( ) ,
66
73
}
67
74
}
68
75
69
- /// The end of the `Rect2` calculated as `position + size`.
76
+ /// Whether `self` covers at least the entire area of `b` (and possibly more).
77
+ #[ inline]
78
+ pub fn encloses ( & self , b : Rect2 ) -> bool {
79
+ let end = self . end ( ) ;
80
+ let b_end = b. end ( ) ;
81
+
82
+ b. position . x >= self . position . x
83
+ && b. position . y >= self . position . y
84
+ && b_end. x <= end. x
85
+ && b_end. y <= end. y
86
+ }
87
+
88
+ /// Returns a copy of this rectangle expanded to include a given point.
89
+ ///
90
+ /// Note: This method is not reliable for `Rect2` with a negative size. Use [`abs`][Self::abs]
91
+ /// to get a positive sized equivalent rectangle for expanding.
92
+ #[ inline]
93
+ pub fn expand ( & self , to : Vector2 ) -> Self {
94
+ self . merge ( Rect2 :: new ( to, Vector2 :: ZERO ) )
95
+ }
96
+
97
+ /// Returns a larger rectangle that contains this `Rect2` and `b`.
98
+ ///
99
+ /// Note: This method is not reliable for `Rect2` with a negative size. Use [`abs`][Self::abs]
100
+ /// to get a positive sized equivalent rectangle for merging.
101
+ #[ inline]
102
+ pub fn merge ( & self , b : Self ) -> Self {
103
+ let position = self . position . coord_min ( b. position ) ;
104
+ let end = self . end ( ) . coord_max ( b. end ( ) ) ;
105
+
106
+ Self :: from_corners ( position, end)
107
+ }
108
+
109
+ /// Returns the area of the rectangle.
110
+ #[ inline]
111
+ pub fn area ( & self ) -> real {
112
+ self . size . x * self . size . y
113
+ }
114
+
115
+ /// Returns the center of the Rect2, which is equal to `position + (size / 2)`.
116
+ #[ inline]
117
+ pub fn center ( & self ) -> Vector2 {
118
+ self . position + ( self . size / 2.0 )
119
+ }
120
+
121
+ /// Returns a copy of the Rect2 grown by the specified `amount` on all sides.
122
+ #[ inline]
123
+ #[ must_use]
124
+ pub fn grow ( & self , amount : real ) -> Self {
125
+ let position = self . position - Vector2 :: new ( amount, amount) ;
126
+ let size = self . size + Vector2 :: new ( amount, amount) * 2.0 ;
127
+
128
+ Self { position, size }
129
+ }
130
+
131
+ /// Returns a copy of the Rect2 grown by the specified amount on each side individually.
132
+ #[ inline]
133
+ pub fn grow_individual ( & self , left : real , top : real , right : real , bottom : real ) -> Self {
134
+ Self :: from_components (
135
+ self . position . x - left,
136
+ self . position . y - top,
137
+ self . size . x + left + right,
138
+ self . size . y + top + bottom,
139
+ )
140
+ }
141
+
142
+ /// Returns a copy of the `Rect2` grown by the specified `amount` on the specified `RectSide`.
70
143
///
71
- /// _Godot equivalent: `Rect2.size` property_
72
- #[ doc( alias = "size" ) ]
144
+ /// `amount` may be negative, but care must be taken: If the resulting `size` has
145
+ /// negative components the computation may be incorrect.
146
+ #[ inline]
147
+ pub fn grow_side ( & self , side : RectSide , amount : real ) -> Self {
148
+ match side {
149
+ RectSide :: Left => self . grow_individual ( amount, 0.0 , 0.0 , 0.0 ) ,
150
+ RectSide :: Top => self . grow_individual ( 0.0 , amount, 0.0 , 0.0 ) ,
151
+ RectSide :: Right => self . grow_individual ( 0.0 , 0.0 , amount, 0.0 ) ,
152
+ RectSide :: Bottom => self . grow_individual ( 0.0 , 0.0 , 0.0 , amount) ,
153
+ }
154
+ }
155
+
156
+ /// Returns `true` if the Rect2 has area, and `false` if the Rect2 is linear, empty, or has a negative size. See also `get_area`.
157
+ #[ inline]
158
+ pub fn has_area ( & self ) -> bool {
159
+ self . size . x > 0.0 && self . size . y > 0.0
160
+ }
161
+
162
+ /// Returns `true` if the Rect2 contains a point. By convention, the right and bottom edges of the Rect2 are considered exclusive, so points on these edges are not included.
163
+ ///
164
+ /// Note: This method is not reliable for Rect2 with a negative size. Use `abs` to get a positive sized equivalent rectangle to check for contained points.
165
+ #[ inline]
166
+ pub fn has_point ( & self , point : Vector2 ) -> bool {
167
+ let point = point - self . position ;
168
+
169
+ point. abs ( ) == point && point. x < self . size . x && point. y < self . size . y
170
+ }
171
+
172
+ /// Returns the intersection of this Rect2 and `b`. If the rectangles do not intersect, an empty Rect2 is returned.
173
+ #[ inline]
174
+ pub fn intersection ( & self , b : Self ) -> Option < Self > {
175
+ if !self . intersects ( b) {
176
+ return None ;
177
+ }
178
+
179
+ let mut rect = b;
180
+ rect. position = rect. position . coord_max ( self . position ) ;
181
+
182
+ let end = self . end ( ) ;
183
+ let end_b = b. end ( ) ;
184
+ rect. size = end. coord_min ( end_b) - rect. position ;
185
+
186
+ Some ( rect)
187
+ }
188
+
189
+ /// Checks whether two rectangles have at least one point in common.
190
+ ///
191
+ /// Also returns `true` if the rects only touch each other (share a point/edge).
192
+ /// See [`intersects_exclude_borders`][Self::intersects_exclude_borders] if you want to return `false` in that case.
193
+ ///
194
+ /// _Godot equivalent: `Rect2.intersects(Rect2 b, bool include_borders = true)`_
195
+ #[ inline]
196
+ pub fn intersects ( & self , b : Self ) -> bool {
197
+ let end = self . end ( ) ;
198
+ let end_b = b. end ( ) ;
199
+
200
+ self . position . x <= end_b. x
201
+ && end. x >= b. position . x
202
+ && self . position . y <= end_b. y
203
+ && end. y >= b. position . y
204
+ }
205
+
206
+ /// Checks whether two rectangles have at least one _inner_ point in common (not on the borders).
207
+ ///
208
+ /// Returns `false` if the rects only touch each other (share a point/edge).
209
+ /// See [`intersects`][Self::intersects] if you want to return `true` in that case.
210
+ ///
211
+ /// _Godot equivalent: `Rect2.intersects(AABB b, bool include_borders = false)`_
212
+ #[ inline]
213
+ pub fn intersects_exclude_borders ( & self , b : Self ) -> bool {
214
+ let end = self . end ( ) ;
215
+ let end_b = b. end ( ) ;
216
+
217
+ self . position . x < end_b. x
218
+ && end. x > b. position . x
219
+ && self . position . y < end_b. y
220
+ && end. y > b. position . y
221
+ }
222
+
223
+ /// Returns `true` if this Rect2 is finite, by calling `@GlobalScope.is_finite` on each component.
224
+ #[ inline]
225
+ pub fn is_finite ( & self ) -> bool {
226
+ self . position . is_finite ( ) && self . size . is_finite ( )
227
+ }
228
+
229
+ /// The end of the `Rect2` calculated as `position + size`.
73
230
#[ inline]
74
231
pub fn end ( & self ) -> Vector2 {
75
232
self . position + self . size
76
233
}
77
234
78
235
/// Set size based on desired end-point.
79
- ///
80
- /// _Godot equivalent: `Rect2.size` property_
81
236
#[ inline]
82
237
pub fn set_end ( & mut self , end : Vector2 ) {
83
238
self . size = end - self . position
84
239
}
85
240
86
- /* Add in when `Rect2::abs()` is implemented.
87
241
/// Assert that the size of the `Rect2` is not negative.
88
242
///
89
243
/// Certain functions will fail to give a correct result if the size is negative.
@@ -95,7 +249,6 @@ impl Rect2 {
95
249
self . size
96
250
) ;
97
251
}
98
- */
99
252
}
100
253
101
254
// SAFETY:
0 commit comments