use crate::editor::prelude::*; #[derive(Debug, Component, Default)] pub struct AnimationWidget; #[derive(Debug, Component)] pub struct AnimationPlayAll; pub fn init_animations_ui(events: Query>, mut commands: Commands) { events.iter().for_each(|entity| { commands.entity(entity).with_children(|parent| { parent.spawn(( AnimationPlayAll, ButtonBundle { style: Style { border: UiRect::all(Val::Px(1.0)), margin: UiRect::all(Val::Px(1.0)), padding: UiRect::all(Val::Px(1.0)), ..default() }, border_color: Color::BLACK.into(), ..default() }, ui::Title { text: "Play All".into(), ..default() }, )); }); }) } /// When a new scene is loaded, add any newly compatible animations /// TODO: Add target entity(s) too pub fn add_animations_ui( player_spawned: Query<&Name, Added>, widget: Query>, mut commands: Commands, gltfs: Res>, clips: Res>, ) { player_spawned.iter().for_each(|player_name| { gltfs .iter() .flat_map(|(_, gltf)| gltf.named_animations.iter()) .filter_map(|(clip_name, handle)| { clips.get(&handle).map(|clip| (clip_name, handle, clip)) }) .filter(|(_, _, clip)| clip.compatible_with(player_name)) .for_each(|(clip_name, handle, _)| { create_asset_button( &widget, &mut commands, ui::TargetAsset { handle: handle.clone(), }, clip_name.clone(), None, ); }); }); } // When a scene is de-selected, remove any outdated animation options pub fn remove_animations_ui( mut removed_players: RemovedComponents>, current: Query<(Entity, &ui::TargetAsset)>, clips: Res>, targets: Query<(&AnimationPlayer, &Name)>, mut commands: Commands, ) { // For each removed scene removed_players.iter().for_each(|_| { // Iterate over the current animation buttons current .iter() .filter(|(_, ui::TargetAsset { handle })| { // Check if this clip is compatible with any remaining entities // NOTE: We are checking this is *not* compatible with any entities clips .get(handle) .map(|clip| !(targets.iter().any(|(_, name)| clip.compatible_with(name)))) .unwrap_or(true) }) .for_each(|(_, ui::TargetAsset { handle })| { // Destroy the buton if it is so destroy_asset_button( ¤t, &mut commands, &ui::TargetAsset { handle: handle.clone(), }, ); }); }); } pub fn play_all_animations( start: Query, Added)>, mut stop: RemovedComponents, play_all_btn: Query>, clip_btns: Query>>, mut commands: Commands, ) { stop.iter() .filter(|&entity| play_all_btn.contains(entity)) .for_each(|_| { clip_btns.iter().for_each(|entity| { commands.entity(entity).remove::(); }) }); start .iter() .filter(|&entity| play_all_btn.contains(entity)) .for_each(|_| { clip_btns.iter().for_each(|entity| { commands.entity(entity).insert(ui::Active); }) }); } pub fn play_animation( start: Query, Added)>, mut stop: RemovedComponents, clip_refs: Query<&ui::TargetAsset>, mut targets: Query<(&mut AnimationPlayer, &Name), With>, clips: Res>, ) { stop.iter().for_each(|entity| { if let Ok(ui::TargetAsset { handle }) = clip_refs.get(entity) { let clip = clips.get(&handle).expect("Load animation clip"); targets .iter_mut() .filter(|(_, name)| clip.compatible_with(name)) .for_each(|(mut player, _)| { player.pause(); }) } }); start.iter().for_each(|entity| { if let Ok(ui::TargetAsset { handle }) = clip_refs.get(entity) { let clip = clips.get(&handle).expect("Load animation clip"); targets .iter_mut() .filter(|(_, name)| clip.compatible_with(name)) .for_each(|(mut player, _)| { if player.is_paused() { player.resume(); } else { player.play(handle.clone()).repeat(); } }) } }); }