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