use bevy::{
color::palettes::css,
ecs::entity::Entity,
math::{UVec3, Vec2, Vec3},
platform::collections::HashMap,
prelude::{Color, Component},
reflect::Reflect,
transform::components::Transform,
};
use crate::{debug::DebugTilemapType, nav_mask::NavMask, NavRegion, SearchLimits};
#[derive(Component, Reflect, Default, Debug, Clone, Eq, PartialEq, Hash)]
pub struct AgentPos(pub UVec3);
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Reflect)]
pub enum PathfindMode {
#[default]
Refined,
Coarse,
AStar,
Waypoints,
ThetaStar,
}
#[derive(Component, Clone, Default, Debug, Reflect)]
pub struct Pathfind {
pub goal: UVec3,
pub mode: Option<PathfindMode>,
pub limits: SearchLimits,
}
impl Pathfind {
pub fn new(goal: UVec3) -> Self {
Pathfind {
goal,
..Default::default()
}
}
pub fn new_2d(x: u32, y: u32) -> Self {
Pathfind {
goal: UVec3::new(x, y, 0),
..Default::default()
}
}
pub fn new_3d(x: u32, y: u32, z: u32) -> Self {
Pathfind {
goal: UVec3::new(x, y, z),
..Default::default()
}
}
pub fn mode(mut self, mode: PathfindMode) -> Self {
self.mode = Some(mode);
self
}
pub fn partial(mut self) -> Self {
self.limits.partial = true;
self
}
pub fn search_region(mut self, region: NavRegion) -> Self {
self.limits.boundary = Some(region);
self
}
pub fn max_distance(mut self, max_distance: u32) -> Self {
self.limits.distance = Some(max_distance);
self
}
pub fn with_limits(mut self, limits: SearchLimits) -> Self {
self.limits = limits;
self
}
}
#[derive(Component, Default, Debug, Reflect)]
#[component(storage = "SparseSet")]
pub struct NextPos(pub UVec3);
#[derive(Component, Default)]
pub struct Blocking;
#[derive(Component, Default, Debug)]
#[component(storage = "SparseSet")]
pub struct AvoidanceFailed;
#[derive(Component, Default, Debug)]
#[component(storage = "SparseSet")]
pub struct PathfindingFailed;
#[derive(Component, Default, Debug)]
#[component(storage = "SparseSet")]
pub struct RerouteFailed;
#[derive(Component, Default, Reflect)]
pub struct DebugOffset(pub Vec3);
#[derive(Component, Default, Reflect)]
pub struct DebugDepthYOffsets(pub HashMap<u32, f32>);
#[derive(Component, Debug, Default, Reflect)]
pub struct DebugCursor(pub Option<Vec2>);
#[derive(Component, Debug, Default)]
pub(crate) struct DebugNode(pub(crate) Option<UVec3>);
#[derive(Component, Reflect)]
pub struct DebugPath {
pub color: Color,
pub draw_unrefined: bool,
}
impl DebugPath {
pub fn new(color: Color) -> Self {
DebugPath {
color,
draw_unrefined: false,
}
}
}
impl Default for DebugPath {
fn default() -> Self {
DebugPath {
color: bevy::prelude::Color::Srgba(css::RED),
draw_unrefined: false,
}
}
}
#[derive(Reflect, Component)]
#[require(Transform, DebugOffset, DebugDepthYOffsets, DebugCursor, DebugNode)]
pub struct DebugGrid {
pub tile_width: u32,
pub tile_height: u32,
pub depth: u32,
pub map_type: DebugTilemapType,
pub voxel_size: f32,
pub swap_yz: bool,
pub draw_chunks: bool,
pub draw_cells: bool,
pub draw_entrances: bool,
pub draw_cached_paths: bool,
pub show_connections_on_hover: bool,
#[reflect(ignore)]
pub debug_mask: Option<NavMask>,
}
impl DebugGrid {
pub fn tile_size(&mut self, width: u32, height: u32) -> &Self {
self.tile_width = width;
self.tile_height = height;
self
}
pub fn set_depth(&mut self, depth: u32) -> &Self {
self.depth = depth;
self
}
pub fn depth(&self) -> u32 {
self.depth
}
pub fn map_type(&mut self, map_type: DebugTilemapType) -> &Self {
self.map_type = map_type;
self
}
pub fn set_draw_chunks(&mut self, value: bool) -> &Self {
self.draw_chunks = value;
self
}
pub fn toggle_chunks(&mut self) -> &Self {
self.draw_chunks = !self.draw_chunks;
self
}
pub fn set_draw_cells(&mut self, value: bool) -> &Self {
self.draw_cells = value;
self
}
pub fn toggle_cells(&mut self) -> &Self {
self.draw_cells = !self.draw_cells;
self
}
pub fn set_draw_entrances(&mut self, value: bool) -> &Self {
self.draw_entrances = value;
self
}
pub fn toggle_entrances(&mut self) -> &Self {
self.draw_entrances = !self.draw_entrances;
self
}
pub fn set_draw_cached_paths(&mut self, value: bool) -> &Self {
self.draw_cached_paths = value;
self
}
pub fn toggle_cached_paths(&mut self) -> &Self {
self.draw_cached_paths = !self.draw_cached_paths;
self
}
pub fn set_show_connections_on_hover(&mut self, value: bool) -> &Self {
self.show_connections_on_hover = value;
self
}
pub fn toggle_show_connections_on_hover(&mut self) -> &Self {
self.show_connections_on_hover = !self.show_connections_on_hover;
self
}
pub fn set_debug_mask(&mut self, mask: NavMask) -> &Self {
self.debug_mask = Some(mask);
self
}
pub fn clear_debug_mask(&mut self) -> &Self {
self.debug_mask = None;
self
}
}
pub struct DebugGridBuilder {
tile_width: u32,
tile_height: u32,
depth: u32,
tilemap_type: DebugTilemapType,
voxel_size: f32,
draw_chunks: bool,
draw_cells: bool,
draw_entrances: bool,
draw_cached_paths: bool,
show_connections_on_hover: bool,
debug_mask: Option<NavMask>,
swap_yz: bool,
}
impl DebugGridBuilder {
pub fn new(tile_width: u32, tile_height: u32) -> Self {
Self {
tile_width,
tile_height,
depth: 0,
tilemap_type: DebugTilemapType::Square,
voxel_size: 1.0,
draw_chunks: false,
draw_cells: false,
draw_entrances: false,
draw_cached_paths: false,
show_connections_on_hover: false,
debug_mask: None,
swap_yz: false,
}
}
pub fn set_depth(mut self, depth: u32) -> Self {
self.depth = depth;
self
}
pub fn tilemap_type(mut self, tilemap_type: DebugTilemapType) -> Self {
self.tilemap_type = tilemap_type;
self
}
pub fn isometric(mut self) -> Self {
self.tilemap_type = DebugTilemapType::Isometric;
self
}
pub fn square_3d(mut self) -> Self {
self.tilemap_type = DebugTilemapType::Square3d;
self
}
pub fn voxel_size(mut self, size: f32) -> Self {
self.voxel_size = size;
self
}
pub fn enable_chunks(mut self) -> Self {
self.draw_chunks = true;
self
}
pub fn enable_cells(mut self) -> Self {
self.draw_cells = true;
self
}
pub fn enable_entrances(mut self) -> Self {
self.draw_entrances = true;
self
}
pub fn enable_cached_paths(mut self) -> Self {
self.draw_cached_paths = true;
self
}
pub fn enable_show_connections_on_hover(mut self) -> Self {
self.show_connections_on_hover = true;
self
}
pub fn with_debug_mask(mut self, debug_mask: NavMask) -> Self {
self.debug_mask = Some(debug_mask);
self
}
pub fn swap_yz(mut self) -> Self {
self.swap_yz = true;
self
}
pub fn build(self) -> DebugGrid {
DebugGrid {
tile_width: self.tile_width,
tile_height: self.tile_height,
depth: self.depth,
map_type: self.tilemap_type,
voxel_size: self.voxel_size,
draw_chunks: self.draw_chunks,
draw_cells: self.draw_cells,
draw_entrances: self.draw_entrances,
draw_cached_paths: self.draw_cached_paths,
show_connections_on_hover: self.show_connections_on_hover,
debug_mask: self.debug_mask,
swap_yz: self.swap_yz,
}
}
}
#[derive(Component, Reflect)]
#[relationship(relationship_target = GridAgents)]
pub struct AgentOfGrid(pub Entity);
#[derive(Component, Reflect)]
#[relationship_target(relationship = AgentOfGrid, linked_spawn)]
pub struct GridAgents(Vec<Entity>);
impl GridAgents {
pub fn entities(&self) -> &[Entity] {
&self.0
}
}
#[derive(Component)]
pub struct AgentMask(pub NavMask);