add AnimationPlayer component only on scene roots that are also animation roots (#4417)

# Objective

- Fix #4416 
- The scene has two root nodes, with the second one being the animation root

## Solution

- Check all scene root nodes, and add the `AnimationPlayer` component to nodes that are also animation roots
This commit is contained in:
François 2022-04-05 21:52:00 +00:00
parent 7e3637c36f
commit 30878e3a7d

View File

@ -133,19 +133,21 @@ async fn load_gltf<'a, 'b>(
#[cfg(feature = "bevy_animation")] #[cfg(feature = "bevy_animation")]
let paths = { let paths = {
let mut paths = HashMap::<usize, Vec<Name>>::new(); let mut paths = HashMap::<usize, (usize, Vec<Name>)>::new();
for scene in gltf.scenes() { for scene in gltf.scenes() {
for node in scene.nodes() { for node in scene.nodes() {
paths_recur(node, &[], &mut paths); let root_index = node.index();
paths_recur(node, &[], &mut paths, root_index);
} }
} }
paths paths
}; };
#[cfg(feature = "bevy_animation")] #[cfg(feature = "bevy_animation")]
let (animations, named_animations) = { let (animations, named_animations, animation_roots) = {
let mut animations = vec![]; let mut animations = vec![];
let mut named_animations = HashMap::default(); let mut named_animations = HashMap::default();
let mut animation_roots = HashSet::default();
for animation in gltf.animations() { for animation in gltf.animations() {
let mut animation_clip = AnimationClip::default(); let mut animation_clip = AnimationClip::default();
for channel in animation.channels() { for channel in animation.channels() {
@ -192,7 +194,8 @@ async fn load_gltf<'a, 'b>(
return Err(GltfError::MissingAnimationSampler(animation.index())); return Err(GltfError::MissingAnimationSampler(animation.index()));
}; };
if let Some(path) = paths.get(&node.index()) { if let Some((root_index, path)) = paths.get(&node.index()) {
animation_roots.insert(root_index);
animation_clip.add_curve_to_path( animation_clip.add_curve_to_path(
EntityPath { EntityPath {
parts: path.clone(), parts: path.clone(),
@ -218,7 +221,7 @@ async fn load_gltf<'a, 'b>(
} }
animations.push(handle); animations.push(handle);
} }
(animations, named_animations) (animations, named_animations, animation_roots)
}; };
let mut meshes = vec![]; let mut meshes = vec![];
@ -470,10 +473,16 @@ async fn load_gltf<'a, 'b>(
} }
#[cfg(feature = "bevy_animation")] #[cfg(feature = "bevy_animation")]
if !animations.is_empty() { {
world // for each node root in a scene, check if it's the root of an animation
.entity_mut(*node_index_to_entity_map.get(&0).unwrap()) // if it is, add the AnimationPlayer component
.insert(AnimationPlayer::default()); for node in scene.nodes() {
if animation_roots.contains(&node.index()) {
world
.entity_mut(*node_index_to_entity_map.get(&node.index()).unwrap())
.insert(AnimationPlayer::default());
}
}
} }
for (&entity, &skin_index) in &entity_to_skin_index_map { for (&entity, &skin_index) in &entity_to_skin_index_map {
@ -529,13 +538,18 @@ fn node_name(node: &Node) -> Name {
Name::new(name) Name::new(name)
} }
fn paths_recur(node: Node, current_path: &[Name], paths: &mut HashMap<usize, Vec<Name>>) { fn paths_recur(
node: Node,
current_path: &[Name],
paths: &mut HashMap<usize, (usize, Vec<Name>)>,
root_index: usize,
) {
let mut path = current_path.to_owned(); let mut path = current_path.to_owned();
path.push(node_name(&node)); path.push(node_name(&node));
for child in node.children() { for child in node.children() {
paths_recur(child, &path, paths); paths_recur(child, &path, paths, root_index);
} }
paths.insert(node.index(), path); paths.insert(node.index(), (root_index, path));
} }
/// Loads a glTF texture as a bevy [`Image`] and returns it together with its label. /// Loads a glTF texture as a bevy [`Image`] and returns it together with its label.