2024-01-18 15:52:50 +00:00
|
|
|
//! A module adding debug visualization of [`Aabb`]s.
|
|
|
|
|
|
|
|
use crate as bevy_gizmos;
|
|
|
|
|
|
|
|
use bevy_app::{Plugin, PostUpdate};
|
`bevy_color`: Add `sequence_dispersed` to `Hsla`, `Lcha`, `Oklcha` (#12173)
# Objective
- Fixes #12170
## Solution
- Moved the existing `color_from_entity` internals into
`Hsla::sequence_dispersed` which generates a randomly distributed but
deterministic color sequence based.
- Replicated the method for `Lcha` and `Oklcha` as well.
## Examples
### Getting a few colours for a quick palette
```rust
let palette = Hsla::sequence_dispersed().take(5).collect::<Vec<_>>();
/*[
Hsla::hsl(0.0, 1., 0.5),
Hsla::hsl(222.49225, 1., 0.5),
Hsla::hsl(84.984474, 1., 0.5),
Hsla::hsl(307.4767, 1., 0.5),
Hsla::hsl(169.96895, 1., 0.5),
]*/
```
### Getting a colour from an `Entity`
```rust
let color = Oklcha::sequence_dispersed().nth(entity.index() as u32).unwrap();
```
## Notes
This was previously a private function exclusively for `Entity` types.
I've decided it should instead be public and operate on a `u32`
directly, since this function may have broader uses for debugging
purposes.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-02-28 21:45:48 +00:00
|
|
|
use bevy_color::Oklcha;
|
2024-01-18 15:52:50 +00:00
|
|
|
use bevy_ecs::{
|
|
|
|
component::Component,
|
|
|
|
entity::Entity,
|
|
|
|
query::Without,
|
|
|
|
reflect::ReflectComponent,
|
|
|
|
schedule::IntoSystemConfigs,
|
|
|
|
system::{Query, Res},
|
|
|
|
};
|
|
|
|
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
|
2024-02-24 21:35:32 +00:00
|
|
|
use bevy_render::{color::LegacyColor, primitives::Aabb};
|
2024-01-18 15:52:50 +00:00
|
|
|
use bevy_transform::{
|
|
|
|
components::{GlobalTransform, Transform},
|
|
|
|
TransformSystem,
|
|
|
|
};
|
|
|
|
|
|
|
|
use crate::{
|
|
|
|
config::{GizmoConfigGroup, GizmoConfigStore},
|
|
|
|
gizmos::Gizmos,
|
|
|
|
AppGizmoBuilder,
|
|
|
|
};
|
|
|
|
|
|
|
|
/// A [`Plugin`] that provides visualization of [`Aabb`]s for debugging.
|
|
|
|
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),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/// The [`GizmoConfigGroup`] used for debug visualizations of [`Aabb`] components on entities
|
|
|
|
#[derive(Clone, Default, Reflect, GizmoConfigGroup)]
|
|
|
|
pub struct AabbGizmoConfigGroup {
|
|
|
|
/// Draws all bounding boxes in the scene when set to `true`.
|
|
|
|
///
|
|
|
|
/// To draw a specific entity's bounding box, you can add the [`ShowAabbGizmo`] component.
|
|
|
|
///
|
|
|
|
/// Defaults to `false`.
|
|
|
|
pub draw_all: bool,
|
|
|
|
/// The default color for bounding box gizmos.
|
|
|
|
///
|
|
|
|
/// A random color is chosen per box if `None`.
|
|
|
|
///
|
|
|
|
/// Defaults to `None`.
|
2024-02-24 21:35:32 +00:00
|
|
|
pub default_color: Option<LegacyColor>,
|
2024-01-18 15:52:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Add this [`Component`] to an entity to draw its [`Aabb`] component.
|
|
|
|
#[derive(Component, Reflect, Default, Debug)]
|
|
|
|
#[reflect(Component, Default)]
|
|
|
|
pub struct ShowAabbGizmo {
|
|
|
|
/// The color of the box.
|
|
|
|
///
|
|
|
|
/// The default color from the [`AabbGizmoConfigGroup`] config is used if `None`,
|
2024-02-24 21:35:32 +00:00
|
|
|
pub color: Option<LegacyColor>,
|
2024-01-18 15:52:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-02-24 21:35:32 +00:00
|
|
|
fn color_from_entity(entity: Entity) -> LegacyColor {
|
`bevy_color`: Add `sequence_dispersed` to `Hsla`, `Lcha`, `Oklcha` (#12173)
# Objective
- Fixes #12170
## Solution
- Moved the existing `color_from_entity` internals into
`Hsla::sequence_dispersed` which generates a randomly distributed but
deterministic color sequence based.
- Replicated the method for `Lcha` and `Oklcha` as well.
## Examples
### Getting a few colours for a quick palette
```rust
let palette = Hsla::sequence_dispersed().take(5).collect::<Vec<_>>();
/*[
Hsla::hsl(0.0, 1., 0.5),
Hsla::hsl(222.49225, 1., 0.5),
Hsla::hsl(84.984474, 1., 0.5),
Hsla::hsl(307.4767, 1., 0.5),
Hsla::hsl(169.96895, 1., 0.5),
]*/
```
### Getting a colour from an `Entity`
```rust
let color = Oklcha::sequence_dispersed().nth(entity.index() as u32).unwrap();
```
## Notes
This was previously a private function exclusively for `Entity` types.
I've decided it should instead be public and operate on a `u32`
directly, since this function may have broader uses for debugging
purposes.
---------
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2024-02-28 21:45:48 +00:00
|
|
|
Oklcha::sequential_dispersed(entity.index()).into()
|
2024-01-18 15:52:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn aabb_transform(aabb: Aabb, transform: GlobalTransform) -> GlobalTransform {
|
|
|
|
transform
|
|
|
|
* GlobalTransform::from(
|
|
|
|
Transform::from_translation(aabb.center.into())
|
|
|
|
.with_scale((aabb.half_extents * 2.).into()),
|
|
|
|
)
|
|
|
|
}
|