use crate::reflect::{self, ReflectError};
use crate::schema::{self, SchemaError, WispSchema};
use bevy_asset::io::Reader;
use bevy_asset::prelude::*;
use bevy_asset::{AssetLoader, LoadContext};
use bevy_derive::{Deref, DerefMut};
use bevy_ecs::prelude::*;
use bevy_reflect::prelude::TypePath;
use bevy_render::extract_component::ExtractComponent;
use bevy_shader::Shader;
use thiserror::Error;
#[derive(Asset, TypePath, Debug, Clone)]
pub struct Wisp {
pub schema: WispSchema,
pub shader: Handle<Shader>,
}
#[derive(Component, ExtractComponent, Deref, DerefMut, Debug, Default, Clone)]
pub struct WispHandle(pub Handle<Wisp>);
#[derive(Default, TypePath)]
pub struct WispLoader;
#[derive(Debug, Error)]
pub enum WispLoadError {
#[error("failed to read wisp shader: {0}")]
Io(#[from] std::io::Error),
#[error("wisp shader is not valid UTF-8: {0}")]
Utf8(#[from] std::str::Utf8Error),
#[error(transparent)]
Reflect(#[from] ReflectError),
#[error(transparent)]
Schema(#[from] SchemaError),
}
impl AssetLoader for WispLoader {
type Asset = Wisp;
type Settings = ();
type Error = WispLoadError;
async fn load(
&self,
reader: &mut dyn Reader,
_settings: &Self::Settings,
load_context: &mut LoadContext<'_>,
) -> Result<Self::Asset, Self::Error> {
let mut bytes = Vec::new();
reader.read_to_end(&mut bytes).await?;
let source = std::str::from_utf8(&bytes)?;
let reflected = reflect::parse_and_validate(source)?;
let schema = schema::schema_from_module(&reflected)?;
let path = load_context.path().to_string();
let padded = crate::align::pad_uniform_structs(source, &reflected.module);
let shader = Shader::from_wgsl(padded, path);
let shader = load_context.add_labeled_asset(String::from("shader"), shader);
Ok(Wisp { schema, shader })
}
fn extensions(&self) -> &[&str] {
&[]
}
}