-
-
Notifications
You must be signed in to change notification settings - Fork 212
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add extension trait for floats #330
Add extension trait for floats #330
Conversation
API docs are being generated and will be shortly available at: https://godot-rust.github.io/docs/gdext/pr-330 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! While this makes sense from a technical perspective, there are some smaller things to discuss about the resulting API.
Some names are now a bit confusing or make it hard to see that they're from Godot: f.sign()
vs. f.signum()
from the standard library.
Others already have a trait: f.approx_eq(other)
-- one should be removed, possibly with #[doc(alias)]
in the ApproxEq
trait itself.
For many functions, the receiver syntax is a bit less clear as it consumes the from
argument, introducing asymmetry: lerp_angle(from, to, weight)
vs. from.lerp_angle(to, weight)
. It's also different from GDScript for floats. At least it's more consistent with vectors, and we could theoretically use the fully qualified syntax... I guess this is just a matter of getting used to?
Also, if we refactor those, are there ergonomic improvements we could do? Some methods take a big number of parameters, but I guess encapsulating just makes matters worse. Other ideas? (This could of course be done separately...)
Apart from that, did you change any of the implementations? It's impossible for me to see because you moved everything to another file and changed indentation, so git cannot detect changes. Just to know what I should review 🙂
@@ -364,15 +364,19 @@ impl Basis { | |||
Self::from_cols(self.rows[0], self.rows[1], self.rows[2]) | |||
} | |||
|
|||
/// Returns the orthonormalized version of the matrix (useful to call from | |||
/// ⚠️ Returns the orthonormalized version of the matrix (useful to call from |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This use of the warning sign is incorrect, according to
Lines 81 to 85 in 565bf10
//! To help you identify panicking methods, we use the symbol "⚠️" at the beginning of the documentation; | |
//! this should also appear immediately in the auto-completion of your IDE. Note that this warning sign is | |
//! not used as a general panic indicator, but particularly for methods which have a `Option`/`Result`-based | |
//! overload. If you want to know whether and how a method can panic, check if its documentation has a | |
//! _Panics_ section. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh i wasn't aware of that distinction. fair enough.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can also discuss it of course. I thought it would be redundant if we already have a "Panics" section that had the exact same meaning. But maybe it helps in IDE suggestions... 🤷
Also:
That issue is not really solved by this PR, but made a bit more convenient to deal with. The default configuration for godot is In some cases, |
Yeah i wasn't sure what to do there, since
fair
You can also just do
I'll have a look
// old
pub fn sign(value: real) -> real {
if value == 0.0 {
0.0
} else if value < 0.0 {
-1.0
} else {
1.0
}
}
// new
fn sign(self) -> Self {
use std::cmp::Ordering;
match self.partial_cmp(&0.0) {
Some(Ordering::Equal) => 0.0,
Some(Ordering::Greater) => 1.0,
Some(Ordering::Less) => -1.0,
// NAN, Godot return `1` in this case.
None => 1.0,
}
}
// old
pub fn fposmod(x: real, y: real) -> real {
let mut value = x % y;
if ((value < 0.0) && (y > 0.0)) || ((value > 0.0) && (y < 0.0)) {
value += y;
}
value += 0.0;
value
}
// new
fn fposmod(self, pmod: Self) -> Self {
let mut value = self % pmod;
if ((value < 0.0) && (pmod > 0.0)) || ((value > 0.0) && (pmod < 0.0)) {
value += pmod;
}
value
}
// old
pub fn is_angle_equal_approx(a: &real, b: &real) -> bool {
let (x1, y1) = a.sin_cos();
let (x2, y2) = b.sin_cos();
println!("({x1}, {y1}) ({x2}, {y2})");
is_equal_approx(
Vector2::distance_to(Vector2::new(x1, y1), Vector2::new(x2, y2)),
0.0,
)
}
// new
fn is_angle_equal_approx(self, other: Self) -> bool {
let (x1, y1) = self.sin_cos();
let (x2, y2) = other.sin_cos();
let point_1 = Vector2::new(real::$to_real(x1), real::$to_real(y1));
let point_2 = Vector2::new(real::$to_real(x2), real::$to_real(y2));
point_1.distance_to(point_2).is_zero_approx()
} The rest should be identical with just some renaming (mainly |
I think it's OK. Maybe a short doc that appears in IDEs helps: /// Godot sign; returns 0 for input 0.
///
/// See also [`signum`][Self::signum], which always returns -1 or +1 (or NaN).
fn sign(self) -> Self { Is Godot's "return 1 for NaN" a feature? It looks like a bug for me, one that our previous implementation also had: the Either way, this is completely unintuitive -- we should return NaN in that case, too. The
It's probably fine.
Thanks a lot for the side-by-side! Changes look good, comments about For the future, please keep refactoring/API changes and semantics in separate commits (at least when easily possible), that allows to track such changes better 🙂 |
seems godot somewhat agrees godotengine/godot#79036
Honestly i somewhat disagree. yes i know the precedence of
oki |
Regarding other refactoring, only thing i can really think of would be to create a like |
7ca49a3
to
e2e1b6f
Compare
Yep, we can always think about other abstractions :) but also, in many cases, polymorphism may not always be needed -- it's also OK if the same methods exist for different types without having an underlying trait. There are some remaining uses of |
oh, yeah it should be. i guess i forgot to run check locally. |
- Add `impl_float_vector_component_fns` macro for float-vectors
e2e1b6f
to
85a8c0e
Compare
Adds an extension trait
FloatExt
that implements the various utility methods we have directly onf32
andf64
.This is implemented for both
f64
andf32
instead of justreal
to make it easier to use them everywhere. Since godotfloat
values are alwaysf64
andreal
may be eitherf32
orf64
depending on configuration.Also moves a bunch of methods in
Vector2
andVector3
that used these methods into a macro, as well as theirApproxEq
impls. And used that macro to implement those methods forVector2
,Vector3
andVector4
. (Vector4
in godot doesn't actually contain the bezier functions but i figured it's fine to add them.)Also split up the tests for eq_approx for floats into f32 and f64 variants, which also makes it so we dont need to use
cfg
in the one test.labelled QOL despite this technically adding a couple of functions to
Vector4
, since it's mainly just about improving ergonomics of float functions.