bevy_dlc/ext.rs
1use bevy::prelude::*;
2
3use crate::{DlcLoader, asset_loader};
4
5pub trait AppExt {
6 /// Register a `DlcLoader` for the given asset type `T`. This is required for any asset type
7 /// that may be loaded from a DLC pack. The plugin registers loaders for common asset types
8 /// (Image, Scene, Mesh, Font, AudioSource, etc.) but you must register loaders for any custom
9 /// asset types.
10 ///
11 /// **Important**: As of `v2.0`, this function also calls `init_asset::<T>()` to register the asset type itself, so you do not need to call `init_asset` separately.
12 ///
13 /// **Suggestion**: If I missed a common asset type that should be supported out-of-the-box,
14 /// please open an issue or PR to add it!
15 fn register_dlc_type<T: Asset>(&mut self) -> &mut Self;
16}
17
18impl AppExt for App {
19 fn register_dlc_type<T: Asset>(&mut self) -> &mut Self {
20 self.init_asset::<T>();
21 self.init_asset_loader::<DlcLoader<T>>();
22
23 // ensure a factory entry exists so `DlcPackLoader` will include a
24 // `TypedSubAssetRegistrar::<T>` when it (re)registers. This allows
25 // `register_dlc_type` to be called *before* or *after* the plugin is
26 // added and still result in the pack loader supporting `T`.
27 let tname = T::type_path();
28 if let Some(factories_res) = self
29 .world_mut()
30 .get_resource_mut::<asset_loader::DlcPackRegistrarFactories>()
31 {
32 let mut inner = factories_res.0.write().unwrap();
33 if !inner.iter().any(|f| f.type_name() == tname) {
34 inner.push(Box::new(asset_loader::TypedRegistrarFactory::<T>::default()));
35 }
36 } else {
37 let mut v: Vec<Box<dyn asset_loader::DlcPackRegistrarFactory>> = Vec::new();
38 v.push(Box::new(asset_loader::TypedRegistrarFactory::<T>::default()));
39 self.insert_resource(asset_loader::DlcPackRegistrarFactories(
40 std::sync::Arc::new(std::sync::RwLock::new(v)),
41 ));
42 }
43 self
44 }
45}