Skip to content

Commit d0b73c4

Browse files
committed
Add try_normalized and try_direction_to
1 parent cd31a83 commit d0b73c4

File tree

4 files changed

+50
-14
lines changed

4 files changed

+50
-14
lines changed

godot-core/src/builtin/vectors/vector_macros.rs

Lines changed: 38 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -511,12 +511,23 @@ macro_rules! impl_float_vector_fns {
511511
)
512512
}
513513

514-
/// Returns the normalized vector pointing from this vector to `to`.
514+
/// Returns the normalized vector pointing from this vector to `to` or [`None`], if `self` and `to` are equal.
515515
///
516-
/// This is equivalent to using `(b - a).normalized()`.
516+
/// This is equivalent to using `(b - a).try_normalized()`. See also [`direction_to()`][Self::direction_to].
517+
#[inline]
518+
pub fn try_direction_to(self, to: Self) -> Option<Self> {
519+
(to - self).try_normalized()
520+
}
521+
522+
/// ⚠️ Returns the normalized vector pointing from this vector to `to`.
523+
///
524+
/// This is equivalent to using `(b - a).normalized()`. See also [`try_direction_to()`][Self::try_direction_to].
525+
///
526+
/// # Panics
527+
/// If `self` and `to` are equal.
517528
#[inline]
518529
pub fn direction_to(self, to: Self) -> Self {
519-
(to - self).normalized()
530+
self.try_direction_to(to).expect("direction_to() called on equal vectors")
520531
}
521532

522533
/// Returns the squared distance between this vector and `to`.
@@ -575,17 +586,36 @@ macro_rules! impl_float_vector_fns {
575586
)
576587
}
577588

578-
/// Returns the vector scaled to unit length. Equivalent to `self / self.length()`. See
579-
/// also `is_normalized()`.
589+
/// Returns the vector scaled to unit length or [`None`], if called on a zero vector.
590+
///
591+
/// Computes `self / self.length()`. See also [`normalized()`][Self::normalized] and [`is_normalized()`][Self::is_normalized].
592+
#[inline]
593+
pub fn try_normalized(self) -> Option<Self> {
594+
if self == Self::ZERO {
595+
return None;
596+
}
597+
598+
// Copy Godot's implementation since it's faster than using glam's normalize_or_zero().
599+
Some(self / self.length())
600+
}
601+
602+
/// ⚠️ Returns the vector scaled to unit length.
603+
///
604+
/// Computes `self / self.length()`. See also [`try_normalized()`][Self::try_normalized] and [`is_normalized()`][Self::is_normalized].
580605
///
581606
/// # Panics
582607
/// If called on a zero vector.
583608
#[inline]
584609
pub fn normalized(self) -> Self {
585-
assert_ne!(self, Self::ZERO, "normalized() called on zero vector");
610+
self.try_normalized().expect("normalized() called on zero vector")
611+
}
586612

587-
// Copy Godot's implementation since it's faster than using glam's normalize_or_zero().
588-
self / self.length()
613+
/// Returns the vector scaled to unit length or [`Self::ZERO`], if called on a zero vector.
614+
///
615+
/// Computes `self / self.length()`. See also [`try_normalized()`][Self::try_normalized] and [`is_normalized()`][Self::is_normalized].
616+
#[inline]
617+
pub fn normalized_or_zero(self) -> Self {
618+
self.try_normalized().unwrap_or_default()
589619
}
590620

591621
/// Returns a vector composed of the [`FloatExt::fposmod`] of this vector's components and `pmod`.

itest/rust/src/builtin_tests/geometry/vector_test/vector2_test.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -327,10 +327,12 @@ fn move_toward() {
327327
}
328328

329329
#[itest]
330-
fn normalized() {
330+
fn try_normalized() {
331331
let a = Vector2::new(1.2, -3.4);
332+
let b = Vector2::ZERO;
332333

333-
assert_eq_approx!(a.normalized(), a.as_inner().normalized());
334+
assert_eq_approx!(a.try_normalized().unwrap(), a.as_inner().normalized());
335+
assert_eq!(b.try_normalized(), None);
334336
}
335337

336338
#[itest]

itest/rust/src/builtin_tests/geometry/vector_test/vector3_test.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -309,10 +309,12 @@ fn move_toward() {
309309
}
310310

311311
#[itest]
312-
fn normalized() {
312+
fn try_normalized() {
313313
let a = Vector3::new(1.2, -3.4, 5.6);
314+
let b = Vector3::ZERO;
314315

315-
assert_eq!(a.normalized(), a.as_inner().normalized());
316+
assert_eq_approx!(a.try_normalized().unwrap(), a.as_inner().normalized());
317+
assert_eq!(b.try_normalized(), None);
316318
}
317319

318320
#[itest]

itest/rust/src/builtin_tests/geometry/vector_test/vector4_test.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -240,10 +240,12 @@ fn min_axis() {
240240
}
241241

242242
#[itest]
243-
fn normalized() {
243+
fn try_normalized() {
244244
let a = Vector4::new(1.2, -3.4, 5.6, -7.8);
245+
let b = Vector4::ZERO;
245246

246-
assert_eq!(a.normalized(), a.as_inner().normalized());
247+
assert_eq_approx!(a.try_normalized().unwrap(), a.as_inner().normalized());
248+
assert_eq!(b.try_normalized(), None);
247249
}
248250

249251
#[itest]

0 commit comments

Comments
 (0)