2020-06-06 00:32:32 +00:00
|
|
|
use crate::{AssetServer, Assets, Handle, AssetVersion, LoadState};
|
2020-05-15 23:55:44 +00:00
|
|
|
use anyhow::Result;
|
|
|
|
use crossbeam_channel::{Receiver, Sender, TryRecvError};
|
|
|
|
use fs::File;
|
|
|
|
use io::Read;
|
|
|
|
use legion::prelude::{Res, ResMut};
|
2020-05-17 03:18:30 +00:00
|
|
|
use std::{
|
|
|
|
fs, io,
|
|
|
|
path::{Path, PathBuf},
|
|
|
|
};
|
2020-05-15 23:55:44 +00:00
|
|
|
use thiserror::Error;
|
|
|
|
|
|
|
|
#[derive(Error, Debug)]
|
|
|
|
pub enum AssetLoadError {
|
|
|
|
#[error("Encountered an io error while loading asset.")]
|
|
|
|
Io(#[from] io::Error),
|
|
|
|
#[error("This asset's loader encountered an error while loading.")]
|
|
|
|
LoaderError(#[from] anyhow::Error),
|
|
|
|
}
|
|
|
|
|
|
|
|
pub trait AssetLoader<T>: Send + Sync + 'static {
|
2020-05-17 03:18:30 +00:00
|
|
|
fn from_bytes(&self, asset_path: &Path, bytes: Vec<u8>) -> Result<T, anyhow::Error>;
|
2020-05-15 23:55:44 +00:00
|
|
|
fn extensions(&self) -> &[&str];
|
2020-05-17 03:18:30 +00:00
|
|
|
fn load_from_file(&self, asset_path: &Path) -> Result<T, AssetLoadError> {
|
|
|
|
let mut file = File::open(asset_path)?;
|
2020-05-15 23:55:44 +00:00
|
|
|
let mut bytes = Vec::new();
|
|
|
|
file.read_to_end(&mut bytes)?;
|
|
|
|
let asset = self.from_bytes(asset_path, bytes)?;
|
|
|
|
Ok(asset)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-05-25 19:03:50 +00:00
|
|
|
pub struct AssetResult<T: 'static> {
|
2020-05-15 23:55:44 +00:00
|
|
|
pub result: Result<T, AssetLoadError>,
|
|
|
|
pub handle: Handle<T>,
|
2020-05-17 03:18:30 +00:00
|
|
|
pub path: PathBuf,
|
2020-06-06 00:32:32 +00:00
|
|
|
pub version: AssetVersion,
|
2020-05-15 23:55:44 +00:00
|
|
|
}
|
|
|
|
|
2020-05-25 19:03:50 +00:00
|
|
|
pub struct AssetChannel<T: 'static> {
|
2020-05-15 23:55:44 +00:00
|
|
|
pub sender: Sender<AssetResult<T>>,
|
|
|
|
pub receiver: Receiver<AssetResult<T>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> AssetChannel<T> {
|
|
|
|
pub fn new() -> Self {
|
|
|
|
let (sender, receiver) = crossbeam_channel::unbounded();
|
|
|
|
AssetChannel { sender, receiver }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn update_asset_storage_system<T>(
|
|
|
|
asset_channel: Res<AssetChannel<T>>,
|
2020-06-06 00:32:32 +00:00
|
|
|
asset_server: Res<AssetServer>,
|
2020-05-15 23:55:44 +00:00
|
|
|
mut assets: ResMut<Assets<T>>,
|
|
|
|
) {
|
|
|
|
loop {
|
|
|
|
match asset_channel.receiver.try_recv() {
|
|
|
|
Ok(result) => {
|
2020-06-06 00:32:32 +00:00
|
|
|
match result.result {
|
|
|
|
Ok(asset) => {
|
|
|
|
assets.set(result.handle, asset);
|
|
|
|
asset_server.set_load_state(result.handle.id, LoadState::Loaded(result.version));
|
|
|
|
},
|
|
|
|
Err(err) => {
|
|
|
|
asset_server.set_load_state(result.handle.id, LoadState::Failed(result.version));
|
|
|
|
log::error!("Failed to load asset: {:?}", err);
|
|
|
|
}
|
|
|
|
}
|
2020-05-15 23:55:44 +00:00
|
|
|
}
|
|
|
|
Err(TryRecvError::Empty) => {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
Err(TryRecvError::Disconnected) => panic!("AssetChannel disconnected"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|