docs/bevy/examples/transforms/scale.rs 3.3 K · 95 lines · raw · history

1 //! Illustrates how to scale an object in each direction.
2
3 use std::f32::consts::PI;
4
5 use bevy::prelude::*;
6
7 // Define a component to keep information for the scaled object.
8 #[derive(Component)]
9 struct Scaling {
10 scale_direction: Vec3,
11 scale_speed: f32,
12 max_element_size: f32,
13 min_element_size: f32,
14 }
15
16 // Implement a simple initialization.
17 impl Scaling {
18 fn new() -> Self {
19 Scaling {
20 scale_direction: Vec3::X,
21 scale_speed: 2.0,
22 max_element_size: 5.0,
23 min_element_size: 1.0,
24 }
25 }
26 }
27
28 fn main() {
29 App::new()
30 .add_plugins(DefaultPlugins)
31 .add_systems(Startup, setup)
32 .add_systems(Update, (change_scale_direction, scale_cube))
33 .run();
34 }
35
36 // Startup system to setup the scene and spawn all relevant entities.
37 fn setup(
38 mut commands: Commands,
39 mut meshes: ResMut<Assets<Mesh>>,
40 mut materials: ResMut<Assets<StandardMaterial>>,
41 ) {
42 // Spawn a cube to scale.
43 commands.spawn((
44 Mesh3d(meshes.add(Cuboid::default())),
45 MeshMaterial3d(materials.add(Color::WHITE)),
46 Transform::from_rotation(Quat::from_rotation_y(PI / 4.0)),
47 Scaling::new(),
48 ));
49
50 // Spawn a camera looking at the entities to show what's happening in this example.
51 commands.spawn((
52 Camera3d::default(),
53 Transform::from_xyz(0.0, 10.0, 20.0).looking_at(Vec3::ZERO, Vec3::Y),
54 ));
55
56 // Add a light source for better 3d visibility.
57 commands.spawn((
58 DirectionalLight::default(),
59 Transform::from_xyz(3.0, 3.0, 3.0).looking_at(Vec3::ZERO, Vec3::Y),
60 ));
61 }
62
63 // This system will check if a scaled entity went above or below the entities scaling bounds
64 // and change the direction of the scaling vector.
65 fn change_scale_direction(mut cubes: Query<(&mut Transform, &mut Scaling)>) {
66 for (mut transform, mut cube) in &mut cubes {
67 // If an entity scaled beyond the maximum of its size in any dimension
68 // the scaling vector is flipped so the scaling is gradually reverted.
69 // Additionally, to ensure the condition does not trigger again we floor the elements to
70 // their next full value, which should be max_element_size at max.
71 if transform.scale.max_element() > cube.max_element_size {
72 cube.scale_direction *= -1.0;
73 transform.scale = transform.scale.floor();
74 }
75 // If an entity scaled beyond the minimum of its size in any dimension
76 // the scaling vector is also flipped.
77 // Additionally the Values are ceiled to be min_element_size at least
78 // and the scale direction is flipped.
79 // This way the entity will change the dimension in which it is scaled any time it
80 // reaches its min_element_size.
81 if transform.scale.min_element() < cube.min_element_size {
82 cube.scale_direction *= -1.0;
83 transform.scale = transform.scale.ceil();
84 cube.scale_direction = cube.scale_direction.zxy();
85 }
86 }
87 }
88
89 // This system will scale any entity with assigned Scaling in each direction
90 // by cycling through the directions to scale.
91 fn scale_cube(mut cubes: Query<(&mut Transform, &Scaling)>, timer: Res<Time>) {
92 for (mut transform, cube) in &mut cubes {
93 transform.scale += cube.scale_direction * cube.scale_speed * timer.delta_secs();
94 }
95 }