3
3
* License, v. 2.0. If a copy of the MPL was not distributed with this
4
4
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
5
5
*/
6
-
7
6
use std:: fmt;
7
+ use std:: ops:: * ;
8
8
9
9
use godot_ffi as sys;
10
10
use sys:: { ffi_methods, GodotFfi } ;
11
11
12
+ use crate :: builtin:: math:: * ;
12
13
use crate :: builtin:: { inner, Vector2i } ;
13
14
14
15
/// Vector used for 2D math using floating point coordinates.
@@ -70,11 +71,6 @@ impl Vector2 {
70
71
}
71
72
}
72
73
73
- /// Returns the result of rotating this vector by `angle` (in radians).
74
- pub fn rotated ( self , angle : f32 ) -> Self {
75
- Self :: from_glam ( glam:: Affine2 :: from_angle ( angle) . transform_vector2 ( self . to_glam ( ) ) )
76
- }
77
-
78
74
/// Converts the corresponding `glam` type to `Self`.
79
75
fn from_glam ( v : glam:: Vec2 ) -> Self {
80
76
Self :: new ( v. x , v. y )
@@ -85,6 +81,213 @@ impl Vector2 {
85
81
glam:: Vec2 :: new ( self . x , self . y )
86
82
}
87
83
84
+ pub fn angle ( self ) -> f32 {
85
+ self . y . atan2 ( self . x )
86
+ }
87
+
88
+ pub fn angle_to ( self , to : Self ) -> f32 {
89
+ self . to_glam ( ) . angle_between ( to. to_glam ( ) )
90
+ }
91
+
92
+ pub fn angle_to_point ( self , to : Self ) -> f32 {
93
+ ( to - self ) . angle ( )
94
+ }
95
+
96
+ pub fn aspect ( self ) -> f32 {
97
+ self . x / self . y
98
+ }
99
+
100
+ pub fn bezier_derivative ( self , control_1 : Self , control_2 : Self , end : Self , t : f32 ) -> Self {
101
+ let x = bezier_derivative ( self . x , control_1. x , control_2. x , end. x , t) ;
102
+ let y = bezier_derivative ( self . y , control_1. y , control_2. y , end. y , t) ;
103
+
104
+ Self :: new ( x, y)
105
+ }
106
+
107
+ pub fn bezier_interpolate ( self , control_1 : Self , control_2 : Self , end : Self , t : f32 ) -> Self {
108
+ let x = bezier_interpolate ( self . x , control_1. x , control_2. x , end. x , t) ;
109
+ let y = bezier_interpolate ( self . y , control_1. y , control_2. y , end. y , t) ;
110
+
111
+ Self :: new ( x, y)
112
+ }
113
+
114
+ pub fn bounce ( self , normal : Self ) -> Self {
115
+ -self . reflect ( normal)
116
+ }
117
+
118
+ pub fn ceil ( self ) -> Self {
119
+ Self :: from_glam ( self . to_glam ( ) . ceil ( ) )
120
+ }
121
+
122
+ pub fn clamp ( self , min : Self , max : Self ) -> Self {
123
+ Self :: from_glam ( self . to_glam ( ) . clamp ( min. to_glam ( ) , max. to_glam ( ) ) )
124
+ }
125
+
126
+ pub fn cross ( self , with : Self ) -> f32 {
127
+ self . to_glam ( ) . perp_dot ( with. to_glam ( ) )
128
+ }
129
+
130
+ pub fn cubic_interpolate ( self , b : Self , pre_a : Self , post_b : Self , weight : f32 ) -> Self {
131
+ let x = cubic_interpolate ( self . x , b. x , pre_a. x , post_b. x , weight) ;
132
+ let y = cubic_interpolate ( self . y , b. y , pre_a. y , post_b. y , weight) ;
133
+
134
+ Self :: new ( x, y)
135
+ }
136
+
137
+ #[ allow( clippy:: too_many_arguments) ]
138
+ pub fn cubic_interpolate_in_time (
139
+ self ,
140
+ b : Self ,
141
+ pre_a : Self ,
142
+ post_b : Self ,
143
+ weight : f32 ,
144
+ b_t : f32 ,
145
+ pre_a_t : f32 ,
146
+ post_b_t : f32 ,
147
+ ) -> Self {
148
+ let x = cubic_interpolate_in_time (
149
+ self . x , b. x , pre_a. x , post_b. x , weight, b_t, pre_a_t, post_b_t,
150
+ ) ;
151
+ let y = cubic_interpolate_in_time (
152
+ self . y , b. y , pre_a. y , post_b. y , weight, b_t, pre_a_t, post_b_t,
153
+ ) ;
154
+
155
+ Self :: new ( x, y)
156
+ }
157
+
158
+ pub fn direction_to ( self , to : Self ) -> Self {
159
+ ( to - self ) . normalized ( )
160
+ }
161
+
162
+ pub fn distance_squared_to ( self , to : Self ) -> f32 {
163
+ ( to - self ) . length_squared ( )
164
+ }
165
+
166
+ pub fn distance_to ( self , to : Self ) -> f32 {
167
+ ( to - self ) . length ( )
168
+ }
169
+
170
+ pub fn dot ( self , other : Self ) -> f32 {
171
+ self . to_glam ( ) . dot ( other. to_glam ( ) )
172
+ }
173
+
174
+ pub fn floor ( self ) -> Self {
175
+ Self :: from_glam ( self . to_glam ( ) . floor ( ) )
176
+ }
177
+
178
+ pub fn from_angle ( angle : f32 ) -> Self {
179
+ Self :: from_glam ( glam:: Vec2 :: from_angle ( angle) )
180
+ }
181
+
182
+ pub fn is_equal_approx ( self , to : Self ) -> bool {
183
+ is_equal_approx ( self . x , to. x ) && is_equal_approx ( self . y , to. y )
184
+ }
185
+
186
+ pub fn is_finite ( self ) -> bool {
187
+ self . to_glam ( ) . is_finite ( )
188
+ }
189
+
190
+ pub fn is_normalized ( self ) -> bool {
191
+ self . to_glam ( ) . is_normalized ( )
192
+ }
193
+
194
+ pub fn is_zero_approx ( self ) -> bool {
195
+ is_zero_approx ( self . x ) && is_zero_approx ( self . y )
196
+ }
197
+
198
+ pub fn length_squared ( self ) -> f32 {
199
+ self . to_glam ( ) . length_squared ( )
200
+ }
201
+
202
+ pub fn lerp ( self , to : Self , weight : f32 ) -> Self {
203
+ Self :: from_glam ( self . to_glam ( ) . lerp ( to. to_glam ( ) , weight) )
204
+ }
205
+
206
+ pub fn limit_length ( self , length : Option < f32 > ) -> Self {
207
+ Self :: from_glam ( self . to_glam ( ) . clamp_length_max ( length. unwrap_or ( 1.0 ) ) )
208
+ }
209
+
210
+ pub fn max_axis_index ( self ) -> Vector2Axis {
211
+ if self . x < self . y {
212
+ Vector2Axis :: Y
213
+ } else {
214
+ Vector2Axis :: X
215
+ }
216
+ }
217
+
218
+ pub fn min_axis_index ( self ) -> Vector2Axis {
219
+ if self . x < self . y {
220
+ Vector2Axis :: X
221
+ } else {
222
+ Vector2Axis :: Y
223
+ }
224
+ }
225
+
226
+ pub fn move_toward ( self , to : Self , delta : f32 ) -> Self {
227
+ let vd = to - self ;
228
+ let len = vd. length ( ) ;
229
+ if len <= delta || len < CMP_EPSILON {
230
+ to
231
+ } else {
232
+ self + vd / len * delta
233
+ }
234
+ }
235
+
236
+ pub fn orthogonal ( self ) -> Self {
237
+ Self :: new ( self . y , -self . x )
238
+ }
239
+
240
+ pub fn posmod ( self , pmod : f32 ) -> Self {
241
+ Self :: new ( fposmod ( self . x , pmod) , fposmod ( self . y , pmod) )
242
+ }
243
+
244
+ pub fn posmodv ( self , modv : Self ) -> Self {
245
+ Self :: new ( fposmod ( self . x , modv. x ) , fposmod ( self . y , modv. y ) )
246
+ }
247
+
248
+ pub fn project ( self , b : Self ) -> Self {
249
+ Self :: from_glam ( self . to_glam ( ) . project_onto ( b. to_glam ( ) ) )
250
+ }
251
+
252
+ pub fn reflect ( self , normal : Self ) -> Self {
253
+ Self :: from_glam ( self . to_glam ( ) . reject_from ( normal. to_glam ( ) ) )
254
+ }
255
+
256
+ pub fn round ( self ) -> Self {
257
+ Self :: from_glam ( self . to_glam ( ) . round ( ) )
258
+ }
259
+
260
+ pub fn sign ( self ) -> Self {
261
+ Self :: new ( sign ( self . x ) , sign ( self . y ) )
262
+ }
263
+
264
+ // TODO compare with gdnative implementation:
265
+ // https://github.com/godot-rust/gdnative/blob/master/gdnative-core/src/core_types/vector3.rs#L335-L343
266
+ pub fn slerp ( self , to : Self , weight : f32 ) -> Self {
267
+ let start_length_sq = self . length_squared ( ) ;
268
+ let end_length_sq = to. length_squared ( ) ;
269
+ if start_length_sq == 0.0 || end_length_sq == 0.0 {
270
+ return self . lerp ( to, weight) ;
271
+ }
272
+ let start_length = start_length_sq. sqrt ( ) ;
273
+ let result_length = lerp ( start_length, end_length_sq. sqrt ( ) , weight) ;
274
+ let angle = self . angle_to ( to) ;
275
+ self . rotated ( angle * weight) * ( result_length / start_length)
276
+ }
277
+
278
+ pub fn slide ( self , normal : Self ) -> Self {
279
+ self - normal * self . dot ( normal)
280
+ }
281
+
282
+ pub fn snapped ( self , step : Self ) -> Self {
283
+ Self :: new ( snapped ( self . x , step. x ) , snapped ( self . y , step. y ) )
284
+ }
285
+
286
+ /// Returns the result of rotating this vector by `angle` (in radians).
287
+ pub fn rotated ( self , angle : f32 ) -> Self {
288
+ Self :: from_glam ( glam:: Affine2 :: from_angle ( angle) . transform_vector2 ( self . to_glam ( ) ) )
289
+ }
290
+
88
291
#[ doc( hidden) ]
89
292
pub fn as_inner ( & self ) -> inner:: InnerVector2 {
90
293
inner:: InnerVector2 :: from_outer ( self )
0 commit comments