use bevy::prelude::*; use std::time::Duration; pub const ALIEN_ASSET_PATH: &str = "models/alien_naked.glb"; #[derive(Resource)] pub struct Animations { pub animations: Vec, pub graph: Handle, } pub fn plugin(app: &mut App) { app.add_systems(Startup, setup); app.add_systems(Update, (setup_once_loaded, toggle_animation)); } fn setup( mut commands: Commands, asset_server: Res, mut graphs: ResMut>, ) { // Build the animation graph let (graph, node_indices) = AnimationGraph::from_clips([ asset_server.load(GltfAssetLabel::Animation(2).from_asset(ALIEN_ASSET_PATH)), asset_server.load(GltfAssetLabel::Animation(1).from_asset(ALIEN_ASSET_PATH)), asset_server.load(GltfAssetLabel::Animation(0).from_asset(ALIEN_ASSET_PATH)), ]); // Insert a resource with the current scene information let graph_handle = graphs.add(graph); commands.insert_resource(Animations { animations: node_indices, graph: graph_handle, }); } fn setup_once_loaded( mut commands: Commands, animations: Res, mut players: Query<(Entity, &mut AnimationPlayer), Added>, ) { for (entity, mut player) in &mut players { let mut transitions = AnimationTransitions::new(); // Make sure to start the animation via the `AnimationTransitions` // component. The `AnimationTransitions` component wants to manage all // the animations and will get confused if the animations are started // directly via the `AnimationPlayer`. transitions .play(&mut player, animations.animations[1], Duration::ZERO) .repeat(); commands .entity(entity) .insert(AnimationGraphHandle(animations.graph.clone())) .insert(transitions); } } fn toggle_animation( animations: Res, mut transitions: Query<(&mut AnimationTransitions, &mut AnimationPlayer)>, keys: Res>, mut animation_index: Local, ) { if keys.just_pressed(KeyCode::KeyT) { for (mut transition, mut player) in &mut transitions { transition .play( &mut player, animations.animations[*animation_index as usize], Duration::from_secs(1), ) .repeat(); } *animation_index ^= 1; // Toggle between 0 and 1 } }