Skip to main content

pebble/assets/
dependent_asset_plugin.rs

1use crate::{
2    app::SystemStage,
3    assets::storage::{Assets, GPUAssets},
4    plugin::Plugin,
5    system::{Res, ResMut},
6};
7
8macro_rules! impl_dependent_asset {
9    ($plugin:ident, $trait_name:ident, $sync_fn:ident, $($dep_ty:ident : $dep_var:ident),+) => {
10        pub trait $trait_name<B, $($dep_ty),+>: 'static + Send + Sync + Sized
11        where $($dep_ty: 'static + Send + Sync),+
12        {
13            type Source: 'static + Send + Sync;
14            fn upload(source: &Self::Source, backend: &B, $($dep_var: &$dep_ty),+) -> Self;
15        }
16        pub struct $plugin<B, T, $($dep_ty),+>(std::marker::PhantomData<(B, T, $($dep_ty),+)>);
17        impl<B, T, $($dep_ty),+> $plugin<B, T, $($dep_ty),+> {
18            pub fn new() -> Self { Self(std::marker::PhantomData) }
19        }
20        impl<B, T, $($dep_ty),+> Plugin for $plugin<B, T, $($dep_ty),+>
21        where
22            B: 'static + Send + Sync,
23            $($dep_ty: 'static + Send + Sync,)+
24            T: $trait_name<B, $($dep_ty),+>,
25        {
26            fn build(&self, app: &mut crate::app::App) {
27                app.try_insert_resource(Assets::<T::Source>::new());
28                app.try_insert_resource(GPUAssets::<T>::new());
29                app.add_system(SystemStage::AssetSyncDeps, $sync_fn::<B, T, $($dep_ty),+>);
30            }
31        }
32        #[allow(clippy::too_many_arguments)]
33        fn $sync_fn<B, T, $($dep_ty),+>(
34            mut cpu: ResMut<Assets<T::Source>>,
35            mut gpu: ResMut<GPUAssets<T>>,
36            backend: Option<Res<B>>,
37            $($dep_var: Option<Res<$dep_ty>>),+
38        ) where
39            B: 'static + Send + Sync,
40            $($dep_ty: 'static + Send + Sync,)+
41            T: $trait_name<B, $($dep_ty),+>,
42        {
43            let Some(backend) = backend else { return };
44            $(let Some($dep_var) = $dep_var else { return };)+
45            for handle in cpu.take_dirty() {
46                if let Some(source) = cpu.get(handle) {
47                    gpu.insert(handle, T::upload(source, &backend, $(&$dep_var),+));
48                } else {
49                    tracing::warn!("Dirty asset handle removed before GPU sync");
50                }
51            }
52        }
53    };
54}
55
56impl_dependent_asset!(
57    DependentAssetPlugin1, DependentUpload1, sync_dependent1,
58    Dep1: dep1
59);
60impl_dependent_asset!(
61    DependentAssetPlugin2, DependentUpload2, sync_dependent2,
62    Dep1: dep1, Dep2: dep2
63);
64impl_dependent_asset!(
65    DependentAssetPlugin3, DependentUpload3, sync_dependent3,
66    Dep1: dep1, Dep2: dep2, Dep3: dep3
67);
68impl_dependent_asset!(
69    DependentAssetPlugin4, DependentUpload4, sync_dependent4,
70    Dep1: dep1, Dep2: dep2, Dep3: dep3, Dep4: dep4
71);