bevy_a5 0.1.1

A Bevy plugin providing A5 geospatial pentagonal cells for floating origin use and spatial queries
Documentation
//! Debug rendering helpers for A5 cells.
//!
//! Currently provides [`DrawCellOutline`], a marker component that draws an
//! entity's [`GeoCell`] boundary as gizmo lines every
//! frame. Useful for "where am I?" debugging and for visualising
//! cell-anchored entities without manually building a mesh.

use bevy_color::Color;
use bevy_ecs::component::Component;
use bevy_ecs::prelude::ReflectComponent;
use bevy_ecs::system::{Query, Res};
use bevy_gizmos::prelude::Gizmos;
use bevy_math::Vec3;
use bevy_reflect::Reflect;
use bevy_transform::prelude::GlobalTransform;

use crate::cell::GeoCell;
use crate::geometry::cell_boundary_local;
use crate::planet::PlanetSettings;

/// Marker component: draw this entity's cell boundary every frame.
///
/// Spawn alongside a [`GeoCell`] and a `Transform`. The
/// boundary is drawn in the entity's cell-local frame using `Gizmos`, anchored
/// to the entity's `GlobalTransform` so it lines up with whatever cell the
/// entity is currently in (including after recentres).
///
/// ```rust,ignore
/// commands.spawn((
///     GeoCell::from_lon_lat(2.3522, 48.8566, 9).unwrap(),
///     Transform::default(),
///     DrawCellOutline::default(),
/// ));
/// ```
#[derive(Component, Debug, Clone, Copy, Reflect)]
#[reflect(Component)]
pub struct DrawCellOutline {
    /// Outline colour. Defaults to bright cyan.
    pub color: Color,
}

impl Default for DrawCellOutline {
    fn default() -> Self {
        Self {
            color: Color::linear_rgb(0.0, 1.0, 0.85),
        }
    }
}

/// System that draws every [`DrawCellOutline`] entity's cell boundary as
/// gizmo line segments. Registered automatically by
/// [`BevyA5Plugin`](crate::BevyA5Plugin).
pub fn draw_cell_outlines(
    planet: Res<PlanetSettings>,
    mut gizmos: Gizmos,
    q: Query<(&GeoCell, &GlobalTransform, &DrawCellOutline)>,
) {
    for (cell, gt, marker) in q.iter() {
        let Some(local_verts) = cell_boundary_local(cell.raw(), planet.radius) else {
            continue;
        };
        if local_verts.len() < 2 {
            continue;
        }
        // `cell_boundary_local` returns vertices in the cell's tangent frame
        // (matching the orientation `propagate_geo_transforms` applies). The
        // entity's `GlobalTransform` already maps that frame to world space.
        let world: Vec<Vec3> = local_verts
            .iter()
            .map(|v| gt.transform_point(*v))
            .collect();
        let n = world.len();
        for i in 0..n {
            let next = (i + 1) % n;
            gizmos.line(world[i], world[next], marker.color);
        }
    }
}