mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Update assets_manager
to 0.7
This commit is contained in:
parent
182d5cf971
commit
aca088388b
8
Cargo.lock
generated
8
Cargo.lock
generated
@ -214,10 +214,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "assets_manager"
|
name = "assets_manager"
|
||||||
version = "0.6.1"
|
version = "0.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "35c55040a3eee1353bfa4bee2c03a695395d64176e8063223aa62d11b4ef669c"
|
checksum = "912acc83cc5bf31b0d9685e8d11a9d7c36b949e850ca2db1a3203b3b656a5e4a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"ab_glyph",
|
||||||
"ahash 0.7.6",
|
"ahash 0.7.6",
|
||||||
"bincode",
|
"bincode",
|
||||||
"crossbeam-channel",
|
"crossbeam-channel",
|
||||||
@ -6081,7 +6082,7 @@ dependencies = [
|
|||||||
"petgraph 0.5.1",
|
"petgraph 0.5.1",
|
||||||
"rand 0.8.4",
|
"rand 0.8.4",
|
||||||
"rayon",
|
"rayon",
|
||||||
"ron 0.6.6",
|
"ron 0.7.0",
|
||||||
"roots",
|
"roots",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_repr",
|
"serde_repr",
|
||||||
@ -6358,6 +6359,7 @@ dependencies = [
|
|||||||
name = "veloren-voxygen"
|
name = "veloren-voxygen"
|
||||||
version = "0.11.0"
|
version = "0.11.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"assets_manager",
|
||||||
"backtrace",
|
"backtrace",
|
||||||
"bincode",
|
"bincode",
|
||||||
"bytemuck",
|
"bytemuck",
|
||||||
|
@ -58,7 +58,7 @@ dot_vox = "4.0"
|
|||||||
serde_repr = "0.1.6"
|
serde_repr = "0.1.6"
|
||||||
|
|
||||||
# csv import
|
# csv import
|
||||||
ron = { version = "0.6", default-features = false, optional = true }
|
ron = { version = "0.7", default-features = false, optional = true }
|
||||||
# csv export
|
# csv export
|
||||||
csv = { version = "1.1.3", optional = true }
|
csv = { version = "1.1.3", optional = true }
|
||||||
structopt = { version = "0.3.13", optional = true }
|
structopt = { version = "0.3.13", optional = true }
|
||||||
|
@ -7,7 +7,7 @@ version = "0.10.0"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
assets_manager = {version = "0.6.0", features = ["bincode", "ron", "json"]}
|
assets_manager = {version = "0.7", features = ["bincode", "ron", "json"]}
|
||||||
ron = { version = "0.7", default-features = false }
|
ron = { version = "0.7", default-features = false }
|
||||||
dot_vox = "4.0"
|
dot_vox = "4.0"
|
||||||
image = { version = "0.23.12", default-features = false, features = ["png"] }
|
image = { version = "0.23.12", default-features = false, features = ["png"] }
|
||||||
|
91
common/assets/src/fs.rs
Normal file
91
common/assets/src/fs.rs
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
use std::{borrow::Cow, io, path::PathBuf};
|
||||||
|
|
||||||
|
use assets_manager::{
|
||||||
|
hot_reloading::{DynUpdateSender, EventSender, FsWatcherBuilder},
|
||||||
|
source::{DirEntry, FileSystem as RawFs, Source},
|
||||||
|
BoxedError,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Loads assets from the default path or `VELOREN_ASSETS_OVERRIDE` env if it is
|
||||||
|
/// set.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct FileSystem {
|
||||||
|
default: RawFs,
|
||||||
|
override_dir: Option<RawFs>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FileSystem {
|
||||||
|
pub fn new() -> io::Result<Self> {
|
||||||
|
let default = RawFs::new(&*super::ASSETS_PATH)?;
|
||||||
|
let override_dir = std::env::var_os("VELOREN_ASSETS_OVERRIDE").and_then(|path| {
|
||||||
|
RawFs::new(path)
|
||||||
|
.map_err(|err| tracing::error!("Error setting override assets directory: {}", err))
|
||||||
|
.ok()
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
default,
|
||||||
|
override_dir,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn path_of(&self, specifier: &str, ext: &str) -> PathBuf {
|
||||||
|
self.default.path_of(DirEntry::File(specifier, ext))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Source for FileSystem {
|
||||||
|
fn read(&self, id: &str, ext: &str) -> io::Result<Cow<[u8]>> {
|
||||||
|
if let Some(dir) = &self.override_dir {
|
||||||
|
match dir.read(id, ext) {
|
||||||
|
Ok(content) => return Ok(content),
|
||||||
|
Err(err) => {
|
||||||
|
if err.kind() != io::ErrorKind::NotFound {
|
||||||
|
let path = dir.path_of(DirEntry::File(id, ext));
|
||||||
|
tracing::warn!("Error reading \"{}\": {}", path.display(), err);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If not found in override path, try load from main asset path
|
||||||
|
self.default.read(id, ext)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_dir(&self, id: &str, f: &mut dyn FnMut(DirEntry)) -> io::Result<()> {
|
||||||
|
if let Some(dir) = &self.override_dir {
|
||||||
|
match dir.read_dir(id, f) {
|
||||||
|
Ok(()) => return Ok(()),
|
||||||
|
Err(err) => {
|
||||||
|
if err.kind() != io::ErrorKind::NotFound {
|
||||||
|
let path = dir.path_of(DirEntry::Directory(id));
|
||||||
|
tracing::warn!("Error reading \"{}\": {}", path.display(), err);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If not found in override path, try load from main asset path
|
||||||
|
self.default.read_dir(id, f)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn exists(&self, entry: DirEntry) -> bool {
|
||||||
|
self.override_dir
|
||||||
|
.as_ref()
|
||||||
|
.map_or(false, |dir| dir.exists(entry))
|
||||||
|
|| self.default.exists(entry)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_source(&self) -> Option<Box<dyn Source + Send>> { Some(Box::new(self.clone())) }
|
||||||
|
|
||||||
|
fn configure_hot_reloading(&self, events: EventSender) -> Result<DynUpdateSender, BoxedError> {
|
||||||
|
let mut builder = FsWatcherBuilder::new()?;
|
||||||
|
|
||||||
|
if let Some(dir) = &self.override_dir {
|
||||||
|
builder.watch(dir.root().to_owned())?;
|
||||||
|
}
|
||||||
|
builder.watch(self.default.root().to_owned())?;
|
||||||
|
|
||||||
|
Ok(builder.build(events))
|
||||||
|
}
|
||||||
|
}
|
@ -4,7 +4,7 @@
|
|||||||
use dot_vox::DotVoxData;
|
use dot_vox::DotVoxData;
|
||||||
use image::DynamicImage;
|
use image::DynamicImage;
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use std::{borrow::Cow, fmt, path::PathBuf, sync::Arc};
|
use std::{borrow::Cow, path::PathBuf, sync::Arc};
|
||||||
|
|
||||||
pub use assets_manager::{
|
pub use assets_manager::{
|
||||||
asset::{DirLoadable, Ron},
|
asset::{DirLoadable, Ron},
|
||||||
@ -15,29 +15,21 @@ pub use assets_manager::{
|
|||||||
Asset, AssetCache, BoxedError, Compound, Error, SharedString,
|
Asset, AssetCache, BoxedError, Compound, Error, SharedString,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
mod fs;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
/// The HashMap where all loaded assets are stored in.
|
/// The HashMap where all loaded assets are stored in.
|
||||||
static ref ASSETS: AssetCache =
|
static ref ASSETS: AssetCache<fs::FileSystem> =
|
||||||
AssetCache::new(&*ASSETS_PATH).unwrap();
|
AssetCache::with_source(fs::FileSystem::new().unwrap());
|
||||||
/// Asset cache for overrides
|
|
||||||
static ref ASSETS_OVERRIDE: Option<AssetCache> = {
|
|
||||||
std::env::var("VELOREN_ASSETS_OVERRIDE").ok().map(|path| {
|
|
||||||
AssetCache::new(path).unwrap()
|
|
||||||
})
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "hot-reloading")]
|
#[cfg(feature = "hot-reloading")]
|
||||||
pub fn start_hot_reloading() {
|
pub fn start_hot_reloading() { ASSETS.enhance_hot_reloading(); }
|
||||||
ASSETS.enhance_hot_reloading();
|
|
||||||
if let Some(cache) = &*ASSETS_OVERRIDE {
|
|
||||||
cache.enhance_hot_reloading();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type AssetHandle<T> = assets_manager::Handle<'static, T>;
|
pub type AssetHandle<T> = assets_manager::Handle<'static, T>;
|
||||||
pub type AssetGuard<T> = assets_manager::AssetGuard<'static, T>;
|
pub type AssetGuard<T> = assets_manager::AssetGuard<'static, T>;
|
||||||
pub type AssetDirHandle<T> = assets_manager::DirHandle<'static, T, source::FileSystem>;
|
pub type AssetDirHandle<T> = assets_manager::DirHandle<'static, T, fs::FileSystem>;
|
||||||
|
pub type ReloadWatcher = assets_manager::ReloadWatcher<'static>;
|
||||||
|
|
||||||
/// The Asset trait, which is implemented by all structures that have their data
|
/// The Asset trait, which is implemented by all structures that have their data
|
||||||
/// stored in the filesystem.
|
/// stored in the filesystem.
|
||||||
@ -76,12 +68,21 @@ pub trait AssetExt: Sized + Send + Sync + 'static {
|
|||||||
/// ```
|
/// ```
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn load_expect(specifier: &str) -> AssetHandle<Self> {
|
fn load_expect(specifier: &str) -> AssetHandle<Self> {
|
||||||
Self::load(specifier).unwrap_or_else(|err| {
|
#[track_caller]
|
||||||
|
#[cold]
|
||||||
|
fn expect_failed(err: Error) -> ! {
|
||||||
panic!(
|
panic!(
|
||||||
"Failed loading essential asset: {} (error={:?})",
|
"Failed loading essential asset: {} (error={:?})",
|
||||||
specifier, err
|
err.id(),
|
||||||
|
err.reason()
|
||||||
)
|
)
|
||||||
})
|
}
|
||||||
|
|
||||||
|
// Avoid using `unwrap_or_else` to avoid breaking `#[track_caller]`
|
||||||
|
match Self::load(specifier) {
|
||||||
|
Ok(handle) => handle,
|
||||||
|
Err(err) => expect_failed(err),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Function used to load essential assets from the filesystem or the cache
|
/// Function used to load essential assets from the filesystem or the cache
|
||||||
@ -111,21 +112,8 @@ pub fn load_dir<T: DirLoadable>(
|
|||||||
specifier: &str,
|
specifier: &str,
|
||||||
recursive: bool,
|
recursive: bool,
|
||||||
) -> Result<AssetDirHandle<T>, Error> {
|
) -> Result<AssetDirHandle<T>, Error> {
|
||||||
use std::io;
|
|
||||||
|
|
||||||
let specifier = specifier.strip_suffix(".*").unwrap_or(specifier);
|
let specifier = specifier.strip_suffix(".*").unwrap_or(specifier);
|
||||||
// Try override path first
|
ASSETS.load_dir(specifier, recursive)
|
||||||
let from_override = match &*ASSETS_OVERRIDE {
|
|
||||||
Some(cache) => cache.load_dir(specifier, recursive),
|
|
||||||
None => return ASSETS.load_dir(specifier, recursive),
|
|
||||||
};
|
|
||||||
// If not found in override path, try load from main asset path
|
|
||||||
match from_override {
|
|
||||||
Err(Error::Io(e)) if e.kind() == io::ErrorKind::NotFound => {
|
|
||||||
ASSETS.load_dir(specifier, recursive)
|
|
||||||
},
|
|
||||||
_ => from_override,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Loads directory and all files in it
|
/// Loads directory and all files in it
|
||||||
@ -138,88 +126,30 @@ pub fn read_expect_dir<T: DirLoadable>(
|
|||||||
specifier: &str,
|
specifier: &str,
|
||||||
recursive: bool,
|
recursive: bool,
|
||||||
) -> impl Iterator<Item = AssetGuard<T>> {
|
) -> impl Iterator<Item = AssetGuard<T>> {
|
||||||
load_dir::<T>(specifier, recursive)
|
#[track_caller]
|
||||||
.unwrap_or_else(|e| panic!("Failed loading directory {}. error={:?}", e, specifier))
|
#[cold]
|
||||||
.ids()
|
fn expect_failed(err: Error) -> ! {
|
||||||
.map(|entry| T::load_expect(entry).read())
|
panic!(
|
||||||
}
|
"Failed loading directory: {} (error={:?})",
|
||||||
|
err.id(),
|
||||||
|
err.reason()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
// Avoid using `unwrap_or_else` to avoid breaking `#[track_caller]`
|
||||||
pub struct AssetError(String, Error);
|
match load_dir::<T>(specifier, recursive) {
|
||||||
|
Ok(dir) => dir.ids().map(|entry| T::load_expect(entry).read()),
|
||||||
impl std::error::Error for AssetError {}
|
Err(err) => expect_failed(err),
|
||||||
impl fmt::Display for AssetError {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
write!(f, "Failed to load '{}': {}", self.0, self.1)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Compound> AssetExt for T {
|
impl<T: Compound> AssetExt for T {
|
||||||
fn load(specifier: &str) -> Result<AssetHandle<Self>, Error> {
|
fn load(specifier: &str) -> Result<AssetHandle<Self>, Error> { ASSETS.load(specifier) }
|
||||||
use std::io;
|
|
||||||
// Try override path first
|
|
||||||
let from_override = match &*ASSETS_OVERRIDE {
|
|
||||||
Some(cache) => cache.load(specifier),
|
|
||||||
None => return ASSETS.load(specifier),
|
|
||||||
};
|
|
||||||
// If not found in override path, try load from main asset path
|
|
||||||
//
|
|
||||||
// NOTE: this won't work if asset catches error with
|
|
||||||
// Asset::default_value during Asset::load.
|
|
||||||
//
|
|
||||||
// We don't use it, and hopefully won't because there is
|
|
||||||
// `AssetExt::get_or_insert` or `AssetExt::load_or_insert_with`
|
|
||||||
// that allows you to do the same.
|
|
||||||
//
|
|
||||||
// If accidentaly we end up using Asset::default_value,
|
|
||||||
// there is possibility of this code trying to load
|
|
||||||
// from override cache and end there returning default value
|
|
||||||
// for `cache.load(specifier)` above.
|
|
||||||
match from_override {
|
|
||||||
Err(Error::Io(e)) if e.kind() == io::ErrorKind::NotFound => ASSETS.load(specifier),
|
|
||||||
Err(e) => Err(Error::Conversion(Box::new(AssetError(
|
|
||||||
specifier.to_string(),
|
|
||||||
e,
|
|
||||||
)))),
|
|
||||||
_ => from_override,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn load_owned(specifier: &str) -> Result<Self, Error> {
|
fn load_owned(specifier: &str) -> Result<Self, Error> { ASSETS.load_owned(specifier) }
|
||||||
use std::io;
|
|
||||||
// Try override path first
|
|
||||||
let from_override = match &*ASSETS_OVERRIDE {
|
|
||||||
Some(cache) => cache.load_owned(specifier),
|
|
||||||
None => return ASSETS.load_owned(specifier),
|
|
||||||
};
|
|
||||||
// If not found in override path, try load from main asset path
|
|
||||||
match from_override {
|
|
||||||
Err(Error::Io(e)) if e.kind() == io::ErrorKind::NotFound => {
|
|
||||||
ASSETS.load_owned(specifier)
|
|
||||||
},
|
|
||||||
_ => from_override,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_or_insert(specifier: &str, default: Self) -> AssetHandle<Self> {
|
fn get_or_insert(specifier: &str, default: Self) -> AssetHandle<Self> {
|
||||||
// 1) Check if we have ASSETS_OVERRIDE, if not - use main ASSETS
|
ASSETS.get_or_insert(specifier, default)
|
||||||
// 2) Check if we have this asset in ASSETS_OVERRIDE, if not -
|
|
||||||
// use main ASSETS
|
|
||||||
// 3) If we have this asset in ASSETS_OVERRIDE, use ASSETS_OVERRIDE.
|
|
||||||
use std::io;
|
|
||||||
|
|
||||||
let override_cache = match &*ASSETS_OVERRIDE {
|
|
||||||
Some(cache) => cache,
|
|
||||||
None => return ASSETS.get_or_insert(specifier, default),
|
|
||||||
};
|
|
||||||
let from_override = override_cache.load::<T>(specifier);
|
|
||||||
// If not found in override path, try load from main asset path
|
|
||||||
match from_override {
|
|
||||||
Err(Error::Io(e)) if e.kind() == io::ErrorKind::NotFound => {
|
|
||||||
ASSETS.get_or_insert(specifier, default)
|
|
||||||
},
|
|
||||||
_ => override_cache.get_or_insert(specifier, default),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -355,11 +285,7 @@ lazy_static! {
|
|||||||
/// Returns the actual path of the specifier with the extension.
|
/// Returns the actual path of the specifier with the extension.
|
||||||
///
|
///
|
||||||
/// For directories, give `""` as extension.
|
/// For directories, give `""` as extension.
|
||||||
pub fn path_of(specifier: &str, ext: &str) -> PathBuf {
|
pub fn path_of(specifier: &str, ext: &str) -> PathBuf { ASSETS.source().path_of(specifier, ext) }
|
||||||
ASSETS
|
|
||||||
.source()
|
|
||||||
.path_of(source::DirEntry::File(specifier, ext))
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
@ -481,7 +407,7 @@ pub mod asset_tweak {
|
|||||||
Specifier::Asset(path) => path.join("."),
|
Specifier::Asset(path) => path.join("."),
|
||||||
};
|
};
|
||||||
let handle = <AssetTweakWrapper<T> as AssetExt>::load_expect(&asset_specifier);
|
let handle = <AssetTweakWrapper<T> as AssetExt>::load_expect(&asset_specifier);
|
||||||
let AssetTweakWrapper(value) = handle.read().clone();
|
let AssetTweakWrapper(value) = handle.cloned();
|
||||||
|
|
||||||
value
|
value
|
||||||
}
|
}
|
||||||
|
@ -226,10 +226,10 @@ fn armor_stats() -> Result<(), Box<dyn Error>> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let pretty_config = PrettyConfig::new()
|
let pretty_config = PrettyConfig::new()
|
||||||
.with_depth_limit(4)
|
.depth_limit(4)
|
||||||
.with_separate_tuple_members(true)
|
.separate_tuple_members(true)
|
||||||
.with_decimal_floats(true)
|
.decimal_floats(true)
|
||||||
.with_enumerate_arrays(true);
|
.enumerate_arrays(true);
|
||||||
|
|
||||||
let mut path = ASSETS_PATH.clone();
|
let mut path = ASSETS_PATH.clone();
|
||||||
for part in item.item_definition_id().split('.') {
|
for part in item.item_definition_id().split('.') {
|
||||||
@ -418,10 +418,10 @@ fn weapon_stats() -> Result<(), Box<dyn Error>> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
let pretty_config = PrettyConfig::new()
|
let pretty_config = PrettyConfig::new()
|
||||||
.with_depth_limit(4)
|
.depth_limit(4)
|
||||||
.with_separate_tuple_members(true)
|
.separate_tuple_members(true)
|
||||||
.with_decimal_floats(true)
|
.decimal_floats(true)
|
||||||
.with_enumerate_arrays(true);
|
.enumerate_arrays(true);
|
||||||
|
|
||||||
let mut path = ASSETS_PATH.clone();
|
let mut path = ASSETS_PATH.clone();
|
||||||
for part in item.item_definition_id().split('.') {
|
for part in item.item_definition_id().split('.') {
|
||||||
@ -494,9 +494,7 @@ fn loot_table(loot_table: &str) -> Result<(), Box<dyn Error>> {
|
|||||||
items.push((chance, item));
|
items.push((chance, item));
|
||||||
}
|
}
|
||||||
|
|
||||||
let pretty_config = PrettyConfig::new()
|
let pretty_config = PrettyConfig::new().depth_limit(4).decimal_floats(true);
|
||||||
.with_depth_limit(4)
|
|
||||||
.with_decimal_floats(true);
|
|
||||||
|
|
||||||
let mut path = ASSETS_PATH.clone();
|
let mut path = ASSETS_PATH.clone();
|
||||||
path.push("common");
|
path.push("common");
|
||||||
|
@ -197,10 +197,10 @@ pub mod figuredata {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl assets::Compound for ShipSpec {
|
impl assets::Compound for ShipSpec {
|
||||||
fn load<S: assets::source::Source>(
|
fn load<S: assets::source::Source + ?Sized>(
|
||||||
cache: &assets::AssetCache<S>,
|
cache: &assets::AssetCache<S>,
|
||||||
_: &str,
|
_: &str,
|
||||||
) -> Result<Self, assets::Error> {
|
) -> Result<Self, assets::BoxedError> {
|
||||||
let manifest: AssetHandle<Ron<ShipCentralSpec>> =
|
let manifest: AssetHandle<Ron<ShipCentralSpec>> =
|
||||||
AssetExt::load("common.manifests.ship_manifest")?;
|
AssetExt::load("common.manifests.ship_manifest")?;
|
||||||
let mut colliders = HashMap::new();
|
let mut colliders = HashMap::new();
|
||||||
|
@ -7,7 +7,7 @@ pub use modular::{ModularComponent, ModularComponentKind, ModularComponentTag};
|
|||||||
pub use tool::{AbilitySet, AbilitySpec, Hands, MaterialStatManifest, Tool, ToolKind};
|
pub use tool::{AbilitySet, AbilitySpec, Hands, MaterialStatManifest, Tool, ToolKind};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
assets::{self, AssetExt, Error},
|
assets::{self, AssetExt, BoxedError, Error},
|
||||||
comp::inventory::{item::tool::AbilityMap, InvSlot},
|
comp::inventory::{item::tool::AbilityMap, InvSlot},
|
||||||
effect::Effect,
|
effect::Effect,
|
||||||
recipe::RecipeInput,
|
recipe::RecipeInput,
|
||||||
@ -550,10 +550,10 @@ impl Deref for Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl assets::Compound for ItemDef {
|
impl assets::Compound for ItemDef {
|
||||||
fn load<S: assets::source::Source>(
|
fn load<S: assets::source::Source + ?Sized>(
|
||||||
cache: &assets::AssetCache<S>,
|
cache: &assets::AssetCache<S>,
|
||||||
specifier: &str,
|
specifier: &str,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, BoxedError> {
|
||||||
// load from the filesystem first, but if the file doesn't exist, see if it's a
|
// load from the filesystem first, but if the file doesn't exist, see if it's a
|
||||||
// programmaticly-generated asset
|
// programmaticly-generated asset
|
||||||
let raw = match cache.load::<RawItemDef>(specifier) {
|
let raw = match cache.load::<RawItemDef>(specifier) {
|
||||||
|
@ -432,10 +432,10 @@ impl Asset for AbilityMap<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl assets::Compound for AbilityMap {
|
impl assets::Compound for AbilityMap {
|
||||||
fn load<S: assets::source::Source>(
|
fn load<S: assets::source::Source + ?Sized>(
|
||||||
cache: &assets::AssetCache<S>,
|
cache: &assets::AssetCache<S>,
|
||||||
specifier: &str,
|
specifier: &str,
|
||||||
) -> Result<Self, assets::Error> {
|
) -> Result<Self, assets::BoxedError> {
|
||||||
let manifest = cache.load::<AbilityMap<String>>(specifier)?.read();
|
let manifest = cache.load::<AbilityMap<String>>(specifier)?.read();
|
||||||
|
|
||||||
Ok(AbilityMap(
|
Ok(AbilityMap(
|
||||||
|
@ -502,7 +502,7 @@ impl LoadoutBuilder {
|
|||||||
/// 3) Will panic while runs in tests and asset doesn't have "correct" form
|
/// 3) Will panic while runs in tests and asset doesn't have "correct" form
|
||||||
#[must_use = "Method consumes builder and returns updated builder."]
|
#[must_use = "Method consumes builder and returns updated builder."]
|
||||||
pub fn with_asset_expect(mut self, asset_specifier: &str, rng: &mut impl Rng) -> Self {
|
pub fn with_asset_expect(mut self, asset_specifier: &str, rng: &mut impl Rng) -> Self {
|
||||||
let spec = LoadoutSpec::load_expect(asset_specifier).read().0.clone();
|
let spec = LoadoutSpec::load_expect_cloned(asset_specifier).0;
|
||||||
for (key, entry) in spec {
|
for (key, entry) in spec {
|
||||||
let item = match entry.try_to_item(asset_specifier, rng) {
|
let item = match entry.try_to_item(asset_specifier, rng) {
|
||||||
Some(item) => item,
|
Some(item) => item,
|
||||||
|
@ -151,10 +151,10 @@ impl EqualitySet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl assets::Compound for EqualitySet {
|
impl assets::Compound for EqualitySet {
|
||||||
fn load<S: assets::source::Source>(
|
fn load<S: assets::source::Source + ?Sized>(
|
||||||
cache: &assets::AssetCache<S>,
|
cache: &assets::AssetCache<S>,
|
||||||
id: &str,
|
id: &str,
|
||||||
) -> Result<Self, assets::Error> {
|
) -> Result<Self, assets::BoxedError> {
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
enum EqualitySpec {
|
enum EqualitySpec {
|
||||||
LootTable(String),
|
LootTable(String),
|
||||||
|
@ -202,7 +202,7 @@ impl EntityInfo {
|
|||||||
|
|
||||||
/// Helper function for applying config from asset
|
/// Helper function for applying config from asset
|
||||||
pub fn with_asset_expect(self, asset_specifier: &str) -> Self {
|
pub fn with_asset_expect(self, asset_specifier: &str) -> Self {
|
||||||
let config = EntityConfig::load_expect(asset_specifier).read().clone();
|
let config = EntityConfig::load_expect_cloned(asset_specifier);
|
||||||
|
|
||||||
self.with_entity_config(config, Some(asset_specifier))
|
self.with_entity_config(config, Some(asset_specifier))
|
||||||
}
|
}
|
||||||
|
@ -234,10 +234,10 @@ impl assets::Asset for RawRecipeBook {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl assets::Compound for RecipeBook {
|
impl assets::Compound for RecipeBook {
|
||||||
fn load<S: assets::source::Source>(
|
fn load<S: assets::source::Source + ?Sized>(
|
||||||
cache: &assets::AssetCache<S>,
|
cache: &assets::AssetCache<S>,
|
||||||
specifier: &str,
|
specifier: &str,
|
||||||
) -> Result<Self, assets::Error> {
|
) -> Result<Self, assets::BoxedError> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn load_item_def(spec: &(String, u32)) -> Result<(Arc<ItemDef>, u32), assets::Error> {
|
fn load_item_def(spec: &(String, u32)) -> Result<(Arc<ItemDef>, u32), assets::Error> {
|
||||||
let def = Arc::<ItemDef>::load_cloned(&spec.0)?;
|
let def = Arc::<ItemDef>::load_cloned(&spec.0)?;
|
||||||
@ -255,7 +255,7 @@ impl assets::Compound for RecipeBook {
|
|||||||
Ok((def, spec.1))
|
Ok((def, spec.1))
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut raw = cache.load::<RawRecipeBook>(specifier)?.read().clone();
|
let mut raw = cache.load::<RawRecipeBook>(specifier)?.cloned();
|
||||||
|
|
||||||
// Avoid showing purple-question-box recipes until the assets are added
|
// Avoid showing purple-question-box recipes until the assets are added
|
||||||
// (the `if false` is needed because commenting out the call will add a warning
|
// (the `if false` is needed because commenting out the call will add a warning
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use super::{BlockKind, SpriteKind};
|
use super::{BlockKind, SpriteKind};
|
||||||
use crate::{
|
use crate::{
|
||||||
assets::{self, AssetExt, AssetHandle, DotVoxAsset, Error},
|
assets::{self, AssetExt, AssetHandle, BoxedError, DotVoxAsset},
|
||||||
make_case_elim,
|
make_case_elim,
|
||||||
vol::{BaseVol, ReadVol, SizedVol, WriteVol},
|
vol::{BaseVol, ReadVol, SizedVol, WriteVol},
|
||||||
volumes::dyna::{Dyna, DynaError},
|
volumes::dyna::{Dyna, DynaError},
|
||||||
@ -67,10 +67,10 @@ impl std::ops::Deref for StructuresGroup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl assets::Compound for StructuresGroup {
|
impl assets::Compound for StructuresGroup {
|
||||||
fn load<S: assets::source::Source>(
|
fn load<S: assets::source::Source + ?Sized>(
|
||||||
cache: &assets::AssetCache<S>,
|
cache: &assets::AssetCache<S>,
|
||||||
specifier: &str,
|
specifier: &str,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, BoxedError> {
|
||||||
let specs = cache.load::<StructuresGroupSpec>(specifier)?.read();
|
let specs = cache.load::<StructuresGroupSpec>(specifier)?.read();
|
||||||
|
|
||||||
Ok(StructuresGroup(
|
Ok(StructuresGroup(
|
||||||
@ -94,7 +94,7 @@ impl assets::Compound for StructuresGroup {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.collect::<Result<_, Error>>()?,
|
.collect::<Result<_, BoxedError>>()?,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -137,10 +137,10 @@ impl ReadVol for Structure {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl assets::Compound for BaseStructure {
|
impl assets::Compound for BaseStructure {
|
||||||
fn load<S: assets::source::Source>(
|
fn load<S: assets::source::Source + ?Sized>(
|
||||||
cache: &assets::AssetCache<S>,
|
cache: &assets::AssetCache<S>,
|
||||||
specifier: &str,
|
specifier: &str,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, BoxedError> {
|
||||||
let dot_vox_data = cache.load::<DotVoxAsset>(specifier)?.read();
|
let dot_vox_data = cache.load::<DotVoxAsset>(specifier)?.read();
|
||||||
let dot_vox_data = &dot_vox_data.0;
|
let dot_vox_data = &dot_vox_data.0;
|
||||||
|
|
||||||
|
@ -89,6 +89,7 @@ gilrs = {version = "0.8.0", features = ["serde-serialize"]}
|
|||||||
server = { package = "veloren-server", path = "../server", optional = true, default-features = false, features = ["worldgen"] }
|
server = { package = "veloren-server", path = "../server", optional = true, default-features = false, features = ["worldgen"] }
|
||||||
|
|
||||||
# Utility
|
# Utility
|
||||||
|
assets_manager = {version = "0.7", features = ["ab_glyph"]}
|
||||||
backtrace = "0.3.40"
|
backtrace = "0.3.40"
|
||||||
bincode = "1.3.1"
|
bincode = "1.3.1"
|
||||||
chrono = { version = "0.4.19", features = ["serde"] }
|
chrono = { version = "0.4.19", features = ["serde"] }
|
||||||
|
@ -11,7 +11,7 @@ pub mod verification;
|
|||||||
pub use path::BasePath;
|
pub use path::BasePath;
|
||||||
|
|
||||||
use crate::path::{LANG_EXTENSION, LANG_MANIFEST_FILE};
|
use crate::path::{LANG_EXTENSION, LANG_MANIFEST_FILE};
|
||||||
use common_assets::{self, source::DirEntry, AssetExt, AssetGuard, AssetHandle};
|
use common_assets::{self, source::DirEntry, AssetExt, AssetGuard, AssetHandle, ReloadWatcher};
|
||||||
use hashbrown::{HashMap, HashSet};
|
use hashbrown::{HashMap, HashSet};
|
||||||
use raw::{RawFragment, RawLanguage, RawManifest};
|
use raw::{RawFragment, RawLanguage, RawManifest};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
@ -102,10 +102,10 @@ impl Language {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl common_assets::Compound for Language {
|
impl common_assets::Compound for Language {
|
||||||
fn load<S: common_assets::source::Source>(
|
fn load<S: common_assets::source::Source + ?Sized>(
|
||||||
cache: &common_assets::AssetCache<S>,
|
cache: &common_assets::AssetCache<S>,
|
||||||
asset_key: &str,
|
asset_key: &str,
|
||||||
) -> Result<Self, common_assets::Error> {
|
) -> Result<Self, common_assets::BoxedError> {
|
||||||
let manifest = cache
|
let manifest = cache
|
||||||
.load::<RawManifest>(&[asset_key, ".", LANG_MANIFEST_FILE].concat())?
|
.load::<RawManifest>(&[asset_key, ".", LANG_MANIFEST_FILE].concat())?
|
||||||
.cloned();
|
.cloned();
|
||||||
@ -145,9 +145,10 @@ impl common_assets::Compound for Language {
|
|||||||
|
|
||||||
/// the central data structure to handle localization in veloren
|
/// the central data structure to handle localization in veloren
|
||||||
// inherit Copy+Clone from AssetHandle
|
// inherit Copy+Clone from AssetHandle
|
||||||
#[derive(Debug, PartialEq, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub struct LocalizationHandle {
|
pub struct LocalizationHandle {
|
||||||
active: AssetHandle<Language>,
|
active: AssetHandle<Language>,
|
||||||
|
watcher: ReloadWatcher,
|
||||||
fallback: Option<AssetHandle<Language>>,
|
fallback: Option<AssetHandle<Language>>,
|
||||||
pub use_english_fallback: bool,
|
pub use_english_fallback: bool,
|
||||||
}
|
}
|
||||||
@ -259,8 +260,10 @@ impl LocalizationHandle {
|
|||||||
let default_key = ["voxygen.i18n.", REFERENCE_LANG].concat();
|
let default_key = ["voxygen.i18n.", REFERENCE_LANG].concat();
|
||||||
let language_key = ["voxygen.i18n.", specifier].concat();
|
let language_key = ["voxygen.i18n.", specifier].concat();
|
||||||
let is_default = language_key == default_key;
|
let is_default = language_key == default_key;
|
||||||
|
let active = Language::load(&language_key)?;
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
active: Language::load(&language_key)?,
|
active,
|
||||||
|
watcher: active.reload_watcher(),
|
||||||
fallback: if is_default {
|
fallback: if is_default {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
@ -274,16 +277,16 @@ impl LocalizationHandle {
|
|||||||
Self::load(specifier).expect("Can't load language files")
|
Self::load(specifier).expect("Can't load language files")
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reloaded(&mut self) -> bool { self.active.reloaded() }
|
pub fn reloaded(&mut self) -> bool { self.watcher.reloaded() }
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FindManifests;
|
struct FindManifests;
|
||||||
|
|
||||||
impl common_assets::Compound for FindManifests {
|
impl common_assets::Compound for FindManifests {
|
||||||
fn load<S: common_assets::Source>(
|
fn load<S: common_assets::Source + ?Sized>(
|
||||||
_: &common_assets::AssetCache<S>,
|
_: &common_assets::AssetCache<S>,
|
||||||
_: &str,
|
_: &str,
|
||||||
) -> Result<Self, common_assets::Error> {
|
) -> Result<Self, common_assets::BoxedError> {
|
||||||
Ok(Self)
|
Ok(Self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -312,10 +315,10 @@ impl common_assets::DirLoadable for FindManifests {
|
|||||||
struct LocalizationList(Vec<LanguageMetadata>);
|
struct LocalizationList(Vec<LanguageMetadata>);
|
||||||
|
|
||||||
impl common_assets::Compound for LocalizationList {
|
impl common_assets::Compound for LocalizationList {
|
||||||
fn load<S: common_assets::Source>(
|
fn load<S: common_assets::Source + ?Sized>(
|
||||||
cache: &common_assets::AssetCache<S>,
|
cache: &common_assets::AssetCache<S>,
|
||||||
specifier: &str,
|
specifier: &str,
|
||||||
) -> Result<Self, common_assets::Error> {
|
) -> Result<Self, common_assets::BoxedError> {
|
||||||
// List language directories
|
// List language directories
|
||||||
let languages = common_assets::load_dir::<FindManifests>(specifier, false)
|
let languages = common_assets::load_dir::<FindManifests>(specifier, false)
|
||||||
.unwrap_or_else(|e| panic!("Failed to get manifests from {}: {:?}", specifier, e))
|
.unwrap_or_else(|e| panic!("Failed to get manifests from {}: {:?}", specifier, e))
|
||||||
|
@ -31,16 +31,11 @@ pub(crate) struct RawLanguage<T> {
|
|||||||
pub(crate) fragments: HashMap</* relative to i18n_path */ PathBuf, RawFragment<T>>,
|
pub(crate) fragments: HashMap</* relative to i18n_path */ PathBuf, RawFragment<T>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
pub(crate) fn load_manifest(path: &LangPath) -> Result<RawManifest, common_assets::BoxedError> {
|
||||||
pub(crate) enum RawError {
|
|
||||||
RonError(ron::Error),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn load_manifest(path: &LangPath) -> Result<RawManifest, common_assets::Error> {
|
|
||||||
let manifest_file = path.file(LANG_MANIFEST_FILE);
|
let manifest_file = path.file(LANG_MANIFEST_FILE);
|
||||||
tracing::debug!(?manifest_file, "manifest loading");
|
tracing::debug!(?manifest_file, "manifest loading");
|
||||||
let f = fs::File::open(&manifest_file)?;
|
let f = fs::File::open(&manifest_file)?;
|
||||||
let manifest: RawManifest = from_reader(f).map_err(RawError::RonError)?;
|
let manifest: RawManifest = from_reader(f)?;
|
||||||
// verify that the folder name `de_DE` matches the value inside the metadata!
|
// verify that the folder name `de_DE` matches the value inside the metadata!
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
manifest.metadata.language_identifier,
|
manifest.metadata.language_identifier,
|
||||||
@ -52,7 +47,7 @@ pub(crate) fn load_manifest(path: &LangPath) -> Result<RawManifest, common_asset
|
|||||||
pub(crate) fn load_raw_language(
|
pub(crate) fn load_raw_language(
|
||||||
path: &LangPath,
|
path: &LangPath,
|
||||||
manifest: RawManifest,
|
manifest: RawManifest,
|
||||||
) -> Result<RawLanguage<String>, common_assets::Error> {
|
) -> Result<RawLanguage<String>, common_assets::BoxedError> {
|
||||||
//get List of files
|
//get List of files
|
||||||
let files = path.fragments()?;
|
let files = path.fragments()?;
|
||||||
|
|
||||||
@ -60,7 +55,7 @@ pub(crate) fn load_raw_language(
|
|||||||
let mut fragments = HashMap::new();
|
let mut fragments = HashMap::new();
|
||||||
for sub_path in files {
|
for sub_path in files {
|
||||||
let f = fs::File::open(path.sub_path(&sub_path))?;
|
let f = fs::File::open(path.sub_path(&sub_path))?;
|
||||||
let fragment = from_reader(f).map_err(RawError::RonError)?;
|
let fragment = from_reader(f)?;
|
||||||
fragments.insert(sub_path, fragment);
|
fragments.insert(sub_path, fragment);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,20 +100,6 @@ impl From<RawLanguage<String>> for Language {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl core::fmt::Display for RawError {
|
|
||||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
|
||||||
match self {
|
|
||||||
RawError::RonError(e) => write!(f, "{}", e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::error::Error for RawError {}
|
|
||||||
|
|
||||||
impl From<RawError> for common_assets::Error {
|
|
||||||
fn from(e: RawError) -> Self { Self::Conversion(Box::new(e)) }
|
|
||||||
}
|
|
||||||
|
|
||||||
impl common_assets::Asset for RawManifest {
|
impl common_assets::Asset for RawManifest {
|
||||||
type Loader = common_assets::RonLoader;
|
type Loader = common_assets::RonLoader;
|
||||||
|
|
||||||
|
@ -420,10 +420,10 @@ impl assets::Asset for SoundtrackCollection<RawSoundtrackItem> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl assets::Compound for SoundtrackCollection<SoundtrackItem> {
|
impl assets::Compound for SoundtrackCollection<SoundtrackItem> {
|
||||||
fn load<S: assets::source::Source>(
|
fn load<S: assets::source::Source + ?Sized>(
|
||||||
_: &assets::AssetCache<S>,
|
_: &assets::AssetCache<S>,
|
||||||
id: &str,
|
id: &str,
|
||||||
) -> Result<Self, assets::Error> {
|
) -> Result<Self, assets::BoxedError> {
|
||||||
let inner = || -> Result<_, assets::Error> {
|
let inner = || -> Result<_, assets::Error> {
|
||||||
let manifest: AssetHandle<SoundtrackCollection<RawSoundtrackItem>> =
|
let manifest: AssetHandle<SoundtrackCollection<RawSoundtrackItem>> =
|
||||||
AssetExt::load(id)?;
|
AssetExt::load(id)?;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::ui::{Graphic, SampleStrat, Transform, Ui};
|
use crate::ui::{Graphic, SampleStrat, Transform, Ui};
|
||||||
use common::{
|
use common::{
|
||||||
assets::{self, AssetExt, AssetHandle, DotVoxAsset},
|
assets::{self, AssetExt, AssetHandle, DotVoxAsset, ReloadWatcher},
|
||||||
comp::item::{
|
comp::item::{
|
||||||
armor::{Armor, ArmorKind},
|
armor::{Armor, ArmorKind},
|
||||||
Glider, ItemDef, ItemDesc, ItemKind, Lantern, Throwable, Utility,
|
Glider, ItemDef, ItemDesc, ItemKind, Lantern, Throwable, Utility,
|
||||||
@ -109,6 +109,7 @@ impl assets::Asset for ItemImagesSpec {
|
|||||||
pub struct ItemImgs {
|
pub struct ItemImgs {
|
||||||
map: HashMap<ItemKey, Id>,
|
map: HashMap<ItemKey, Id>,
|
||||||
manifest: AssetHandle<ItemImagesSpec>,
|
manifest: AssetHandle<ItemImagesSpec>,
|
||||||
|
watcher: ReloadWatcher,
|
||||||
not_found: Id,
|
not_found: Id,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,6 +129,7 @@ impl ItemImgs {
|
|||||||
Self {
|
Self {
|
||||||
map,
|
map,
|
||||||
manifest,
|
manifest,
|
||||||
|
watcher: manifest.reload_watcher(),
|
||||||
not_found,
|
not_found,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -135,7 +137,7 @@ impl ItemImgs {
|
|||||||
/// Checks if the manifest has been changed and reloads the images if so
|
/// Checks if the manifest has been changed and reloads the images if so
|
||||||
/// Reuses img ids
|
/// Reuses img ids
|
||||||
pub fn reload_if_changed(&mut self, ui: &mut Ui) {
|
pub fn reload_if_changed(&mut self, ui: &mut Ui) {
|
||||||
if self.manifest.reloaded() {
|
if self.watcher.reloaded() {
|
||||||
for (kind, spec) in self.manifest.read().0.iter() {
|
for (kind, spec) in self.manifest.read().0.iter() {
|
||||||
// Load new graphic
|
// Load new graphic
|
||||||
let graphic = spec.create_graphic();
|
let graphic = spec.create_graphic();
|
||||||
|
@ -28,7 +28,7 @@ use super::{
|
|||||||
AaMode, AddressMode, FilterMode, OtherModes, PipelineModes, RenderError, RenderMode,
|
AaMode, AddressMode, FilterMode, OtherModes, PipelineModes, RenderError, RenderMode,
|
||||||
ShadowMapMode, ShadowMode, Vertex,
|
ShadowMapMode, ShadowMode, Vertex,
|
||||||
};
|
};
|
||||||
use common::assets::{self, AssetExt, AssetHandle};
|
use common::assets::{self, AssetExt, AssetHandle, ReloadWatcher};
|
||||||
use common_base::span;
|
use common_base::span;
|
||||||
use core::convert::TryFrom;
|
use core::convert::TryFrom;
|
||||||
#[cfg(feature = "egui-ui")]
|
#[cfg(feature = "egui-ui")]
|
||||||
@ -157,6 +157,7 @@ pub struct Renderer {
|
|||||||
quad_index_buffer_u32: Buffer<u32>,
|
quad_index_buffer_u32: Buffer<u32>,
|
||||||
|
|
||||||
shaders: AssetHandle<Shaders>,
|
shaders: AssetHandle<Shaders>,
|
||||||
|
shaders_watcher: ReloadWatcher,
|
||||||
|
|
||||||
pipeline_modes: PipelineModes,
|
pipeline_modes: PipelineModes,
|
||||||
other_modes: OtherModes,
|
other_modes: OtherModes,
|
||||||
@ -360,6 +361,7 @@ impl Renderer {
|
|||||||
.ok();
|
.ok();
|
||||||
|
|
||||||
let shaders = Shaders::load_expect("");
|
let shaders = Shaders::load_expect("");
|
||||||
|
let shaders_watcher = shaders.reload_watcher();
|
||||||
|
|
||||||
let layouts = {
|
let layouts = {
|
||||||
let global = GlobalsLayouts::new(&device);
|
let global = GlobalsLayouts::new(&device);
|
||||||
@ -407,7 +409,7 @@ impl Renderer {
|
|||||||
immutable: Arc::clone(&layouts.immutable),
|
immutable: Arc::clone(&layouts.immutable),
|
||||||
postprocess: Arc::clone(&layouts.postprocess),
|
postprocess: Arc::clone(&layouts.postprocess),
|
||||||
},
|
},
|
||||||
shaders.read().clone(),
|
shaders.cloned(),
|
||||||
pipeline_modes.clone(),
|
pipeline_modes.clone(),
|
||||||
sc_desc.clone(), // Note: cheap clone
|
sc_desc.clone(), // Note: cheap clone
|
||||||
shadow_views.is_some(),
|
shadow_views.is_some(),
|
||||||
@ -510,6 +512,7 @@ impl Renderer {
|
|||||||
quad_index_buffer_u32,
|
quad_index_buffer_u32,
|
||||||
|
|
||||||
shaders,
|
shaders,
|
||||||
|
shaders_watcher,
|
||||||
|
|
||||||
pipeline_modes,
|
pipeline_modes,
|
||||||
other_modes,
|
other_modes,
|
||||||
@ -1053,7 +1056,7 @@ impl Renderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If the shaders files were changed attempt to recreate the shaders
|
// If the shaders files were changed attempt to recreate the shaders
|
||||||
if self.shaders.reloaded() {
|
if self.shaders_watcher.reloaded() {
|
||||||
self.recreate_pipelines(self.pipeline_modes.clone());
|
self.recreate_pipelines(self.pipeline_modes.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1113,7 +1116,7 @@ impl Renderer {
|
|||||||
pipeline_creation::recreate_pipelines(
|
pipeline_creation::recreate_pipelines(
|
||||||
Arc::clone(&self.device),
|
Arc::clone(&self.device),
|
||||||
Arc::clone(&self.layouts.immutable),
|
Arc::clone(&self.layouts.immutable),
|
||||||
self.shaders.read().clone(),
|
self.shaders.cloned(),
|
||||||
pipeline_modes,
|
pipeline_modes,
|
||||||
// NOTE: if present_mode starts to be used to configure pipelines then it
|
// NOTE: if present_mode starts to be used to configure pipelines then it
|
||||||
// needs to become a part of the pipeline modes
|
// needs to become a part of the pipeline modes
|
||||||
|
@ -24,10 +24,10 @@ pub struct Shaders {
|
|||||||
impl assets::Compound for Shaders {
|
impl assets::Compound for Shaders {
|
||||||
// TODO: Taking the specifier argument as a base for shaders specifiers
|
// TODO: Taking the specifier argument as a base for shaders specifiers
|
||||||
// would allow to use several shaders groups easily
|
// would allow to use several shaders groups easily
|
||||||
fn load<S: assets::source::Source>(
|
fn load<S: assets::source::Source + ?Sized>(
|
||||||
_: &assets::AssetCache<S>,
|
_: &assets::AssetCache<S>,
|
||||||
_: &str,
|
_: &str,
|
||||||
) -> Result<Shaders, assets::Error> {
|
) -> Result<Shaders, assets::BoxedError> {
|
||||||
let shaders = [
|
let shaders = [
|
||||||
"include.constants",
|
"include.constants",
|
||||||
"include.globals",
|
"include.globals",
|
||||||
|
@ -6,6 +6,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use anim::Skeleton;
|
use anim::Skeleton;
|
||||||
use common::{
|
use common::{
|
||||||
|
assets::ReloadWatcher,
|
||||||
comp::{
|
comp::{
|
||||||
inventory::{
|
inventory::{
|
||||||
slot::{ArmorSlot, EquipSlot},
|
slot::{ArmorSlot, EquipSlot},
|
||||||
@ -287,6 +288,7 @@ where
|
|||||||
{
|
{
|
||||||
models: HashMap<FigureKey<Skel::Body>, ((FigureModelEntryFuture<LOD_COUNT>, Skel::Attr), u64)>,
|
models: HashMap<FigureKey<Skel::Body>, ((FigureModelEntryFuture<LOD_COUNT>, Skel::Attr), u64)>,
|
||||||
manifests: <Skel::Body as BodySpec>::Manifests,
|
manifests: <Skel::Body as BodySpec>::Manifests,
|
||||||
|
watcher: ReloadWatcher,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Skel: Skeleton> FigureModelCache<Skel>
|
impl<Skel: Skeleton> FigureModelCache<Skel>
|
||||||
@ -295,10 +297,14 @@ where
|
|||||||
{
|
{
|
||||||
#[allow(clippy::new_without_default)] // TODO: Pending review in #587
|
#[allow(clippy::new_without_default)] // TODO: Pending review in #587
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
|
// NOTE: It might be better to bubble this error up rather than panicking.
|
||||||
|
let manifests = <Skel::Body as BodySpec>::load_spec().unwrap();
|
||||||
|
let watcher = <Skel::Body as BodySpec>::reload_watcher(&manifests);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
models: HashMap::new(),
|
models: HashMap::new(),
|
||||||
// NOTE: It might be better to bubble this error up rather than panicking.
|
manifests,
|
||||||
manifests: <Skel::Body as BodySpec>::load_spec().unwrap(),
|
watcher,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -561,7 +567,7 @@ where
|
|||||||
{
|
{
|
||||||
// Check for reloaded manifests
|
// Check for reloaded manifests
|
||||||
// TODO: maybe do this in a different function, maintain?
|
// TODO: maybe do this in a different function, maintain?
|
||||||
if <Skel::Body as BodySpec>::is_reloaded(&mut self.manifests) {
|
if self.watcher.reloaded() {
|
||||||
col_lights.atlas.clear();
|
col_lights.atlas.clear();
|
||||||
self.models.clear();
|
self.models.clear();
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use super::cache::{FigureKey, ToolKey};
|
use super::cache::{FigureKey, ToolKey};
|
||||||
use common::{
|
use common::{
|
||||||
assets::{self, AssetExt, AssetHandle, DotVoxAsset, Ron},
|
assets::{self, AssetExt, AssetHandle, DotVoxAsset, ReloadWatcher, Ron},
|
||||||
comp::{
|
comp::{
|
||||||
biped_large::{self, BodyType as BLBodyType, Species as BLSpecies},
|
biped_large::{self, BodyType as BLBodyType, Species as BLSpecies},
|
||||||
biped_small,
|
biped_small,
|
||||||
@ -96,7 +96,7 @@ pub trait BodySpec: Sized {
|
|||||||
fn load_spec() -> Result<Self::Manifests, assets::Error>;
|
fn load_spec() -> Result<Self::Manifests, assets::Error>;
|
||||||
|
|
||||||
/// Determine whether the cache's manifest was reloaded
|
/// Determine whether the cache's manifest was reloaded
|
||||||
fn is_reloaded(manifests: &mut Self::Manifests) -> bool;
|
fn reload_watcher(manifests: &Self::Manifests) -> ReloadWatcher;
|
||||||
|
|
||||||
/// Mesh bones using the given spec, character state, and mesh generation
|
/// Mesh bones using the given spec, character state, and mesh generation
|
||||||
/// function.
|
/// function.
|
||||||
@ -124,7 +124,7 @@ macro_rules! make_vox_spec {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl assets::Compound for $Spec {
|
impl assets::Compound for $Spec {
|
||||||
fn load<S: assets::source::Source>(_: &assets::AssetCache<S>, _: &str) -> Result<Self, assets::Error> {
|
fn load<S: assets::source::Source + ?Sized>(_: &assets::AssetCache<S>, _: &str) -> Result<Self, assets::BoxedError> {
|
||||||
Ok($Spec {
|
Ok($Spec {
|
||||||
$( $field: AssetExt::load($asset_path)?, )*
|
$( $field: AssetExt::load($asset_path)?, )*
|
||||||
})
|
})
|
||||||
@ -141,7 +141,7 @@ macro_rules! make_vox_spec {
|
|||||||
Self::Spec::load("")
|
Self::Spec::load("")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_reloaded(manifests: &mut Self::Manifests) -> bool { manifests.reloaded() }
|
fn reload_watcher(manifests: &Self::Manifests) -> ReloadWatcher { manifests.reload_watcher() }
|
||||||
|
|
||||||
fn bone_meshes(
|
fn bone_meshes(
|
||||||
$self_pat: &FigureKey<Self>,
|
$self_pat: &FigureKey<Self>,
|
||||||
@ -4549,7 +4549,7 @@ impl BodySpec for ship::Body {
|
|||||||
#[allow(unused_variables)]
|
#[allow(unused_variables)]
|
||||||
fn load_spec() -> Result<Self::Manifests, assets::Error> { Self::Spec::load("") }
|
fn load_spec() -> Result<Self::Manifests, assets::Error> { Self::Spec::load("") }
|
||||||
|
|
||||||
fn is_reloaded(manifests: &mut Self::Manifests) -> bool { manifests.reloaded() }
|
fn reload_watcher(manifests: &Self::Manifests) -> ReloadWatcher { manifests.reload_watcher() }
|
||||||
|
|
||||||
fn bone_meshes(
|
fn bone_meshes(
|
||||||
FigureKey { body, .. }: &FigureKey<Self>,
|
FigureKey { body, .. }: &FigureKey<Self>,
|
||||||
|
@ -61,7 +61,9 @@ impl BodySpec for VolumeKey {
|
|||||||
|
|
||||||
fn load_spec() -> Result<Self::Manifests, assets::Error> { Ok(()) }
|
fn load_spec() -> Result<Self::Manifests, assets::Error> { Ok(()) }
|
||||||
|
|
||||||
fn is_reloaded(_: &mut Self::Manifests) -> bool { false }
|
fn reload_watcher(_: &Self::Manifests) -> assets::ReloadWatcher {
|
||||||
|
assets::ReloadWatcher::default()
|
||||||
|
}
|
||||||
|
|
||||||
fn bone_meshes(
|
fn bone_meshes(
|
||||||
_: &FigureKey<Self>,
|
_: &FigureKey<Self>,
|
||||||
|
@ -5,10 +5,7 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use common::assets::{self, AssetExt};
|
use common::assets::{self, AssetExt};
|
||||||
use glyph_brush::GlyphBrushBuilder;
|
use glyph_brush::GlyphBrushBuilder;
|
||||||
use std::{
|
use std::cell::{RefCell, RefMut};
|
||||||
borrow::Cow,
|
|
||||||
cell::{RefCell, RefMut},
|
|
||||||
};
|
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
// Multiplied by current window size
|
// Multiplied by current window size
|
||||||
@ -24,22 +21,7 @@ type GlyphBrush = glyph_brush::GlyphBrush<(Aabr<f32>, Aabr<f32>), ()>;
|
|||||||
// TODO: might not need pub
|
// TODO: might not need pub
|
||||||
pub type Font = glyph_brush::ab_glyph::FontArc;
|
pub type Font = glyph_brush::ab_glyph::FontArc;
|
||||||
|
|
||||||
struct FontAsset(Font);
|
pub fn load_font(specifier: &str) -> Font { Font::load_expect(specifier).cloned() }
|
||||||
struct FontLoader;
|
|
||||||
impl assets::Loader<FontAsset> for FontLoader {
|
|
||||||
fn load(data: Cow<[u8]>, _: &str) -> Result<FontAsset, assets::BoxedError> {
|
|
||||||
let font = Font::try_from_vec(data.into_owned())?;
|
|
||||||
Ok(FontAsset(font))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl assets::Asset for FontAsset {
|
|
||||||
type Loader = FontLoader;
|
|
||||||
|
|
||||||
const EXTENSION: &'static str = "ttf";
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn load_font(specifier: &str) -> Font { FontAsset::load_expect(specifier).read().0.clone() }
|
|
||||||
|
|
||||||
#[derive(Clone, Copy, Default)]
|
#[derive(Clone, Copy, Default)]
|
||||||
pub struct FontId(pub(super) glyph_brush::FontId);
|
pub struct FontId(pub(super) glyph_brush::FontId);
|
||||||
|
@ -38,7 +38,7 @@ impl assets::Asset for SpawnEntry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl SpawnEntry {
|
impl SpawnEntry {
|
||||||
pub fn from(asset_specifier: &str) -> Self { Self::load_expect(asset_specifier).read().clone() }
|
pub fn from(asset_specifier: &str) -> Self { Self::load_expect_cloned(asset_specifier) }
|
||||||
|
|
||||||
pub fn request(&self, requested_period: DayPeriod, underwater: bool) -> Option<Pack> {
|
pub fn request(&self, requested_period: DayPeriod, underwater: bool) -> Option<Pack> {
|
||||||
self.rules
|
self.rules
|
||||||
|
@ -442,18 +442,17 @@ impl WorldSim {
|
|||||||
FileOpts::LoadAsset(ref specifier) => match WorldFile::load_owned(specifier) {
|
FileOpts::LoadAsset(ref specifier) => match WorldFile::load_owned(specifier) {
|
||||||
Ok(map) => map.into_modern(),
|
Ok(map) => map.into_modern(),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
match err {
|
match err.reason().downcast_ref::<std::io::Error>() {
|
||||||
assets::Error::Io(e) => {
|
Some(e) => {
|
||||||
warn!(?e, ?specifier, "Couldn't read asset specifier for maps");
|
warn!(?e, ?specifier, "Couldn't read asset specifier for maps");
|
||||||
},
|
},
|
||||||
assets::Error::Conversion(e) => {
|
None => {
|
||||||
warn!(
|
warn!(
|
||||||
?e,
|
?err,
|
||||||
"Couldn't parse modern map. Maybe you meant to try a legacy \
|
"Couldn't parse modern map. Maybe you meant to try a legacy \
|
||||||
load?"
|
load?"
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
assets::Error::NoDefaultValue => unreachable!(),
|
|
||||||
}
|
}
|
||||||
return None;
|
return None;
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user