Skip to content

Commit fa8eb0c

Browse files
authored
Try #180:
2 parents cccf247 + c82e566 commit fa8eb0c

File tree

13 files changed

+608
-28
lines changed

13 files changed

+608
-28
lines changed

examples/dodge-the-creeps/rust/src/player.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ impl Area2DVirtual for Player {
5353

5454
fn ready(&mut self) {
5555
let viewport = self.base.get_viewport_rect();
56-
self.screen_size = viewport.size();
56+
self.screen_size = viewport.size;
5757
self.base.hide();
5858
}
5959

godot-core/src/builtin/aabb.rs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*
2+
* This Source Code Form is subject to the terms of the Mozilla Public
3+
* License, v. 2.0. If a copy of the MPL was not distributed with this
4+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
5+
*/
6+
7+
use godot_ffi as sys;
8+
use sys::{ffi_methods, GodotFfi};
9+
10+
use super::Vector3;
11+
12+
/// Axis-aligned bounding box in 3D space.
13+
///
14+
/// `Aabb` consists of a position, a size, and several utility functions. It is typically used for
15+
/// fast overlap tests.
16+
///
17+
/// Currently most methods are only available through [`InnerAabb`](super::inner::InnerAabb).
18+
///
19+
/// The 2D counterpart to `Aabb` is [`Rect2`](super::Rect2).
20+
#[derive(Default, Copy, Clone, PartialEq, Debug)]
21+
#[repr(C)]
22+
pub struct Aabb {
23+
pub position: Vector3,
24+
pub size: Vector3,
25+
}
26+
27+
impl Aabb {
28+
/// Create a new `Aabb` from a position and a size.
29+
///
30+
/// _Godot equivalent: `Aabb(Vector3 position, Vector3 size)`_
31+
#[inline]
32+
pub const fn new(position: Vector3, size: Vector3) -> Self {
33+
Self { position, size }
34+
}
35+
36+
/// The end of the `Aabb` calculated as `position + size`.
37+
///
38+
/// _Godot equivalent: `Aabb.size`_
39+
#[inline]
40+
pub fn end(&self) -> Vector3 {
41+
self.position + self.size
42+
}
43+
44+
/// Set size based on desired end-point.
45+
///
46+
/// _Godot equivalent: `Aabb.size`_
47+
#[inline]
48+
pub fn set_end(&mut self, end: Vector3) {
49+
self.size = end - self.position
50+
}
51+
52+
/// Returns `true` if the two `Aabb`s are approximately equal, by calling `is_equal_approx` on
53+
/// `position` and `size`.
54+
///
55+
/// _Godot equivalent: `Aabb.is_equal_approx()`_
56+
#[inline]
57+
pub fn is_equal_approx(&self, other: &Self) -> bool {
58+
self.position.is_equal_approx(other.position) && self.size.is_equal_approx(other.size)
59+
}
60+
61+
/* Add in when `Aabb::abs()` is implemented.
62+
/// Assert that the size of the `Aabb` is not negative.
63+
///
64+
/// Certain functions will fail to give a correct result if the size is negative.
65+
#[inline]
66+
fn assert_nonnegative(&self) {
67+
assert!(
68+
self.size.x >= 0.0 && self.size.y >= 0.0 && self.size.z >= 0.0,
69+
"Aabb size is negative, this is not supported. Use Aabb.abs() to get an Aabb with a positive size."
70+
);
71+
}
72+
*/
73+
}
74+
75+
impl GodotFfi for Aabb {
76+
ffi_methods! { type sys::GDExtensionTypePtr = *mut Self; .. }
77+
}

godot-core/src/builtin/mod.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
// Re-export macros.
3636
pub use crate::{array, dict, varray};
3737

38+
pub use aabb::*;
3839
pub use array_inner::{Array, VariantArray};
3940
pub use basis::*;
4041
pub use color::*;
@@ -43,8 +44,11 @@ pub use math::*;
4344
pub use node_path::*;
4445
pub use others::*;
4546
pub use packed_array::*;
47+
pub use plane::*;
4648
pub use projection::*;
4749
pub use quaternion::*;
50+
pub use rect2::*;
51+
pub use rect2i::*;
4852
pub use rid::*;
4953
pub use string::*;
5054
pub use string_name::*;
@@ -84,15 +88,19 @@ mod array_inner;
8488
#[path = "dictionary.rs"]
8589
mod dictionary_inner;
8690

91+
mod aabb;
8792
mod basis;
8893
mod color;
8994
mod glam_helpers;
9095
mod math;
9196
mod node_path;
9297
mod others;
9398
mod packed_array;
99+
mod plane;
94100
mod projection;
95101
mod quaternion;
102+
mod rect2;
103+
mod rect2i;
96104
mod rid;
97105
mod string;
98106
mod string_chars;
@@ -318,3 +326,14 @@ macro_rules! real {
318326
f
319327
}};
320328
}
329+
330+
/// The side of a [`Rect2`] or [`Rect2i`].
331+
///
332+
/// _Godot equivalent: `@GlobalScope.Side`_
333+
#[repr(C)]
334+
pub enum RectSide {
335+
Left = 0,
336+
Top = 1,
337+
Right = 2,
338+
Bottom = 3,
339+
}

