1use std::cell::RefMut;
2use std::ops::{Deref, DerefMut};
3
4use crate::ecs::resources::Resources;
5
6#[derive(Clone, Copy)]
16pub struct RequiredResource {
17 pub name: &'static str,
18 pub type_id: std::any::TypeId,
19 pub present: fn(&hecs::World, &Resources) -> bool,
20}
21
22pub struct Res<'a, T: hecs::Component> {
26 pub(crate) data: hecs::Ref<'a, T>,
27}
28
29impl<'a, T: hecs::Component> Deref for Res<'a, T> {
30 type Target = T;
31 fn deref(&self) -> &Self::Target {
32 &self.data
33 }
34}
35
36pub struct ResMut<'a, T: hecs::Component> {
40 data: hecs::RefMut<'a, T>,
41}
42
43impl<'a, T: hecs::Component> Deref for ResMut<'a, T> {
44 type Target = T;
45 fn deref(&self) -> &Self::Target {
46 &self.data
47 }
48}
49
50impl<'a, T: hecs::Component> DerefMut for ResMut<'a, T> {
51 fn deref_mut(&mut self) -> &mut Self::Target {
52 &mut self.data
53 }
54}
55
56pub struct Query<'a, Q: hecs::Query> {
81 world: &'a hecs::World,
82 borrow: hecs::QueryBorrow<'a, Q>,
83}
84
85impl<'a, Q: hecs::Query> Deref for Query<'a, Q> {
86 type Target = hecs::QueryBorrow<'a, Q>;
87 fn deref(&self) -> &Self::Target {
88 &self.borrow
89 }
90}
91
92impl<'a, Q: hecs::Query> DerefMut for Query<'a, Q> {
93 fn deref_mut(&mut self) -> &mut Self::Target {
94 &mut self.borrow
95 }
96}
97
98impl<'q, Q: hecs::Query> IntoIterator for &'q mut Query<'_, Q> {
99 type Item = Q::Item<'q>;
100 type IntoIter = hecs::QueryIter<'q, Q>;
101
102 fn into_iter(self) -> Self::IntoIter {
103 (&mut self.borrow).into_iter()
104 }
105}
106
107impl<'a, Q: hecs::Query> Query<'a, Q> {
108 pub fn get(&self, entity: hecs::Entity) -> hecs::QueryOne<'_, Q> {
111 self.world.query_one::<Q>(entity)
112 }
113
114 pub fn with<R: hecs::Query>(self) -> hecs::QueryBorrow<'a, hecs::With<Q, R>> {
118 self.borrow.with::<R>()
119 }
120
121 pub fn without<R: hecs::Query>(self) -> hecs::QueryBorrow<'a, hecs::Without<Q, R>> {
124 self.borrow.without::<R>()
125 }
126
127 pub fn single(&mut self) -> Q::Item<'_> {
135 self.get_single()
136 .expect("Query::single: expected exactly one matching entity")
137 }
138
139 pub fn get_single(&mut self) -> Option<Q::Item<'_>> {
142 let mut iter = self.borrow.iter();
143 let first = iter.next()?;
144 if iter.next().is_some() {
145 return None;
146 }
147 Some(first)
148 }
149}
150
151pub struct Commands<'a> {
160 buffer: RefMut<'a, hecs::CommandBuffer>,
161 resource_entity: hecs::Entity,
162 resources: &'a Resources,
164}
165
166impl<'a> Commands<'a> {
167 pub fn insert_resource<T: hecs::Component>(&mut self, res: T) {
173 self.buffer.insert_one(self.resource_entity, res);
174 self.resources.bump_generation();
175 }
176
177 pub fn remove_resource<T: hecs::Component>(&mut self) {
179 self.buffer.remove_one::<T>(self.resource_entity);
180 }
181}
182
183impl<'a> Deref for Commands<'a> {
184 type Target = hecs::CommandBuffer;
185 fn deref(&self) -> &Self::Target {
186 &self.buffer
187 }
188}
189
190impl<'a> DerefMut for Commands<'a> {
191 fn deref_mut(&mut self) -> &mut Self::Target {
192 &mut self.buffer
193 }
194}
195
196pub struct Local<'a, T: Default + Send + Sync + 'static> {
206 data: &'a mut T,
207}
208
209impl<'a, T: Default + Send + Sync + 'static> Deref for Local<'a, T> {
210 type Target = T;
211 fn deref(&self) -> &Self::Target {
212 self.data
213 }
214}
215
216impl<'a, T: Default + Send + Sync + 'static> DerefMut for Local<'a, T> {
217 fn deref_mut(&mut self) -> &mut Self::Target {
218 self.data
219 }
220}
221
222pub trait SystemParam {
230 type Item<'a>;
231 type State: Default + 'static;
232 fn fetch<'a>(
233 state: &'a mut Self::State,
234 world: &'a hecs::World,
235 resources: &'a Resources,
236 ) -> Self::Item<'a>;
237
238 fn requires() -> Vec<RequiredResource> {
249 Vec::new()
250 }
251}
252
253impl<T> SystemParam for Res<'static, T>
254where
255 T: 'static + Sync + Send,
256{
257 type Item<'a> = Res<'a, T>;
258 type State = ();
259
260 fn fetch<'a>(
261 _state: &'a mut Self::State,
262 world: &'a hecs::World,
263 resource: &'a Resources,
264 ) -> Self::Item<'a> {
265 Res {
266 data: resource.get_resource(world),
267 }
268 }
269
270 fn requires() -> Vec<RequiredResource> {
271 vec![RequiredResource {
272 name: std::any::type_name::<T>(),
273 type_id: std::any::TypeId::of::<T>(),
274 present: |world, resources| resources.has_resource::<T>(world),
275 }]
276 }
277}
278
279impl<T> SystemParam for Option<Res<'static, T>>
280where
281 T: 'static + Sync + Send,
282{
283 type Item<'a> = Option<Res<'a, T>>;
284 type State = ();
285
286 fn fetch<'a>(
287 _state: &'a mut Self::State,
288 world: &'a hecs::World,
289 resource: &'a Resources,
290 ) -> Self::Item<'a> {
291 if resource.has_resource::<T>(world) {
292 return Some(Res {
293 data: resource.get_resource(world),
294 });
295 }
296
297 None
298 }
299}
300
301impl<T> SystemParam for ResMut<'static, T>
302where
303 T: 'static + Sync + Send,
304{
305 type Item<'a> = ResMut<'a, T>;
306 type State = ();
307
308 fn fetch<'a>(
309 _state: &'a mut Self::State,
310 world: &'a hecs::World,
311 resource: &'a Resources,
312 ) -> Self::Item<'a> {
313 ResMut {
314 data: resource.get_resource_mut(world),
315 }
316 }
317
318 fn requires() -> Vec<RequiredResource> {
319 vec![RequiredResource {
320 name: std::any::type_name::<T>(),
321 type_id: std::any::TypeId::of::<T>(),
322 present: |world, resources| resources.has_resource::<T>(world),
323 }]
324 }
325}
326
327impl<T> SystemParam for Option<ResMut<'static, T>>
328where
329 T: 'static + Sync + Send,
330{
331 type Item<'a> = Option<ResMut<'a, T>>;
332 type State = ();
333
334 fn fetch<'a>(
335 _state: &'a mut Self::State,
336 world: &'a hecs::World,
337 resource: &'a Resources,
338 ) -> Self::Item<'a> {
339 if resource.has_resource::<T>(world) {
340 return Some(ResMut {
341 data: resource.get_resource_mut(world),
342 });
343 }
344
345 None
346 }
347}
348
349impl<Q> SystemParam for Query<'static, Q>
350where
351 Q: hecs::Query + 'static,
352{
353 type Item<'a> = Query<'a, Q>;
354 type State = ();
355
356 fn fetch<'a>(
357 _state: &'a mut Self::State,
358 world: &'a hecs::World,
359 _resources: &'a Resources,
360 ) -> Self::Item<'a> {
361 Query {
362 world: world,
363 borrow: world.query::<Q>(),
364 }
365 }
366}
367
368impl SystemParam for Commands<'static> {
369 type Item<'a> = Commands<'a>;
370 type State = ();
371
372 fn fetch<'a>(
373 _state: &'a mut Self::State,
374 _world: &'a hecs::World,
375 resources: &'a Resources,
376 ) -> Self::Item<'a> {
377 Commands {
378 buffer: resources.get_command_buffer(),
379 resource_entity: resources.resource_entity,
380 resources,
381 }
382 }
383}
384
385impl SystemParam for &'static hecs::World {
386 type Item<'a> = &'a hecs::World;
387 type State = ();
388
389 fn fetch<'a>(
390 _state: &'a mut Self::State,
391 world: &'a hecs::World,
392 _resources: &'a Resources,
393 ) -> Self::Item<'a> {
394 world
395 }
396}
397
398impl SystemParam for &'static Resources {
399 type Item<'a> = &'a Resources;
400 type State = ();
401
402 fn fetch<'a>(
403 _state: &'a mut Self::State,
404 _world: &'a hecs::World,
405 resources: &'a Resources,
406 ) -> Self::Item<'a> {
407 resources
408 }
409}
410
411impl<T> SystemParam for Local<'static, T>
412where
413 T: Default + Send + Sync + 'static,
414{
415 type Item<'a> = Local<'a, T>;
416 type State = T;
417
418 fn fetch<'a>(
419 state: &'a mut Self::State,
420 _world: &'a hecs::World,
421 _resources: &'a Resources,
422 ) -> Self::Item<'a> {
423 Local { data: state }
424 }
425}
426
427pub trait System: 'static {
429 fn run(&mut self, world: &hecs::World, resources: &Resources);
430
431 fn requires(&self) -> Vec<RequiredResource> {
438 Vec::new()
439 }
440
441 fn name(&self) -> &'static str {
447 std::any::type_name::<Self>()
448 }
449
450 fn ordering_id(&self) -> std::any::TypeId {
459 std::any::TypeId::of::<Self>()
460 }
461
462 fn after_ids(&self) -> &[std::any::TypeId] {
466 &[]
467 }
468
469 fn before_ids(&self) -> &[std::any::TypeId] {
473 &[]
474 }
475}
476
477pub struct Labeled<S: System> {
486 inner: S,
487 after: Vec<std::any::TypeId>,
488 before: Vec<std::any::TypeId>,
489}
490
491impl<S: System> Labeled<S> {
492 pub fn after<F: 'static, Marker>(mut self, system: F) -> Self
495 where
496 F: IntoSystem<Marker>,
497 {
498 let _ = system;
499 self.after.push(std::any::TypeId::of::<F>());
500 self
501 }
502
503 pub fn before<F: 'static, Marker>(mut self, system: F) -> Self
506 where
507 F: IntoSystem<Marker>,
508 {
509 let _ = system;
510 self.before.push(std::any::TypeId::of::<F>());
511 self
512 }
513}
514
515impl<S: System> System for Labeled<S> {
516 fn run(&mut self, world: &hecs::World, resources: &Resources) {
517 self.inner.run(world, resources)
518 }
519
520 fn requires(&self) -> Vec<RequiredResource> {
521 self.inner.requires()
522 }
523
524 fn name(&self) -> &'static str {
525 self.inner.name()
526 }
527
528 fn ordering_id(&self) -> std::any::TypeId {
529 self.inner.ordering_id()
530 }
531
532 fn after_ids(&self) -> &[std::any::TypeId] {
533 &self.after
534 }
535
536 fn before_ids(&self) -> &[std::any::TypeId] {
537 &self.before
538 }
539}
540
541impl<S: System> IntoSystem<()> for Labeled<S> {
542 type System = Self;
543
544 fn into_system(self) -> Self::System {
545 self
546 }
547}
548
549pub trait SystemOrderingExt<Marker>: IntoSystem<Marker> + Sized {
559 fn after<F: 'static, Marker2>(self, system: F) -> Labeled<Self::System>
561 where
562 F: IntoSystem<Marker2>,
563 {
564 let _ = system;
565 Labeled {
566 inner: self.into_system(),
567 after: vec![std::any::TypeId::of::<F>()],
568 before: Vec::new(),
569 }
570 }
571
572 fn before<F: 'static, Marker2>(self, system: F) -> Labeled<Self::System>
574 where
575 F: IntoSystem<Marker2>,
576 {
577 let _ = system;
578 Labeled {
579 inner: self.into_system(),
580 after: Vec::new(),
581 before: vec![std::any::TypeId::of::<F>()],
582 }
583 }
584}
585
586impl<T, Marker> SystemOrderingExt<Marker> for T where T: IntoSystem<Marker> {}
587
588pub struct FunctionSystem<F, Marker, State = ()> {
593 pub func: F,
594 state: State,
595 _marker: std::marker::PhantomData<Marker>,
596}
597
598pub trait IntoSystem<Marker> {
603 type System: System;
604
605 fn into_system(self) -> Self::System;
606}
607
608macro_rules! impl_system {
609 ($($param:ident),*) => {
610 impl<T, $($param),*> IntoSystem<($($param,)*)> for T
611 where
612 T: for<'a> FnMut($($param::Item<'a>),*) + 'static,
613 for<'a> &'a mut T: FnMut($($param),*),
614 $($param: SystemParam + 'static),*
615 {
616 type System = FunctionSystem<T, ($($param,)*), ($($param::State,)*)>;
617
618 fn into_system(self) -> Self::System {
619 FunctionSystem {
620 func: self,
621 state: Default::default(),
622 _marker: std::marker::PhantomData,
623 }
624 }
625 }
626
627 impl<T, $($param),*> System for FunctionSystem<T, ($($param,)*), ($($param::State,)*)>
628 where
629 T: for<'a> FnMut($($param::Item<'a>),*) + 'static,
630 $($param: SystemParam + 'static),*
631 {
632 fn run(&mut self, _world: &hecs::World, _resources: &Resources) {
633 #[allow(non_snake_case)]
634 let ($($param,)*) = &mut self.state;
635 (self.func)($($param::fetch($param, _world, _resources)),*);
636 }
637
638 fn requires(&self) -> Vec<RequiredResource> {
639 let mut _v = Vec::new();
640 $(_v.extend($param::requires());)*
641 _v
642 }
643
644 fn name(&self) -> &'static str {
645 std::any::type_name::<T>()
646 }
647
648 fn ordering_id(&self) -> std::any::TypeId {
649 std::any::TypeId::of::<T>()
650 }
651 }
652 };
653}
654
655impl_system!();
656impl_system!(A);
657impl_system!(A, B);
658impl_system!(A, B, C);
659impl_system!(A, B, C, D);
660impl_system!(A, B, C, D, E);
661impl_system!(A, B, C, D, E, F);
662impl_system!(A, B, C, D, E, F, G);
663impl_system!(A, B, C, D, E, F, G, H);
664impl_system!(A, B, C, D, E, F, G, H, I);
665impl_system!(A, B, C, D, E, F, G, H, I, J);
666impl_system!(A, B, C, D, E, F, G, H, I, J, K);
667impl_system!(A, B, C, D, E, F, G, H, I, J, K, L);
668
669pub struct OnceFunctionSystem<F, Marker, State = ()> {
676 func: F,
677 state: State,
678 done: bool,
679 _marker: std::marker::PhantomData<Marker>,
680}
681
682pub trait OnceExt<Marker> {
704 type System: System;
705 fn once(self) -> Self::System;
706}
707
708macro_rules! impl_once_system {
709 ($($param:ident),*) => {
710 impl<T, $($param),*> OnceExt<($($param,)*)> for T
711 where
712 T: for<'a> FnMut($($param::Item<'a>),*) -> Option<()> + 'static,
713 for<'a> &'a mut T: FnMut($($param),*) -> Option<()>,
714 $($param: SystemParam + 'static),*
715 {
716 type System = OnceFunctionSystem<T, ($($param,)*), ($($param::State,)*)>;
717
718 fn once(self) -> Self::System {
719 OnceFunctionSystem {
720 func: self,
721 state: Default::default(),
722 done: false,
723 _marker: std::marker::PhantomData,
724 }
725 }
726 }
727
728 impl<T, $($param),*> IntoSystem<($($param,)*)> for OnceFunctionSystem<T, ($($param,)*), ($($param::State,)*)>
729 where
730 T: for<'a> FnMut($($param::Item<'a>),*) -> Option<()> + 'static,
731 $($param: SystemParam + 'static),*
732 {
733 type System = Self;
734
735 fn into_system(self) -> Self::System {
736 self
737 }
738 }
739
740 impl<T, $($param),*> System for OnceFunctionSystem<T, ($($param,)*), ($($param::State,)*)>
741 where
742 T: for<'a> FnMut($($param::Item<'a>),*) -> Option<()> + 'static,
743 $($param: SystemParam + 'static),*
744 {
745 fn run(&mut self, _world: &hecs::World, _resources: &Resources) {
746 if self.done {
747 return;
748 }
749 #[allow(non_snake_case)]
750 let ($($param,)*) = &mut self.state;
751 let result = (self.func)($($param::fetch($param, _world, _resources)),*);
752 if result.is_some() {
753 self.done = true;
754 }
755 }
756
757 fn requires(&self) -> Vec<RequiredResource> {
758 if self.done {
759 return Vec::new();
760 }
761 let mut _v = Vec::new();
762 $(_v.extend($param::requires());)*
763 _v
764 }
765
766 fn name(&self) -> &'static str {
767 std::any::type_name::<T>()
768 }
769
770 fn ordering_id(&self) -> std::any::TypeId {
771 std::any::TypeId::of::<T>()
772 }
773 }
774 };
775}
776
777impl_once_system!();
778impl_once_system!(A);
779impl_once_system!(A, B);
780impl_once_system!(A, B, C);
781impl_once_system!(A, B, C, D);
782impl_once_system!(A, B, C, D, E);
783impl_once_system!(A, B, C, D, E, F);
784impl_once_system!(A, B, C, D, E, F, G);
785impl_once_system!(A, B, C, D, E, F, G, H);
786impl_once_system!(A, B, C, D, E, F, G, H, I);
787impl_once_system!(A, B, C, D, E, F, G, H, I, J);
788impl_once_system!(A, B, C, D, E, F, G, H, I, J, K);
789impl_once_system!(A, B, C, D, E, F, G, H, I, J, K, L);