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
94pub struct Local<'a, T: Default + Send + Sync + 'static> {
104 data: &'a mut T,
105}
106
107impl<'a, T: Default + Send + Sync + 'static> Deref for Local<'a, T> {
108 type Target = T;
109 fn deref(&self) -> &Self::Target {
110 self.data
111 }
112}
113
114impl<'a, T: Default + Send + Sync + 'static> DerefMut for Local<'a, T> {
115 fn deref_mut(&mut self) -> &mut Self::Target {
116 self.data
117 }
118}
119
120pub trait SystemParam {
128 type Item<'a>;
129 type State: Default + 'static;
130 fn fetch<'a>(
131 state: &'a mut Self::State,
132 world: &'a hecs::World,
133 resources: &'a Resources,
134 ) -> Self::Item<'a>;
135}
136
137impl<T> SystemParam for Res<'static, T>
138where
139 T: 'static + Sync + Send,
140{
141 type Item<'a> = Res<'a, T>;
142 type State = ();
143
144 fn fetch<'a>(
145 _state: &'a mut Self::State,
146 world: &'a hecs::World,
147 resource: &'a Resources,
148 ) -> Self::Item<'a> {
149 Res {
150 data: resource.get_resource(world),
151 }
152 }
153}
154
155impl<T> SystemParam for Option<Res<'static, T>>
156where
157 T: 'static + Sync + Send,
158{
159 type Item<'a> = Option<Res<'a, T>>;
160 type State = ();
161
162 fn fetch<'a>(
163 _state: &'a mut Self::State,
164 world: &'a hecs::World,
165 resource: &'a Resources,
166 ) -> Self::Item<'a> {
167 if resource.has_resource::<T>(world) {
168 return Some(Res {
169 data: resource.get_resource(world),
170 });
171 }
172
173 None
174 }
175}
176
177impl<T> SystemParam for ResMut<'static, T>
178where
179 T: 'static + Sync + Send,
180{
181 type Item<'a> = ResMut<'a, T>;
182 type State = ();
183
184 fn fetch<'a>(
185 _state: &'a mut Self::State,
186 world: &'a hecs::World,
187 resource: &'a Resources,
188 ) -> Self::Item<'a> {
189 ResMut {
190 data: resource.get_resource_mut(world),
191 }
192 }
193}
194
195impl<T> SystemParam for Option<ResMut<'static, T>>
196where
197 T: 'static + Sync + Send,
198{
199 type Item<'a> = Option<ResMut<'a, T>>;
200 type State = ();
201
202 fn fetch<'a>(
203 _state: &'a mut Self::State,
204 world: &'a hecs::World,
205 resource: &'a Resources,
206 ) -> Self::Item<'a> {
207 if resource.has_resource::<T>(world) {
208 return Some(ResMut {
209 data: resource.get_resource_mut(world),
210 });
211 }
212
213 None
214 }
215}
216
217impl<Q> SystemParam for Query<'static, Q>
218where
219 Q: hecs::Query + 'static,
220{
221 type Item<'a> = Query<'a, Q>;
222 type State = ();
223
224 fn fetch<'a>(
225 _state: &'a mut Self::State,
226 world: &'a hecs::World,
227 _resources: &'a Resources,
228 ) -> Self::Item<'a> {
229 Query {
230 borrow: world.query::<Q>(),
231 }
232 }
233}
234
235impl SystemParam for Commands<'static> {
236 type Item<'a> = Commands<'a>;
237 type State = ();
238
239 fn fetch<'a>(
240 _state: &'a mut Self::State,
241 _world: &'a hecs::World,
242 resources: &'a Resources,
243 ) -> Self::Item<'a> {
244 Commands {
245 buffer: resources.get_command_buffer(),
246 resource_entity: resources.resource_entity,
247 }
248 }
249}
250
251impl SystemParam for &'static hecs::World {
252 type Item<'a> = &'a hecs::World;
253 type State = ();
254
255 fn fetch<'a>(
256 _state: &'a mut Self::State,
257 world: &'a hecs::World,
258 _resources: &'a Resources,
259 ) -> Self::Item<'a> {
260 world
261 }
262}
263
264impl SystemParam for &'static Resources {
265 type Item<'a> = &'a Resources;
266 type State = ();
267
268 fn fetch<'a>(
269 _state: &'a mut Self::State,
270 _world: &'a hecs::World,
271 resources: &'a Resources,
272 ) -> Self::Item<'a> {
273 resources
274 }
275}
276
277impl<T> SystemParam for Local<'static, T>
278where
279 T: Default + Send + Sync + 'static,
280{
281 type Item<'a> = Local<'a, T>;
282 type State = T;
283
284 fn fetch<'a>(
285 state: &'a mut Self::State,
286 _world: &'a hecs::World,
287 _resources: &'a Resources,
288 ) -> Self::Item<'a> {
289 Local { data: state }
290 }
291}
292
293pub trait System: 'static {
295 fn run(&mut self, world: &hecs::World, resources: &Resources);
296}
297
298pub struct FunctionSystem<F, Marker, State = ()> {
303 pub func: F,
304 state: State,
305 _marker: std::marker::PhantomData<Marker>,
306}
307
308pub trait IntoSystem<Marker> {
313 type System: System;
314
315 fn into_system(self) -> Self::System;
316}
317
318macro_rules! impl_system {
319 ($($param:ident),*) => {
320 impl<T, $($param),*> IntoSystem<($($param,)*)> for T
321 where
322 T: for<'a> FnMut($($param::Item<'a>),*) + 'static,
323 for<'a> &'a mut T: FnMut($($param),*),
324 $($param: SystemParam + 'static),*
325 {
326 type System = FunctionSystem<T, ($($param,)*), ($($param::State,)*)>;
327
328 fn into_system(self) -> Self::System {
329 FunctionSystem {
330 func: self,
331 state: Default::default(),
332 _marker: std::marker::PhantomData,
333 }
334 }
335 }
336
337 impl<T, $($param),*> System for FunctionSystem<T, ($($param,)*), ($($param::State,)*)>
338 where
339 T: for<'a> FnMut($($param::Item<'a>),*) + 'static,
340 $($param: SystemParam + 'static),*
341 {
342 fn run(&mut self, _world: &hecs::World, _resources: &Resources) {
343 #[allow(non_snake_case)]
344 let ($($param,)*) = &mut self.state;
345 (self.func)($($param::fetch($param, _world, _resources)),*);
346 }
347 }
348 };
349}
350
351impl_system!();
352impl_system!(A);
353impl_system!(A, B);
354impl_system!(A, B, C);
355impl_system!(A, B, C, D);
356impl_system!(A, B, C, D, E);
357impl_system!(A, B, C, D, E, F);
358impl_system!(A, B, C, D, E, F, G);
359impl_system!(A, B, C, D, E, F, G, H);