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) {
55 self.triggers.0.push(Box::new(move |world, resources| {
56 if !resources.contains::<Observers<E>>() {
57 return;
58 }
59 let mut observers = std::mem::take(&mut resources.get_mut::<Observers<E>>().0);
60 for observer in observers.iter_mut() {
61 observer.run(&event, world, resources);
62 }
63 resources.get_mut::<Observers<E>>().0 = observers;
64 }));
65 }
66}
67
68impl SystemParam for Commands<'_> {
69 type Item<'w> = Commands<'w>;
70 type State = ((), (), ());
71
72 fn fetch<'w>(
73 world: &'w hecs::World,
74 resources: &'w Resources,
75 state: &'w mut Self::State,
76 ) -> Self::Item<'w> {
77 Commands {
78 buffer: Write::fetch(world, resources, &mut state.0),
79 resource_commands: Write::fetch(world, resources, &mut state.1),
80 triggers: Write::fetch(world, resources, &mut state.2),
81 }
82 }
83}