1use std::borrow::Cow;
2use std::marker::PhantomData;
3use std::ops::{Deref, DerefMut};
4
5use pi_proc_macros::all_tuples;
6use pi_share::Share;
7
8use crate::archetype::{ArchetypeIndex, ComponentInfo, Row, COMPONENT_TICK};
9use crate::column::{BlobRef, Column};
10use crate::prelude::FromWorld;
11use crate::single_res::TickRes;
12use crate::system::{Relation, SystemMeta};
13use crate::world::{ComponentIndex, Entity, Tick, World};
14
15pub trait FetchComponents {
16 type Item<'a>;
18 type ReadOnly: FetchComponents;
20 type Fetch<'a>;
22
23 type State: Send + Sync + Sized;
27
28 fn init_state(_world: &mut World, _meta: &mut SystemMeta) -> Self::State;
30
31 fn init_fetch<'w>(
39 world: &'w World,
40 state: &'w Self::State,
41 index: ArchetypeIndex,
42 tick: Tick,
43 last_run: Tick,
44 ) -> Self::Fetch<'w>;
45
46 fn init_fetch_opt<'w>(
47 world: &'w World,
48 state: &'w Self::State,
49 index: ArchetypeIndex,
50 tick: Tick,
51 last_run: Tick,
52 ) -> Option<Self::Fetch<'w>>;
53
54 fn fetch<'w>(fetch: &Self::Fetch<'w>, row: Row, e: Entity) -> Self::Item<'w>;
68}
69
70impl FetchComponents for Entity {
71 type Fetch<'w> = ();
72 type Item<'w> = Entity;
73 type ReadOnly = Self;
74 type State = ();
75
76 fn init_state(_world: &mut World, _meta: &mut SystemMeta) -> Self::State {}
77 fn init_fetch<'w>(
79 _world: &'w World,
80 _state: &'w Self::State,
81 _index: ArchetypeIndex,
82 _tick: Tick,
83 _last_run: Tick,
84 ) -> Self::Fetch<'w>{
85 ()
86 }
87
88 fn init_fetch_opt<'w>(
90 _world: &'w World,
91 _state: &'w Self::State,
92 _index: ArchetypeIndex,
93 _tick: Tick,
94 _last_run: Tick,
95 ) -> Option<Self::Fetch<'w>>{
96 Some(())
97 }
98
99 fn fetch<'w>(_fetch: &Self::Fetch<'w>, _row: Row, e: Entity) -> Self::Item<'w> {
101 e
102 }
103}
104
105impl<T: 'static> FetchComponents for &T {
106 type Fetch<'w> = BlobRef<'w>; type Item<'w> = &'w T;
108 type ReadOnly = Self;
109 type State = Share<Column>;
110
111 fn init_state(world: &mut World, meta: &mut SystemMeta) -> Self::State {
112 meta.component_relate(
113 world,
114 ComponentInfo::of::<T>(0),
115 Relation::Read(0usize.into()),
116 )
117 .1
118 }
119 fn init_fetch<'w>(
121 _world: &'w World,
122 state: &'w Self::State,
123 index: ArchetypeIndex,
124 _tick: Tick,
125 _last_run: Tick,
126 ) -> Self::Fetch<'w>{
127 state.blob_ref_unchecked(index)
128 }
129
130 fn init_fetch_opt<'w>(
132 _world: &'w World,
133 state: &'w Self::State,
134 index: ArchetypeIndex,
135 _tick: Tick,
136 _last_run: Tick,
137 ) -> Option<Self::Fetch<'w>>{
138 state.blob_ref(index)
139 }
140
141 fn fetch<'w>(fetch: &Self::Fetch<'w>, row: Row, _e: Entity) -> Self::Item<'w> {
143 fetch.get_unchecked::<T>(row)
144 }
145}
146
147impl<T: 'static> FetchComponents for &mut T {
148 type Fetch<'w> = ColumnTick<'w>;
149 type Item<'w> = Mut<'w, T>;
150 type ReadOnly = &'static T;
151 type State = Share<Column>;
152
153 fn init_state(world: &mut World, meta: &mut SystemMeta) -> Self::State {
154 meta.component_relate(
155 world,
156 ComponentInfo::of::<T>(0),
157 Relation::Write(0usize.into()),
158 )
159 .1
160 }
161 fn init_fetch<'w>(
163 _world: &'w World,
164 state: &'w Self::State,
165 index: ArchetypeIndex,
166 tick: Tick,
167 last_run: Tick,
168 ) -> Self::Fetch<'w>{
169 ColumnTick::new(state.blob_ref_unchecked(index), tick, last_run)
170 }
171
172 fn init_fetch_opt<'w>(
174 _world: &'w World,
175 state: &'w Self::State,
176 index: ArchetypeIndex,
177 tick: Tick,
178 last_run: Tick,
179 ) -> Option<Self::Fetch<'w>>{
180 state.blob_ref(index).map(|r| {
181 ColumnTick::new(r, tick, last_run)
182 })
183 }
184
185 fn fetch<'w>(fetch: &Self::Fetch<'w>, row: Row, e: Entity) -> Self::Item<'w> {
187 Mut::new(fetch, e, row)
188 }
189}
190
191pub struct Ref<T: 'static>(PhantomData<T>);
192impl<T: 'static> FetchComponents for Ref<T> {
193 type Fetch<'w> = ColumnTick<'w>;
194 type Item<'w> = TickRef<'w, T>;
195 type ReadOnly = Self;
196 type State = Share<Column>;
197
198 fn init_state(world: &mut World, meta: &mut SystemMeta) -> Self::State {
199 meta.component_relate(
200 world,
201 ComponentInfo::of::<T>(COMPONENT_TICK),
202 Relation::Read(0usize.into()),
203 )
204 .1
205 }
206 fn init_fetch<'w>(
208 _world: &'w World,
209 state: &'w Self::State,
210 index: ArchetypeIndex,
211 tick: Tick,
212 last_run: Tick,
213 ) -> Self::Fetch<'w>{
214 ColumnTick::new(state.blob_ref_unchecked(index), tick, last_run)
215 }
216
217 fn init_fetch_opt<'w>(
219 _world: &'w World,
220 state: &'w Self::State,
221 index: ArchetypeIndex,
222 tick: Tick,
223 last_run: Tick,
224 ) -> Option<Self::Fetch<'w>>{
225 state.blob_ref(index).map(|r| {
226 ColumnTick::new(r, tick, last_run)
227 })
228 }
229
230 fn fetch<'w>(fetch: &Self::Fetch<'w>, row: Row, e: Entity) -> Self::Item<'w> {
232 TickRef::new(fetch, row, e)
233 }
234}
235
236impl<T: 'static> FetchComponents for Option<Ref<T>> {
237 type Fetch<'w> = Option<ColumnTick<'w>>;
238 type Item<'w> = Option<TickRef<'w, T>>;
239 type ReadOnly = Self;
240 type State = Share<Column>;
241
242 fn init_state(world: &mut World, meta: &mut SystemMeta) -> Self::State {
243 meta.component_relate(
244 world,
245 ComponentInfo::of::<T>(COMPONENT_TICK),
246 Relation::OptRead(0usize.into()),
247 )
248 .1
249 }
250 fn init_fetch<'w>(
252 _world: &'w World,
253 state: &'w Self::State,
254 index: ArchetypeIndex,
255 tick: Tick,
256 last_run: Tick,
257 ) -> Self::Fetch<'w> {
258 if let Some(column) = state.blob_ref(index) {
259 Some(ColumnTick::new(column, tick, last_run))
260 } else {
261 None
262 }
263 }
264
265 fn init_fetch_opt<'w>(
267 _world: &'w World,
268 state: &'w Self::State,
269 index: ArchetypeIndex,
270 tick: Tick,
271 last_run: Tick,
272 ) -> Option<Self::Fetch<'w>> {
273 Some(Self::init_fetch(_world, state, index, tick, last_run))
274 }
275
276 fn fetch<'w>(fetch: &Self::Fetch<'w>, row: Row, e: Entity) -> Self::Item<'w> {
278 match fetch {
279 Some(c) => Some(TickRef::new(c, row, e)),
280 None => None,
281 }
282 }
283}
284
285impl<T: 'static> FetchComponents for Ticker<'_, &'_ T> {
286 type Fetch<'w> = ColumnTick<'w>;
287 type Item<'w> = Ticker<'w, &'w T>;
288 type ReadOnly = Ticker<'static, &'static T>;
289 type State = Share<Column>;
290
291 fn init_state(world: &mut World, meta: &mut SystemMeta) -> Self::State {
292 meta.component_relate(
293 world,
294 ComponentInfo::of::<T>(COMPONENT_TICK),
295 Relation::Read(0usize.into()),
296 )
297 .1
298 }
299 fn init_fetch<'w>(
301 _world: &'w World,
302 state: &'w Self::State,
303 index: ArchetypeIndex,
304 tick: Tick,
305 last_run: Tick,
306 ) -> Self::Fetch<'w> {
307 ColumnTick::new(state.blob_ref_unchecked(index), tick, last_run)
308 }
309 fn init_fetch_opt<'w>(
311 _world: &'w World,
312 state: &'w Self::State,
313 index: ArchetypeIndex,
314 tick: Tick,
315 last_run: Tick,
316 ) -> Option<Self::Fetch<'w>>{
317 state.blob_ref(index).map(|r| {
318 ColumnTick::new(r, tick, last_run)
319 })
320 }
321 fn fetch<'w>(fetch: &Self::Fetch<'w>, row: Row, e: Entity) -> Self::Item<'w> {
323 Ticker::new(fetch, e, row)
324 }
325}
326
327impl<T: 'static> FetchComponents for Ticker<'_, &'_ mut T> {
328 type Fetch<'w> = ColumnTick<'w>;
329 type Item<'w> = Ticker<'w, &'w mut T>;
330 type ReadOnly = Ticker<'static, &'static T>;
331 type State = Share<Column>;
332
333 fn init_state(world: &mut World, meta: &mut SystemMeta) -> Self::State {
334 meta.component_relate(
335 world,
336 ComponentInfo::of::<T>(COMPONENT_TICK),
337 Relation::Write(0usize.into()),
338 )
339 .1
340 }
341 fn init_fetch<'w>(
343 _world: &'w World,
344 state: &'w Self::State,
345 index: ArchetypeIndex,
346 tick: Tick,
347 last_run: Tick,
348 ) -> Self::Fetch<'w> {
349 ColumnTick::new(state.blob_ref_unchecked(index), tick, last_run)
350 }
351 fn init_fetch_opt<'w>(
353 _world: &'w World,
354 state: &'w Self::State,
355 index: ArchetypeIndex,
356 tick: Tick,
357 last_run: Tick,
358 ) -> Option<Self::Fetch<'w>>{
359 state.blob_ref(index).map(|r| {
360 ColumnTick::new(r, tick, last_run)
361 })
362 }
363 fn fetch<'w>(fetch: &Self::Fetch<'w>, row: Row, e: Entity) -> Self::Item<'w> {
365 Ticker::new(fetch, e, row)
366 }
367}
368
369impl<T: 'static> FetchComponents for Option<Ticker<'_, &'_ T>> {
370 type Fetch<'w> = Option<ColumnTick<'w>>;
371 type Item<'w> = Option<Ticker<'w, &'w T>>;
372 type ReadOnly = Option<Ticker<'static, &'static T>>;
373 type State = Share<Column>;
374
375 fn init_state(world: &mut World, meta: &mut SystemMeta) -> Self::State {
376 meta.component_relate(
377 world,
378 ComponentInfo::of::<T>(COMPONENT_TICK),
379 Relation::OptRead(0usize.into()),
380 )
381 .1
382 }
383 fn init_fetch<'w>(
385 _world: &'w World,
386 state: &'w Self::State,
387 index: ArchetypeIndex,
388 tick: Tick,
389 last_run: Tick,
390 ) -> Self::Fetch<'w> {
391 if let Some(column) = state.blob_ref(index) {
392 Some(ColumnTick::new(column, tick, last_run))
393 } else {
394 None
395 }
396 }
397
398 fn init_fetch_opt<'w>(
400 world: &'w World,
401 state: &'w Self::State,
402 index: ArchetypeIndex,
403 tick: Tick,
404 last_run: Tick,
405 ) -> Option<Self::Fetch<'w>>{
406 Some(Self::init_fetch(world, state, index, tick, last_run))
407 }
408 fn fetch<'w>(fetch: &Self::Fetch<'w>, row: Row, e: Entity) -> Self::Item<'w> {
410 match fetch {
411 Some(f) => Some(Ticker::new(f, e, row)),
412 None => None,
413 }
414 }
415}
416
417impl<T: 'static> FetchComponents for Option<Ticker<'_, &'_ mut T>> {
418 type Fetch<'w> = Option<ColumnTick<'w>>;
419 type Item<'w> = Option<Ticker<'w, &'w mut T>>;
420 type ReadOnly = Option<Ticker<'static, &'static T>>;
421 type State = Share<Column>;
422
423 fn init_state(world: &mut World, meta: &mut SystemMeta) -> Self::State {
424 meta.component_relate(
425 world,
426 ComponentInfo::of::<T>(COMPONENT_TICK),
427 Relation::OptWrite(0usize.into()),
428 )
429 .1
430 }
431 fn init_fetch<'w>(
433 _world: &'w World,
434 state: &'w Self::State,
435 index: ArchetypeIndex,
436 tick: Tick,
437 last_run: Tick,
438 ) -> Self::Fetch<'w> {
439 if let Some(column) = state.blob_ref(index) {
440 Some(ColumnTick::new(column, tick, last_run))
441 } else {
442 None
443 }
444 }
445 fn init_fetch_opt<'w>(
447 world: &'w World,
448 state: &'w Self::State,
449 index: ArchetypeIndex,
450 tick: Tick,
451 last_run: Tick,
452 ) -> Option<Self::Fetch<'w>>{
453 Some(Self::init_fetch(world, state, index, tick, last_run))
454 }
455 fn fetch<'w>(fetch: &Self::Fetch<'w>, row: Row, e: Entity) -> Self::Item<'w> {
457 match fetch {
458 Some(f) => Some(Ticker::new(f, e, row)),
459 None => None,
460 }
461 }
462}
463
464impl<T: 'static> FetchComponents for Option<&T> {
465 type Fetch<'w> = Option<ColumnTick<'w>>;
466 type Item<'w> = Option<&'w T>;
467 type ReadOnly = Self;
468 type State = Share<Column>;
469
470 fn init_state(world: &mut World, meta: &mut SystemMeta) -> Self::State {
471 meta.component_relate(
472 world,
473 ComponentInfo::of::<T>(0),
474 Relation::OptRead(0usize.into()),
475 )
476 .1
477 }
478 fn init_fetch<'w>(
480 _world: &'w World,
481 state: &'w Self::State,
482 index: ArchetypeIndex,
483 tick: Tick,
484 last_run: Tick,
485 ) -> Self::Fetch<'w> {
486 if let Some(column) = state.blob_ref(index) {
487 Some(ColumnTick::new(column, tick, last_run))
488 } else {
489 None
490 }
491 }
492 fn init_fetch_opt<'w>(
494 world: &'w World,
495 state: &'w Self::State,
496 index: ArchetypeIndex,
497 tick: Tick,
498 last_run: Tick,
499 ) -> Option<Self::Fetch<'w>>{
500 Some(Self::init_fetch(world, state, index, tick, last_run))
501 }
502 fn fetch<'w>(fetch: &Self::Fetch<'w>, row: Row, _e: Entity) -> Self::Item<'w> {
504 match fetch {
505 Some(c) => Some(c.column.get_unchecked::<T>(row)),
506 None => None,
507 }
508 }
509}
510
511impl<T: 'static> FetchComponents for Option<&mut T> {
512 type Fetch<'w> = Option<ColumnTick<'w>>;
513 type Item<'w> = Option<Mut<'w, T>>;
514 type ReadOnly = Option<&'static T>;
515 type State = Share<Column>;
516
517 fn init_state(world: &mut World, meta: &mut SystemMeta) -> Self::State {
518 meta.component_relate(
519 world,
520 ComponentInfo::of::<T>(0),
521 Relation::OptWrite(0usize.into()),
522 )
523 .1
524 }
525 fn init_fetch<'w>(
527 _world: &'w World,
528 state: &'w Self::State,
529 index: ArchetypeIndex,
530 tick: Tick,
531 last_run: Tick,
532 ) -> Self::Fetch<'w> {
533 if let Some(column) = state.blob_ref(index) {
534 Some(ColumnTick::new(column, tick, last_run))
535 } else {
536 None
537 }
538 }
539 fn init_fetch_opt<'w>(
541 world: &'w World,
542 state: &'w Self::State,
543 index: ArchetypeIndex,
544 tick: Tick,
545 last_run: Tick,
546 ) -> Option<Self::Fetch<'w>>{
547 Some(Self::init_fetch(world, state, index, tick, last_run))
548 }
549 fn fetch<'w>(fetch: &Self::Fetch<'w>, row: Row, e: Entity) -> Self::Item<'w> {
551 match fetch {
552 Some(f) => Some(Mut::new(f, e, row)),
553 None => None,
554 }
555 }
556}
557
558fn _init_state_ordefault(world: &mut World, meta: &mut SystemMeta, info: ComponentInfo) -> Share<Column> {
559 meta.add_res(Relation::Read(*info.type_id()));
560 let column = meta
561 .component_relate(world, info, Relation::OptRead(0usize.into()))
562 .1;
563 column
564}
565
566pub struct OrDefault<T: 'static + FromWorld>(PhantomData<T>);
570impl<T: 'static + FromWorld> FetchComponents for OrDefault<T> {
571 type Fetch<'w> = Result<BlobRef<'w>, &'w T>;
572 type Item<'w> = &'w T;
573 type ReadOnly = Self;
574 type State = (Share<Column>, Share<TickRes<T>>);
575
576 fn init_state(world: &mut World, meta: &mut SystemMeta) -> Self::State {
577 let info = ComponentInfo::of::<T>(0);
578 let column = _init_state_ordefault(world, meta, info);
579 let _index = world.init_single_res::<T>();
584 (column, world.get_share_single_res::<T>().unwrap())
585 }
586 fn init_fetch<'w>(
588 _world: &'w World,
589 state: &'w Self::State,
590 index: ArchetypeIndex,
591 _tick: Tick,
592 _last_run: Tick,
593 ) -> Self::Fetch<'w> {
594 if let Some(column) = state.0.blob_ref(index) {
595 Ok(column)
596 } else {
597 Err(&state.1)
598 }
599 }
600 fn init_fetch_opt<'w>(
602 world: &'w World,
603 state: &'w Self::State,
604 index: ArchetypeIndex,
605 tick: Tick,
606 last_run: Tick,
607 ) -> Option<Self::Fetch<'w>> {
608 Some(Self::init_fetch(world, state, index, tick, last_run))
609 }
610 fn fetch<'w>(fetch: &Self::Fetch<'w>, row: Row, _e: Entity) -> Self::Item<'w> {
612 match fetch {
613 Ok(c) => c.get_unchecked::<T>(row),
614 Err(r) => *r,
615 }
616 }
617}
618pub struct OrDefaultRef<T: 'static + FromWorld>(PhantomData<T>);
622impl<T: 'static + FromWorld> FetchComponents for OrDefaultRef<T> {
623 type Fetch<'w> = Result<ColumnTick<'w>, (&'w T, Tick)>;
624 type Item<'w> = ValueRef<'w, T>;
625 type ReadOnly = Self;
626 type State = (Share<Column>, Share<TickRes<T>>);
627
628 fn init_state(world: &mut World, meta: &mut SystemMeta) -> Self::State {
629 let info = ComponentInfo::of::<T>(0);
630 let column = _init_state_ordefault(world, meta, info);
631 let _index = world.init_single_res::<T>();
636 (column, world.get_share_single_res::<T>().unwrap())
637 }
638 fn init_fetch<'w>(
640 _world: &'w World,
641 state: &'w Self::State,
642 index: ArchetypeIndex,
643 tick: Tick,
644 last_run: Tick,
645 ) -> Self::Fetch<'w> {
646 if let Some(column) = state.0.blob_ref(index) {
647 Ok(ColumnTick::new(column, tick, last_run))
648 } else {
649 Err((&state.1, last_run))
650 }
651 }
652 fn init_fetch_opt<'w>(
654 world: &'w World,
655 state: &'w Self::State,
656 index: ArchetypeIndex,
657 tick: Tick,
658 last_run: Tick,
659 ) -> Option<Self::Fetch<'w>> {
660 Some(Self::init_fetch(world, state, index, tick, last_run))
661 }
662 fn fetch<'w>(fetch: &Self::Fetch<'w>, row: Row, _e: Entity) -> Self::Item<'w> {
664 match fetch {
665 Ok(c) => {
666 let tick = c.column.get_tick_unchecked(row);
667 ValueRef::new(c.column.get_unchecked::<T>(row), tick, c.last_run)
668 }
669 Err(r) => ValueRef::new(r.0, 0usize.into(), r.1),
670 }
671 }
672}
673
674pub struct Has<T: 'static>(PhantomData<T>);
675impl<T: 'static> FetchComponents for Has<T> {
676 type Fetch<'w> = bool;
677 type Item<'w> = bool;
678 type ReadOnly = Self;
679 type State = Share<Column>;
680
681 fn init_state(world: &mut World, meta: &mut SystemMeta) -> Self::State {
682 meta.component_relate(
683 world,
684 ComponentInfo::of::<T>(0),
685 Relation::OptRead(0usize.into()),
686 )
687 .1
688 }
689 fn init_fetch<'w>(
691 _world: &'w World,
692 state: &'w Self::State,
693 index: ArchetypeIndex,
694 _tick: Tick,
695 _last_run: Tick,
696 ) -> Self::Fetch<'w> {
697 state.contains(index)
698 }
699 fn init_fetch_opt<'w>(
701 world: &'w World,
702 state: &'w Self::State,
703 index: ArchetypeIndex,
704 tick: Tick,
705 last_run: Tick,
706 ) -> Option<Self::Fetch<'w>> {
707 Some(Self::init_fetch(world, state, index, tick, last_run))
708 }
709 fn fetch<'w>(fetch: &Self::Fetch<'w>, _row: Row, _e: Entity) -> Self::Item<'w> {
711 *fetch
712 }
713}
714
715#[derive(Debug)]
716pub struct ComponentId<T: 'static>(pub ComponentIndex, PhantomData<T>);
717impl<T: 'static> FetchComponents for ComponentId<T> {
718 type Fetch<'w> = ComponentIndex;
719 type Item<'w> = ComponentIndex;
720 type ReadOnly = Self;
721 type State = ComponentIndex;
722
723 fn init_state(world: &mut World, _meta: &mut SystemMeta) -> Self::State {
724 world.init_component::<T>()
725 }
726
727 fn init_fetch<'w>(
728 _world: &'w World,
729 state: &'w Self::State,
730 _index: ArchetypeIndex,
731 _tick: Tick,
732 _last_run: Tick,
733 ) -> Self::Fetch<'w> {
734 *state
735 }
736 fn init_fetch_opt<'w>(
738 world: &'w World,
739 state: &'w Self::State,
740 index: ArchetypeIndex,
741 tick: Tick,
742 last_run: Tick,
743 ) -> Option<Self::Fetch<'w>> {
744 Some(Self::init_fetch(world, state, index, tick, last_run))
745 }
746
747 fn fetch<'w>(fetch: &Self::Fetch<'w>, _row: Row, _e: Entity) -> Self::Item<'w> {
748 *fetch
749 }
750}
751
752#[derive(Debug)]
753pub struct ArchetypeName<'a>(pub &'a Cow<'static, str>, pub ArchetypeIndex, pub Row);
754impl FetchComponents for ArchetypeName<'_> {
755 type Fetch<'w> = (&'w Cow<'static, str>, ArchetypeIndex);
756 type Item<'w> = ArchetypeName<'w>;
757 type ReadOnly = Self;
758 type State = ();
759
760 fn init_state(_world: &mut World, _meta: &mut SystemMeta) -> Self::State {}
761
762 fn init_fetch<'w>(
763 world: &'w World,
764 _state: &'w Self::State,
765 index: ArchetypeIndex,
766 _tick: Tick,
767 _last_run: Tick,
768 ) -> Self::Fetch<'w> {
769 let archetype = world.get_archetype(index).unwrap();
770 (archetype.name(), archetype.index())
771 }
772
773 fn init_fetch_opt<'w>(
775 world: &'w World,
776 state: &'w Self::State,
777 index: ArchetypeIndex,
778 tick: Tick,
779 last_run: Tick,
780 ) -> Option<Self::Fetch<'w>> {
781 Some(Self::init_fetch(world, state, index, tick, last_run))
782 }
783
784 fn fetch<'w>(fetch: &Self::Fetch<'w>, row: Row, _e: Entity) -> Self::Item<'w> {
785 ArchetypeName(fetch.0, fetch.1, row)
786 }
787}
788
789#[derive(Debug, Clone)]
790pub struct ColumnTick<'a> {
791 pub(crate) column: BlobRef<'a>,
792 pub(crate) tick: Tick,
793 pub(crate) last_run: Tick,
794}
795impl<'a> ColumnTick<'a> {
796 pub(crate) fn new(column: BlobRef<'a>, tick: Tick, last_run: Tick) -> Self {
798 Self {
799 column,
800 tick,
801 last_run,
802 }
803 }
804}
805
806#[derive(Debug)]
807pub struct TickRef<'a, T> {
808 pub(crate) c: ColumnTick<'a>,
809 pub(crate) row: Row,
810 pub(crate) e: Entity,
811 _p: PhantomData<T>,
812}
813
814impl<'a, T> TickRef<'a, T> {
815 pub fn new(c: &ColumnTick<'a>, row: Row, e: Entity) -> Self {
817 Self {
818 c: c.clone(),
819 row,
820 e,
821 _p: PhantomData,
822 }
823 }
824 pub fn entity(&self) -> Entity {
826 self.e
827 }
828 pub fn tick(&self) -> Tick {
829 self.c.column.get_tick_unchecked(self.row)
830 }
831 pub fn last_tick(&self) -> Tick {
833 self.c.last_run
834 }
835 pub fn is_changed(&self) -> bool {
837 self.c.column.get_tick_unchecked(self.row) > self.c.last_run
838 }
839}
840impl<'a, T: 'static> Deref for TickRef<'a, T> {
841 type Target = T;
842 fn deref(&self) -> &Self::Target {
844 self.c.column.get::<T>(self.row, self.e)
845 }
846}
847
848#[derive(Debug)]
849pub struct ValueRef<'a, T> {
850 pub(crate) value: &'a T,
851 pub(crate) tick: Tick,
852 pub(crate) last_run: Tick,
853}
854
855impl<'a, T> ValueRef<'a, T> {
856 pub fn new(value: &'a T, tick: Tick, last_run: Tick) -> Self {
858 Self {
859 value,
860 tick,
861 last_run,
862 }
863 }
864
865 pub fn tick(&self) -> Tick {
866 self.tick
867 }
868 pub fn last_tick(&self) -> Tick {
870 self.last_run
871 }
872 pub fn is_changed(&self) -> bool {
874 self.tick > self.last_run
875 }
876}
877impl<'a, T: 'static> Deref for ValueRef<'a, T> {
878 type Target = T;
879 fn deref(&self) -> &Self::Target {
881 self.value
882 }
883}
884
885#[derive(Debug)]
886pub struct Ticker<'a, T> {
887 pub(crate) c: ColumnTick<'a>,
888 pub(crate) e: Entity,
889 pub(crate) row: Row,
890 _p: PhantomData<T>,
891}
892
893impl<'a, T> Ticker<'a, T> {
894 pub fn new(c: &ColumnTick<'a>, e: Entity, row: Row) -> Self {
895 Self {
896 c: c.clone(),
897 e,
898 row,
899 _p: PhantomData,
900 }
901 }
902
903 pub fn entity(&self) -> Entity {
904 self.e
905 }
906
907 pub fn tick(&self) -> Tick {
908 self.c.column.get_tick_unchecked(self.row)
909 }
910
911 pub fn last_tick(&self) -> Tick {
912 self.c.last_run
913 }
914
915 pub fn is_changed(&self) -> bool {
916 self.c.column.get_tick_unchecked(self.row) > self.c.last_run
917 }
918}
919impl<'a, T: 'static> Deref for Ticker<'a, &'_ T> {
920 type Target = T;
921
922 fn deref(&self) -> &Self::Target {
923 self.c.column.get_unchecked::<T>(self.row)
924 }
925}
926
927impl<'a, T: 'static> Deref for Ticker<'a, &'_ mut T> {
928 type Target = T;
929
930 fn deref(&self) -> &Self::Target {
931 self.c.column.get_unchecked::<T>(self.row)
932 }
933}
934
935impl<'a, T: 'static> Ticker<'a, &'_ mut T> {
936 pub fn bypass_change_detection(&mut self) -> &mut T {
937 self.c.column.get_mut::<T>(self.row, self.e)
938 }
939
940 pub fn set_changed(&mut self) {
941 self.c.column.changed_tick(self.e, self.row, self.c.tick);
942 }
943}
944
945impl<'a, T: 'static> DerefMut for Ticker<'a, &'_ mut T> {
946 fn deref_mut(&mut self) -> &mut Self::Target {
947 self.c.column.changed_tick(self.e, self.row, self.c.tick);
948 self.c.column.get_mut::<T>(self.row, self.e)
949 }
950}
951
952#[derive(Debug)]
954pub struct Mut<'a, T: 'static> {
955 pub(crate) c: ColumnTick<'a>,
956 pub(crate) e: Entity,
957 pub(crate) row: Row,
958 _p: PhantomData<T>,
959}
960impl<'a, T: Sized> Mut<'a, T> {
961 pub fn new(c: &ColumnTick<'a>, e: Entity, row: Row) -> Self {
963 Self {
964 c: c.clone(),
965 e,
966 row,
967 _p: PhantomData,
968 }
969 }
970 pub fn entity(&self) -> Entity {
972 self.e
973 }
974 pub fn tick(&self) -> Tick {
975 self.c.column.get_tick_unchecked(self.row)
976 }
977 pub fn last_tick(&self) -> Tick {
979 self.c.last_run
980 }
981 pub fn is_changed(&self) -> bool {
983 self.c.column.get_tick_unchecked(self.row) > self.c.last_run
984 }
985 pub fn bypass_change_detection(&mut self) -> &mut T {
986 self.c.column.get_mut::<T>(self.row, self.e)
987 }
988
989 pub fn set_changed(&mut self) {
990 self.c.column.changed_tick(self.e, self.row, self.c.tick);
991 }
992
993 pub fn into_inner(self) -> &'a mut T {
994 self.c.column.changed_tick(self.e, self.row, self.c.tick);
995 self.c.column.get_mut::<T>(self.row, self.e)
996 }
997}
998impl<'a, T: 'static> Deref for Mut<'a, T> {
999 type Target = T;
1000 fn deref(&self) -> &Self::Target {
1002 self.c.column.get_unchecked::<T>(self.row)
1003 }
1004}
1005impl<'a, T: 'static> DerefMut for Mut<'a, T> {
1006 fn deref_mut(&mut self) -> &mut Self::Target {
1008 self.c.column.changed_tick(self.e, self.row, self.c.tick);
1010 self.c.column.get_unchecked_mut::<T>(self.row)
1011 }
1012}
1013
1014macro_rules! impl_tuple_fetch {
1015 ($(($name: ident, $state: ident)),*) => {
1016 #[allow(non_snake_case)]
1017 #[allow(clippy::unused_unit)]
1018
1019 impl<$($name: FetchComponents),*> FetchComponents for ($($name,)*) {
1020 type Fetch<'w> = ($($name::Fetch<'w>,)*);
1021 type Item<'w> = ($($name::Item<'w>,)*);
1022 type ReadOnly = ($($name::ReadOnly,)*);
1023 type State = ($($name::State,)*);
1024
1025 fn init_state(_world: &mut World, _meta: &mut SystemMeta) -> Self::State {
1026 ($($name::init_state(_world, _meta),)*)
1027 }
1028 #[allow(clippy::unused_unit)]
1029 fn init_fetch<'w>(
1031 _world: &'w World,
1032 _state: &'w Self::State,
1033 _index: ArchetypeIndex,
1034 _tick: Tick,
1035 _last_run: Tick,
1036 ) -> Self::Fetch<'w> {
1037 let ($($state,)*) = _state;
1038 ($($name::init_fetch(_world, $state, _index, _tick, _last_run),)*)
1039 }
1040
1041 fn init_fetch_opt<'w>(
1043 _world: &'w World,
1044 _state: &'w Self::State,
1045 _index: ArchetypeIndex,
1046 _tick: Tick,
1047 _last_run: Tick,
1048 ) -> Option<Self::Fetch<'w>> {
1049 let ($($state,)*) = _state;
1050 let r = ($(match $name::init_fetch_opt(_world, $state, _index, _tick, _last_run) {
1051 Some(fetch) => fetch,
1052 None => return None,
1053 },)*);
1054 Some(r)
1055 }
1056
1057 #[allow(clippy::unused_unit)]
1058 fn fetch<'w>(
1060 _fetch: &Self::Fetch<'w>,
1061 _row: Row,
1062 _e: Entity,
1063 ) -> Self::Item<'w> {
1064 let ($($name,)*) = _fetch;
1065 ($($name::fetch($name, _row, _e),)*)
1066 }
1067 }
1068
1069 };
1070}
1071all_tuples!(impl_tuple_fetch, 0, 15, F, S);