Skip to content
Snippets Groups Projects
loader.rs 2.91 KiB
Newer Older
use std::error::Error;
use std::fmt::{Debug, Display, Formatter};

#[derive(Debug)]
pub enum LoaderError {
	#[cfg(feature = "json_loader")]
	Json(serde_json::Error),
	#[cfg(feature = "toml_loader")]
	Toml(toml::de::Error),
	Custom(String),
}

impl Display for LoaderError {
	fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
		match self {
			Self::Custom(message) => Display::fmt(message, f),
			#[cfg(feature = "json_loader")]
			Self::Json(err) => Display::fmt(err, f),
			#[cfg(feature = "toml_loader")]
			Self::Toml(err) => Display::fmt(err, f),
		}
	}
}

impl Error for LoaderError {}

Louis's avatar
Louis committed
#[cfg(feature = "json_loader")]
mod json_loader {
	use bevy::asset::io::Reader;
	use bevy::asset::{AssetLoader, AsyncReadExt, BoxedFuture, LoadContext};
Louis's avatar
Louis committed

	use crate::definitions::AnimationSet;
	use crate::loader::LoaderError;

	pub struct AnimationLoader;
	impl AssetLoader for AnimationLoader {
		type Asset = AnimationSet;
		type Settings = ();
		type Error = LoaderError;
Louis's avatar
Louis committed

		fn load<'a>(
			&'a self,
			reader: &'a mut Reader,
			_settings: &'a Self::Settings,
			_load_context: &'a mut LoadContext,
		) -> BoxedFuture<'a, Result<Self::Asset, Self::Error>> {
Louis's avatar
Louis committed
			Box::pin(async move {
				let mut bytes = Vec::new();
				reader
					.read_to_end(&mut bytes)
					.await
					.expect("Failed to read all bytes");

				serde_json::from_slice(bytes.as_slice()).map_err(LoaderError::Json)
Louis's avatar
Louis committed
			})
		}

		fn extensions(&self) -> &[&str] {
			static EXTENSIONS: &[&str] = &["anim.json"];
			EXTENSIONS
		}
	}
}

#[cfg(feature = "toml_loader")]
mod toml_loader {
	use bevy::asset::io::Reader;
	use bevy::asset::{AssetLoader, AsyncReadExt, BoxedFuture, LoadContext};
Louis's avatar
Louis committed

	use crate::definitions::AnimationSet;
	use crate::loader::LoaderError;

	pub struct AnimationLoader;
	impl AssetLoader for AnimationLoader {
		type Asset = AnimationSet;
		type Settings = ();
		type Error = LoaderError;
Louis's avatar
Louis committed

		fn load<'a>(
			&'a self,
			reader: &'a mut Reader,
			_settings: &'a Self::Settings,
			_load_context: &'a mut LoadContext,
		) -> BoxedFuture<'a, Result<Self::Asset, Self::Error>> {
Louis's avatar
Louis committed
			Box::pin(async move {
				let mut bytes = String::new();
				reader
					.read_to_string(&mut bytes)
					.await
					.expect("Failed to read all bytes");

				toml::from_str(bytes.as_str()).map_err(LoaderError::Toml)
Louis's avatar
Louis committed
			})
		}

		fn extensions(&self) -> &[&str] {
			static EXTENSIONS: &[&str] = &["anim.toml"];
			EXTENSIONS
		}
	}
}

mod _plugin {
	use bevy::app::{App, Plugin};
	use bevy::asset::AssetApp;

	pub struct AnimationLoadersPlugin;
	impl Plugin for AnimationLoadersPlugin {
		fn build(&self, app: &mut App) {
			#[cfg(any(feature = "json_loader", feature = "toml_loader"))]
			app.init_asset::<crate::definitions::AnimationSet>();

			#[cfg(feature = "json_loader")]
			app.register_asset_loader(super::json_loader::AnimationLoader);
			#[cfg(feature = "toml_loader")]
			app.register_asset_loader(super::toml_loader::AnimationLoader);
		}

pub use _plugin::AnimationLoadersPlugin;