1use bevy_app::{Plugin, PostUpdate};
4use bevy_color::{Color, Oklcha};
5use bevy_ecs::{
6 component::Component,
7 entity::Entity,
8 query::Without,
9 reflect::ReflectComponent,
10 schedule::IntoScheduleConfigs,
11 system::{Query, Res},
12};
13use bevy_reflect::{std_traits::ReflectDefault, Reflect};
14use bevy_render::primitives::Aabb;
15use bevy_transform::{
16 components::{GlobalTransform, Transform},
17 TransformSystem,
18};
19
20use crate::{
21 config::{GizmoConfigGroup, GizmoConfigStore},
22 gizmos::Gizmos,
23 AppGizmoBuilder,
24};
25
26pub struct AabbGizmoPlugin;
28
29impl Plugin for AabbGizmoPlugin {
30 fn build(&self, app: &mut bevy_app::App) {
31 app.register_type::<AabbGizmoConfigGroup>()
32 .init_gizmo_group::<AabbGizmoConfigGroup>()
33 .add_systems(
34 PostUpdate,
35 (
36 draw_aabbs,
37 draw_all_aabbs.run_if(|config: Res<GizmoConfigStore>| {
38 config.config::<AabbGizmoConfigGroup>().1.draw_all
39 }),
40 )
41 .after(bevy_render::view::VisibilitySystems::CalculateBounds)
42 .after(TransformSystem::TransformPropagate),
43 );
44 }
45}
46#[derive(Clone, Default, Reflect, GizmoConfigGroup)]
48#[reflect(Clone, Default)]
49pub struct AabbGizmoConfigGroup {
50 pub draw_all: bool,
56 pub default_color: Option<Color>,
62}
63
64#[derive(Component, Reflect, Default, Debug)]
66#[reflect(Component, Default, Debug)]
67pub struct ShowAabbGizmo {
68 pub color: Option<Color>,
72}
73
74fn draw_aabbs(
75 query: Query<(Entity, &Aabb, &GlobalTransform, &ShowAabbGizmo)>,
76 mut gizmos: Gizmos<AabbGizmoConfigGroup>,
77) {
78 for (entity, &aabb, &transform, gizmo) in &query {
79 let color = gizmo
80 .color
81 .or(gizmos.config_ext.default_color)
82 .unwrap_or_else(|| color_from_entity(entity));
83 gizmos.cuboid(aabb_transform(aabb, transform), color);
84 }
85}
86
87fn draw_all_aabbs(
88 query: Query<(Entity, &Aabb, &GlobalTransform), Without<ShowAabbGizmo>>,
89 mut gizmos: Gizmos<AabbGizmoConfigGroup>,
90) {
91 for (entity, &aabb, &transform) in &query {
92 let color = gizmos
93 .config_ext
94 .default_color
95 .unwrap_or_else(|| color_from_entity(entity));
96 gizmos.cuboid(aabb_transform(aabb, transform), color);
97 }
98}
99
100fn color_from_entity(entity: Entity) -> Color {
101 Oklcha::sequential_dispersed(entity.index()).into()
102}
103
104fn aabb_transform(aabb: Aabb, transform: GlobalTransform) -> GlobalTransform {
105 transform
106 * GlobalTransform::from(
107 Transform::from_translation(aabb.center.into())
108 .with_scale((aabb.half_extents * 2.).into()),
109 )
110}