use bevy::app::{App, Update};
use bevy::prelude::*;
use bevy::utils::HashSet;
use crate::bevy_ryot::perspective::*;
use crate::bevy_ryot::tile_flags::TileFlags;
use crate::bevy_ryot::CacheSystems;
use crate::position::TilePosition;
pub trait TrajectoryApp {
fn add_trajectory<T: Trajectory>(&mut self) -> &mut Self;
}
impl TrajectoryApp for App {
fn add_trajectory<T: Trajectory>(&mut self) -> &mut Self {
self.init_resource::<Cache<RadialArea, Vec<Vec<TilePosition>>>>()
.add_systems(
Update,
(
update_intersection_cache::<T>.in_set(CacheSystems::UpdateCache),
process_perspectives::<T>
.in_set(PerspectiveSystems::CalculatePerspectives)
.after(CacheSystems::UpdateCache),
)
.chain(),
)
}
}
pub trait Trajectory: Component + Send + Sync + 'static {
fn get_area(&self) -> RadialArea;
fn meets_condition(&self, flags: &TileFlags, _: &TilePosition) -> bool {
flags.walkable
}
}
#[derive(Clone, Component, Debug, Reflect)]
#[reflect]
pub struct InterestPositions<T: Trajectory> {
#[reflect(ignore)]
pub shared_with: HashSet<Entity>,
#[reflect(ignore)]
pub positions: Vec<TilePosition>,
_phantom: PhantomData<T>,
}
impl<T: Trajectory> Default for InterestPositions<T> {
fn default() -> Self {
Self {
shared_with: HashSet::default(),
positions: Vec::default(),
_phantom: PhantomData::<T>,
}
}
}
impl<T: Trajectory> InterestPositions<T> {
pub fn share_with(mut self, entities: Vec<Entity>) -> Self {
self.shared_with.extend(entities);
self
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Component)]
pub struct VisibleTrajectory<T>(pub RadialArea, PhantomData<T>);
impl<T> VisibleTrajectory<T> {
pub fn new(area: RadialArea) -> Self {
Self(area, PhantomData::<T>)
}
}
impl<T: Copy + Send + Sync + 'static> Trajectory for VisibleTrajectory<T> {
fn get_area(&self) -> RadialArea {
(*self).into()
}
fn meets_condition(&self, flags: &TileFlags, _: &TilePosition) -> bool {
!flags.blocks_sight
}
}
impl<T> From<VisibleTrajectory<T>> for RadialArea {
fn from(visible: VisibleTrajectory<T>) -> Self {
visible.0
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Component)]
pub struct WalkableTrajectory<T>(pub RadialArea, PhantomData<T>);
impl<T> WalkableTrajectory<T> {
pub fn new(area: RadialArea) -> Self {
Self(area, PhantomData::<T>)
}
}
impl<T: Copy + Send + Sync + 'static> Trajectory for WalkableTrajectory<T> {
fn get_area(&self) -> RadialArea {
(*self).into()
}
}
impl<T> From<WalkableTrajectory<T>> for RadialArea {
fn from(path: WalkableTrajectory<T>) -> Self {
path.0
}
}