1use crate::ecs::{
2 observers::Observers,
3 resources::{Resources, Write},
4 system_param::SystemParam,
5};
6
7#[derive(Default)]
8pub struct ResourceCommandQueue(pub(crate) Vec<Box<dyn FnOnce(&mut Resources)>>);
9
10#[derive(Default)]
11pub(crate) struct TriggerQueue(pub(crate) Vec<Box<dyn FnOnce(&hecs::World, &Resources)>>);
12
13pub struct Commands<'a> {
17 buffer: Write<'a, hecs::CommandBuffer>,
18 resource_commands: Write<'a, ResourceCommandQueue>,
19 triggers: Write<'a, TriggerQueue>,
20}
21
22impl<'a> std::ops::Deref for Commands<'a> {
23 type Target = hecs::CommandBuffer;
24 fn deref(&self) -> &hecs::CommandBuffer {
25 &self.buffer
26 }
27}
28
29impl<'a> std::ops::DerefMut for Commands<'a> {
30 fn deref_mut(&mut self) -> &mut hecs::CommandBuffer {
31 &mut self.buffer
32 }
33}
34
35impl<'a> Commands<'a> {
36 pub fn insert_resource<T: 'static>(&mut self, value: T) {
38 self.resource_commands
39 .0
40 .push(Box::new(move |resources| resources.insert(value)));
41 }
42
43 pub fn remove_resource<T: 'static>(&mut self) {
45 self.resource_commands.0.push(Box::new(|resources| {
46 resources.remove::<T>();
47 }));
48 }
49
50 pub fn trigger<E: 'static + Send + Sync>(&mut self, event: E) {
54 self.triggers.0.push(Box::new(move |world, resources| {
55 if !resources.contains::<Observers<E>>() {
56 return;
57 }
58 let mut observers = std::mem::take(&mut resources.get_mut::<Observers<E>>().0);
59 for observer in observers.iter_mut() {
60 observer.run(&event, world, resources);
61 }
62 resources.get_mut::<Observers<E>>().0 = observers;
63 }));
64 }
65}
66
67impl SystemParam for Commands<'_> {
68 type Item<'w> = Commands<'w>;
69 type State = ((), (), ());
70
71 fn fetch<'w>(
72 world: &'w hecs::World,
73 resources: &'w Resources,
74 state: &'w mut Self::State,
75 ) -> Self::Item<'w> {
76 Commands {
77 buffer: Write::fetch(world, resources, &mut state.0),
78 resource_commands: Write::fetch(world, resources, &mut state.1),
79 triggers: Write::fetch(world, resources, &mut state.2),
80 }
81 }
82}