use gizmo_core::query::{Query, Mut};
use gizmo_core::system::Res;
use gizmo_core::Time;
use gizmo_core::component::{Children, EntityName};
use gizmo_core::entity::Entity;
use gizmo_core::world::Entities;
use gizmo_physics_core::Transform;
use crate::player::AnimationPlayer;
use crate::clip::InterpolatedValue;
pub fn animation_system(
time: Res<Time>,
entities: Res<Entities>,
mut commands: gizmo_core::Commands,
mut players: Query<Mut<AnimationPlayer>>,
names: Query<&EntityName>,
children: Query<&Children>,
transforms: Query<(Mut<Transform>, gizmo_core::query::With<crate::player::Animated>)>,
) {
let dt = time.dt();
for (root_id, mut player) in players.iter_mut() {
if !player.playing {
continue;
}
let clip = match &player.clip {
Some(c) => c.clone(),
None => continue,
};
player.elapsed_time += dt * player.speed;
let duration = clip.duration();
if player.looping {
if duration > 0.0 {
player.elapsed_time %= duration;
}
} else if player.elapsed_time > duration {
player.elapsed_time = duration;
player.playing = false;
}
if player.target_entities.is_empty() && !clip.tracks.is_empty() {
let mut stack = vec![root_id];
while let Some(current) = stack.pop() {
if let Some(name) = names.get(current) {
for track in &clip.tracks {
if track.target_name == name.0 {
let gen = {
let state = entities.state.lock().unwrap();
state.generations[current as usize]
};
let entity = Entity::new(current, gen);
player.target_entities.insert(name.0.clone(), entity);
commands.entity(entity).insert(crate::player::Animated);
}
}
}
if let Some(child_comp) = children.get(current) {
for &child in &child_comp.0 {
stack.push(child);
}
}
}
}
for track in &clip.tracks {
if let Some(&target_entity) = player.target_entities.get(&track.target_name) {
if !entities.is_alive(target_entity) {
continue;
}
let target_id = target_entity.id();
let interpolated = track.sample(player.elapsed_time);
if let Some((mut transform, _)) = transforms.get_mut(target_id) {
match interpolated {
InterpolatedValue::Translation(v) => {
transform.position = v;
}
InterpolatedValue::Rotation(q) => {
transform.rotation = q;
}
InterpolatedValue::Scale(s) => {
transform.scale = s;
}
InterpolatedValue::None => {}
}
}
}
}
}
}