use crate::{ update_asset_storage_system, AssetChannel, AssetLoader, AssetServer, ChannelAssetHandler, Handle, HandleId, }; use bevy_app::{AppBuilder, Events, FromResources}; use bevy_core::bytes::GetBytes; use legion::prelude::*; use std::{ collections::HashMap, path::{Path, PathBuf}, }; pub enum AssetEvent { Created { handle: Handle }, Modified { handle: Handle }, Removed { handle: Handle }, } pub struct Assets { assets: HashMap, T>, paths: HashMap>, events: Events>, } impl Default for Assets { fn default() -> Self { Assets { assets: HashMap::default(), paths: HashMap::default(), events: Events::default(), } } } impl Assets { pub fn get_with_path>(&mut self, path: P) -> Option> { self.paths.get(path.as_ref()).map(|handle| *handle) } pub fn add(&mut self, asset: T) -> Handle { let handle = Handle::new(); self.assets.insert(handle, asset); self.events.send(AssetEvent::Created { handle }); handle } pub fn set(&mut self, handle: Handle, asset: T) { let exists = self.assets.contains_key(&handle); self.assets.insert(handle, asset); if exists { self.events.send(AssetEvent::Modified { handle }); } else { self.events.send(AssetEvent::Created { handle }); } } pub fn add_default(&mut self, asset: T) -> Handle { let handle = Handle::default(); let exists = self.assets.contains_key(&handle); self.assets.insert(handle, asset); if exists { self.events.send(AssetEvent::Modified { handle }); } else { self.events.send(AssetEvent::Created { handle }); } handle } pub fn set_path>(&mut self, handle: Handle, path: P) { self.paths.insert(path.as_ref().to_owned(), handle); } pub fn get_id(&self, id: HandleId) -> Option<&T> { self.assets.get(&Handle::from_id(id)) } pub fn get_id_mut(&mut self, id: HandleId) -> Option<&mut T> { self.assets.get_mut(&Handle::from_id(id)) } pub fn get(&self, handle: &Handle) -> Option<&T> { self.assets.get(&handle) } pub fn get_mut(&mut self, handle: &Handle) -> Option<&mut T> { self.assets.get_mut(&handle) } pub fn get_or_insert_with( &mut self, handle: Handle, insert_fn: impl FnOnce() -> T, ) -> &mut T { let mut event = None; let borrowed = self.assets.entry(handle).or_insert_with(|| { event = Some(AssetEvent::Created { handle }); insert_fn() }); if let Some(event) = event { self.events.send(event); } borrowed } pub fn iter(&self) -> impl Iterator, &T)> { self.assets.iter().map(|(k, v)| (*k, v)) } pub fn remove(&mut self, handle: &Handle) -> Option { self.assets.remove(&handle) } pub fn asset_event_system( mut events: ResMut>>, mut assets: ResMut>, ) { events.extend(assets.events.drain()) } } impl GetBytes for Handle { fn get_bytes(&self) -> Vec { Vec::new() } fn get_bytes_ref(&self) -> Option<&[u8]> { None } } pub trait AddAsset { fn add_asset(&mut self) -> &mut Self where T: Send + Sync + 'static; fn add_asset_loader(&mut self) -> &mut Self where TLoader: AssetLoader + FromResources, TAsset: Send + Sync + 'static; } impl AddAsset for AppBuilder { fn add_asset(&mut self) -> &mut Self where T: Send + Sync + 'static, { self.init_resource::>() .add_system_to_stage( super::stage::ASSET_EVENTS, Assets::::asset_event_system.system(), ) .add_event::>() } fn add_asset_loader(&mut self) -> &mut Self where TLoader: AssetLoader + FromResources, TAsset: Send + Sync + 'static, { { if !self.resources().contains::>() { self.resources_mut().insert(AssetChannel::::new()); self.add_system_to_stage( crate::stage::LOAD_ASSETS, update_asset_storage_system::.system(), ); } let asset_channel = self .resources() .get::>() .expect("AssetChannel should always exist at this point."); let mut asset_server = self .resources() .get_mut::() .expect("AssetServer does not exist. Consider adding it as a resource."); asset_server.add_loader(TLoader::from_resources(self.resources())); let handler = ChannelAssetHandler::new(TLoader::from_resources(self.resources()), asset_channel.sender.clone()); asset_server.add_handler(handler); } self } }