bevy_trait_query/all/core/
write.rs1use bevy_ecs::{
2 change_detection::{DetectChanges, Mut, Ref},
3 component::{ComponentId, Tick},
4 entity::Entity,
5 ptr::UnsafeCellDeref,
6 storage::{SparseSets, Table, TableRow},
7};
8
9use crate::{
10 zip_exact, CombinedReadTraitsIter, ReadSparseTraitsIter, ReadTableTraitsIter, TraitImplMeta,
11 TraitImplRegistry, TraitQuery,
12};
13
14pub struct WriteTraits<'a, Trait: ?Sized + TraitQuery> {
21 pub(crate) registry: &'a TraitImplRegistry<Trait>,
25
26 pub(crate) table: &'a Table,
27 pub(crate) table_row: TableRow,
28
29 pub(crate) last_run: Tick,
30 pub(crate) this_run: Tick,
31
32 pub(crate) sparse_sets: &'a SparseSets,
37}
38
39#[doc(hidden)]
40pub type CombinedWriteTraitsIter<'a, Trait> =
41 std::iter::Chain<WriteTableTraitsIter<'a, Trait>, WriteSparseTraitsIter<'a, Trait>>;
42
43#[doc(hidden)]
44pub struct WriteTableTraitsIter<'a, Trait: ?Sized> {
45 pub(crate) components: std::slice::Iter<'a, ComponentId>,
47 pub(crate) meta: std::slice::Iter<'a, TraitImplMeta<Trait>>,
48 pub(crate) table: &'a Table,
49 pub(crate) table_row: TableRow,
52 pub(crate) last_run: Tick,
53 pub(crate) this_run: Tick,
54}
55
56impl<'a, Trait: ?Sized + TraitQuery> Iterator for WriteTableTraitsIter<'a, Trait> {
57 type Item = Mut<'a, Trait>;
58 fn next(&mut self) -> Option<Self::Item> {
59 let (ptr, component_id, meta) = unsafe { zip_exact(&mut self.components, &mut self.meta) }
62 .find_map(|(&component, meta)| {
63 let ptr = unsafe { self.table.get_component(component, self.table_row) }?;
65 Some((ptr, component, meta))
66 })?;
67 let ptr = unsafe { ptr.assert_unique() };
73 let trait_object = unsafe { meta.dyn_ctor.cast_mut(ptr) };
74 let added = unsafe {
77 self.table
78 .get_added_tick(component_id, self.table_row)?
79 .deref_mut()
80 };
81 let changed = unsafe {
82 self.table
83 .get_changed_tick(component_id, self.table_row)?
84 .deref_mut()
85 };
86 let location = unsafe {
87 self.table
88 .get_changed_by(component_id, self.table_row)
89 .transpose()?
90 .map(|loc| loc.deref_mut())
91 };
92 Some(Mut::new(
93 trait_object,
94 added,
95 changed,
96 self.last_run,
97 self.this_run,
98 location,
99 ))
100 }
101}
102
103#[doc(hidden)]
104pub struct WriteSparseTraitsIter<'a, Trait: ?Sized> {
105 pub(crate) components: std::slice::Iter<'a, ComponentId>,
107 pub(crate) meta: std::slice::Iter<'a, TraitImplMeta<Trait>>,
108 pub(crate) entity: Entity,
111 pub(crate) sparse_sets: &'a SparseSets,
112 pub(crate) last_run: Tick,
113 pub(crate) this_run: Tick,
114}
115
116impl<'a, Trait: ?Sized + TraitQuery> Iterator for WriteSparseTraitsIter<'a, Trait> {
117 type Item = Mut<'a, Trait>;
118 fn next(&mut self) -> Option<Self::Item> {
119 let (ptr, component_ticks, meta, location) =
122 unsafe { zip_exact(&mut self.components, &mut self.meta) }.find_map(
123 |(&component, meta)| {
124 let set = self.sparse_sets.get(component)?;
125 let (ptr, ticks, location) = set.get_with_ticks(self.entity)?;
126 Some((ptr, ticks, meta, location))
127 },
128 )?;
129
130 let ptr = unsafe { ptr.assert_unique() };
136 let trait_object = unsafe { meta.dyn_ctor.cast_mut(ptr) };
137 let added = unsafe { component_ticks.added.deref_mut() };
140 let changed = unsafe { component_ticks.changed.deref_mut() };
141
142 Some(Mut::new(
143 trait_object,
144 added,
145 changed,
146 self.last_run,
147 self.this_run,
148 location.map(|loc| unsafe { loc.deref_mut() }),
149 ))
150 }
151}
152
153impl<Trait: ?Sized + TraitQuery> WriteTraits<'_, Trait> {
154 pub fn iter(&self) -> CombinedReadTraitsIter<'_, Trait> {
156 self.into_iter()
157 }
158
159 pub fn iter_mut(&mut self) -> CombinedWriteTraitsIter<'_, Trait> {
161 self.into_iter()
162 }
163
164 pub fn iter_added(&self) -> impl Iterator<Item = Ref<'_, Trait>> {
167 self.iter().filter(DetectChanges::is_added)
168 }
169
170 pub fn iter_changed(&self) -> impl Iterator<Item = Ref<'_, Trait>> {
173 self.iter().filter(DetectChanges::is_changed)
174 }
175
176 pub fn iter_added_mut(&mut self) -> impl Iterator<Item = Mut<'_, Trait>> {
179 self.iter_mut().filter(DetectChanges::is_added)
180 }
181
182 pub fn iter_changed_mut(&mut self) -> impl Iterator<Item = Mut<'_, Trait>> {
185 self.iter_mut().filter(DetectChanges::is_changed)
186 }
187}
188
189impl<'w, Trait: ?Sized + TraitQuery> IntoIterator for WriteTraits<'w, Trait> {
190 type Item = Mut<'w, Trait>;
191 type IntoIter = CombinedWriteTraitsIter<'w, Trait>;
192 #[inline]
193 fn into_iter(self) -> Self::IntoIter {
194 let table = WriteTableTraitsIter {
195 components: self.registry.table_components.iter(),
196 meta: self.registry.table_meta.iter(),
197 table: self.table,
198 table_row: self.table_row,
199 last_run: self.last_run,
200 this_run: self.this_run,
201 };
202 let sparse = WriteSparseTraitsIter {
203 components: self.registry.sparse_components.iter(),
204 meta: self.registry.sparse_meta.iter(),
205 entity: self.table.entities()[self.table_row.as_usize()],
206 sparse_sets: self.sparse_sets,
207 last_run: self.last_run,
208 this_run: self.this_run,
209 };
210 table.chain(sparse)
211 }
212}
213
214impl<'local, Trait: ?Sized + TraitQuery> IntoIterator for &'local WriteTraits<'_, Trait> {
215 type Item = Ref<'local, Trait>;
216 type IntoIter = CombinedReadTraitsIter<'local, Trait>;
217 #[inline]
218 fn into_iter(self) -> Self::IntoIter {
219 let table = ReadTableTraitsIter {
220 components: self.registry.table_components.iter(),
221 meta: self.registry.table_meta.iter(),
222 table: self.table,
223 table_row: self.table_row,
224 last_run: self.last_run,
225 this_run: self.this_run,
226 };
227 let sparse = ReadSparseTraitsIter {
228 components: self.registry.sparse_components.iter(),
229 meta: self.registry.sparse_meta.iter(),
230 entity: self.table.entities()[self.table_row.as_usize()],
231 sparse_sets: self.sparse_sets,
232 last_run: self.last_run,
233 this_run: self.this_run,
234 };
235 table.chain(sparse)
236 }
237}
238
239impl<'local, Trait: ?Sized + TraitQuery> IntoIterator for &'local mut WriteTraits<'_, Trait> {
240 type Item = Mut<'local, Trait>;
241 type IntoIter = CombinedWriteTraitsIter<'local, Trait>;
242 #[inline]
243 fn into_iter(self) -> Self::IntoIter {
244 let table = WriteTableTraitsIter {
245 components: self.registry.table_components.iter(),
246 meta: self.registry.table_meta.iter(),
247 table: self.table,
248 table_row: self.table_row,
249 last_run: self.last_run,
250 this_run: self.this_run,
251 };
252 let sparse = WriteSparseTraitsIter {
253 components: self.registry.sparse_components.iter(),
254 meta: self.registry.sparse_meta.iter(),
255 entity: self.table.entities()[self.table_row.as_usize()],
256 sparse_sets: self.sparse_sets,
257 last_run: self.last_run,
258 this_run: self.this_run,
259 };
260 table.chain(sparse)
261 }
262}