use std::iter::Iterator; use glc::{ error::Error as GlcError, shader::{Program, Shader, Type}, texture::{Data, FilterMag, FilterMin, Target, Texture, Wrap}, }; use space_crush_common::misc::Vfs; use specs::World; use crate::Error; /* WorldHelper */ pub trait WorldHelper { fn load_program(&self, iter: I) -> Result where I: IntoIterator; fn load_shader(&self, type_: Type, file: &str) -> Result; fn load_texture(&self, path: &str) -> Result; } impl WorldHelper for World { fn load_program(&self, iter: I) -> Result where I: IntoIterator, { Program::from_shaders_result(iter.into_iter().map(|(t, p)| self.load_shader(t, p))) } fn load_shader(&self, type_: Type, path: &str) -> Result { let vfs = self.fetch::(); let path = vfs.join(path)?; let mut file = path.open_file()?; let path = path.parent().unwrap(); let shader = Shader::from_reader(type_, &mut file, |include| { let p = if include.starts_with('.') { path.join(include) } else { vfs.join(include) }; let p = match p { Ok(p) => p, Err(err) => return Err(GlcError::ShaderInclude(format!("{}", err))), }; let mut r = match p.open_file() { Ok(r) => r, Err(err) => return Err(GlcError::ShaderInclude(format!("{}", err))), }; let mut code = String::default(); if let Err(err) = r.read_to_string(&mut code) { return Err(GlcError::ShaderInclude(format!("{}", err))); } Ok(code) })?; Ok(shader) } fn load_texture(&self, path: &str) -> Result { let vfs = self.fetch::(); let mut file = vfs.join(path)?.open_file()?; let mut data = Data::from_reader(&mut file)?; data.convert_to(data.format().info().format_gl_support)?; let mut texture = Texture::new(Target::Texture2D)?; texture.upload(&data, true)?; texture.set_filter(FilterMin::LinearMipmapLinear, FilterMag::Linear)?; texture.set_wrap( Wrap::ClampToBorder, Wrap::ClampToBorder, Wrap::ClampToBorder, )?; Ok(texture) } }