use std::fmt::Debug;
use std::marker::PhantomData;
use bevy::ecs::system::SystemParam;
use bevy::prelude::*;
use bevy_gearbox::RegistrationAppExt;
use crate::events::{CollidedEntity, CollidedPosition, OnRepeat, StartInvoke};
use crate::gearbox::repeater;
use crate::spawn::{OnSpawnInvoker, OnSpawnOrigin, OnSpawnTarget};
use crate::target::Target;
pub trait SpatialBackend: Send + Sync + 'static {
type Pos: Clone
+ Copy
+ Send
+ Sync
+ Default
+ Debug
+ bevy::reflect::TypePath
+ bevy::reflect::Reflect
+ 'static;
type Offset: Clone + Send + Sync + Default + Debug + 'static;
type Gatherer: Clone + Send + Sync + Debug + 'static;
type Filter: Clone + Send + Sync + Default + Debug + 'static;
type Context<'w, 's>: SystemParam;
fn apply_offset(
ctx: &mut Self::Context<'_, '_>,
pos: Self::Pos,
offset: &Self::Offset,
) -> Self::Pos;
fn distance(a: &Self::Pos, b: &Self::Pos) -> f32;
fn position_of(ctx: &Self::Context<'_, '_>, entity: Entity) -> Option<Self::Pos>;
fn gather(
ctx: &mut Self::Context<'_, '_>,
origin: Self::Pos,
gatherer: &Self::Gatherer,
exclude: Entity,
) -> Vec<Target<Self::Pos>>;
fn apply_filter(
ctx: &mut Self::Context<'_, '_>,
targets: Vec<Target<Self::Pos>>,
filter: &Self::Filter,
invoker: Entity,
origin: Self::Pos,
) -> Vec<Target<Self::Pos>>;
fn spawn_transform(
world_pos: Self::Pos,
parent: Option<Entity>,
q_global_transform: &Query<&GlobalTransform>,
) -> Transform;
fn plugin_core() -> DieselCorePlugin<Self>
where
Self: Sized,
{
DieselCorePlugin {
_marker: PhantomData,
}
}
fn plugin() -> impl Plugin
where
Self: Sized,
{
Self::plugin_core()
}
}
pub struct DieselCorePlugin<B: SpatialBackend> {
_marker: PhantomData<B>,
}
impl<B: SpatialBackend> Plugin for DieselCorePlugin<B> {
fn build(&self, app: &mut App) {
app.add_plugins(bevy_gearbox::GearboxPlugin);
app.add_plugins(bevy_gauge::plugin::AttributesPlugin);
app.add_plugins(crate::gauge::pae::DieselPaePlugin);
app.init_resource::<crate::spawn::TemplateRegistry>();
app.add_observer(repeater::repeater_observer::<OnRepeat<B::Pos>>);
app.add_observer(repeater::reset_repeater);
app.register_type::<repeater::Repeater>();
app.add_observer(crate::despawn::queue_despawn_observer::<B::Pos>);
app.add_systems(PostUpdate, crate::despawn::despawn_queue_system);
app.register_state_component::<crate::despawn::DelayedDespawn>();
app.register_transition::<StartInvoke<B::Pos>>();
app.register_transition::<OnRepeat<B::Pos>>();
app.register_transition::<CollidedEntity<B::Pos>>();
app.register_transition::<CollidedPosition<B::Pos>>();
app.register_transition::<OnSpawnOrigin<B::Pos>>();
app.register_transition::<OnSpawnTarget<B::Pos>>();
app.register_transition::<OnSpawnInvoker<B::Pos>>();
crate::propagation::plugin(app);
}
}