1use std::{cell::RefCell, pin::Pin};
4
5use crate::prelude::*;
6
7type DashmapRef<'a, T> = dashmap::mapref::one::MappedRef<'a, Cid, LoadedAsset, T>;
8
9type DashmapIter<'a, K, V> = dashmap::iter::Iter<'a, K, V>;
10
11pub struct Root<'a, T: HasSchema>(DashmapRef<'a, T>);
13
14impl<'a, T: HasSchema> std::ops::Deref for Root<'a, T> {
15 type Target = T;
16 fn deref(&self) -> &Self::Target {
17 &self.0
18 }
19}
20
21impl<'a, T: HasSchema> SystemParam for Root<'a, T> {
22 type State = AssetServer;
23 type Param<'s> = Root<'s, T>;
24
25 fn get_state(world: &World) -> Self::State {
26 (*world.resources.get::<AssetServer>().unwrap()).clone()
27 }
28 fn borrow<'s>(_world: &'s World, asset_server: &'s mut Self::State) -> Self::Param<'s> {
29 Root(asset_server.root())
30 }
31}
32
33pub struct Packs<'a, T> {
66 asset_server: AssetServer,
67 _pack_t: std::marker::PhantomData<&'a T>,
68}
69
70impl<'a, T: HasSchema> SystemParam for Packs<'a, T> {
71 type State = AssetServer;
72 type Param<'s> = Packs<'s, T>;
73
74 fn get_state(world: &World) -> Self::State {
75 (*world.resource::<AssetServer>()).clone()
76 }
77
78 fn borrow<'s>(_world: &'s World, state: &'s mut Self::State) -> Self::Param<'s> {
79 Packs {
80 asset_server: state.clone(),
81 _pack_t: std::marker::PhantomData,
82 }
83 }
84}
85
86impl<T> Packs<'_, T> {
87 pub fn iter(&self) -> PacksIter<'_, T> {
89 PacksIter {
90 asset_server: &self.asset_server,
91 asset_packs_iter: self.asset_server.packs().iter(),
92 _pack_t: std::marker::PhantomData,
93 }
94 }
95}
96
97pub struct PacksIter<'a, T> {
99 asset_server: &'a AssetServer,
100 asset_packs_iter: DashmapIter<'a, AssetPackSpec, AssetPack>,
101 _pack_t: std::marker::PhantomData<&'a T>,
102}
103
104impl<'a, T: HasSchema> Iterator for PacksIter<'a, T> {
105 type Item = DashmapRef<'a, T>;
106
107 fn next(&mut self) -> Option<Self::Item> {
108 let pack = self.asset_packs_iter.next()?;
109 let pack_root = self.asset_server.get(pack.root.typed::<T>());
110 Some(pack_root)
111 }
112}
113
114pub struct AllPacksData<'a, Core, Pack>
165where
166 Core: HasSchema,
167 Pack: HasSchema,
168{
169 core_root: Root<'a, Core>,
170 pack_roots: Packs<'a, Pack>,
171}
172
173impl<'a, Core, Pack> SystemParam for AllPacksData<'a, Core, Pack>
174where
175 Core: HasSchema,
176 Pack: HasSchema,
177{
178 type State = (
179 <Root<'a, Core> as SystemParam>::State,
180 <Packs<'a, Pack> as SystemParam>::State,
181 );
182 type Param<'s> = AllPacksData<'s, Core, Pack>;
183
184 fn get_state(world: &World) -> Self::State {
185 (
186 Root::<'a, Core>::get_state(world),
187 Packs::<'a, Pack>::get_state(world),
188 )
189 }
190
191 fn borrow<'s>(world: &'s World, state: &'s mut Self::State) -> Self::Param<'s> {
192 AllPacksData {
193 core_root: Root::<'s, Core>::borrow(world, &mut state.0),
194 pack_roots: Packs::<'s, Pack>::borrow(world, &mut state.1),
195 }
196 }
197}
198
199impl<'a, Core, Pack> AllPacksData<'a, Core, Pack>
200where
201 Core: HasSchema,
202 Pack: HasSchema,
203{
204 pub fn iter_with<T, CoreItemIt: Iterator<Item = T>, PackItemIt: Iterator<Item = T>>(
212 &'a self,
213 mut core_accessor: impl FnMut(&'a Core) -> CoreItemIt,
214 pack_accessor: impl 'static + FnMut(&'a Pack) -> PackItemIt,
215 ) -> AllPacksDataIter<'a, T, CoreItemIt, Pack, PacksIter<'a, Pack>, PackItemIt> {
216 AllPacksDataIter {
217 core_item_iter: core_accessor(&*self.core_root),
218 pack_iter: self.pack_roots.iter(),
219 pack_accessor: Box::new(pack_accessor),
220 current_pack: AllPacksDataCurrentPack::new(),
221 }
222 }
223}
224
225pub struct AllPacksDataIter<'a, T, CoreItemIt, Pack, PackIt, PackItemIt> {
235 core_item_iter: CoreItemIt,
236 pack_iter: PackIt,
237 pack_accessor: Box<dyn FnMut(&'a Pack) -> PackItemIt>,
238 current_pack: Pin<Box<RefCell<AllPacksDataCurrentPack<'a, Pack, T, PackItemIt>>>>,
239}
240
241struct AllPacksDataCurrentPack<'a, Pack, T, PackItemIt> {
242 pack: Option<DashmapRef<'a, Pack>>,
243 item_iter: Option<PackItemIt>,
244 _marker: std::marker::PhantomData<fn() -> T>,
245}
246
247impl<'a, Pack, T, PackItemIt> AllPacksDataCurrentPack<'a, Pack, T, PackItemIt> {
248 fn new() -> Pin<Box<RefCell<Self>>> {
249 Box::pin(RefCell::new(AllPacksDataCurrentPack {
250 pack: None,
251 item_iter: None,
252 _marker: std::marker::PhantomData,
253 }))
254 }
255
256 fn set_pack(
257 &mut self,
258 next_pack: DashmapRef<'a, Pack>,
259 pack_accessor: &mut dyn FnMut(&'a Pack) -> PackItemIt,
260 ) -> &mut PackItemIt {
261 _ = self.item_iter.take();
263
264 let pack = self.pack.insert(next_pack);
266
267 let pack = unsafe { std::mem::transmute::<&Pack, &'a Pack>(pack) };
269 let pack_item_iter = (pack_accessor)(pack);
270 self.item_iter.insert(pack_item_iter)
271 }
272}
273
274impl<'a, Pack, T, CoreItemIt, PackIt, PackItemIt> Iterator
275 for AllPacksDataIter<'a, T, CoreItemIt, Pack, PackIt, PackItemIt>
276where
277 CoreItemIt: Iterator<Item = T>,
278 PackIt: Iterator<Item = DashmapRef<'a, Pack>>,
279 PackItemIt: Iterator<Item = T>,
280{
281 type Item = T;
282
283 fn next(&mut self) -> Option<Self::Item> {
284 let next_core_item = self.core_item_iter.next();
285 if next_core_item.is_some() {
286 return next_core_item;
287 }
288
289 if let Some(iter) = self.current_pack.borrow_mut().item_iter.as_mut() {
290 let next_pack_item = iter.next();
291 if next_pack_item.is_some() {
292 return next_pack_item;
293 }
294 }
295
296 let next_pack = self.pack_iter.next()?;
297
298 let mut current_pack = self.current_pack.borrow_mut();
299 let current_pack_item_iter = current_pack.set_pack(next_pack, &mut self.pack_accessor);
300
301 current_pack_item_iter.next()
302 }
303}