morph_targets/
morph_targets.rs1use bevy::{prelude::*, scene::SceneInstanceReady};
6use std::f32::consts::PI;
7
8const GLTF_PATH: &str = "models/animated/MorphStressTest.gltf";
9
10fn main() {
11 App::new()
12 .add_plugins(DefaultPlugins)
13 .insert_resource(AmbientLight {
14 brightness: 150.0,
15 ..default()
16 })
17 .add_systems(Startup, setup)
18 .add_systems(Update, name_morphs)
19 .run();
20}
21
22#[derive(Component)]
23struct AnimationToPlay {
24 graph_handle: Handle<AnimationGraph>,
25 index: AnimationNodeIndex,
26}
27
28fn setup(
29 mut commands: Commands,
30 asset_server: Res<AssetServer>,
31 mut graphs: ResMut<Assets<AnimationGraph>>,
32) {
33 let (graph, index) = AnimationGraph::from_clip(
34 asset_server.load(GltfAssetLabel::Animation(2).from_asset(GLTF_PATH)),
35 );
36
37 commands
38 .spawn((
39 AnimationToPlay {
40 graph_handle: graphs.add(graph),
41 index,
42 },
43 SceneRoot(asset_server.load(GltfAssetLabel::Scene(0).from_asset(GLTF_PATH))),
44 ))
45 .observe(play_animation_when_ready);
46
47 commands.spawn((
48 DirectionalLight::default(),
49 Transform::from_rotation(Quat::from_rotation_z(PI / 2.0)),
50 ));
51
52 commands.spawn((
53 Camera3d::default(),
54 Transform::from_xyz(3.0, 2.1, 10.2).looking_at(Vec3::ZERO, Vec3::Y),
55 ));
56}
57
58fn play_animation_when_ready(
59 scene_ready: On<SceneInstanceReady>,
60 mut commands: Commands,
61 children: Query<&Children>,
62 animations_to_play: Query<&AnimationToPlay>,
63 mut players: Query<&mut AnimationPlayer>,
64) {
65 if let Ok(animation_to_play) = animations_to_play.get(scene_ready.entity) {
66 for child in children.iter_descendants(scene_ready.entity) {
67 if let Ok(mut player) = players.get_mut(child) {
68 player.play(animation_to_play.index).repeat();
69
70 commands
71 .entity(child)
72 .insert(AnimationGraphHandle(animation_to_play.graph_handle.clone()));
73 }
74 }
75 }
76}
77
78fn name_morphs(
81 asset_server: Res<AssetServer>,
82 mut events: MessageReader<AssetEvent<Mesh>>,
83 meshes: Res<Assets<Mesh>>,
84) {
85 for event in events.read() {
86 if let AssetEvent::<Mesh>::Added { id } = event
87 && let Some(path) = asset_server.get_path(*id)
88 && let Some(mesh) = meshes.get(*id)
89 && let Some(names) = mesh.morph_target_names()
90 {
91 info!("Morph target names for {path:?}:");
92
93 for name in names {
94 info!(" {name}");
95 }
96 }
97 }
98}