bevy_trait_query/all/core/
read.rs1use bevy_ecs::{
2 change_detection::{DetectChanges, Ref},
3 component::{ComponentId, Tick},
4 entity::Entity,
5 ptr::UnsafeCellDeref,
6 storage::{SparseSets, Table, TableRow},
7};
8
9use crate::{zip_exact, TraitImplMeta, TraitImplRegistry, TraitQuery};
10
11pub struct ReadTraits<'a, Trait: ?Sized + TraitQuery> {
18 pub(crate) registry: &'a TraitImplRegistry<Trait>,
22 pub(crate) table: &'a Table,
23 pub(crate) table_row: TableRow,
24 pub(crate) sparse_sets: &'a SparseSets,
29 pub(crate) last_run: Tick,
30 pub(crate) this_run: Tick,
31}
32
33#[doc(hidden)]
34pub type CombinedReadTraitsIter<'a, Trait> =
35 std::iter::Chain<ReadTableTraitsIter<'a, Trait>, ReadSparseTraitsIter<'a, Trait>>;
36
37#[doc(hidden)]
38pub struct ReadTableTraitsIter<'a, Trait: ?Sized> {
39 pub(crate) components: std::slice::Iter<'a, ComponentId>,
41 pub(crate) meta: std::slice::Iter<'a, TraitImplMeta<Trait>>,
42 pub(crate) table_row: TableRow,
43 pub(crate) table: &'a Table,
46 pub(crate) last_run: Tick,
47 pub(crate) this_run: Tick,
48}
49
50impl<'a, Trait: ?Sized + TraitQuery> Iterator for ReadTableTraitsIter<'a, Trait> {
51 type Item = Ref<'a, Trait>;
52 fn next(&mut self) -> Option<Self::Item> {
53 let (ptr, component_id, meta) = unsafe { zip_exact(&mut self.components, &mut self.meta) }
56 .find_map(|(&component, meta)| {
57 let ptr = unsafe { self.table.get_component(component, self.table_row) }?;
59 Some((ptr, component, meta))
60 })?;
61 let trait_object = unsafe { meta.dyn_ctor.cast(ptr) };
62
63 let added_tick = unsafe {
66 self.table
67 .get_added_tick(component_id, self.table_row)?
68 .deref()
69 };
70 let changed_tick = unsafe {
71 self.table
72 .get_changed_tick(component_id, self.table_row)?
73 .deref()
74 };
75 let location = unsafe {
76 self.table
77 .get_changed_by(component_id, self.table_row)
78 .transpose()?
79 .map(|loc| loc.deref())
80 };
81
82 Some(Ref::new(
83 trait_object,
84 added_tick,
85 changed_tick,
86 self.last_run,
87 self.this_run,
88 location,
89 ))
90 }
91}
92
93#[doc(hidden)]
94pub struct ReadSparseTraitsIter<'a, Trait: ?Sized> {
95 pub(crate) components: std::slice::Iter<'a, ComponentId>,
97 pub(crate) meta: std::slice::Iter<'a, TraitImplMeta<Trait>>,
98 pub(crate) entity: Entity,
99 pub(crate) sparse_sets: &'a SparseSets,
101 pub(crate) last_run: Tick,
102 pub(crate) this_run: Tick,
103}
104
105impl<'a, Trait: ?Sized + TraitQuery> Iterator for ReadSparseTraitsIter<'a, Trait> {
106 type Item = Ref<'a, Trait>;
107 fn next(&mut self) -> Option<Self::Item> {
108 let (ptr, ticks_ptr, meta, location) =
111 unsafe { zip_exact(&mut self.components, &mut self.meta) }.find_map(
112 |(&component, meta)| {
113 let set = self.sparse_sets.get(component)?;
114 let (ptr, ticks, location) = set.get_with_ticks(self.entity)?;
115 Some((ptr, ticks, meta, location))
116 },
117 )?;
118 let trait_object = unsafe { meta.dyn_ctor.cast(ptr) };
119 let added_tick = unsafe { ticks_ptr.added.deref() };
120 let changed_tick = unsafe { ticks_ptr.changed.deref() };
121 Some(Ref::new(
122 trait_object,
123 added_tick,
124 changed_tick,
125 self.last_run,
126 self.this_run,
127 location.map(|loc| unsafe { loc.deref() }),
128 ))
129 }
130}
131
132impl<'w, Trait: ?Sized + TraitQuery> IntoIterator for ReadTraits<'w, Trait> {
133 type Item = Ref<'w, Trait>;
134 type IntoIter = CombinedReadTraitsIter<'w, Trait>;
135 #[inline]
136 fn into_iter(self) -> Self::IntoIter {
137 let table = ReadTableTraitsIter {
138 components: self.registry.table_components.iter(),
139 meta: self.registry.table_meta.iter(),
140 table: self.table,
141 table_row: self.table_row,
142 last_run: self.last_run,
143 this_run: self.this_run,
144 };
145 let sparse = ReadSparseTraitsIter {
146 components: self.registry.sparse_components.iter(),
147 meta: self.registry.sparse_meta.iter(),
148 entity: self.table.entities()[self.table_row.as_usize()],
149 sparse_sets: self.sparse_sets,
150 last_run: self.last_run,
151 this_run: self.this_run,
152 };
153 table.chain(sparse)
154 }
155}
156
157impl<'w, Trait: ?Sized + TraitQuery> IntoIterator for &ReadTraits<'w, Trait> {
158 type Item = Ref<'w, Trait>;
159 type IntoIter = CombinedReadTraitsIter<'w, Trait>;
160 #[inline]
161 fn into_iter(self) -> Self::IntoIter {
162 let table = ReadTableTraitsIter {
163 components: self.registry.table_components.iter(),
164 meta: self.registry.table_meta.iter(),
165 table: self.table,
166 table_row: self.table_row,
167 last_run: self.last_run,
168 this_run: self.this_run,
169 };
170 let sparse = ReadSparseTraitsIter {
171 components: self.registry.sparse_components.iter(),
172 meta: self.registry.sparse_meta.iter(),
173 entity: self.table.entities()[self.table_row.as_usize()],
174 sparse_sets: self.sparse_sets,
175 last_run: self.last_run,
176 this_run: self.this_run,
177 };
178 table.chain(sparse)
179 }
180}
181
182impl<'w, Trait: ?Sized + TraitQuery> ReadTraits<'w, Trait> {
183 pub fn iter(&self) -> CombinedReadTraitsIter<'w, Trait> {
185 self.into_iter()
186 }
187
188 pub fn iter_added(&self) -> impl Iterator<Item = Ref<'w, Trait>> + use<'w, Trait> {
191 self.iter().filter(DetectChanges::is_added)
192 }
193
194 pub fn iter_changed(&self) -> impl Iterator<Item = Ref<'w, Trait>> + use<'w, Trait> {
197 self.iter().filter(DetectChanges::is_changed)
198 }
199}