godot-core/src/builtin/others.rs

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,36 +6,16 @@
66

77
// Stub for various other built-in classes, which are currently incomplete, but whose types
88
// are required for codegen
9-
use crate::builtin::{inner, StringName, Vector2};
9+
use crate::builtin::{inner, StringName};
1010
use crate::obj::{Gd, GodotClass};
1111
use godot_ffi as sys;
1212
use sys::{ffi_methods, GodotFfi};
1313

1414
// TODO: Swap more inner math types with glam types
1515
// Note: ordered by enum ord in extension JSON
16-
impl_builtin_stub!(Rect2, OpaqueRect2);
17-
impl_builtin_stub!(Rect2i, OpaqueRect2i);
18-
impl_builtin_stub!(Plane, OpaquePlane);
19-
impl_builtin_stub!(Aabb, OpaqueAabb);
2016
impl_builtin_stub!(Callable, OpaqueCallable);
2117
impl_builtin_stub!(Signal, OpaqueSignal);
2218

23-
#[repr(C)]
24-
struct InnerRect {
25-
position: Vector2,
26-
size: Vector2,
27-
}
28-
29-
impl Rect2 {
30-
pub fn size(self) -> Vector2 {
31-
self.inner().size
32-
}
33-
34-
fn inner(self) -> InnerRect {
35-
unsafe { std::mem::transmute(self) }
36-
}
37-
}
38-
3919
impl Callable {
4020
pub fn from_object_method<T, S>(object: Gd<T>, method: S) -> Self
4121
where

godot-core/src/builtin/plane.rs

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
/*
2+
* This Source Code Form is subject to the terms of the Mozilla Public
3+
* License, v. 2.0. If a copy of the MPL was not distributed with this
4+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
5+
*/
6+
7+
use std::ops::Neg;
8+
9+
use godot_ffi as sys;
10+
use sys::{ffi_methods, GodotFfi};
11+
12+
use super::{is_equal_approx, real, Vector3};
13+
14+
/// 3D plane in Hessian form: `a*b + b*y + c*z + d = 0`
15+
///
16+
/// Currently most methods are only available through [`InnerPlane`](super::inner::InnerPlane).
17+
///
18+
/// Note: almost all methods on `Plane` require that the `normal` vector have
19+
/// unit length and will panic if this invariant is violated. This is not separately
20+
/// annotated for each method.
21+
#[derive(Copy, Clone, PartialEq, Debug)]
22+
#[repr(C)]
23+
pub struct Plane {
24+
pub normal: Vector3,
25+
pub d: real,
26+
}
27+
28+
impl Plane {
29+
/// Creates a new `Plane` from the `normal` and the distance from the origin `d`.
30+
///
31+
/// # Panics
32+
/// In contrast to construction via `Plane { normal, d }`, this verifies that `normal` has unit length, and will
33+
/// panic if this is not the case.
34+
///
35+
/// _Godot equivalent: `Plane(Vector3 normal, float d)`_
36+
#[inline]
37+
pub fn new(normal: Vector3, d: real) -> Self {
38+
let plane = Self { normal, d };
39+
plane.assert_normalized();
40+
plane
41+
}
42+
43+
/// Create a new `Plane` through the origin from a normal.
44+
///
45+
/// # Panics
46+
/// See [`Self::new()`].
47+
///
48+
/// _Godot equivalent: `Plane(Vector3 normal)`_
49+
#[inline]
50+
pub fn from_normal_at_origin(normal: Vector3) -> Self {
51+
Self::new(normal, 0.0)
52+
}
53+
54+
/// Create a new `Plane` from a normal and a point in the plane.
55+
///
56+
/// # Panics
57+
/// See [`Self::new()`].
58+
///
59+
/// _Godot equivalent: `Plane(Vector3 normal, Vector3 point)`_
60+
#[inline]
61+
pub fn from_point_normal(point: Vector3, normal: Vector3) -> Self {
62+
Self::new(normal, normal.dot(point))
63+
}
64+
65+
/// Creates a new `Plane` from normal and origin distance.
66+
///
67+
/// `a`, `b`, `c` are used for the `normal` vector.
68+
/// `d` is the distance from the origin.
69+
///
70+
/// # Panics
71+
/// See [`Self::new()`].
72+
///
73+
/// _Godot equivalent: `Plane(float a, float b, float c, float d)`_
74+
#[inline]
75+
pub fn from_coordinates(a: real, b: real, c: real, d: real) -> Self {
76+
Self::new(Vector3::new(a, b, c), d)
77+
}
78+
79+
/// Creates a new `Plane` from three points, given in clockwise order.
80+
///
81+
/// # Panics
82+
/// Will panic if all three points are colinear.
83+
///
84+
/// _Godot equivalent: `Plane(Vector3 point1, Vector3 point2, Vector3 point3)`_
85+
#[inline]
86+
pub fn from_points(a: Vector3, b: Vector3, c: Vector3) -> Self {
87+
let normal = (a - c).cross(a - b);
88+
assert!(
89+
normal != Vector3::ZERO,
90+
"The points {a}, {b}, {c} are all colinear"
91+
);
92+
let normal = normal.normalized();
93+
Self {
94+
normal,
95+
d: normal.dot(a),
96+
}
97+
}
98+
99+
/// Returns `true` if the two `Plane`s are approximately equal, by calling `is_equal_approx` on
100+
/// `normal` and `d` or on `-normal` and `-d`.
101+
///
102+
/// _Godot equivalent: `Plane.is_equal_approx()`_
103+
#[inline]
104+
pub fn is_equal_approx(&self, other: &Self) -> bool {
105+
(self.normal.is_equal_approx(other.normal) && is_equal_approx(self.d, other.d))
106+
|| (self.normal.is_equal_approx(-other.normal) && is_equal_approx(self.d, -other.d))
107+
}
108+
109+
#[inline]
110+
fn assert_normalized(self) {
111+
assert!(
112+
self.normal.is_normalized(),
113+
"Plane {:?} -- normal does not have unit length",
114+
self.normal
115+
);
116+
}
117+
}
118+
119+
impl Neg for Plane {
120+
type Output = Plane;
121+
122+
/// Returns the negative value of the plane by flipping both the normal and the distance value. Meaning
123+
/// it creates a plane that is in the same place, but facing the opposite direction.
124+
fn neg(self) -> Self::Output {
125+
Self::new(-self.normal, -self.d)
126+
}
127+
}
128+
129+
impl GodotFfi for Plane {
130+
ffi_methods! { type sys::GDExtensionTypePtr = *mut Self; .. }
131+
}
132+
133+
#[cfg(test)]
134+
mod test {
135+
use super::*;
136+
137+
/// Tests that none of the constructors panic for some simple planes.
138+
#[test]
139+
fn construction_succeeds() {
140+
let vec = Vector3::new(1.0, 2.0, 3.0).normalized();
141+
let Vector3 { x, y, z } = vec;
142+
let _ = Plane::new(vec, 5.0);
143+
let _ = Plane::from_normal_at_origin(vec);
144+
let _ = Plane::from_point_normal(Vector3::new(10.0, 20.0, 30.0), vec);
145+
let _ = Plane::from_coordinates(x, y, z, 5.0);
146+
let _ = Plane::from_points(
147+
Vector3::new(1.0, 2.0, 3.0),
148+
Vector3::new(2.0, 3.0, 1.0),
149+
Vector3::new(3.0, 2.0, 1.0),
150+
);
151+
}
152+
153+
#[test]
154+
#[should_panic]
155+
fn new_unnormalized_panics() {
156+
let _ = Plane::new(Vector3::new(1.0, 2.0, 3.0), 5.0);
157+
}
158+
159+
#[test]
160+
#[should_panic]
161+
fn from_points_colinear_panics() {
162+
let _ = Plane::from_points(
163+
Vector3::new(0.0, 0.0, 0.0),
164+
Vector3::new(0.0, 0.0, 1.0),
165+
Vector3::new(0.0, 0.0, 2.0),
166+
);
167+
}
168+
}

0 commit comments

Comments
 (0)