1use std::cell::RefMut;
2use std::ops::{Deref, DerefMut};
3
4use crate::ecs::resources::Resources;
5
6pub struct Res<'a, T: hecs::Component> {
10 pub(crate) data: hecs::Ref<'a, T>,
11}
12
13impl<'a, T: hecs::Component> Deref for Res<'a, T> {
14 type Target = T;
15 fn deref(&self) -> &Self::Target {
16 &self.data
17 }
18}
19
20pub struct ResMut<'a, T: hecs::Component> {
24 data: hecs::RefMut<'a, T>,
25}
26
27impl<'a, T: hecs::Component> Deref for ResMut<'a, T> {
28 type Target = T;
29 fn deref(&self) -> &Self::Target {
30 &self.data
31 }
32}
33
34impl<'a, T: hecs::Component> DerefMut for ResMut<'a, T> {
35 fn deref_mut(&mut self) -> &mut Self::Target {
36 &mut self.data
37 }
38}
39
40pub struct Query<'a, Q: hecs::Query> {
44 borrow: hecs::QueryBorrow<'a, Q>,
45}
46
47impl<'a, Q: hecs::Query> Deref for Query<'a, Q> {
48 type Target = hecs::QueryBorrow<'a, Q>;
49 fn deref(&self) -> &Self::Target {
50 &self.borrow
51 }
52}
53
54impl<'a, Q: hecs::Query> DerefMut for Query<'a, Q> {
55 fn deref_mut(&mut self) -> &mut Self::Target {
56 &mut self.borrow
57 }
58}
59
60pub struct Commands<'a> {
65 buffer: RefMut<'a, hecs::CommandBuffer>,
66 resource_entity: hecs::Entity,
67}
68
69impl<'a> Commands<'a> {
70 pub fn insert_resource<T: hecs::Component>(&mut self, res: T) {
72 self.buffer.insert_one(self.resource_entity, res);
73 }
74
75 pub fn remove_resource<T: hecs::Component>(&mut self) {
77 self.buffer.remove_one::<T>(self.resource_entity);
78 }
79}
80
81impl<'a> Deref for Commands<'a> {
82 type Target = hecs::CommandBuffer;
83 fn deref(&self) -> &Self::Target {
84 &self.buffer
85 }
86}
87
88impl<'a> DerefMut for Commands<'a> {
89 fn deref_mut(&mut self) -> &mut Self::Target {
90 &mut self.buffer
91 }
92}
93
94trait SystemParam {
100 type Item<'a>;
101 fn fetch<'a>(world: &'a hecs::World, resources: &'a Resources) -> Self::Item<'a>;
102}
103
104impl<T> SystemParam for Res<'static, T>
105where
106 T: 'static + Sync + Send,
107{
108 type Item<'a> = Res<'a, T>;
109
110 fn fetch<'a>(world: &'a hecs::World, resource: &'a Resources) -> Self::Item<'a> {
111 Res {
112 data: resource.get_resource(world),
113 }
114 }
115}
116
117impl<T> SystemParam for Option<Res<'static, T>>
118where
119 T: 'static + Sync + Send,
120{
121 type Item<'a> = Option<Res<'a, T>>;
122
123 fn fetch<'a>(world: &'a hecs::World, resource: &'a Resources) -> Self::Item<'a> {
124 if resource.has_resource::<T>(world) {
125 return Some(Res {
126 data: resource.get_resource(world),
127 });
128 }
129
130 None
131 }
132}
133
134impl<T> SystemParam for ResMut<'static, T>
135where
136 T: 'static + Sync + Send,
137{
138 type Item<'a> = ResMut<'a, T>;
139
140 fn fetch<'a>(world: &'a hecs::World, resource: &'a Resources) -> Self::Item<'a> {
141 ResMut {
142 data: resource.get_resource_mut(world),
143 }
144 }
145}
146
147impl<T> SystemParam for Option<ResMut<'static, T>>
148where
149 T: 'static + Sync + Send,
150{
151 type Item<'a> = Option<ResMut<'a, T>>;
152
153 fn fetch<'a>(world: &'a hecs::World, resource: &'a Resources) -> Self::Item<'a> {
154 if resource.has_resource::<T>(world) {
155 return Some(ResMut {
156 data: resource.get_resource_mut(world),
157 });
158 }
159
160 None
161 }
162}
163
164impl<Q> SystemParam for Query<'static, Q>
165where
166 Q: hecs::Query + 'static,
167{
168 type Item<'a> = Query<'a, Q>;
169
170 fn fetch<'a>(world: &'a hecs::World, _resources: &'a Resources) -> Self::Item<'a> {
171 Query {
172 borrow: world.query::<Q>(),
173 }
174 }
175}
176
177impl SystemParam for Commands<'static> {
178 type Item<'a> = Commands<'a>;
179
180 fn fetch<'a>(_world: &'a hecs::World, resources: &'a Resources) -> Self::Item<'a> {
181 Commands {
182 buffer: resources.get_command_buffer(),
183 resource_entity: resources.resource_entity,
184 }
185 }
186}
187
188impl SystemParam for &'static hecs::World {
189 type Item<'a> = &'a hecs::World;
190
191 fn fetch<'a>(world: &'a hecs::World, _resources: &'a Resources) -> Self::Item<'a> {
192 world
193 }
194}
195
196impl SystemParam for &'static Resources {
197 type Item<'a> = &'a Resources;
198
199 fn fetch<'a>(_world: &'a hecs::World, resources: &'a Resources) -> Self::Item<'a> {
200 resources
201 }
202}
203
204pub trait System: 'static {
206 fn run(&mut self, world: &hecs::World, resources: &Resources);
207}
208
209pub struct FunctionSystem<F, Marker> {
211 pub func: F,
212 _marker: std::marker::PhantomData<Marker>,
213}
214
215pub trait IntoSystem<Marker> {
220 type System: System;
221
222 fn into_system(self) -> Self::System;
223}
224
225macro_rules! impl_system {
226 ($($param:ident),*) => {
227 impl<T, $($param),*> IntoSystem<($($param,)*)> for T
228 where
229 T: for<'a> FnMut($($param::Item<'a>),*) + 'static,
230 for<'a> &'a mut T: FnMut($($param),*),
231 $($param: SystemParam + 'static),*
232 {
233 type System = FunctionSystem<T, ($($param,)*)>;
234
235 fn into_system(self) -> Self::System {
236 FunctionSystem {
237 func: self,
238 _marker: std::marker::PhantomData,
239 }
240 }
241 }
242
243 impl<T, $($param),*> System for FunctionSystem<T, ($($param,)*)>
244 where
245 T: for<'a> FnMut($($param::Item<'a>),*) + 'static,
246 $($param: SystemParam + 'static),*
247 {
248 fn run(&mut self, _world: &hecs::World, _resources: &Resources) {
249 (self.func)($($param::fetch(_world, _resources)),*);
250 }
251 }
252 };
253}
254
255impl_system!();
256impl_system!(A);
257impl_system!(A, B);
258impl_system!(A, B, C);
259impl_system!(A, B, C, D);
260impl_system!(A, B, C, D, E);
261impl_system!(A, B, C, D, E, F);
262impl_system!(A, B, C, D, E, F, G);
263impl_system!(A, B, C, D, E, F, G, H);