mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
1d5020634d
Former-commit-id: edfc83397ed897fcec37589261c2cfae42d6ec32
147 lines
3.9 KiB
Rust
147 lines
3.9 KiB
Rust
use dot_vox::DotVoxData;
|
|
use image::DynamicImage;
|
|
use lazy_static::lazy_static;
|
|
use std::{
|
|
any::Any,
|
|
collections::HashMap,
|
|
fs::File,
|
|
io::Read,
|
|
sync::{Arc, PoisonError, RwLock},
|
|
};
|
|
use crate::figure::Segment;
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub enum Error {
|
|
InvalidType,
|
|
NotFound,
|
|
Poison,
|
|
}
|
|
|
|
impl From<Arc<dyn Any + 'static + Sync + Send>> for Error {
|
|
fn from(_err: Arc<dyn Any + 'static + Sync + Send>) -> Self {
|
|
Error::InvalidType
|
|
}
|
|
}
|
|
|
|
impl From<std::io::Error> for Error {
|
|
fn from(_err: std::io::Error) -> Self {
|
|
Error::NotFound
|
|
}
|
|
}
|
|
|
|
impl<T> From<PoisonError<T>> for Error {
|
|
fn from(_err: PoisonError<T>) -> Self {
|
|
Error::Poison
|
|
}
|
|
}
|
|
|
|
lazy_static! {
|
|
static ref ASSETS: RwLock<HashMap<String, Arc<dyn Any + 'static + Sync + Send>>> =
|
|
RwLock::new(HashMap::new());
|
|
}
|
|
|
|
/// Function used to load assets
|
|
/// Example usage:
|
|
/// ```
|
|
/// use image::DynamicImage;
|
|
///
|
|
/// let my_image = common::asset::load::<DynamicImage>("core.ui.backgrounds.city").unwrap();
|
|
/// ```
|
|
// TODO: consider assets that we only need in one place or that don't need to be kept in memory?
|
|
pub fn load<A: Asset + 'static>(specifier: &str) -> Result<Arc<A>, Error> {
|
|
Ok(ASSETS
|
|
.write()?
|
|
.entry(specifier.to_string())
|
|
.or_insert(Arc::new(A::load(specifier)?))
|
|
.clone()
|
|
.downcast()?)
|
|
}
|
|
|
|
/// Asset Trait
|
|
pub trait Asset: Send + Sync + Sized {
|
|
fn load(specifier: &str) -> Result<Self, Error>;
|
|
}
|
|
|
|
impl Asset for DynamicImage {
|
|
fn load(specifier: &str) -> Result<Self, Error> {
|
|
Ok(image::load_from_memory(load_from_path(specifier)?.as_slice()).unwrap())
|
|
}
|
|
}
|
|
|
|
impl Asset for DotVoxData {
|
|
fn load(specifier: &str) -> Result<Self, Error> {
|
|
Ok(dot_vox::load_bytes(load_from_path(specifier)?.as_slice()).unwrap())
|
|
}
|
|
}
|
|
|
|
impl Asset for Segment {
|
|
fn load(specifier: &str) -> Result<Self, Error> {
|
|
Ok(Segment::from(dot_vox::load_bytes(load_from_path(specifier)?.as_slice()).unwrap()))
|
|
}
|
|
}
|
|
|
|
// TODO: System to load file from specifiers (eg "core.ui.backgrounds.city")
|
|
fn try_load_from_path(name: &str) -> Option<File> {
|
|
let basepaths = [
|
|
// if it's stupid and it works..,
|
|
"assets".to_string(),
|
|
"../../assets".to_string(),
|
|
"../assets".to_string(), /* optimizations */
|
|
[env!("CARGO_MANIFEST_DIR"), "/assets"].concat(),
|
|
[env!("CARGO_MANIFEST_DIR"), "/../../assets"].concat(),
|
|
[env!("CARGO_MANIFEST_DIR"), "/../assets"].concat(),
|
|
"../../../assets".to_string(),
|
|
[env!("CARGO_MANIFEST_DIR"), "/../../../assets"].concat(),
|
|
];
|
|
for bp in &basepaths {
|
|
let filename = [bp, name].concat();
|
|
match File::open(&filename) {
|
|
Ok(f) => {
|
|
debug!("loading {} succedeed", filename);
|
|
return Some(f);
|
|
},
|
|
Err(e) => {
|
|
debug!("loading {} did not work with error: {}", filename, e);
|
|
}
|
|
};
|
|
};
|
|
None
|
|
}
|
|
|
|
pub fn load_from_path(name: &str) -> Result<Vec<u8>, Error> {
|
|
match try_load_from_path(name) {
|
|
Some(mut f) => {
|
|
let mut content: Vec<u8> = vec!();
|
|
f.read_to_end(&mut content);
|
|
info!("loaded asset successful: {}", name);
|
|
Ok(content)
|
|
},
|
|
None => {
|
|
warn!("Loading asset failed, wanted to load {} but could not load it, check debug log!", name);
|
|
Err(Error::NotFound)
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
/// Translation Asset
|
|
pub struct Translations {
|
|
pub translations: Value
|
|
}
|
|
impl Translations {
|
|
pub fn get_lang(&self, lang: &str) -> &str {
|
|
self.translations[lang].as_str().unwrap()
|
|
}
|
|
}
|
|
impl Asset for Translations {
|
|
type T=Self;
|
|
fn load(path: &str) -> Result<Self, ()>{
|
|
let file_out = read_from_path(path).unwrap();
|
|
let content = from_utf8(file_out.as_slice()).unwrap();
|
|
let value = content.parse::<Value>().unwrap();
|
|
|
|
Ok(Translations{translations: value})
|
|
}
|
|
}
|
|
*/
|