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