69 lines
1.7 KiB
Rust
69 lines
1.7 KiB
Rust
use godot::{
|
|
classes::{PhysicsRayQueryParameters3D, World3D},
|
|
prelude::*,
|
|
};
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
|
|
pub struct NetVector3 {
|
|
pub x: f32,
|
|
pub y: f32,
|
|
pub z: f32,
|
|
}
|
|
|
|
impl From<Vector3> for NetVector3 {
|
|
fn from(value: Vector3) -> Self {
|
|
NetVector3 {
|
|
x: value.x,
|
|
y: value.y,
|
|
z: value.z,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<NetVector3> for Vector3 {
|
|
fn from(value: NetVector3) -> Self {
|
|
Vector3::new(value.x, value.y, value.z)
|
|
}
|
|
}
|
|
|
|
pub fn cast_ray(
|
|
from: Vector3,
|
|
to: Vector3,
|
|
world: Option<Gd<World3D>>,
|
|
exclude: Array<Rid>,
|
|
) -> Option<RaycastResult> {
|
|
let ray = PhysicsRayQueryParameters3D::create(from, to);
|
|
if let Some(mut ray) = ray {
|
|
ray.set_collision_mask(0b111);
|
|
ray.set_hit_back_faces(false);
|
|
ray.set_hit_from_inside(false);
|
|
ray.set_collide_with_bodies(true);
|
|
ray.set_exclude(&exclude);
|
|
if let Some(world) = world
|
|
&& let Some(mut space) = world.get_direct_space_state()
|
|
{
|
|
let results = space.intersect_ray(&ray);
|
|
if let (Some(position), Some(collider)) =
|
|
(results.get("position"), results.get("collider"))
|
|
{
|
|
Some(RaycastResult {
|
|
position: Vector3::from_variant(&position),
|
|
collider: Gd::from_variant(&collider),
|
|
})
|
|
} else {
|
|
None
|
|
}
|
|
} else {
|
|
None
|
|
}
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
|
|
pub struct RaycastResult {
|
|
pub position: Vector3,
|
|
pub collider: Gd<Object>,
|
|
}
|