use crate::plugin::AssetRoot;
use crate::prelude::*;
#[cfg(not(any(target_arch = "wasm32", target_os = "android")))]
use anyhow::{Result, ensure};
use bevy::prelude::*;
#[cfg(not(any(target_arch = "wasm32", target_os = "android")))]
use glob::glob;
use std::path::PathBuf;
#[derive(Debug, Clone, PartialEq, Eq, Hash, Reflect)]
pub enum YarnFileSource {
Handle(Handle<YarnFile>),
InMemory(YarnFile),
File(PathBuf),
#[cfg(not(any(target_arch = "wasm32", target_os = "android")))]
Folder(PathBuf),
}
impl From<Handle<YarnFile>> for YarnFileSource {
fn from(handle: Handle<YarnFile>) -> Self {
Self::Handle(handle)
}
}
impl From<YarnFile> for YarnFileSource {
fn from(yarn_file: YarnFile) -> Self {
Self::InMemory(yarn_file)
}
}
impl YarnFileSource {
pub fn file(path: impl Into<PathBuf>) -> Self {
Self::File(path.into())
}
#[cfg(not(any(target_arch = "wasm32", target_os = "android")))]
pub fn folder(path: impl Into<PathBuf>) -> Self {
Self::Folder(path.into())
}
pub(crate) fn load(
&self,
asset_server: &AssetServer,
assets: &mut ResMut<Assets<YarnFile>>,
#[allow(unused_variables, reason = "conditional compilation")] asset_root: &AssetRoot,
) -> Result<Vec<Handle<YarnFile>>> {
match self {
Self::Handle(handle) => Ok(vec![handle.clone()]),
Self::InMemory(yarn_file) => Ok(vec![assets.add(yarn_file.clone())]),
Self::File(path) => Ok(vec![asset_server.load(path.clone())]),
#[cfg(not(any(target_arch = "wasm32", target_os = "android")))]
Self::Folder(path) => Self::load_folder(asset_server, path.as_path(), asset_root),
}
}
#[cfg(not(any(target_arch = "wasm32", target_os = "android")))]
fn load_folder(
asset_server: &AssetServer,
path: &std::path::Path,
asset_root: &AssetRoot,
) -> Result<Vec<Handle<YarnFile>>> {
let path = asset_root.0.join(path);
ensure!(
path.is_dir(),
"Failed to load Yarn file folder {path}.\nHelp: Does the folder exist?",
path = path.display()
);
let handles: Result<Vec<_>> =
glob(path.join("**/*.yarn").to_str().with_context(|| {
format!(
"Failed to create string from path: {path}",
path = path.display(),
)
})?)?
.map(|entry| {
let full_path = entry?;
let path = full_path.strip_prefix(&asset_root.0)?;
let asset_path = path.to_string_lossy().replace('\\', "/");
Ok(asset_server.load(asset_path))
})
.collect();
let handles = handles?;
if handles.is_empty() {
warn!(
"No Yarn files found in the assets subdirectory {path}, so Yarn Spinner won't be able to do anything this run. \
Help: Add some Yarn files to get started.",
path = path.display()
);
}
Ok(handles)
}
}