Replace Handle<AnimationGraph> component with a wrapper (#15742)

# Objective

- Closes #15717 

## Solution

- Wrap the handle in a new wrapper component: `AnimationGraphHandle`.

## Testing

Searched for all instances of `AnimationGraph` in the examples and
updated and tested those

## Migration Guide

`Handle<AnimationGraph>` is no longer a component. Instead, use the
`AnimationGraphHandle` component which contains a
`Handle<AnimationGraph>`.
This commit is contained in:
Tim 2024-10-08 22:41:24 +00:00 committed by GitHub
parent 01b37d67fc
commit 700123ec64
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 50 additions and 20 deletions

View File

@ -7,11 +7,14 @@ use std::io::{self, Write};
use bevy_asset::{ use bevy_asset::{
io::Reader, Asset, AssetEvent, AssetId, AssetLoader, AssetPath, Assets, Handle, LoadContext, io::Reader, Asset, AssetEvent, AssetId, AssetLoader, AssetPath, Assets, Handle, LoadContext,
}; };
use bevy_derive::{Deref, DerefMut};
use bevy_ecs::{ use bevy_ecs::{
component::Component,
event::EventReader, event::EventReader,
reflect::ReflectComponent,
system::{Res, ResMut, Resource}, system::{Res, ResMut, Resource},
}; };
use bevy_reflect::{Reflect, ReflectSerialize}; use bevy_reflect::{prelude::ReflectDefault, Reflect, ReflectSerialize};
use bevy_utils::HashMap; use bevy_utils::HashMap;
use petgraph::{ use petgraph::{
graph::{DiGraph, NodeIndex}, graph::{DiGraph, NodeIndex},
@ -122,6 +125,29 @@ pub struct AnimationGraph {
pub mask_groups: HashMap<AnimationTargetId, AnimationMask>, pub mask_groups: HashMap<AnimationTargetId, AnimationMask>,
} }
/// A [`Handle`] to the [`AnimationGraph`] to be used by the [`AnimationPlayer`](crate::AnimationPlayer) on the same entity.
#[derive(Component, Clone, Debug, Default, Deref, DerefMut, Reflect, PartialEq, Eq)]
#[reflect(Component, Default)]
pub struct AnimationGraphHandle(pub Handle<AnimationGraph>);
impl From<Handle<AnimationGraph>> for AnimationGraphHandle {
fn from(handle: Handle<AnimationGraph>) -> Self {
Self(handle)
}
}
impl From<AnimationGraphHandle> for AssetId<AnimationGraph> {
fn from(handle: AnimationGraphHandle) -> Self {
handle.id()
}
}
impl From<&AnimationGraphHandle> for AssetId<AnimationGraph> {
fn from(handle: &AnimationGraphHandle) -> Self {
handle.id()
}
}
/// A type alias for the `petgraph` data structure that defines the animation /// A type alias for the `petgraph` data structure that defines the animation
/// graph. /// graph.
pub type AnimationDiGraph = DiGraph<AnimationGraphNode, (), u32>; pub type AnimationDiGraph = DiGraph<AnimationGraphNode, (), u32>;

View File

@ -28,10 +28,10 @@ use core::{
use graph::AnimationNodeType; use graph::AnimationNodeType;
use prelude::AnimationCurveEvaluator; use prelude::AnimationCurveEvaluator;
use crate::graph::ThreadedAnimationGraphs; use crate::graph::{AnimationGraphHandle, ThreadedAnimationGraphs};
use bevy_app::{App, Plugin, PostUpdate}; use bevy_app::{App, Plugin, PostUpdate};
use bevy_asset::{Asset, AssetApp, Assets, Handle}; use bevy_asset::{Asset, AssetApp, Assets};
use bevy_core::Name; use bevy_core::Name;
use bevy_ecs::{ use bevy_ecs::{
entity::{VisitEntities, VisitEntitiesMut}, entity::{VisitEntities, VisitEntitiesMut},
@ -942,7 +942,7 @@ fn trigger_untargeted_animation_events(
mut commands: Commands, mut commands: Commands,
clips: Res<Assets<AnimationClip>>, clips: Res<Assets<AnimationClip>>,
graphs: Res<Assets<AnimationGraph>>, graphs: Res<Assets<AnimationGraph>>,
players: Query<(Entity, &AnimationPlayer, &Handle<AnimationGraph>)>, players: Query<(Entity, &AnimationPlayer, &AnimationGraphHandle)>,
) { ) {
for (entity, player, graph_id) in &players { for (entity, player, graph_id) in &players {
// The graph might not have loaded yet. Safely bail. // The graph might not have loaded yet. Safely bail.
@ -989,7 +989,7 @@ pub fn advance_animations(
time: Res<Time>, time: Res<Time>,
animation_clips: Res<Assets<AnimationClip>>, animation_clips: Res<Assets<AnimationClip>>,
animation_graphs: Res<Assets<AnimationGraph>>, animation_graphs: Res<Assets<AnimationGraph>>,
mut players: Query<(&mut AnimationPlayer, &Handle<AnimationGraph>)>, mut players: Query<(&mut AnimationPlayer, &AnimationGraphHandle)>,
) { ) {
let delta_seconds = time.delta_seconds(); let delta_seconds = time.delta_seconds();
players players
@ -1030,7 +1030,7 @@ pub type AnimationEntityMut<'w> = EntityMutExcept<
AnimationTarget, AnimationTarget,
Transform, Transform,
AnimationPlayer, AnimationPlayer,
Handle<AnimationGraph>, AnimationGraphHandle,
), ),
>; >;
@ -1041,7 +1041,7 @@ pub fn animate_targets(
clips: Res<Assets<AnimationClip>>, clips: Res<Assets<AnimationClip>>,
graphs: Res<Assets<AnimationGraph>>, graphs: Res<Assets<AnimationGraph>>,
threaded_animation_graphs: Res<ThreadedAnimationGraphs>, threaded_animation_graphs: Res<ThreadedAnimationGraphs>,
players: Query<(&AnimationPlayer, &Handle<AnimationGraph>)>, players: Query<(&AnimationPlayer, &AnimationGraphHandle)>,
mut targets: Query<( mut targets: Query<(
Entity, Entity,
&AnimationTarget, &AnimationTarget,

View File

@ -18,7 +18,7 @@ use crate::{graph::AnimationNodeIndex, ActiveAnimation, AnimationPlayer};
/// between animations. /// between animations.
/// ///
/// To use this component, place it on the same entity as the /// To use this component, place it on the same entity as the
/// [`AnimationPlayer`] and [`bevy_asset::Handle<AnimationGraph>`]. It'll take /// [`AnimationPlayer`] and [`AnimationGraphHandle`](crate::AnimationGraphHandle). It'll take
/// responsibility for adjusting the weight on the [`ActiveAnimation`] in order /// responsibility for adjusting the weight on the [`ActiveAnimation`] in order
/// to fade out animations smoothly. /// to fade out animations smoothly.
/// ///

View File

@ -522,12 +522,12 @@ impl FromWorld for ExampleAssets {
fn play_animations( fn play_animations(
mut commands: Commands, mut commands: Commands,
assets: Res<ExampleAssets>, assets: Res<ExampleAssets>,
mut players: Query<(Entity, &mut AnimationPlayer), Without<Handle<AnimationGraph>>>, mut players: Query<(Entity, &mut AnimationPlayer), Without<AnimationGraphHandle>>,
) { ) {
for (entity, mut player) in players.iter_mut() { for (entity, mut player) in players.iter_mut() {
commands commands
.entity(entity) .entity(entity)
.insert(assets.fox_animation_graph.clone()); .insert(AnimationGraphHandle(assets.fox_animation_graph.clone()));
player.play(assets.fox_animation_node).repeat(); player.play(assets.fox_animation_node).repeat();
} }
} }

View File

@ -172,7 +172,7 @@ fn setup_scene_once_loaded(
commands commands
.entity(entity) .entity(entity)
.insert(animations.graph.clone()) .insert(AnimationGraphHandle(animations.graph.clone()))
.insert(transitions); .insert(transitions);
} }
} }

View File

@ -138,7 +138,7 @@ fn setup(
MeshMaterial3d(materials.add(Color::srgb(0.8, 0.7, 0.6))), MeshMaterial3d(materials.add(Color::srgb(0.8, 0.7, 0.6))),
// Add the animation graph and player // Add the animation graph and player
planet, planet,
graphs.add(graph), AnimationGraphHandle(graphs.add(graph)),
player, player,
)) ))
.id(); .id();

View File

@ -165,7 +165,7 @@ fn setup(
..default() ..default()
}) })
.insert(animation_player) .insert(animation_player)
.insert(animation_graph) .insert(AnimationGraphHandle(animation_graph))
.with_children(|builder| { .with_children(|builder| {
// Build the text node. // Build the text node.
let player = builder.parent_entity(); let player = builder.parent_entity();

View File

@ -108,7 +108,7 @@ fn setup(
let mut player = AnimationPlayer::default(); let mut player = AnimationPlayer::default();
player.play(animation_index).repeat(); player.play(animation_index).repeat();
commands.spawn((graphs.add(graph), player)); commands.spawn((AnimationGraphHandle(graphs.add(graph)), player));
} }
// Slowly fade out the text opacity. // Slowly fade out the text opacity.

View File

@ -392,7 +392,7 @@ fn init_animations(
for (entity, mut player) in query.iter_mut() { for (entity, mut player) in query.iter_mut() {
commands.entity(entity).insert(( commands.entity(entity).insert((
animation_graph.0.clone(), AnimationGraphHandle(animation_graph.0.clone()),
ExampleAnimationWeights::default(), ExampleAnimationWeights::default(),
)); ));
for &node_index in &CLIP_NODE_INDICES { for &node_index in &CLIP_NODE_INDICES {

View File

@ -411,7 +411,9 @@ fn setup_animation_graph_once_loaded(
// We're doing constructing the animation graph. Add it as an asset. // We're doing constructing the animation graph. Add it as an asset.
let animation_graph = animation_graphs.add(animation_graph); let animation_graph = animation_graphs.add(animation_graph);
commands.entity(entity).insert(animation_graph); commands
.entity(entity)
.insert(AnimationGraphHandle(animation_graph));
// Remove animation targets that aren't in any of the mask groups. If we // Remove animation targets that aren't in any of the mask groups. If we
// don't do that, those bones will play all animations at once, which is // don't do that, those bones will play all animations at once, which is
@ -436,7 +438,7 @@ fn setup_animation_graph_once_loaded(
// off. // off.
fn handle_button_toggles( fn handle_button_toggles(
mut interactions: Query<(&Interaction, &mut AnimationControl), Changed<Interaction>>, mut interactions: Query<(&Interaction, &mut AnimationControl), Changed<Interaction>>,
mut animation_players: Query<&Handle<AnimationGraph>, With<AnimationPlayer>>, mut animation_players: Query<&AnimationGraphHandle, With<AnimationPlayer>>,
mut animation_graphs: ResMut<Assets<AnimationGraph>>, mut animation_graphs: ResMut<Assets<AnimationGraph>>,
mut animation_nodes: Option<ResMut<AnimationNodes>>, mut animation_nodes: Option<ResMut<AnimationNodes>>,
mut app_state: ResMut<AppState>, mut app_state: ResMut<AppState>,

View File

@ -77,7 +77,9 @@ fn setup_animations(
} }
let (graph, animation) = AnimationGraph::from_clip(morph_data.the_wave.clone()); let (graph, animation) = AnimationGraph::from_clip(morph_data.the_wave.clone());
commands.entity(entity).insert(graphs.add(graph)); commands
.entity(entity)
.insert(AnimationGraphHandle(graphs.add(graph)));
player.play(animation).repeat(); player.play(animation).repeat();
*has_setup = true; *has_setup = true;

View File

@ -239,7 +239,7 @@ fn setup_scene_once_loaded(
for (entity, mut player) in &mut player { for (entity, mut player) in &mut player {
commands commands
.entity(entity) .entity(entity)
.insert(animations.graph.clone()) .insert(AnimationGraphHandle(animations.graph.clone()))
.insert(AnimationTransitions::new()); .insert(AnimationTransitions::new());
let playing_animation = player.play(animations.node_indices[0]).repeat(); let playing_animation = player.play(animations.node_indices[0]).repeat();

View File

@ -145,7 +145,7 @@ fn assign_clips(
commands commands
.entity(player_entity) .entity(player_entity)
.insert(animations) .insert(animations)
.insert(graph); .insert(AnimationGraphHandle(graph));
} }
} }