You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
156 lines
5.3 KiB
Rust
156 lines
5.3 KiB
Rust
use crate::editor::prelude::*;
|
|
|
|
#[derive(Debug, Component, Default)]
|
|
pub struct AnimationWidget;
|
|
|
|
#[derive(Debug, Component)]
|
|
pub struct AnimationPlayAll;
|
|
|
|
pub fn init_animations_ui(events: Query<Entity, Added<AnimationWidget>>, 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<AnimationPlayer>>,
|
|
widget: Query<Entity, With<AnimationWidget>>,
|
|
mut commands: Commands,
|
|
gltfs: Res<Assets<Gltf>>,
|
|
clips: Res<Assets<AnimationClip>>,
|
|
) {
|
|
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<Handle<Scene>>,
|
|
current: Query<(Entity, &ui::TargetAsset<AnimationClip>)>,
|
|
clips: Res<Assets<AnimationClip>>,
|
|
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<Entity, (With<Button>, Added<ui::Active>)>,
|
|
mut stop: RemovedComponents<ui::Active>,
|
|
play_all_btn: Query<Entity, With<AnimationPlayAll>>,
|
|
clip_btns: Query<Entity, With<ui::TargetAsset<AnimationClip>>>,
|
|
mut commands: Commands,
|
|
) {
|
|
stop.iter()
|
|
.filter(|&entity| play_all_btn.contains(entity))
|
|
.for_each(|_| {
|
|
clip_btns.iter().for_each(|entity| {
|
|
commands.entity(entity).remove::<ui::Active>();
|
|
})
|
|
});
|
|
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<Entity, (With<Button>, Added<ui::Active>)>,
|
|
mut stop: RemovedComponents<ui::Active>,
|
|
clip_refs: Query<&ui::TargetAsset<AnimationClip>>,
|
|
mut targets: Query<(&mut AnimationPlayer, &Name), With<Transform>>,
|
|
clips: Res<Assets<AnimationClip>>,
|
|
) {
|
|
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();
|
|
}
|
|
})
|
|
}
|
|
});
|
|
}
|