bevy_cef 0.7.0

Bevy CEF integration for web rendering
use bevy::camera::primitives::Aabb;
use bevy::ecs::system::SystemParam;
use bevy::math::{Affine3A, Vec3};
use bevy::prelude::*;

#[derive(SystemParam)]
pub struct MeshAabb<'w, 's> {
    meshes: Query<
        'w,
        's,
        (
            &'static GlobalTransform,
            Option<&'static Aabb>,
            Option<&'static Children>,
        ),
    >,
}

impl MeshAabb<'_, '_> {
    pub fn calculate_local(&self, mesh_root: Entity) -> (Vec3, Vec3) {
        let Ok((root_tf, _, _)) = self.meshes.get(mesh_root) else {
            return (Vec3::splat(f32::INFINITY), Vec3::splat(f32::NEG_INFINITY));
        };
        let root_inv = root_tf.affine().inverse();
        calculate_aabb_with_root_inv(&[mesh_root], true, &self.meshes, &root_inv)
    }
}

fn calculate_aabb_with_root_inv(
    entities: &[Entity],
    include_children: bool,
    entities_query: &Query<(&GlobalTransform, Option<&Aabb>, Option<&Children>)>,
    root_inv: &Affine3A,
) -> (Vec3, Vec3) {
    let combine_bounds = |(a_min, a_max): (Vec3, Vec3), (b_min, b_max): (Vec3, Vec3)| {
        (a_min.min(b_min), a_max.max(b_max))
    };
    let default_bounds = (Vec3::splat(f32::INFINITY), Vec3::splat(f32::NEG_INFINITY));
    entities
        .iter()
        .filter_map(|&entity| {
            entities_query
                .get(entity)
                .map(|(&tf, bounds, children)| {
                    let local_tf = *root_inv * tf.affine();
                    let mut entity_bounds = bounds.map_or(default_bounds, |bounds| {
                        (
                            local_tf.transform_point3(Vec3::from(bounds.min())),
                            local_tf.transform_point3(Vec3::from(bounds.max())),
                        )
                    });
                    if include_children && let Some(children) = children {
                        let children_bounds = calculate_aabb_with_root_inv(
                            children,
                            include_children,
                            entities_query,
                            root_inv,
                        );
                        entity_bounds = combine_bounds(entity_bounds, children_bounds);
                    }
                    entity_bounds
                })
                .ok()
        })
        .fold(default_bounds, combine_bounds)
}