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
451pub struct FunctionSystem<F, Marker, State = ()> {
456 pub func: F,
457 state: State,
458 _marker: std::marker::PhantomData<Marker>,
459}
460
461pub trait IntoSystem<Marker> {
466 type System: System;
467
468 fn into_system(self) -> Self::System;
469}
470
471macro_rules! impl_system {
472 ($($param:ident),*) => {
473 impl<T, $($param),*> IntoSystem<($($param,)*)> for T
474 where
475 T: for<'a> FnMut($($param::Item<'a>),*) + 'static,
476 for<'a> &'a mut T: FnMut($($param),*),
477 $($param: SystemParam + 'static),*
478 {
479 type System = FunctionSystem<T, ($($param,)*), ($($param::State,)*)>;
480
481 fn into_system(self) -> Self::System {
482 FunctionSystem {
483 func: self,
484 state: Default::default(),
485 _marker: std::marker::PhantomData,
486 }
487 }
488 }
489
490 impl<T, $($param),*> System for FunctionSystem<T, ($($param,)*), ($($param::State,)*)>
491 where
492 T: for<'a> FnMut($($param::Item<'a>),*) + 'static,
493 $($param: SystemParam + 'static),*
494 {
495 fn run(&mut self, _world: &hecs::World, _resources: &Resources) {
496 #[allow(non_snake_case)]
497 let ($($param,)*) = &mut self.state;
498 (self.func)($($param::fetch($param, _world, _resources)),*);
499 }
500
501 fn requires(&self) -> Vec<RequiredResource> {
502 let mut _v = Vec::new();
503 $(_v.extend($param::requires());)*
504 _v
505 }
506
507 fn name(&self) -> &'static str {
508 std::any::type_name::<T>()
509 }
510 }
511 };
512}
513
514impl_system!();
515impl_system!(A);
516impl_system!(A, B);
517impl_system!(A, B, C);
518impl_system!(A, B, C, D);
519impl_system!(A, B, C, D, E);
520impl_system!(A, B, C, D, E, F);
521impl_system!(A, B, C, D, E, F, G);
522impl_system!(A, B, C, D, E, F, G, H);
523impl_system!(A, B, C, D, E, F, G, H, I);
524impl_system!(A, B, C, D, E, F, G, H, I, J);
525impl_system!(A, B, C, D, E, F, G, H, I, J, K);
526impl_system!(A, B, C, D, E, F, G, H, I, J, K, L);
527
528pub struct OnceFunctionSystem<F, Marker, State = ()> {
535 func: F,
536 state: State,
537 done: bool,
538 _marker: std::marker::PhantomData<Marker>,
539}
540
541pub trait OnceExt<Marker> {
563 type System: System;
564 fn once(self) -> Self::System;
565}
566
567macro_rules! impl_once_system {
568 ($($param:ident),*) => {
569 impl<T, $($param),*> OnceExt<($($param,)*)> for T
570 where
571 T: for<'a> FnMut($($param::Item<'a>),*) -> Option<()> + 'static,
572 for<'a> &'a mut T: FnMut($($param),*) -> Option<()>,
573 $($param: SystemParam + 'static),*
574 {
575 type System = OnceFunctionSystem<T, ($($param,)*), ($($param::State,)*)>;
576
577 fn once(self) -> Self::System {
578 OnceFunctionSystem {
579 func: self,
580 state: Default::default(),
581 done: false,
582 _marker: std::marker::PhantomData,
583 }
584 }
585 }
586
587 impl<T, $($param),*> IntoSystem<($($param,)*)> for OnceFunctionSystem<T, ($($param,)*), ($($param::State,)*)>
588 where
589 T: for<'a> FnMut($($param::Item<'a>),*) -> Option<()> + 'static,
590 $($param: SystemParam + 'static),*
591 {
592 type System = Self;
593
594 fn into_system(self) -> Self::System {
595 self
596 }
597 }
598
599 impl<T, $($param),*> System for OnceFunctionSystem<T, ($($param,)*), ($($param::State,)*)>
600 where
601 T: for<'a> FnMut($($param::Item<'a>),*) -> Option<()> + 'static,
602 $($param: SystemParam + 'static),*
603 {
604 fn run(&mut self, _world: &hecs::World, _resources: &Resources) {
605 if self.done {
606 return;
607 }
608 #[allow(non_snake_case)]
609 let ($($param,)*) = &mut self.state;
610 let result = (self.func)($($param::fetch($param, _world, _resources)),*);
611 if result.is_some() {
612 self.done = true;
613 }
614 }
615
616 fn requires(&self) -> Vec<RequiredResource> {
617 if self.done {
618 return Vec::new();
619 }
620 let mut _v = Vec::new();
621 $(_v.extend($param::requires());)*
622 _v
623 }
624
625 fn name(&self) -> &'static str {
626 std::any::type_name::<T>()
627 }
628 }
629 };
630}
631
632impl_once_system!();
633impl_once_system!(A);
634impl_once_system!(A, B);
635impl_once_system!(A, B, C);
636impl_once_system!(A, B, C, D);
637impl_once_system!(A, B, C, D, E);
638impl_once_system!(A, B, C, D, E, F);
639impl_once_system!(A, B, C, D, E, F, G);
640impl_once_system!(A, B, C, D, E, F, G, H);
641impl_once_system!(A, B, C, D, E, F, G, H, I);
642impl_once_system!(A, B, C, D, E, F, G, H, I, J);
643impl_once_system!(A, B, C, D, E, F, G, H, I, J, K);
644impl_once_system!(A, B, C, D, E, F, G, H, I, J, K, L);