//! This example demonstrates the implementation and behavior of the axes gizmo. use bevy::{prelude::*, render::primitives::Aabb}; use rand::{Rng, SeedableRng}; use rand_chacha::ChaCha8Rng; use std::f32::consts::PI; const TRANSITION_DURATION: f32 = 2.0; fn main() { App::new() .add_plugins(DefaultPlugins) .add_systems(Startup, setup) .add_systems(Update, (move_cubes, draw_axes).chain()) .run(); } /// The `ShowAxes` component is attached to an entity to get the `draw_axes` system to /// display axes according to its Transform component. #[derive(Component)] struct ShowAxes; /// The `TransformTracking` component keeps track of the data we need to interpolate /// between two transforms in our example. #[derive(Component)] struct TransformTracking { /// The initial transform of the cube during the move initial_transform: Transform, /// The target transform of the cube during the move target_transform: Transform, /// The progress of the cube during the move in seconds progress: f32, } #[derive(Resource)] struct SeededRng(ChaCha8Rng); fn setup( mut commands: Commands, mut meshes: ResMut>, mut materials: ResMut>, ) { // We're seeding the PRNG here to make this example deterministic for testing purposes. // This isn't strictly required in practical use unless you need your app to be deterministic. let mut rng = ChaCha8Rng::seed_from_u64(19878367467713); // Lights... commands.spawn(( PointLight { shadows_enabled: true, ..default() }, Transform::from_xyz(2., 6., 0.), )); // Camera... commands.spawn(Camera3dBundle { transform: Transform::from_xyz(0., 1.5, -8.).looking_at(Vec3::new(0., -0.5, 0.), Vec3::Y), ..default() }); // Action! (Our cubes that are going to move) commands.spawn(( Mesh3d(meshes.add(Cuboid::new(1., 1., 1.))), MeshMaterial3d(materials.add(Color::srgb(0.8, 0.7, 0.6))), ShowAxes, TransformTracking { initial_transform: default(), target_transform: random_transform(&mut rng), progress: 0.0, }, )); commands.spawn(( Mesh3d(meshes.add(Cuboid::new(0.5, 0.5, 0.5))), MeshMaterial3d(materials.add(Color::srgb(0.6, 0.7, 0.8))), ShowAxes, TransformTracking { initial_transform: default(), target_transform: random_transform(&mut rng), progress: 0.0, }, )); // A plane to give a sense of place commands.spawn(( Mesh3d(meshes.add(Plane3d::default().mesh().size(20., 20.))), MeshMaterial3d(materials.add(Color::srgb(0.1, 0.1, 0.1))), Transform::from_xyz(0., -2., 0.), )); commands.insert_resource(SeededRng(rng)); } // This system draws the axes based on the cube's transform, with length based on the size of // the entity's axis-aligned bounding box (AABB). fn draw_axes(mut gizmos: Gizmos, query: Query<(&Transform, &Aabb), With>) { for (&transform, &aabb) in &query { let length = aabb.half_extents.length(); gizmos.axes(transform, length); } } // This system changes the cubes' transforms to interpolate between random transforms fn move_cubes( mut query: Query<(&mut Transform, &mut TransformTracking)>, time: Res