use teleia::*; use crate::overlay; #[derive(Clone, Copy, PartialEq, Eq)] pub enum AssetSort { Texture, Mesh, } impl AssetSort { pub fn from_str(s: &str) -> Option { match s { "texture" => Some(Self::Texture), "mesh" => Some(Self::Mesh), _ => None, } } } #[derive(Clone, PartialEq, Eq)] pub struct DisplayedAsset { sort: AssetSort, path: String, } pub struct Overlay { loaded: Option, displayed: Option, texture_placeholder: texture::Texture, texture: texture::Texture, mesh: mesh::Mesh, } impl Overlay { pub fn new(ctx: &context::Context) -> Self { Self { loaded: None, displayed: None, texture_placeholder: texture::Texture::new(ctx, include_bytes!("../assets/textures/placeholder.png")), texture: texture::Texture::new_empty(ctx), mesh: mesh::Mesh::new_empty(ctx, true, true), } } pub fn load_displayed(&mut self, ctx: &context::Context) -> Erm<()> { if let Some(d) = &self.displayed { match d.sort { AssetSort::Texture => { let bs = std::fs::read(&d.path)?; self.texture.upload(ctx, &bs); }, AssetSort::Mesh => { let bs = std::fs::read(&d.path)?; self.mesh.upload_obj(ctx, &bs); }, } } Ok(()) } } impl overlay::Overlay for Overlay { fn handle_binary(&mut self, ctx: &context::Context, st: &mut state::State, ost: &mut overlay::State, msg: &net::fig::BinaryMessage) -> Erm<()> { match &*msg.event { b"overlay asset display" => { let mut reader = std::io::Cursor::new(&msg.data); let ssort = net::fig::read_length_prefixed_utf8(&mut reader)?; let path = net::fig::read_length_prefixed_utf8(&mut reader)?; if let Some(sort) = AssetSort::from_str(&ssort) { log::warn!("displaying {} asset at: {}", ssort, path); let new = Some(DisplayedAsset {sort, path}); if new != self.displayed { self.displayed = new.clone(); if self.displayed != self.loaded { if let Err(e) = self.load_displayed(ctx) { self.displayed = None; log::warn!("error when loading asset: {}", e); } else { self.loaded = new; } } } } else { log::warn!("unknown asset sort: {}", ssort); } }, b"overlay asset clear" => { self.displayed = None; }, _ => {}, } Ok(()) } fn render(&mut self, ctx: &context::Context, st: &mut state::State, ost: &mut overlay::State) -> Erm<()> { if let Some(d) = &self.displayed { match d.sort { AssetSort::Texture => { st.bind_2d(ctx, &ost.assets.shader_flat); self.texture.bind(ctx); ost.assets.shader_flat.set_position_2d( ctx, st, &glam::Vec2::new(ost.info.emacs_cursor.0, ost.info.emacs_cursor.1), &glam::Vec2::new(self.texture.width as f32, self.texture.height as f32) ); st.mesh_square.render(ctx); }, AssetSort::Mesh => { st.bind_3d(ctx, &ost.assets.shader_flat); ost.assets.shader_flat.set_f32(ctx, "transparency", 0.0); self.texture_placeholder.bind(ctx); ost.assets.shader_flat.set_position_3d( ctx, st, &glam::Mat4::from_scale_rotation_translation( glam::Vec3::new(1.0, 1.0, 1.0), glam::Quat::from_rotation_y(st.tick as f32 / 75.0), glam::Vec3::new(0.0, 0.0, -8.0) ), ); self.mesh.render(ctx); }, } } Ok(()) } }