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
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
//! # Tnua - A Character Controller for Bevy.
//!
//! Tnua ("motion" in Hebrew) is a floating character controller, which means that instead of
//! constantly touching the ground the character floats above it, which makes many aspects of the
//! motion control simpler.
//!
//! Tnua can use [Rapier](https://rapier.rs/) or [Avian](https://github.com/Jondolf/avian), and
//! supports both the 2D and 3D versions of both with integration crates:
//!
//! * For Rapier 2D, add the [bevy-tnua-rapier2d](https://crates.io/crates/bevy-tnua-rapier2d) crate.
//! * For Rapier 3D, add the [bevy-tnua-rapier3d](https://crates.io/crates/bevy-tnua-rapier3d) crate.
//! * For Avian 2D, add the [bevy-tnua-avian2d](https://crates.io/crates/bevy-tnua-avian2d) crate.
//! * For Avian 3D, add the [bevy-tnua-avian3d](https://crates.io/crates/bevy-tnua-avian3d) crate.
//! * Third party integration crates. Such crates should depend on
//! [bevy-tnua-physics-integration-layer](https://crates.io/crates/bevy-tnua-physics-integration-layer)
//! and not the main bevy-tnua crate.
//!
//! Each physics integration crate has basic usage instructions for adding it in its documentation.
//!
//! When using a physics backend with double precision (like Avian with the `f64` flag), the `f64`
//! flag should be added to all the Tnua crates. This applies to double precision data that gets
//! defined by the physics backend - Bevy itself will still use single precision, and this is the
//! precision the position and rotation will use.
//!
//! In addition to the physics integration plugin, the [`TnuaControllerPlugin`] should also be
//! added.
//!
//! Some physics backends support running in different schedules (e.g. `FixedUpdate` to make the
//! simulation deterministic). When using this feature, the physics integration plugin,
//! `TnuaControllerPlugin`, and any other Tnua plugin that supports it must also be registered in
//! that schedule, using their `::new()` method instead of `::default()`.
//!
//! ## Defining the control scheme
//!
//! The range of movement actions available to the character controller is defined by the _control
//! scheme_. The controle scheme is an enum that derives [`TnuaScheme`]. It needs to use an
//! attribute to define the _basis_ - a constant mode of movement that character is always going to
//! be in. Simple games prboably want to use [`TnuaBuiltinWalk`](crate::builtins::TnuaBuiltinWalk),
//! which defines a simple floating character that can be moved around with a simple vector and can
//! be told to face a direcetion.
//!
//! The enum's variants define the actions - various movement commands on top of the basis, like
//! jumping, crouching, climbing, etc. The variants need to be tuple variants, with the action's
//! type as the first tuple member of each variants.
//!
//! ```no_run
//! # use bevy::prelude::*;
//! # use bevy_tnua::prelude::*;
//! #[derive(TnuaScheme)]
//! #[scheme(basis = TnuaBuiltinWalk)]
//! enum ControlScheme {
//! Jump(TnuaBuiltinJump),
//! // more actions can be defined as more variants
//! }
//! ```
//!
//! For more avaialbe attributes, see [the `TnuaScheme` derive macro](bevy_tnua_macros::TnuaScheme)
//! documentation
//!
//! ## Spawning the character controller
//!
//! A Tnua controlled character must have a dynamic rigid body, a [`TnuaConfig`]. The controller is
//! parameterized by the control scheme and needs a configuration (based on the control scheme) as
//! an asset handle:
//! ```no_run
//! # use bevy::prelude::*;
//! # // Not importing from Rapier because there are two versions and the default features does not
//! # // enable either:
//! # #[derive(Component)]
//! # enum RigidBody { Dynamic }
//! # use bevy_tnua::prelude::*;
//! # use bevy_tnua::builtins::{TnuaBuiltinWalkConfig, TnuaBuiltinJumpConfig};
//! # let mut commands: Commands = panic!();
//! # let mut cmd = commands.spawn_empty();
//! # #[derive(TnuaScheme)] #[scheme(basis = TnuaBuiltinWalk)] enum ControlScheme {Jump(TnuaBuiltinJump)}
//! # let control_scheme_configs: Assets<ControlSchemeConfig> = panic!();
//! cmd.insert(RigidBody::Dynamic);
//! cmd.insert(TnuaController::<ControlScheme>::default());
//! cmd.insert(TnuaConfig::<ControlScheme>(
//! // This example creates the configuration by code and injects it to the Assets resource,
//! // but a proper game will probably want to load it from an asset file.
//! control_scheme_configs.add(ControlSchemeConfig {
//! // The basis' configuration is alwayts named `basis`:
//! basis: TnuaBuiltinWalkConfig {
//! // Must be larger than the height of the entity's center from the bottom of its
//! // collider, or else the character will not float and Tnua will not work properly:
//! float_height: 2.0,
//!
//! // TnuaBuiltinWalkConfig has many other fields that can be configured:
//! ..Default::default()
//! },
//! // Actions' configurations are named after the variants defining the actions:
//! jump: TnuaBuiltinJumpConfig {
//! // The full height of the jump, if the player does not release the button:
//! height: 4.0,
//!
//! // TnuaBuiltinJumpConfig too has other fields that can be configured:
//! ..Default::default()
//! },
//! })
//! ));
//! ```
//! Typically though it'd also include a `Collider`.
//!
//! ## Optional But Recommended
//!
//! * Tnua, by default, casts a single ray to the ground. This can be a problem when the character
//! stands on a ledge, because the ray may be past the ledge while the character's collider
//! isn't. To avoid that, use `Tnua<physics-backend>SensorShape` (e.g. - for Rapier 3D, use
//! `TnuaRapier3dSensorShape`) to replace the ray with a shape that resembles the collider. It is
//! better to use a shape a little bit smaller than the collider, so that when the character
//! presses against a wall Tnua won't think it should be lifted up when the casted shape hits
//! that wall.
//! * Tnua will apply forces to keep the character upright, but it is also possible to lock
//! rotation so that there would be no tilting at all. This is done by Tnua itself - it has to be
//! done by the physics engine. Both Rapier and Avian can do it using a component called
//! `LockedAxes`. When using it in 3D in combination of rotation controls (such as
//! [`TnuaBuiltinWalk::desired_forward`](builtins::TnuaBuiltinWalk::desired_forward)) make sure
//! to only lock the X and Z axess, so that Tnua could rotate the character around the Y axis.
//!
//! ## Controlling the Character
//!
//! To control the character, update the [`TnuaController`] by feeding it a [basis](TnuaBasis) and
//! zero or more [actions](TnuaAction). For some of the advanced features to work, the system that
//! does this needs to be placed inside the [`TnuaUserControlsSystems`] system set.
//!
//! ```no_run
//! # use bevy::prelude::*;
//! # use bevy_tnua::prelude::*;
//! # use bevy_tnua::math::Vector3;
//! # #[derive(Component)]
//! # struct PlayerInputComponent;
//! # impl PlayerInputComponent {
//! # fn direction_vector(&self) -> Vector3 { Vector3::ZERO }
//! # fn jump_pressed(&self) -> bool { false }
//! # }
//! # #[derive(TnuaScheme)] #[scheme(basis = TnuaBuiltinWalk)] enum ControlScheme {Jump(TnuaBuiltinJump)}
//! fn player_control_system(mut query: Query<(
//! &mut TnuaController<ControlScheme>,
//! &PlayerInputComponent, // not part of Tnua - defined in user code
//! )>) {
//! for (mut controller, player_input) in query.iter_mut() {
//! controller.basis = TnuaBuiltinWalk {
//! // Move in the direction the player entered:
//! desired_motion: player_input.direction_vector(),
//!
//! // Turn the character in the movement direction:
//! desired_forward: Dir3::new(player_input.direction_vector()).ok(),
//! };
//!
//! if player_input.jump_pressed() {
//! // The jump action must be fed as long as the player holds the button.
//! controller.action(ControlScheme::Jump(Default::default()));
//! }
//! }
//! }
//! ```
//! Refer to the documentation of [`TnuaController`] for more information, but essentially the
//! _basis_ controls the general movement and the _action_ is something special (jump, dash,
//! crouch, etc.)
//!
//! ## Motion Based Animation
//!
//! [`TnuaController`] can also be used to retreive data that can be used to decide which animation
//! to play. A useful helper for that is [`TnuaAnimatingState`].
pub use serde;
pub use ;
pub use ;
pub use ;
pub use TnuaScheme;
pub use ;
pub use TnuaGhostOverwrites;
pub use TnuaSensorsEntities;
pub use *;
pub use *;
use *;
/// The user controls should be applied in this system set.
;