use crate as bevy_gizmos;
use bevy_app::{Plugin, PostUpdate};
use bevy_ecs::{
component::Component,
entity::Entity,
query::Without,
reflect::ReflectComponent,
schedule::IntoSystemConfigs,
system::{Query, Res},
};
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
use bevy_render::{color::Color, primitives::Aabb};
use bevy_transform::{
components::{GlobalTransform, Transform},
TransformSystem,
};
use crate::{
config::{GizmoConfigGroup, GizmoConfigStore},
gizmos::Gizmos,
AppGizmoBuilder,
};
pub struct AabbGizmoPlugin;
impl Plugin for AabbGizmoPlugin {
fn build(&self, app: &mut bevy_app::App) {
app.register_type::<AabbGizmoConfigGroup>()
.init_gizmo_group::<AabbGizmoConfigGroup>()
.add_systems(
PostUpdate,
(
draw_aabbs,
draw_all_aabbs.run_if(|config: Res<GizmoConfigStore>| {
config.config::<AabbGizmoConfigGroup>().1.draw_all
}),
)
.after(TransformSystem::TransformPropagate),
);
}
}
#[derive(Clone, Default, Reflect, GizmoConfigGroup)]
pub struct AabbGizmoConfigGroup {
pub draw_all: bool,
pub default_color: Option<Color>,
}
#[derive(Component, Reflect, Default, Debug)]
#[reflect(Component, Default)]
pub struct ShowAabbGizmo {
pub color: Option<Color>,
}
fn draw_aabbs(
query: Query<(Entity, &Aabb, &GlobalTransform, &ShowAabbGizmo)>,
mut gizmos: Gizmos<AabbGizmoConfigGroup>,
) {
for (entity, &aabb, &transform, gizmo) in &query {
let color = gizmo
.color
.or(gizmos.config_ext.default_color)
.unwrap_or_else(|| color_from_entity(entity));
gizmos.cuboid(aabb_transform(aabb, transform), color);
}
}
fn draw_all_aabbs(
query: Query<(Entity, &Aabb, &GlobalTransform), Without<ShowAabbGizmo>>,
mut gizmos: Gizmos<AabbGizmoConfigGroup>,
) {
for (entity, &aabb, &transform) in &query {
let color = gizmos
.config_ext
.default_color
.unwrap_or_else(|| color_from_entity(entity));
gizmos.cuboid(aabb_transform(aabb, transform), color);
}
}
fn color_from_entity(entity: Entity) -> Color {
let index = entity.index();
const FRAC_U32MAX_GOLDEN_RATIO: u32 = 2654435769; const RATIO_360: f32 = 360.0 / u32::MAX as f32;
let hue = index.wrapping_mul(FRAC_U32MAX_GOLDEN_RATIO) as f32 * RATIO_360;
Color::hsl(hue, 1., 0.5)
}
fn aabb_transform(aabb: Aabb, transform: GlobalTransform) -> GlobalTransform {
transform
* GlobalTransform::from(
Transform::from_translation(aabb.center.into())
.with_scale((aabb.half_extents * 2.).into()),
)
}