Skip to content

Commit 895283f

Browse files
bors[bot]RealAstolfo
and
RealAstolfo
authored
Merge #67
67: PR #3/5 Astolfo feature/builtin-vector r=Bromeon a=RealAstolfo This PR builds upon ttencates macro and my math functions to create a rust implementation of what godot has in its C++ as close as i think, meant to be merged after #66 Co-authored-by: RealAstolfo <[email protected]>
2 parents c1a36da + c9996c3 commit 895283f

File tree

4 files changed

+439
-6
lines changed

4 files changed

+439
-6
lines changed

godot-core/src/builtin/math.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,16 @@ pub fn snapped(mut value: f32, step: f32) -> f32 {
4141
value
4242
}
4343

44+
pub fn sign(value: f32) -> f32 {
45+
if value == 0.0 {
46+
0.0
47+
} else if value < 0.0 {
48+
-1.0
49+
} else {
50+
1.0
51+
}
52+
}
53+
4454
pub fn bezier_derivative(start: f32, control_1: f32, control_2: f32, end: f32, t: f32) -> f32 {
4555
let omt = 1.0 - t;
4656
let omt2 = omt * omt;
@@ -66,6 +76,7 @@ pub fn cubic_interpolate(from: f32, to: f32, pre: f32, post: f32, weight: f32) -
6676
+ (-pre + 3.0 * from - 3.0 * to + post) * (weight * weight * weight))
6777
}
6878

79+
#[allow(clippy::too_many_arguments)]
6980
pub fn cubic_interpolate_in_time(
7081
from: f32,
7182
to: f32,

godot-core/src/builtin/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ mod vector_macros;
3838
mod arrays;
3939
mod color;
4040
mod dictionary;
41+
mod math;
4142
mod node_path;
4243
mod others;
4344
mod packed_array;
@@ -58,6 +59,7 @@ pub use crate::dict;
5859
pub use arrays::*;
5960
pub use color::*;
6061
pub use dictionary::*;
62+
pub use math::*;
6163
pub use node_path::*;
6264
pub use others::*;
6365
pub use packed_array::*;

godot-core/src/builtin/vector2.rs

Lines changed: 209 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,13 @@
33
* License, v. 2.0. If a copy of the MPL was not distributed with this
44
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
55
*/
6-
76
use std::fmt;
7+
use std::ops::*;
88

99
use godot_ffi as sys;
1010
use sys::{ffi_methods, GodotFfi};
1111

12+
use crate::builtin::math::*;
1213
use crate::builtin::{inner, Vector2i};
1314

1415
/// Vector used for 2D math using floating point coordinates.
@@ -70,11 +71,6 @@ impl Vector2 {
7071
}
7172
}
7273

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-
7874
/// Converts the corresponding `glam` type to `Self`.
7975
fn from_glam(v: glam::Vec2) -> Self {
8076
Self::new(v.x, v.y)
@@ -85,6 +81,213 @@ impl Vector2 {
8581
glam::Vec2::new(self.x, self.y)
8682
}
8783

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+
88291
#[doc(hidden)]
89292
pub fn as_inner(&self) -> inner::InnerVector2 {
90293
inner::InnerVector2::from_outer(self)

0 commit comments

Comments
 (0)