Add AnimationGraph::from_clips and simplify animated_fox example (#14853)

# Objective

Add a convenience constructor to make simple animation graphs easier to
build.

I've had some notes about attempting this since #11989 that I just
remembered after seeing #14852.

This partially addresses #14852, but I don't really know animation well
enough to write all of the documentation it's asking for.

## Solution

Add `AnimationGraph::from_clips` and use it to simplify `animated_fox`.

Do some other little bits of incidental cleanup and documentation .

## Testing

I ran `cargo run --example animated_fox`.
This commit is contained in:
Rob Parrett 2024-08-25 07:16:04 -07:00 committed by GitHub
parent 6250698b56
commit 2c3f5a00ac
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 34 additions and 20 deletions

View File

@ -192,6 +192,23 @@ impl AnimationGraph {
(graph, node_index) (graph, node_index)
} }
/// A convenience method to create an [`AnimationGraph`]s with an iterator
/// of clips.
///
/// All of the animation clips will be direct children of the root with
/// weight 1.0.
///
/// Returns the the graph and indices of the new nodes.
pub fn from_clips<'a, I>(clips: I) -> (Self, Vec<AnimationNodeIndex>)
where
I: IntoIterator<Item = Handle<AnimationClip>>,
<I as IntoIterator>::IntoIter: 'a,
{
let mut graph = Self::new();
let indices = graph.add_clips(clips, 1.0, graph.root).collect();
(graph, indices)
}
/// Adds an [`AnimationClip`] to the animation graph with the given weight /// Adds an [`AnimationClip`] to the animation graph with the given weight
/// and returns its index. /// and returns its index.
/// ///

View File

@ -529,7 +529,10 @@ impl ActiveAnimation {
} }
} }
/// Animation controls /// Animation controls.
///
/// Automatically added to any root animations of a `SceneBundle` when it is
/// spawned.
#[derive(Component, Default, Reflect)] #[derive(Component, Default, Reflect)]
#[reflect(Component)] #[reflect(Component)]
pub struct AnimationPlayer { pub struct AnimationPlayer {

View File

@ -9,6 +9,8 @@ use bevy::{
prelude::*, prelude::*,
}; };
const FOX_PATH: &str = "models/animated/Fox.glb";
fn main() { fn main() {
App::new() App::new()
.insert_resource(AmbientLight { .insert_resource(AmbientLight {
@ -37,26 +39,17 @@ fn setup(
mut graphs: ResMut<Assets<AnimationGraph>>, mut graphs: ResMut<Assets<AnimationGraph>>,
) { ) {
// Build the animation graph // Build the animation graph
let mut graph = AnimationGraph::new(); let (graph, node_indices) = AnimationGraph::from_clips([
let animations = graph asset_server.load(GltfAssetLabel::Animation(2).from_asset(FOX_PATH)),
.add_clips( asset_server.load(GltfAssetLabel::Animation(1).from_asset(FOX_PATH)),
[ asset_server.load(GltfAssetLabel::Animation(0).from_asset(FOX_PATH)),
GltfAssetLabel::Animation(2).from_asset("models/animated/Fox.glb"), ]);
GltfAssetLabel::Animation(1).from_asset("models/animated/Fox.glb"),
GltfAssetLabel::Animation(0).from_asset("models/animated/Fox.glb"),
]
.into_iter()
.map(|path| asset_server.load(path)),
1.0,
graph.root,
)
.collect();
// Insert a resource with the current scene information // Insert a resource with the current scene information
let graph = graphs.add(graph); let graph_handle = graphs.add(graph);
commands.insert_resource(Animations { commands.insert_resource(Animations {
animations, animations: node_indices,
graph: graph.clone(), graph: graph_handle,
}); });
// Camera // Camera
@ -91,7 +84,7 @@ fn setup(
// Fox // Fox
commands.spawn(SceneBundle { commands.spawn(SceneBundle {
scene: asset_server.load(GltfAssetLabel::Scene(0).from_asset("models/animated/Fox.glb")), scene: asset_server.load(GltfAssetLabel::Scene(0).from_asset(FOX_PATH)),
..default() ..default()
}); });
@ -104,7 +97,8 @@ fn setup(
println!(" - return: change animation"); println!(" - return: change animation");
} }
// Once the scene is loaded, start the animation // An `AnimationPlayer` is automatically added to the scene when it's ready.
// When the player is added, start the animation.
fn setup_scene_once_loaded( fn setup_scene_once_loaded(
mut commands: Commands, mut commands: Commands,
animations: Res<Animations>, animations: Res<Animations>,