pebble/assets/
asset_plugin.rs1use crate::{
2 app::SystemStage,
3 assets::{
4 dependent_asset_plugin::Dependencies,
5 storage::{Assets, ProcessedAssets},
6 upload::DeviceUpload,
7 },
8 plugin::Plugin,
9 resources::Resources,
10 system::{Res, ResMut},
11};
12
13pub struct DeviceAssetPlugin<D, T: DeviceUpload<D>> {
14 _marker: std::marker::PhantomData<(D, T)>,
15}
16
17impl<D, T: DeviceUpload<D>> DeviceAssetPlugin<D, T> {
18 pub fn new() -> Self {
19 Self {
20 _marker: std::marker::PhantomData,
21 }
22 }
23}
24
25impl<D, T> Plugin for DeviceAssetPlugin<D, T>
26where
27 D: 'static + Send + Sync,
28 T: DeviceUpload<D>,
29{
30 fn build(&self, app: &mut crate::prelude::App) {
31 app.try_insert_resource(Assets::<T::Source>::new());
32 app.try_insert_resource(ProcessedAssets::<T>::new());
33 app.add_system(SystemStage::AssetSync, sync_device_assets::<D, T>);
34 }
35}
36
37fn sync_device_assets<D, T>(
38 mut cpu: ResMut<Assets<T::Source>>,
39 mut processed: ResMut<ProcessedAssets<T>>,
40 device: Option<Res<D>>,
41 world: &hecs::World,
42 resources: &Resources,
43) where
44 D: 'static + Send + Sync,
45 T: DeviceUpload<D>,
46{
47 let Some(device) = device else {
48 log_waiting::<D, T>(&cpu, "device");
49 return;
50 };
51 let Some(deps) = T::Deps::try_gather(world, resources) else {
52 log_waiting::<D, T>(&cpu, "dependencies");
53 return;
54 };
55 for handle in cpu.take_dirty() {
56 if let Some(source) = cpu.get(handle) {
57 processed.insert(handle, T::upload(source, &device, &deps));
58 }
59 }
60}
61
62fn log_waiting<D, T>(cpu: &Assets<T::Source>, what: &str)
63where
64 D: 'static + Send + Sync,
65 T: DeviceUpload<D>,
66{
67 if !cpu.dirty_is_empty() {
68 tracing::trace!(
69 "{}: waiting on {what}, {} pending",
70 std::any::type_name::<T>(),
71 cpu.dirty_len()
72 );
73 }
74}