1use std::cell::RefMut;
2use std::ops::{Deref, DerefMut};
3
4use crate::ecs::resources::Resources;
5
6#[derive(Clone, Copy)]
12pub struct RequiredResource {
13 pub name: &'static str,
14 pub present: fn(&hecs::World, &Resources) -> bool,
15}
16
17pub struct Res<'a, T: hecs::Component> {
21 pub(crate) data: hecs::Ref<'a, T>,
22}
23
24impl<'a, T: hecs::Component> Deref for Res<'a, T> {
25 type Target = T;
26 fn deref(&self) -> &Self::Target {
27 &self.data
28 }
29}
30
31pub struct ResMut<'a, T: hecs::Component> {
35 data: hecs::RefMut<'a, T>,
36}
37
38impl<'a, T: hecs::Component> Deref for ResMut<'a, T> {
39 type Target = T;
40 fn deref(&self) -> &Self::Target {
41 &self.data
42 }
43}
44
45impl<'a, T: hecs::Component> DerefMut for ResMut<'a, T> {
46 fn deref_mut(&mut self) -> &mut Self::Target {
47 &mut self.data
48 }
49}
50
51pub struct Query<'a, Q: hecs::Query> {
76 world: &'a hecs::World,
77 borrow: hecs::QueryBorrow<'a, Q>,
78}
79
80impl<'a, Q: hecs::Query> Deref for Query<'a, Q> {
81 type Target = hecs::QueryBorrow<'a, Q>;
82 fn deref(&self) -> &Self::Target {
83 &self.borrow
84 }
85}
86
87impl<'a, Q: hecs::Query> DerefMut for Query<'a, Q> {
88 fn deref_mut(&mut self) -> &mut Self::Target {
89 &mut self.borrow
90 }
91}
92
93impl<'q, Q: hecs::Query> IntoIterator for &'q mut Query<'_, Q> {
94 type Item = Q::Item<'q>;
95 type IntoIter = hecs::QueryIter<'q, Q>;
96
97 fn into_iter(self) -> Self::IntoIter {
98 (&mut self.borrow).into_iter()
99 }
100}
101
102impl<'a, Q: hecs::Query> Query<'a, Q> {
103 pub fn get(&self, entity: hecs::Entity) -> hecs::QueryOne<'_, Q> {
106 self.world.query_one::<Q>(entity)
107 }
108
109 pub fn with<R: hecs::Query>(self) -> hecs::QueryBorrow<'a, hecs::With<Q, R>> {
113 self.borrow.with::<R>()
114 }
115
116 pub fn without<R: hecs::Query>(self) -> hecs::QueryBorrow<'a, hecs::Without<Q, R>> {
119 self.borrow.without::<R>()
120 }
121
122 pub fn single(&mut self) -> Q::Item<'_> {
130 self.get_single()
131 .expect("Query::single: expected exactly one matching entity")
132 }
133
134 pub fn get_single(&mut self) -> Option<Q::Item<'_>> {
137 let mut iter = self.borrow.iter();
138 let first = iter.next()?;
139 if iter.next().is_some() {
140 return None;
141 }
142 Some(first)
143 }
144}
145
146pub struct Commands<'a> {
155 buffer: RefMut<'a, hecs::CommandBuffer>,
156 resource_entity: hecs::Entity,
157 resources: &'a Resources,
159}
160
161impl<'a> Commands<'a> {
162 pub fn insert_resource<T: hecs::Component>(&mut self, res: T) {
168 self.buffer.insert_one(self.resource_entity, res);
169 self.resources.bump_generation();
170 }
171
172 pub fn remove_resource<T: hecs::Component>(&mut self) {
174 self.buffer.remove_one::<T>(self.resource_entity);
175 }
176}
177
178impl<'a> Deref for Commands<'a> {
179 type Target = hecs::CommandBuffer;
180 fn deref(&self) -> &Self::Target {
181 &self.buffer
182 }
183}
184
185impl<'a> DerefMut for Commands<'a> {
186 fn deref_mut(&mut self) -> &mut Self::Target {
187 &mut self.buffer
188 }
189}
190
191pub struct Local<'a, T: Default + Send + Sync + 'static> {
201 data: &'a mut T,
202}
203
204impl<'a, T: Default + Send + Sync + 'static> Deref for Local<'a, T> {
205 type Target = T;
206 fn deref(&self) -> &Self::Target {
207 self.data
208 }
209}
210
211impl<'a, T: Default + Send + Sync + 'static> DerefMut for Local<'a, T> {
212 fn deref_mut(&mut self) -> &mut Self::Target {
213 self.data
214 }
215}
216
217pub trait SystemParam {
225 type Item<'a>;
226 type State: Default + 'static;
227 fn fetch<'a>(
228 state: &'a mut Self::State,
229 world: &'a hecs::World,
230 resources: &'a Resources,
231 ) -> Self::Item<'a>;
232
233 fn requires() -> Vec<RequiredResource> {
244 Vec::new()
245 }
246}
247
248impl<T> SystemParam for Res<'static, T>
249where
250 T: 'static + Sync + Send,
251{
252 type Item<'a> = Res<'a, T>;
253 type State = ();
254
255 fn fetch<'a>(
256 _state: &'a mut Self::State,
257 world: &'a hecs::World,
258 resource: &'a Resources,
259 ) -> Self::Item<'a> {
260 Res {
261 data: resource.get_resource(world),
262 }
263 }
264
265 fn requires() -> Vec<RequiredResource> {
266 vec![RequiredResource {
267 name: std::any::type_name::<T>(),
268 present: |world, resources| resources.has_resource::<T>(world),
269 }]
270 }
271}
272
273impl<T> SystemParam for Option<Res<'static, T>>
274where
275 T: 'static + Sync + Send,
276{
277 type Item<'a> = Option<Res<'a, T>>;
278 type State = ();
279
280 fn fetch<'a>(
281 _state: &'a mut Self::State,
282 world: &'a hecs::World,
283 resource: &'a Resources,
284 ) -> Self::Item<'a> {
285 if resource.has_resource::<T>(world) {
286 return Some(Res {
287 data: resource.get_resource(world),
288 });
289 }
290
291 None
292 }
293}
294
295impl<T> SystemParam for ResMut<'static, T>
296where
297 T: 'static + Sync + Send,
298{
299 type Item<'a> = ResMut<'a, T>;
300 type State = ();
301
302 fn fetch<'a>(
303 _state: &'a mut Self::State,
304 world: &'a hecs::World,
305 resource: &'a Resources,
306 ) -> Self::Item<'a> {
307 ResMut {
308 data: resource.get_resource_mut(world),
309 }
310 }
311
312 fn requires() -> Vec<RequiredResource> {
313 vec![RequiredResource {
314 name: std::any::type_name::<T>(),
315 present: |world, resources| resources.has_resource::<T>(world),
316 }]
317 }
318}
319
320impl<T> SystemParam for Option<ResMut<'static, T>>
321where
322 T: 'static + Sync + Send,
323{
324 type Item<'a> = Option<ResMut<'a, T>>;
325 type State = ();
326
327 fn fetch<'a>(
328 _state: &'a mut Self::State,
329 world: &'a hecs::World,
330 resource: &'a Resources,
331 ) -> Self::Item<'a> {
332 if resource.has_resource::<T>(world) {
333 return Some(ResMut {
334 data: resource.get_resource_mut(world),
335 });
336 }
337
338 None
339 }
340}
341
342impl<Q> SystemParam for Query<'static, Q>
343where
344 Q: hecs::Query + 'static,
345{
346 type Item<'a> = Query<'a, Q>;
347 type State = ();
348
349 fn fetch<'a>(
350 _state: &'a mut Self::State,
351 world: &'a hecs::World,
352 _resources: &'a Resources,
353 ) -> Self::Item<'a> {
354 Query {
355 world: world,
356 borrow: world.query::<Q>(),
357 }
358 }
359}
360
361impl SystemParam for Commands<'static> {
362 type Item<'a> = Commands<'a>;
363 type State = ();
364
365 fn fetch<'a>(
366 _state: &'a mut Self::State,
367 _world: &'a hecs::World,
368 resources: &'a Resources,
369 ) -> Self::Item<'a> {
370 Commands {
371 buffer: resources.get_command_buffer(),
372 resource_entity: resources.resource_entity,
373 resources,
374 }
375 }
376}
377
378impl SystemParam for &'static hecs::World {
379 type Item<'a> = &'a hecs::World;
380 type State = ();
381
382 fn fetch<'a>(
383 _state: &'a mut Self::State,
384 world: &'a hecs::World,
385 _resources: &'a Resources,
386 ) -> Self::Item<'a> {
387 world
388 }
389}
390
391impl SystemParam for &'static Resources {
392 type Item<'a> = &'a Resources;
393 type State = ();
394
395 fn fetch<'a>(
396 _state: &'a mut Self::State,
397 _world: &'a hecs::World,
398 resources: &'a Resources,
399 ) -> Self::Item<'a> {
400 resources
401 }
402}
403
404impl<T> SystemParam for Local<'static, T>
405where
406 T: Default + Send + Sync + 'static,
407{
408 type Item<'a> = Local<'a, T>;
409 type State = T;
410
411 fn fetch<'a>(
412 state: &'a mut Self::State,
413 _world: &'a hecs::World,
414 _resources: &'a Resources,
415 ) -> Self::Item<'a> {
416 Local { data: state }
417 }
418}
419
420pub trait System: 'static {
422 fn run(&mut self, world: &hecs::World, resources: &Resources);
423
424 fn requires(&self) -> Vec<RequiredResource> {
431 Vec::new()
432 }
433}
434
435pub struct FunctionSystem<F, Marker, State = ()> {
440 pub func: F,
441 state: State,
442 _marker: std::marker::PhantomData<Marker>,
443}
444
445pub trait IntoSystem<Marker> {
450 type System: System;
451
452 fn into_system(self) -> Self::System;
453}
454
455macro_rules! impl_system {
456 ($($param:ident),*) => {
457 impl<T, $($param),*> IntoSystem<($($param,)*)> for T
458 where
459 T: for<'a> FnMut($($param::Item<'a>),*) + 'static,
460 for<'a> &'a mut T: FnMut($($param),*),
461 $($param: SystemParam + 'static),*
462 {
463 type System = FunctionSystem<T, ($($param,)*), ($($param::State,)*)>;
464
465 fn into_system(self) -> Self::System {
466 FunctionSystem {
467 func: self,
468 state: Default::default(),
469 _marker: std::marker::PhantomData,
470 }
471 }
472 }
473
474 impl<T, $($param),*> System for FunctionSystem<T, ($($param,)*), ($($param::State,)*)>
475 where
476 T: for<'a> FnMut($($param::Item<'a>),*) + 'static,
477 $($param: SystemParam + 'static),*
478 {
479 fn run(&mut self, _world: &hecs::World, _resources: &Resources) {
480 #[allow(non_snake_case)]
481 let ($($param,)*) = &mut self.state;
482 (self.func)($($param::fetch($param, _world, _resources)),*);
483 }
484
485 fn requires(&self) -> Vec<RequiredResource> {
486 let mut _v = Vec::new();
487 $(_v.extend($param::requires());)*
488 _v
489 }
490 }
491 };
492}
493
494impl_system!();
495impl_system!(A);
496impl_system!(A, B);
497impl_system!(A, B, C);
498impl_system!(A, B, C, D);
499impl_system!(A, B, C, D, E);
500impl_system!(A, B, C, D, E, F);
501impl_system!(A, B, C, D, E, F, G);
502impl_system!(A, B, C, D, E, F, G, H);
503impl_system!(A, B, C, D, E, F, G, H, I);
504impl_system!(A, B, C, D, E, F, G, H, I, J);
505impl_system!(A, B, C, D, E, F, G, H, I, J, K);
506impl_system!(A, B, C, D, E, F, G, H, I, J, K, L);