bevy_tnua/basis_capabilities.rs
1//! Generic properties of [basis](TnuaBasis) that [actions](crate::TnuaAction) and control helpers
2//! may rely on.
3//!
4//! All the basis capabilities provided by Tnua itself should be in this module, but third party
5//! crates can define their own. Custom capabilities for user code (an actual game that uses Tnua)
6//! are usually redundant, since actions and control helpers defined there can usually just use the
7//! concrete basis.
8//!
9//! Capabilities typically use [`TnuaBasisAccess`] to access the basis, since it provides the
10//! configuration and memory of the basis rather than just the input.
11
12use std::ops::Range;
13
14use bevy_tnua_physics_integration_layer::data_for_backends::{TnuaProximitySensor, TnuaVelChange};
15
16use crate::TnuaBasis;
17use crate::basis_action_traits::TnuaBasisAccess;
18use crate::{TnuaBasisContext, math::*};
19
20/// The character controlled by the basis may stand on the surface of an moving object, and needs
21/// to move together with said object.
22pub trait TnuaBasisWithFrameOfReferenceSurface: TnuaBasis {
23 /// The velocity of the character, relative the what the basis considers its frame of
24 /// reference.
25 ///
26 /// This is a query method, used by the action to determine what the basis thinks.
27 fn effective_velocity(access: &TnuaBasisAccess<Self>) -> Vector3;
28
29 /// The vertical velocity the character requires to stay the same height if it wants to move in
30 /// [`effective_velocity`](Self::effective_velocity).
31 fn vertical_velocity(access: &TnuaBasisAccess<Self>) -> Float;
32}
33
34/// The basis has a specific point the character should be at, which may not be the actual position
35/// in Bevy or in the physics engine.
36///
37/// This typically means the basis is applying forces to get the characeter to that position.
38pub trait TnuaBasisWithDisplacement: TnuaBasis {
39 /// The displacement of the character from where the basis wants it to be.
40 ///
41 /// This is a query method, used by the action to determine what the basis thinks.
42 fn displacement(access: &TnuaBasisAccess<Self>) -> Option<Vector3>;
43}
44
45/// The basis keeps track on the entity the chracter stands on - and whether or not it stands on
46/// something.
47pub trait TnuaBasisWithGround: TnuaBasis {
48 /// Can be queried by an action to determine if the character should be considered "in the air".
49 ///
50 /// This is a query method, used by the action to determine what the basis thinks.
51 fn is_airborne(access: &TnuaBasisAccess<Self>) -> bool;
52
53 /// If the basis is at coyote time - finish the coyote time.
54 ///
55 /// This is typically called by air actions so that a long coyote time will not allow, for
56 /// example, unaccounted air jumps. These actions should invoke this method inside their
57 /// [`influence_basis`](crate::TnuaAction::influence_basis) method.
58 ///
59 /// If the character is fully grounded, this method must not change that.
60 fn violate_coyote_time(memory: &mut Self::Memory);
61
62 /// The sensor used to detect the ground.
63 fn ground_sensor<'a>(sensors: &Self::Sensors<'a>) -> &'a TnuaProximitySensor;
64}
65
66/// The basis can keeps track of the space above the character.
67///
68/// Note that it's possible to opt out of this in the configuration.
69pub trait TnuaBasisWithHeadroom: TnuaBasis {
70 /// The headroom sensor has detected a ceiling above the character's head.
71 ///
72 /// This returns `None` when either no ceiling is deteceted in the sensor's range - or when the
73 /// headroom sensor is not configured.
74 ///
75 /// The start of the returned range is the distance from the center of the character's collider
76 /// to top of the collider. The end of the range is the distance from the center of the
77 /// character's colldier to the detected ceiling.
78 fn headroom_intrusion<'a>(
79 access: &TnuaBasisAccess<Self>,
80 sensors: &Self::Sensors<'a>,
81 ) -> Option<Range<Float>>;
82
83 /// Increase the range of the headroom sensor.
84 fn set_extra_headroom(memory: &mut Self::Memory, extra_headroom: Float);
85}
86
87/// The basis is a floating character controller.
88pub trait TnuaBasisWithFloating: TnuaBasis {
89 /// The height the basis is configured to float at, measured from the ground to the center of
90 /// the character collider.
91 fn float_height(access: &TnuaBasisAccess<Self>) -> Float;
92}
93
94/// The basis applies a spring force.
95pub trait TnuaBasisWithSpring: TnuaBasis {
96 /// Calculate the vertical spring force that this basis would need to apply assuming its
97 /// vertical distance from the vertical distance it needs to be at equals the `spring_offset`
98 /// argument.
99 fn spring_force(
100 access: &TnuaBasisAccess<Self>,
101 ctx: &TnuaBasisContext,
102 spring_offset: Float,
103 ) -> TnuaVelChange;
104}