Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/examples/animation/animated_mesh_control.rs
6592 views
1
//! Plays animations from a skinned glTF.
2
3
use std::{f32::consts::PI, time::Duration};
4
5
use bevy::{animation::RepeatAnimation, light::CascadeShadowConfigBuilder, prelude::*};
6
7
const FOX_PATH: &str = "models/animated/Fox.glb";
8
9
fn main() {
10
App::new()
11
.insert_resource(AmbientLight {
12
color: Color::WHITE,
13
brightness: 2000.,
14
..default()
15
})
16
.add_plugins(DefaultPlugins)
17
.add_systems(Startup, setup)
18
.add_systems(Update, setup_scene_once_loaded)
19
.add_systems(Update, keyboard_control)
20
.run();
21
}
22
23
#[derive(Resource)]
24
struct Animations {
25
animations: Vec<AnimationNodeIndex>,
26
graph_handle: Handle<AnimationGraph>,
27
}
28
29
fn setup(
30
mut commands: Commands,
31
asset_server: Res<AssetServer>,
32
mut meshes: ResMut<Assets<Mesh>>,
33
mut materials: ResMut<Assets<StandardMaterial>>,
34
mut graphs: ResMut<Assets<AnimationGraph>>,
35
) {
36
// Build the animation graph
37
let (graph, node_indices) = AnimationGraph::from_clips([
38
asset_server.load(GltfAssetLabel::Animation(2).from_asset(FOX_PATH)),
39
asset_server.load(GltfAssetLabel::Animation(1).from_asset(FOX_PATH)),
40
asset_server.load(GltfAssetLabel::Animation(0).from_asset(FOX_PATH)),
41
]);
42
43
// Keep our animation graph in a Resource so that it can be inserted onto
44
// the correct entity once the scene actually loads.
45
let graph_handle = graphs.add(graph);
46
commands.insert_resource(Animations {
47
animations: node_indices,
48
graph_handle,
49
});
50
51
// Camera
52
commands.spawn((
53
Camera3d::default(),
54
Transform::from_xyz(100.0, 100.0, 150.0).looking_at(Vec3::new(0.0, 20.0, 0.0), Vec3::Y),
55
));
56
57
// Plane
58
commands.spawn((
59
Mesh3d(meshes.add(Plane3d::default().mesh().size(500000.0, 500000.0))),
60
MeshMaterial3d(materials.add(Color::srgb(0.3, 0.5, 0.3))),
61
));
62
63
// Light
64
commands.spawn((
65
Transform::from_rotation(Quat::from_euler(EulerRot::ZYX, 0.0, 1.0, -PI / 4.)),
66
DirectionalLight {
67
shadows_enabled: true,
68
..default()
69
},
70
CascadeShadowConfigBuilder {
71
first_cascade_far_bound: 200.0,
72
maximum_distance: 400.0,
73
..default()
74
}
75
.build(),
76
));
77
78
// Fox
79
commands.spawn(SceneRoot(
80
asset_server.load(GltfAssetLabel::Scene(0).from_asset(FOX_PATH)),
81
));
82
83
// Instructions
84
85
commands.spawn((
86
Text::new(concat!(
87
"space: play / pause\n",
88
"up / down: playback speed\n",
89
"left / right: seek\n",
90
"1-3: play N times\n",
91
"L: loop forever\n",
92
"return: change animation\n",
93
)),
94
Node {
95
position_type: PositionType::Absolute,
96
top: px(12),
97
left: px(12),
98
..default()
99
},
100
));
101
}
102
103
// An `AnimationPlayer` is automatically added to the scene when it's ready.
104
// When the player is added, start the animation.
105
fn setup_scene_once_loaded(
106
mut commands: Commands,
107
animations: Res<Animations>,
108
mut players: Query<(Entity, &mut AnimationPlayer), Added<AnimationPlayer>>,
109
) {
110
for (entity, mut player) in &mut players {
111
let mut transitions = AnimationTransitions::new();
112
113
// Make sure to start the animation via the `AnimationTransitions`
114
// component. The `AnimationTransitions` component wants to manage all
115
// the animations and will get confused if the animations are started
116
// directly via the `AnimationPlayer`.
117
transitions
118
.play(&mut player, animations.animations[0], Duration::ZERO)
119
.repeat();
120
121
commands
122
.entity(entity)
123
.insert(AnimationGraphHandle(animations.graph_handle.clone()))
124
.insert(transitions);
125
}
126
}
127
128
fn keyboard_control(
129
keyboard_input: Res<ButtonInput<KeyCode>>,
130
mut animation_players: Query<(&mut AnimationPlayer, &mut AnimationTransitions)>,
131
animations: Res<Animations>,
132
mut current_animation: Local<usize>,
133
) {
134
for (mut player, mut transitions) in &mut animation_players {
135
let Some((&playing_animation_index, _)) = player.playing_animations().next() else {
136
continue;
137
};
138
139
if keyboard_input.just_pressed(KeyCode::Space) {
140
let playing_animation = player.animation_mut(playing_animation_index).unwrap();
141
if playing_animation.is_paused() {
142
playing_animation.resume();
143
} else {
144
playing_animation.pause();
145
}
146
}
147
148
if keyboard_input.just_pressed(KeyCode::ArrowUp) {
149
let playing_animation = player.animation_mut(playing_animation_index).unwrap();
150
let speed = playing_animation.speed();
151
playing_animation.set_speed(speed * 1.2);
152
}
153
154
if keyboard_input.just_pressed(KeyCode::ArrowDown) {
155
let playing_animation = player.animation_mut(playing_animation_index).unwrap();
156
let speed = playing_animation.speed();
157
playing_animation.set_speed(speed * 0.8);
158
}
159
160
if keyboard_input.just_pressed(KeyCode::ArrowLeft) {
161
let playing_animation = player.animation_mut(playing_animation_index).unwrap();
162
let elapsed = playing_animation.seek_time();
163
playing_animation.seek_to(elapsed - 0.1);
164
}
165
166
if keyboard_input.just_pressed(KeyCode::ArrowRight) {
167
let playing_animation = player.animation_mut(playing_animation_index).unwrap();
168
let elapsed = playing_animation.seek_time();
169
playing_animation.seek_to(elapsed + 0.1);
170
}
171
172
if keyboard_input.just_pressed(KeyCode::Enter) {
173
*current_animation = (*current_animation + 1) % animations.animations.len();
174
175
transitions
176
.play(
177
&mut player,
178
animations.animations[*current_animation],
179
Duration::from_millis(250),
180
)
181
.repeat();
182
}
183
184
if keyboard_input.just_pressed(KeyCode::Digit1) {
185
let playing_animation = player.animation_mut(playing_animation_index).unwrap();
186
playing_animation
187
.set_repeat(RepeatAnimation::Count(1))
188
.replay();
189
}
190
191
if keyboard_input.just_pressed(KeyCode::Digit2) {
192
let playing_animation = player.animation_mut(playing_animation_index).unwrap();
193
playing_animation
194
.set_repeat(RepeatAnimation::Count(2))
195
.replay();
196
}
197
198
if keyboard_input.just_pressed(KeyCode::Digit3) {
199
let playing_animation = player.animation_mut(playing_animation_index).unwrap();
200
playing_animation
201
.set_repeat(RepeatAnimation::Count(3))
202
.replay();
203
}
204
205
if keyboard_input.just_pressed(KeyCode::KeyL) {
206
let playing_animation = player.animation_mut(playing_animation_index).unwrap();
207
playing_animation.set_repeat(RepeatAnimation::Forever);
208
}
209
}
210
}
211
212