use bevy::{
color::Color,
ecs::{
component::Component,
entity::Entity,
event::{Event, EventReader},
hierarchy::ChildOf,
query::{With, Without},
system::{Commands, Query},
},
gizmos::{config::GizmoConfigGroup, gizmos::Gizmos},
math::{Isometry2d, Vec3Swizzles},
prelude::Visibility,
reflect::Reflect,
transform::components::{GlobalTransform, Transform},
};
use ghx_grid::cartesian::coordinates::CartesianPosition;
use super::{
get_translation_from_grid_pos_3d,
view::{DebugGridView, DebugGridView2d, DebugGridView3d},
};
#[derive(Event)]
pub enum MarkerDespawnEvent {
Marker(Entity),
Grid(Entity),
All,
}
#[derive(Component)]
pub struct GridMarker {
pub color: Color,
pub pos: CartesianPosition,
}
impl GridMarker {
pub fn new(color: Color, pos: CartesianPosition) -> Self {
Self { color, pos }
}
}
#[derive(Default, Reflect, GizmoConfigGroup)]
pub struct MarkersGroup;
pub fn spawn_marker(
commands: &mut Commands,
grid_entity: Entity,
color: Color,
pos: CartesianPosition,
) -> Entity {
let marker_entity = commands.spawn(GridMarker { color, pos }).id();
commands.entity(grid_entity).add_child(marker_entity);
marker_entity
}
pub fn despawn_debug_markers(
mut commands: Commands,
mut marker_events: EventReader<MarkerDespawnEvent>,
markers: Query<(&ChildOf, Entity), With<GridMarker>>,
) {
for marker_event in marker_events.read() {
match marker_event {
MarkerDespawnEvent::Marker(marker_entity) => {
if let Ok(_) = markers.get(*marker_entity) {
commands.entity(*marker_entity).despawn();
}
}
MarkerDespawnEvent::Grid(grid_entity) => {
for (parent_grid, marker_entity) in markers.iter() {
if parent_grid.parent() == *grid_entity {
if let Ok(_) = markers.get(marker_entity) {
commands.entity(marker_entity).despawn();
}
}
}
}
MarkerDespawnEvent::All => {
for (_parent_grid, marker_entity) in markers.iter() {
if let Ok(_) = markers.get(marker_entity) {
commands.entity(marker_entity).despawn();
}
}
}
}
}
}
pub fn insert_transform_on_new_markers(
mut commands: Commands,
debug_grid_views: Query<&DebugGridView>,
mut new_markers: Query<(&ChildOf, Entity, &GridMarker), Without<Transform>>,
) {
for (grid_entity, marker_entity, marker) in &mut new_markers {
if let Ok(view) = debug_grid_views.get(grid_entity.parent()) {
let marker_translation = get_translation_from_grid_pos_3d(&marker.pos, &view.node_size);
commands.entity(marker_entity).try_insert((
Transform::from_translation(marker_translation),
Visibility::default(),
));
}
}
}
pub fn draw_debug_markers_3d(
mut gizmos: Gizmos,
debug_grid_views: Query<&DebugGridView, With<DebugGridView3d>>,
markers: Query<(&ChildOf, &GlobalTransform, &GridMarker)>,
) {
for (parent_grid, global_transform, marker) in markers.iter() {
if let Ok(view) = debug_grid_views.get(parent_grid.parent()) {
if !view.display_markers {
continue;
}
gizmos.cuboid(
Transform::from(*global_transform).with_scale(view.node_size * 1.05),
marker.color,
);
}
}
}
pub fn draw_debug_markers_2d(
mut gizmos: Gizmos,
debug_grid_views: Query<&DebugGridView, With<DebugGridView2d>>,
markers: Query<(&ChildOf, &GlobalTransform, &GridMarker)>,
) {
for (parent_grid, global_transform, marker) in markers.iter() {
if let Ok(view) = debug_grid_views.get(parent_grid.parent()) {
if !view.display_markers {
continue;
}
let node_size = view.node_size.xy();
let (_scale, rot, translation) = global_transform.to_scale_rotation_translation();
gizmos.rect_2d(
Isometry2d::new(translation.xy(), rot.to_axis_angle().1.into()),
node_size * 1.05,
marker.color,
);
}
}
}