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::{
io::Reader, Asset, AssetEvent, AssetId, AssetLoader, AssetPath, Assets, Handle, LoadContext,
};
use bevy_derive::{Deref, DerefMut};
use bevy_ecs::{
component::Component,
event::EventReader,
reflect::ReflectComponent,
system::{Res, ResMut, Resource},
};
use bevy_reflect::{Reflect, ReflectSerialize};
use bevy_reflect::{prelude::ReflectDefault, Reflect, ReflectSerialize};
use bevy_utils::HashMap;
use petgraph::{
graph::{DiGraph, NodeIndex},
@ -122,6 +125,29 @@ pub struct AnimationGraph {
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
/// graph.
pub type AnimationDiGraph = DiGraph<AnimationGraphNode, (), u32>;

View file

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

View file

@ -18,7 +18,7 @@ use crate::{graph::AnimationNodeIndex, ActiveAnimation, AnimationPlayer};
/// between animations.
///
/// 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
/// to fade out animations smoothly.
///

View file

@ -522,12 +522,12 @@ impl FromWorld for ExampleAssets {
fn play_animations(
mut commands: Commands,
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() {
commands
.entity(entity)
.insert(assets.fox_animation_graph.clone());
.insert(AnimationGraphHandle(assets.fox_animation_graph.clone()));
player.play(assets.fox_animation_node).repeat();
}
}

View file

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

View file

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

View file

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

View file

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

View file

@ -392,7 +392,7 @@ fn init_animations(
for (entity, mut player) in query.iter_mut() {
commands.entity(entity).insert((
animation_graph.0.clone(),
AnimationGraphHandle(animation_graph.0.clone()),
ExampleAnimationWeights::default(),
));
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.
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
// 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.
fn handle_button_toggles(
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_nodes: Option<ResMut<AnimationNodes>>,
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());
commands.entity(entity).insert(graphs.add(graph));
commands
.entity(entity)
.insert(AnimationGraphHandle(graphs.add(graph)));
player.play(animation).repeat();
*has_setup = true;

View file

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

View file

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