use crate::{
atlas::*,
vertex::*
};
use std::sync::Mutex;
use bevy_asset::*;
use bevy_render::{
mesh::{Indices, Mesh},
render_asset::RenderAssetUsages,
render_resource::PrimitiveTopology
};
use bevy_utils::BoxedFuture;
use cached::proc_macro::once;
use chair::{MeshFeature, MeshReader};
use tokio::sync::oneshot::Receiver;
pub struct ChairLoader {
atlas_rx: Mutex<Option<Receiver<ChairAtlas>>>,
usages: RenderAssetUsages
}
impl ChairLoader {
pub fn new(rx: Receiver<ChairAtlas>) -> Self {
Self {
atlas_rx: Mutex::new(Some(rx)),
usages: RenderAssetUsages::RENDER_WORLD
}
}
pub fn with_usages(self, usages: RenderAssetUsages) -> Self {
Self {
usages,
..self
}
}
}
impl AssetLoader for ChairLoader {
type Asset = Mesh;
type Settings = ();
type Error = chair::Error;
fn load<'a>(
&'a self,
reader: &'a mut io::Reader,
_settings: &'a Self::Settings,
_load_context: &'a mut LoadContext
) -> BoxedFuture<'a, chair::Result<Self::Asset>> {
Box::pin(async move {
let mut bytes = vec![];
reader.read_to_end(&mut bytes).await
.map_err(chair::Error::from)?;
let atlas = get_atlas(&self.atlas_rx).await;
let reader = MeshReader::new::<FatVertex>(atlas.0, Some("error"));
let (features, vertices, indices) = reader.read::<FatVertex>(&bytes)?;
let mut mesh = Mesh::new(PrimitiveTopology::TriangleList, self.usages);
mesh.insert_attribute(Mesh::ATTRIBUTE_POSITION, vertices.iter()
.map(|v| v.pos)
.collect::<Vec<_>>());
if features.contains(MeshFeature::Coloured) {
mesh.insert_attribute(Mesh::ATTRIBUTE_COLOR, vertices.iter()
.map(|v| v.col)
.collect::<Vec<_>>());
}
if features.contains(MeshFeature::Normals) {
mesh.insert_attribute(Mesh::ATTRIBUTE_NORMAL, vertices.iter()
.map(|v| v.normals)
.collect::<Vec<_>>());
}
if features.contains(MeshFeature::Textured) {
mesh.insert_attribute(Mesh::ATTRIBUTE_UV_0, vertices.iter()
.map(|v| v.uvs)
.collect::<Vec<_>>());
}
mesh.insert_indices(Indices::U32(indices));
Ok(mesh)
})
}
fn extensions(&self) -> &[&str] {
&["chr"]
}
}
#[once(sync_writes = true)]
async fn get_atlas(rx: &Mutex<Option<Receiver<ChairAtlas>>>) -> ChairAtlas {
let rx = {
let mut lock = rx.lock().unwrap();
lock.take()
.expect("get_atlas called multiple times, bug in cached?")
};
rx.await
.expect("Receiving atlas failed")
}