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> {
65 world: &'a hecs::World,
66 borrow: hecs::QueryBorrow<'a, Q>,
67}
68
69impl<'a, Q: hecs::Query> Deref for Query<'a, Q> {
70 type Target = hecs::QueryBorrow<'a, Q>;
71 fn deref(&self) -> &Self::Target {
72 &self.borrow
73 }
74}
75
76impl<'a, Q: hecs::Query> DerefMut for Query<'a, Q> {
77 fn deref_mut(&mut self) -> &mut Self::Target {
78 &mut self.borrow
79 }
80}
81
82impl<'q, Q: hecs::Query> IntoIterator for &'q mut Query<'_, Q> {
83 type Item = Q::Item<'q>;
84 type IntoIter = hecs::QueryIter<'q, Q>;
85
86 fn into_iter(self) -> Self::IntoIter {
87 (&mut self.borrow).into_iter()
88 }
89}
90
91impl<'a, Q: hecs::Query> Query<'a, Q> {
92 pub fn get(&self, entity: hecs::Entity) -> hecs::QueryOne<'_, Q> {
95 self.world.query_one::<Q>(entity)
96 }
97
98 pub fn with<R: hecs::Query>(self) -> hecs::QueryBorrow<'a, hecs::With<Q, R>> {
102 self.borrow.with::<R>()
103 }
104
105 pub fn without<R: hecs::Query>(self) -> hecs::QueryBorrow<'a, hecs::Without<Q, R>> {
108 self.borrow.without::<R>()
109 }
110
111 pub fn single(&mut self) -> Q::Item<'_> {
119 self.get_single()
120 .expect("Query::single: expected exactly one matching entity")
121 }
122
123 pub fn get_single(&mut self) -> Option<Q::Item<'_>> {
126 let mut iter = self.borrow.iter();
127 let first = iter.next()?;
128 if iter.next().is_some() {
129 return None;
130 }
131 Some(first)
132 }
133}
134
135pub struct Commands<'a> {
140 buffer: RefMut<'a, hecs::CommandBuffer>,
141 resource_entity: hecs::Entity,
142}
143
144impl<'a> Commands<'a> {
145 pub fn insert_resource<T: hecs::Component>(&mut self, res: T) {
147 self.buffer.insert_one(self.resource_entity, res);
148 }
149
150 pub fn remove_resource<T: hecs::Component>(&mut self) {
152 self.buffer.remove_one::<T>(self.resource_entity);
153 }
154}
155
156impl<'a> Deref for Commands<'a> {
157 type Target = hecs::CommandBuffer;
158 fn deref(&self) -> &Self::Target {
159 &self.buffer
160 }
161}
162
163impl<'a> DerefMut for Commands<'a> {
164 fn deref_mut(&mut self) -> &mut Self::Target {
165 &mut self.buffer
166 }
167}
168
169pub struct Local<'a, T: Default + Send + Sync + 'static> {
179 data: &'a mut T,
180}
181
182impl<'a, T: Default + Send + Sync + 'static> Deref for Local<'a, T> {
183 type Target = T;
184 fn deref(&self) -> &Self::Target {
185 self.data
186 }
187}
188
189impl<'a, T: Default + Send + Sync + 'static> DerefMut for Local<'a, T> {
190 fn deref_mut(&mut self) -> &mut Self::Target {
191 self.data
192 }
193}
194
195pub trait SystemParam {
203 type Item<'a>;
204 type State: Default + 'static;
205 fn fetch<'a>(
206 state: &'a mut Self::State,
207 world: &'a hecs::World,
208 resources: &'a Resources,
209 ) -> Self::Item<'a>;
210}
211
212impl<T> SystemParam for Res<'static, T>
213where
214 T: 'static + Sync + Send,
215{
216 type Item<'a> = Res<'a, T>;
217 type State = ();
218
219 fn fetch<'a>(
220 _state: &'a mut Self::State,
221 world: &'a hecs::World,
222 resource: &'a Resources,
223 ) -> Self::Item<'a> {
224 Res {
225 data: resource.get_resource(world),
226 }
227 }
228}
229
230impl<T> SystemParam for Option<Res<'static, T>>
231where
232 T: 'static + Sync + Send,
233{
234 type Item<'a> = Option<Res<'a, T>>;
235 type State = ();
236
237 fn fetch<'a>(
238 _state: &'a mut Self::State,
239 world: &'a hecs::World,
240 resource: &'a Resources,
241 ) -> Self::Item<'a> {
242 if resource.has_resource::<T>(world) {
243 return Some(Res {
244 data: resource.get_resource(world),
245 });
246 }
247
248 None
249 }
250}
251
252impl<T> SystemParam for ResMut<'static, T>
253where
254 T: 'static + Sync + Send,
255{
256 type Item<'a> = ResMut<'a, T>;
257 type State = ();
258
259 fn fetch<'a>(
260 _state: &'a mut Self::State,
261 world: &'a hecs::World,
262 resource: &'a Resources,
263 ) -> Self::Item<'a> {
264 ResMut {
265 data: resource.get_resource_mut(world),
266 }
267 }
268}
269
270impl<T> SystemParam for Option<ResMut<'static, T>>
271where
272 T: 'static + Sync + Send,
273{
274 type Item<'a> = Option<ResMut<'a, T>>;
275 type State = ();
276
277 fn fetch<'a>(
278 _state: &'a mut Self::State,
279 world: &'a hecs::World,
280 resource: &'a Resources,
281 ) -> Self::Item<'a> {
282 if resource.has_resource::<T>(world) {
283 return Some(ResMut {
284 data: resource.get_resource_mut(world),
285 });
286 }
287
288 None
289 }
290}
291
292impl<Q> SystemParam for Query<'static, Q>
293where
294 Q: hecs::Query + 'static,
295{
296 type Item<'a> = Query<'a, Q>;
297 type State = ();
298
299 fn fetch<'a>(
300 _state: &'a mut Self::State,
301 world: &'a hecs::World,
302 _resources: &'a Resources,
303 ) -> Self::Item<'a> {
304 Query {
305 world: world,
306 borrow: world.query::<Q>(),
307 }
308 }
309}
310
311impl SystemParam for Commands<'static> {
312 type Item<'a> = Commands<'a>;
313 type State = ();
314
315 fn fetch<'a>(
316 _state: &'a mut Self::State,
317 _world: &'a hecs::World,
318 resources: &'a Resources,
319 ) -> Self::Item<'a> {
320 Commands {
321 buffer: resources.get_command_buffer(),
322 resource_entity: resources.resource_entity,
323 }
324 }
325}
326
327impl SystemParam for &'static hecs::World {
328 type Item<'a> = &'a hecs::World;
329 type State = ();
330
331 fn fetch<'a>(
332 _state: &'a mut Self::State,
333 world: &'a hecs::World,
334 _resources: &'a Resources,
335 ) -> Self::Item<'a> {
336 world
337 }
338}
339
340impl SystemParam for &'static Resources {
341 type Item<'a> = &'a Resources;
342 type State = ();
343
344 fn fetch<'a>(
345 _state: &'a mut Self::State,
346 _world: &'a hecs::World,
347 resources: &'a Resources,
348 ) -> Self::Item<'a> {
349 resources
350 }
351}
352
353impl<T> SystemParam for Local<'static, T>
354where
355 T: Default + Send + Sync + 'static,
356{
357 type Item<'a> = Local<'a, T>;
358 type State = T;
359
360 fn fetch<'a>(
361 state: &'a mut Self::State,
362 _world: &'a hecs::World,
363 _resources: &'a Resources,
364 ) -> Self::Item<'a> {
365 Local { data: state }
366 }
367}
368
369pub trait System: 'static {
371 fn run(&mut self, world: &hecs::World, resources: &Resources);
372}
373
374pub struct FunctionSystem<F, Marker, State = ()> {
379 pub func: F,
380 state: State,
381 _marker: std::marker::PhantomData<Marker>,
382}
383
384pub trait IntoSystem<Marker> {
389 type System: System;
390
391 fn into_system(self) -> Self::System;
392}
393
394macro_rules! impl_system {
395 ($($param:ident),*) => {
396 impl<T, $($param),*> IntoSystem<($($param,)*)> for T
397 where
398 T: for<'a> FnMut($($param::Item<'a>),*) + 'static,
399 for<'a> &'a mut T: FnMut($($param),*),
400 $($param: SystemParam + 'static),*
401 {
402 type System = FunctionSystem<T, ($($param,)*), ($($param::State,)*)>;
403
404 fn into_system(self) -> Self::System {
405 FunctionSystem {
406 func: self,
407 state: Default::default(),
408 _marker: std::marker::PhantomData,
409 }
410 }
411 }
412
413 impl<T, $($param),*> System for FunctionSystem<T, ($($param,)*), ($($param::State,)*)>
414 where
415 T: for<'a> FnMut($($param::Item<'a>),*) + 'static,
416 $($param: SystemParam + 'static),*
417 {
418 fn run(&mut self, _world: &hecs::World, _resources: &Resources) {
419 #[allow(non_snake_case)]
420 let ($($param,)*) = &mut self.state;
421 (self.func)($($param::fetch($param, _world, _resources)),*);
422 }
423 }
424 };
425}
426
427impl_system!();
428impl_system!(A);
429impl_system!(A, B);
430impl_system!(A, B, C);
431impl_system!(A, B, C, D);
432impl_system!(A, B, C, D, E);
433impl_system!(A, B, C, D, E, F);
434impl_system!(A, B, C, D, E, F, G);
435impl_system!(A, B, C, D, E, F, G, H);