use std::{borrow::Cow, fmt, io::Cursor};
use binrw::{BinRead, NullString};
use getset::{CopyGetters, Getters};
use crate::{error::Result, file::File};
use super::structs;
pub struct Material {
file: structs::Material,
shader: String,
samplers: Vec<Sampler>,
}
impl Material {
pub fn version(&self) -> u32 {
self.file.version
}
pub fn shader(&self) -> &str {
&self.shader
}
pub fn samplers(&self) -> &[Sampler] {
&self.samplers
}
}
impl Material {
fn read_shader(file: &structs::Material) -> Result<String> {
let mut cursor = Cursor::new(&file.string_data);
cursor.set_position(file.shader_package_name_offset.into());
let shader = NullString::read(&mut cursor)?.into_string();
Ok(shader)
}
fn read_samplers(file: &structs::Material) -> Result<Vec<Sampler>> {
let mut cursor = Cursor::new(&file.string_data);
file.samplers
.iter()
.map(|sampler| {
let offset = &file.texture_offsets[usize::from(sampler.texture_index)];
cursor.set_position(offset.offset.into());
let texture = NullString::read(&mut cursor)?.into_string();
Ok(Sampler {
id: sampler.id,
texture,
})
})
.collect()
}
}
impl File for Material {
fn read<'a>(data: impl Into<Cow<'a, [u8]>>) -> Result<Self> {
let file = structs::Material::read(&mut Cursor::new(data.into()))?;
Ok(Material {
shader: Material::read_shader(&file)?,
samplers: Material::read_samplers(&file)?,
file,
})
}
}
impl fmt::Debug for Material {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Material")
.field("version", &self.version())
.field("shader", &self.shader)
.field("samplers", &self.samplers)
.finish()
}
}
#[derive(Debug, Getters, CopyGetters)]
pub struct Sampler {
#[get_copy = "pub"]
id: u32,
texture: String,
}
impl Sampler {
pub fn texture(&self) -> String {
self.texture.clone()
}
}