use std::{marker::PhantomData, time::Duration};
use bevy::{
ecs::schedule::{ScheduleLabel, SystemSet},
prelude::*,
};
use crate::{
TComp,
automatic_systems::{AutoGT, AutoT, TransformMode},
kdtree::{KDTree2, KDTree3, KDTree3A},
timestep::{TimestepLength, on_timer_changeable},
};
#[derive(SystemSet, Debug, Hash, PartialEq, Eq, Clone, Copy)]
pub struct SpatialSet;
#[derive(Copy, Clone, Default)]
pub enum SpatialStructure {
KDTree2,
#[default]
KDTree3,
KDTree3A,
}
pub struct AutomaticUpdate<Comp, Set = SpatialSet, Schedule = Update>
where
Set: SystemSet,
Schedule: ScheduleLabel + Clone,
{
pub(crate) comp: PhantomData<Comp>,
pub(crate) set: Set,
pub(crate) schedule: Schedule,
pub(crate) frequency: Duration,
pub(crate) transform: TransformMode,
pub(crate) spatial_ds: SpatialStructure,
}
impl<Comp, Set: SystemSet, Schedule: ScheduleLabel + Clone> AutomaticUpdate<Comp, Set, Schedule> {
#[must_use]
pub fn new() -> AutomaticUpdate<Comp> {
AutomaticUpdate {
comp: PhantomData,
set: SpatialSet,
schedule: Update,
frequency: Duration::from_millis(50),
transform: TransformMode::Transform,
spatial_ds: default(),
}
}
pub fn with_schedule<NewSchedule: ScheduleLabel + Clone>(
self,
schedule: NewSchedule,
) -> AutomaticUpdate<Comp, Set, NewSchedule> {
AutomaticUpdate {
set: self.set,
schedule,
comp: PhantomData,
frequency: self.frequency,
transform: self.transform,
spatial_ds: self.spatial_ds,
}
}
pub fn with_set<NewSet: SystemSet + Copy>(
self,
set: NewSet,
) -> AutomaticUpdate<Comp, NewSet, Schedule> {
AutomaticUpdate::<Comp, NewSet, Schedule> {
set,
schedule: self.schedule,
comp: PhantomData,
frequency: self.frequency,
transform: self.transform,
spatial_ds: self.spatial_ds,
}
}
#[must_use]
pub fn with_spatial_ds(self, spatial_ds: SpatialStructure) -> Self {
Self { spatial_ds, ..self }
}
#[must_use]
pub fn with_frequency(self, frequency: Duration) -> Self {
Self { frequency, ..self }
}
#[must_use]
pub fn with_transform(self, transform: TransformMode) -> Self {
Self { transform, ..self }
}
}
impl<Comp: TComp, Set: SystemSet + Copy, Schedule: ScheduleLabel + Clone> Plugin
for AutomaticUpdate<Comp, Set, Schedule>
{
fn build(&self, app: &mut App) {
app.insert_resource(TimestepLength(self.frequency, PhantomData::<Comp>))
.configure_sets(
self.schedule.clone(),
self.set.run_if(on_timer_changeable::<Comp>),
);
match self.spatial_ds {
SpatialStructure::KDTree2 => app.init_resource::<KDTree2<Comp>>(),
SpatialStructure::KDTree3 => app.init_resource::<KDTree3<Comp>>(),
SpatialStructure::KDTree3A => app.init_resource::<KDTree3A<Comp>>(),
};
match self.transform {
TransformMode::Transform => match self.spatial_ds {
SpatialStructure::KDTree2 => {
AutoT::<KDTree2<Comp>>::build(app, self.schedule.clone(), self.set);
}
SpatialStructure::KDTree3 => {
AutoT::<KDTree3<Comp>>::build(app, self.schedule.clone(), self.set);
}
SpatialStructure::KDTree3A => {
AutoT::<KDTree3A<Comp>>::build(app, self.schedule.clone(), self.set);
}
},
TransformMode::GlobalTransform => match self.spatial_ds {
SpatialStructure::KDTree2 => {
AutoGT::<KDTree2<Comp>>::build(app, self.schedule.clone(), self.set);
}
SpatialStructure::KDTree3 => {
AutoGT::<KDTree3<Comp>>::build(app, self.schedule.clone(), self.set);
}
SpatialStructure::KDTree3A => {
AutoGT::<KDTree3A<Comp>>::build(app, self.schedule.clone(), self.set);
}
},
}
}
}