7
7
use godot_ffi as sys;
8
8
use sys:: { ffi_methods, GodotFfi } ;
9
9
10
- use super :: { real, Rect2i , Vector2 } ;
10
+ use super :: { real, Rect2i , RectSide , Vector2 } ;
11
11
12
12
/// 2D axis-aligned bounding box.
13
13
///
@@ -44,6 +44,184 @@ impl Rect2 {
44
44
}
45
45
}
46
46
47
+ /// Returns a rectangle with equivalent position and area, modified so that the top-left corner is the origin and `width` and `height` are positive.
48
+ ///
49
+ /// _Godot equivalent: `Rect2.abs()`_
50
+ #[ inline]
51
+ pub fn abs ( & self ) -> Self {
52
+ Self {
53
+ position : self . position + self . size . coord_min ( Vector2 :: ZERO ) ,
54
+ size : self . size . abs ( ) ,
55
+ }
56
+ }
57
+
58
+ /// Returns true if this rectangle (inclusively) encloses `b`. This is true when `self` covers all the area of `b`, and possibly (but not necessarily) more.
59
+ ///
60
+ /// _Godot equivalent: `Rect2.encloses(Rect2 b)`_
61
+ #[ inline]
62
+ pub fn encloses ( & self , b : Rect2 ) -> bool {
63
+ let end = self . end ( ) ;
64
+ let b_end = b. end ( ) ;
65
+
66
+ b. position . x >= self . position . x
67
+ && b. position . y >= self . position . y
68
+ && b_end. x <= end. x
69
+ && b_end. y <= end. y
70
+ }
71
+
72
+ /// Returns a copy of this rectangle expanded to include a given point.
73
+ ///
74
+ /// Note: This method is not reliable for `Rect2` with a negative size. Use [`abs`][Self::abs]
75
+ /// to get a positive sized equivalent rectangle for expanding.
76
+ ///
77
+ /// _Godot equivalent: `Rect2.expand(Vector2 to)`_
78
+ #[ inline]
79
+ pub fn expand ( & self , to : Vector2 ) -> Self {
80
+ self . merge ( Rect2 :: new ( to, Vector2 :: ZERO ) )
81
+ }
82
+
83
+ /// Returns a larger rectangle that contains this `Rect2` and `b`.
84
+ ///
85
+ /// Note: This method is not reliable for `Rect2` with a negative size. Use [`abs`][Self::abs]
86
+ /// to get a positive sized equivalent rectangle for merging.
87
+ ///
88
+ /// _Godot equivalent: `Rect2.merge(Rect2 b)`_
89
+ #[ inline]
90
+ pub fn merge ( & self , b : Self ) -> Self {
91
+ let position = self . position . coord_min ( b. position ) ;
92
+ let end = self . end ( ) . coord_max ( b. end ( ) ) ;
93
+
94
+ Self :: from_corners ( position, end)
95
+ }
96
+
97
+ /// Returns the area of the rectangle.
98
+ ///
99
+ /// _Godot equivalent: `Rect2.get_area()`_
100
+ #[ doc( alias = "get_area" ) ]
101
+ #[ inline]
102
+ pub fn area ( & self ) -> real {
103
+ self . size . x * self . size . y
104
+ }
105
+
106
+ /// Returns the center of the Rect2, which is equal to `position + (size / 2)`.
107
+ ///
108
+ /// _Godot equivalent: `Rect2.get_center()`_
109
+ #[ doc( alias = "get_center" ) ]
110
+ #[ inline]
111
+ pub fn center ( & self ) -> Vector2 {
112
+ self . position + ( self . size / 2.0 )
113
+ }
114
+
115
+ /// Returns a copy of the Rect2 grown by the specified `amount` on all sides.
116
+ ///
117
+ /// _Godot equivalent: `Rect2.grow(float amount)`_
118
+ #[ inline]
119
+ #[ must_use]
120
+ pub fn grow ( & self , amount : real ) -> Self {
121
+ let position = self . position - Vector2 :: new ( amount, amount) ;
122
+ let size = self . size + Vector2 :: new ( amount, amount) * 2.0 ;
123
+
124
+ Self { position, size }
125
+ }
126
+
127
+ /// Returns a copy of the Rect2 grown by the specified amount on each side individually.
128
+ ///
129
+ /// _Godot equivalent: `Rect2.grow_individual(float left, float top, float right, float bottom)`_
130
+ #[ inline]
131
+ pub fn grow_individual ( & self , left : real , top : real , right : real , bottom : real ) -> Self {
132
+ Self :: from_components (
133
+ self . position . x - left,
134
+ self . position . y - top,
135
+ self . size . x + left + right,
136
+ self . size . y + top + bottom,
137
+ )
138
+ }
139
+
140
+ /// Returns a copy of the `Rect2` grown by the specified `amount` on the specified `RectSide`.
141
+ ///
142
+ /// `amount` may be negative, but care must be taken: If the resulting `size` has
143
+ /// negative components the computation may be incorrect.
144
+ ///
145
+ /// _Godot equivalent: `Rect2.grow_side(int side, float amount)`_
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
+ ///
158
+ /// _Godot equivalent: `Rect2.has_area()`_
159
+ #[ inline]
160
+ pub fn has_area ( & self ) -> bool {
161
+ self . size . x > 0.0 && self . size . y > 0.0
162
+ }
163
+
164
+ /// 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.
165
+ ///
166
+ /// 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.
167
+ ///
168
+ /// _Godot equivalent: `Rect2.has_area()`_
169
+ #[ inline]
170
+ pub fn has_point ( & self , point : Vector2 ) -> bool {
171
+ let point = point - self . position ;
172
+
173
+ point. abs ( ) == point && point. x < self . size . x && point. y < self . size . y
174
+ }
175
+
176
+ /// Returns the intersection of this Rect2 and `b`. If the rectangles do not intersect, an empty Rect2 is returned.
177
+ ///
178
+ /// _Godot equivalent: `Rect2.intersection(Rect2 b)`_
179
+ #[ inline]
180
+ pub fn intersection ( & self , b : Self ) -> Option < Self > {
181
+ if !self . intersects ( b, true ) {
182
+ return None ;
183
+ }
184
+
185
+ let mut rect = b;
186
+ rect. position = rect. position . coord_max ( self . position ) ;
187
+
188
+ let end = self . end ( ) ;
189
+ let end_b = b. end ( ) ;
190
+ rect. size = end. coord_min ( end_b) - rect. position ;
191
+
192
+ Some ( rect)
193
+ }
194
+
195
+ /// Returns `true` if the Rect2 overlaps with `b` (i.e. they have at least one point in common).
196
+ ///
197
+ /// If `include_borders` is `true`, they will also be considered overlapping if their borders touch, even without intersection.
198
+ ///
199
+ /// _Godot equivalent: `Rect2.intersects(Rect2 b, bool include_borders)`_
200
+ #[ inline]
201
+ pub fn intersects ( & self , b : Self , include_borders : bool ) -> bool {
202
+ let end = self . end ( ) ;
203
+ let end_b = b. end ( ) ;
204
+
205
+ if include_borders {
206
+ self . position . x <= end_b. x
207
+ && end. x >= b. position . x
208
+ && self . position . y <= end_b. y
209
+ && end. y >= b. position . y
210
+ } else {
211
+ self . position . x < end_b. x
212
+ && end. x > b. position . x
213
+ && self . position . y < end_b. y
214
+ && end. y > b. position . y
215
+ }
216
+ }
217
+
218
+ /// Returns `true` if this Rect2 is finite, by calling `@GlobalScope.is_finite` on each component.
219
+ ///
220
+ /// _Godot equivalent: `Rect2.is_finite()`_
221
+ pub fn is_finite ( & self ) -> bool {
222
+ self . position . is_finite ( ) && self . size . is_finite ( )
223
+ }
224
+
47
225
/// Create a new `Rect2` from a `Rect2i`, using `as` for `i32` to `real` conversions.
48
226
///
49
227
/// _Godot equivalent: `Rect2(Rect2i from)`_
@@ -60,7 +238,7 @@ impl Rect2 {
60
238
pub fn from_corners ( position : Vector2 , end : Vector2 ) -> Self {
61
239
Self {
62
240
position,
63
- size : position + end ,
241
+ size : end - position ,
64
242
}
65
243
}
66
244
@@ -89,7 +267,6 @@ impl Rect2 {
89
267
self . position . is_equal_approx ( other. position ) && self . size . is_equal_approx ( other. size )
90
268
}
91
269
92
- /* Add in when `Rect2::abs()` is implemented.
93
270
/// Assert that the size of the `Rect2` is not negative.
94
271
///
95
272
/// Certain functions will fail to give a correct result if the size is negative.
@@ -101,7 +278,6 @@ impl Rect2 {
101
278
self . size
102
279
) ;
103
280
}
104
- */
105
281
}
106
282
107
283
// SAFETY:
0 commit comments