scale/
scale.rs

1//! Illustrates how to scale an object in each direction.
2
3use std::f32::consts::PI;
4
5use bevy::prelude::*;
6
7// Define a component to keep information for the scaled object.
8#[derive(Component)]
9struct 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.
17impl 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
28fn 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.
37fn 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.
65fn 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.
91fn 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}