bevy_vrm1 0.7.1

Allows you to use VRM and VRMA in Bevy
Documentation
use crate::vrm::Vrm;
use crate::vrma::Vrma;
use bevy::ecs::system::SystemParam;
use bevy::prelude::*;

#[derive(SystemParam)]
pub struct ParentSearcher<'w, 's> {
    entities: Query<'w, 's, (Option<&'static ChildOf>, Has<Vrm>, Has<Vrma>)>,
}

impl ParentSearcher<'_, '_> {
    #[inline]
    pub fn find_vrm(
        &self,
        source: Entity,
    ) -> Option<Entity> {
        find_entity(true, source, &self.entities)
    }
}

#[allow(clippy::if_same_then_else)]
fn find_entity(
    require_vrm: bool,
    entity: Entity,
    entities: &Query<(Option<&ChildOf>, Has<Vrm>, Has<Vrma>)>,
) -> Option<Entity> {
    let (child_of, has_vrm, has_vrma) = entities.get(entity).ok()?;

    if require_vrm && has_vrm {
        return Some(entity);
    } else if !require_vrm && has_vrma {
        return Some(entity);
    }
    if let Some(parent) = child_of {
        return find_entity(require_vrm, parent.0, entities);
    }
    None
}

#[cfg(test)]
mod tests {
    use crate::prelude::*;
    use crate::system_param::parent_searcher::ParentSearcher;
    use crate::tests::test_app;
    use bevy_test_helper::system::SystemExt;

    #[test]
    fn test_find_vrm() {
        let mut app = test_app();

        let vrm = app.world_mut().spawn(Vrm).id();
        let child = app.world_mut().spawn_empty().id();
        app.world_mut().commands().entity(vrm).add_child(child);
        app.update();

        let actual = app.run_system_once(move |s: ParentSearcher| s.find_vrm(child));
        assert_eq!(actual, Some(vrm));
    }

    #[test]
    fn test_find_vrm_with_root() {
        let mut app = test_app();

        let root = app.world_mut().spawn_empty().id();
        let vrm = app.world_mut().spawn(Vrm).id();
        app.world_mut().commands().entity(root).add_child(vrm);
        let child = app.world_mut().spawn_empty().id();
        app.world_mut().commands().entity(vrm).add_child(child);
        app.update();

        let actual = app.run_system_once(move |s: ParentSearcher| s.find_vrm(child));
        assert_eq!(actual, Some(vrm));
    }
}