bevy_tnua_physics_integration_layer/spatial_ext.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75
use bevy::prelude::*;
use crate::math::{Float, Vector3};
/// Structured spatial queries.
///
/// Physics integration crates should define a [`SystemParam`](bevy::ecs::system::SystemParam) type
/// and implement this trait on it. The main Tnua crate (or third party crates) can define wrappers
/// (like `TnuaRadarLens`) that can utilize these queries to present helper methods for user code.
pub trait TnuaSpatialExt {
/// The data required to answer queries on a collider.
type ColliderData<'a>
where
Self: 'a;
/// Get the [`ColliderData`](TnuaSpatialExt::ColliderData) from the sytem.
///
/// Since the struct implementing `TnuaSpatialExt` is typically a `SystemParam`, it can use its
/// fields to get that data from the ECS.
fn fetch_collider_data(&self, entity: Entity) -> Option<Self::ColliderData<'_>>;
/// Return the point on the collider that's closest to some external point.
fn project_point(
&self,
point: Vector3,
solid: bool,
collider_data: &Self::ColliderData<'_>,
) -> TnuaPointProjectionResult;
/// Cast a ray on the collider, returning the time-of-impact and the normal.
fn cast_ray(
&self,
origin: Vector3,
direction: Vector3,
max_time_of_impact: Float,
collider_data: &Self::ColliderData<'_>,
) -> Option<(Float, Vector3)>;
/// Check if the physics engine is solving interaction between the two entities.
///
/// If the physics engine is detecting the collision but does not apply forces according to it,
/// this method should return `false`.
fn can_interact(&self, entity1: Entity, entity2: Entity) -> bool;
}
#[derive(Debug, Copy, Clone)]
pub enum TnuaPointProjectionResult {
Outside(Vector3),
Inside(Vector3),
}
impl TnuaPointProjectionResult {
pub fn get(&self) -> Vector3 {
match self {
TnuaPointProjectionResult::Outside(point) => *point,
TnuaPointProjectionResult::Inside(point) => *point,
}
}
pub fn outside(&self) -> Option<Vector3> {
if let Self::Outside(point) = self {
Some(*point)
} else {
None
}
}
pub fn inside(&self) -> Option<Vector3> {
if let Self::Inside(point) = self {
Some(*point)
} else {
None
}
}
}