@@ -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
///
@@ -46,6 +46,184 @@ impl Rect2 {
46
46
}
47
47
}
48
48
49
+ /// Returns a rectangle with the same geometry, with top-left corner as `position` and non-negative size.
50
+ ///
51
+ /// _Godot equivalent: `Rect2.abs()`_
52
+ #[ inline]
53
+ pub fn abs ( & self ) -> Self {
54
+ Self {
55
+ position : self . position + self . size . coord_min ( Vector2 :: ZERO ) ,
56
+ size : self . size . abs ( ) ,
57
+ }
58
+ }
59
+
60
+ /// Whether `self` covers at least the entire area of `b` (and possibly more).
61
+ ///
62
+ /// _Godot equivalent: `Rect2.encloses(Rect2 b)`_
63
+ #[ inline]
64
+ pub fn encloses ( & self , b : Rect2 ) -> bool {
65
+ let end = self . end ( ) ;
66
+ let b_end = b. end ( ) ;
67
+
68
+ b. position . x >= self . position . x
69
+ && b. position . y >= self . position . y
70
+ && b_end. x <= end. x
71
+ && b_end. y <= end. y
72
+ }
73
+
74
+ /// Returns a copy of this rectangle expanded to include a given point.
75
+ ///
76
+ /// Note: This method is not reliable for `Rect2` with a negative size. Use [`abs`][Self::abs]
77
+ /// to get a positive sized equivalent rectangle for expanding.
78
+ ///
79
+ /// _Godot equivalent: `Rect2.expand(Vector2 to)`_
80
+ #[ inline]
81
+ pub fn expand ( & self , to : Vector2 ) -> Self {
82
+ self . merge ( Rect2 :: new ( to, Vector2 :: ZERO ) )
83
+ }
84
+
85
+ /// Returns a larger rectangle that contains this `Rect2` and `b`.
86
+ ///
87
+ /// Note: This method is not reliable for `Rect2` with a negative size. Use [`abs`][Self::abs]
88
+ /// to get a positive sized equivalent rectangle for merging.
89
+ ///
90
+ /// _Godot equivalent: `Rect2.merge(Rect2 b)`_
91
+ #[ inline]
92
+ pub fn merge ( & self , b : Self ) -> Self {
93
+ let position = self . position . coord_min ( b. position ) ;
94
+ let end = self . end ( ) . coord_max ( b. end ( ) ) ;
95
+
96
+ Self :: from_corners ( position, end)
97
+ }
98
+
99
+ /// Returns the area of the rectangle.
100
+ ///
101
+ /// _Godot equivalent: `Rect2.get_area()`_
102
+ #[ doc( alias = "get_area" ) ]
103
+ #[ inline]
104
+ pub fn area ( & self ) -> real {
105
+ self . size . x * self . size . y
106
+ }
107
+
108
+ /// Returns the center of the Rect2, which is equal to `position + (size / 2)`.
109
+ ///
110
+ /// _Godot equivalent: `Rect2.get_center()`_
111
+ #[ doc( alias = "get_center" ) ]
112
+ #[ inline]
113
+ pub fn center ( & self ) -> Vector2 {
114
+ self . position + ( self . size / 2.0 )
115
+ }
116
+
117
+ /// Returns a copy of the Rect2 grown by the specified `amount` on all sides.
118
+ ///
119
+ /// _Godot equivalent: `Rect2.grow(float amount)`_
120
+ #[ inline]
121
+ #[ must_use]
122
+ pub fn grow ( & self , amount : real ) -> Self {
123
+ let position = self . position - Vector2 :: new ( amount, amount) ;
124
+ let size = self . size + Vector2 :: new ( amount, amount) * 2.0 ;
125
+
126
+ Self { position, size }
127
+ }
128
+
129
+ /// Returns a copy of the Rect2 grown by the specified amount on each side individually.
130
+ ///
131
+ /// _Godot equivalent: `Rect2.grow_individual(float left, float top, float right, float bottom)`_
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`.
143
+ ///
144
+ /// `amount` may be negative, but care must be taken: If the resulting `size` has
145
+ /// negative components the computation may be incorrect.
146
+ ///
147
+ /// _Godot equivalent: `Rect2.grow_side(int side, float amount)`_
148
+ #[ inline]
149
+ pub fn grow_side ( & self , side : RectSide , amount : real ) -> Self {
150
+ match side {
151
+ RectSide :: Left => self . grow_individual ( amount, 0.0 , 0.0 , 0.0 ) ,
152
+ RectSide :: Top => self . grow_individual ( 0.0 , amount, 0.0 , 0.0 ) ,
153
+ RectSide :: Right => self . grow_individual ( 0.0 , 0.0 , amount, 0.0 ) ,
154
+ RectSide :: Bottom => self . grow_individual ( 0.0 , 0.0 , 0.0 , amount) ,
155
+ }
156
+ }
157
+
158
+ /// Returns `true` if the Rect2 has area, and `false` if the Rect2 is linear, empty, or has a negative size. See also `get_area`.
159
+ ///
160
+ /// _Godot equivalent: `Rect2.has_area()`_
161
+ #[ inline]
162
+ pub fn has_area ( & self ) -> bool {
163
+ self . size . x > 0.0 && self . size . y > 0.0
164
+ }
165
+
166
+ /// 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.
167
+ ///
168
+ /// 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.
169
+ ///
170
+ /// _Godot equivalent: `Rect2.has_area()`_
171
+ #[ inline]
172
+ pub fn has_point ( & self , point : Vector2 ) -> bool {
173
+ let point = point - self . position ;
174
+
175
+ point. abs ( ) == point && point. x < self . size . x && point. y < self . size . y
176
+ }
177
+
178
+ /// Returns the intersection of this Rect2 and `b`. If the rectangles do not intersect, an empty Rect2 is returned.
179
+ ///
180
+ /// _Godot equivalent: `Rect2.intersection(Rect2 b)`_
181
+ #[ inline]
182
+ pub fn intersection ( & self , b : Self ) -> Option < Self > {
183
+ if !self . intersects ( b, true ) {
184
+ return None ;
185
+ }
186
+
187
+ let mut rect = b;
188
+ rect. position = rect. position . coord_max ( self . position ) ;
189
+
190
+ let end = self . end ( ) ;
191
+ let end_b = b. end ( ) ;
192
+ rect. size = end. coord_min ( end_b) - rect. position ;
193
+
194
+ Some ( rect)
195
+ }
196
+
197
+ /// Returns `true` if the Rect2 overlaps with `b` (i.e. they have at least one point in common).
198
+ ///
199
+ /// If `include_borders` is `true`, they will also be considered overlapping if their borders touch, even without intersection.
200
+ ///
201
+ /// _Godot equivalent: `Rect2.intersects(Rect2 b, bool include_borders)`_
202
+ #[ inline]
203
+ pub fn intersects ( & self , b : Self , include_borders : bool ) -> bool {
204
+ let end = self . end ( ) ;
205
+ let end_b = b. end ( ) ;
206
+
207
+ if include_borders {
208
+ self . position . x <= end_b. x
209
+ && end. x >= b. position . x
210
+ && self . position . y <= end_b. y
211
+ && end. y >= b. position . y
212
+ } else {
213
+ self . position . x < end_b. x
214
+ && end. x > b. position . x
215
+ && self . position . y < end_b. y
216
+ && end. y > b. position . y
217
+ }
218
+ }
219
+
220
+ /// Returns `true` if this Rect2 is finite, by calling `@GlobalScope.is_finite` on each component.
221
+ ///
222
+ /// _Godot equivalent: `Rect2.is_finite()`_
223
+ pub fn is_finite ( & self ) -> bool {
224
+ self . position . is_finite ( ) && self . size . is_finite ( )
225
+ }
226
+
49
227
/// Create a new `Rect2` from a `Rect2i`, using `as` for `i32` to `real` conversions.
50
228
///
51
229
/// _Godot equivalent: `Rect2(Rect2i from)`_
@@ -62,7 +240,7 @@ impl Rect2 {
62
240
pub fn from_corners ( position : Vector2 , end : Vector2 ) -> Self {
63
241
Self {
64
242
position,
65
- size : position + end ,
243
+ size : end - position ,
66
244
}
67
245
}
68
246
@@ -83,7 +261,6 @@ impl Rect2 {
83
261
self . size = end - self . position
84
262
}
85
263
86
- /* Add in when `Rect2::abs()` is implemented.
87
264
/// Assert that the size of the `Rect2` is not negative.
88
265
///
89
266
/// Certain functions will fail to give a correct result if the size is negative.
@@ -95,7 +272,6 @@ impl Rect2 {
95
272
self . size
96
273
) ;
97
274
}
98
- */
99
275
}
100
276
101
277
// SAFETY:
0 commit comments