This repository has been archived by the owner on Jul 8, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathspawner.rs
82 lines (74 loc) · 2.78 KB
/
spawner.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
use crate::events::{delay_spawn_events, ReadySpawnEvent};
use crate::plugin::SpewSystemSet;
use bevy::ecs::system::SystemState;
use bevy::prelude::*;
use bevy::utils::all_tuples;
use std::fmt::Debug;
/// Abstraction over a tuple of [`Spawner`]s.
/// See [`SpewApp::add_spawners`](crate::prelude::SpewApp::add_spawners) for more information.
pub trait Spawners<Marker>: Send + Sync + 'static {
/// Add all spawners to the app. Called internally.
fn add_to_app(self, app: &mut App);
}
/// Abstraction over a tuple of an enum variant and a spawning function.
/// See [`SpewApp::add_spawners`](crate::prelude::SpewApp::add_spawners) for more information.
pub trait Spawner<Marker>: Send + Sync + 'static {
/// Add the spawner to the app. Called internally.
fn add_to_app(self, app: &mut App);
}
impl<T, F, Marker> Spawner<Marker> for (T, F)
where
T: Debug + Eq + Send + Sync + 'static,
F: SystemParamFunction<Marker>,
Marker: Send + Sync + 'static,
F::In: Send + Sync + 'static,
{
fn add_to_app(self, app: &mut App) {
let (object, mut spawn_function) = self;
let system = move |world: &mut World| {
let mut events = world
.get_resource_mut::<Events<ReadySpawnEvent<T, F::In>>>()
.unwrap();
let mut handled_events = Vec::new();
let mut unhandled_events = Vec::new();
for event in events.drain() {
if event.object == object {
handled_events.push(event);
} else {
unhandled_events.push(event);
}
}
for event in unhandled_events {
events.send(event);
}
for event in handled_events {
let mut system_state: SystemState<F::Param> = SystemState::new(world);
let user_data = event.data;
let param = system_state.get_mut(world);
spawn_function.run(user_data, param);
system_state.apply(world);
}
};
app.add_systems(
Update,
system
.after(delay_spawn_events::<T, F::In>)
.in_set(SpewSystemSet),
);
}
}
macro_rules! impl_spawners_tuples {
($(($param: ident, $spawners: ident)),*) => {
impl<$($param, $spawners),*> Spawners<($($param,)*)> for ($($spawners,)*)
where
$($spawners: Spawner<$param>),*
{
#[allow(non_snake_case, unused_variables)]
fn add_to_app(self, app: &mut App) {
let ($($spawners,)*) = self;
$($spawners.add_to_app(app);)*
}
}
}
}
all_tuples!(impl_spawners_tuples, 0, 15, S, D);