use crate::types::Texture;
use amethyst_assets::{Asset, Handle};
use amethyst_core::ecs::prelude::DenseVecStorage;
#[derive(Debug, Clone, PartialEq, serde::Deserialize, serde::Serialize)]
pub struct TextureOffset {
pub u: (f32, f32),
pub v: (f32, f32),
}
impl Default for TextureOffset {
fn default() -> Self {
TextureOffset {
u: (0., 1.),
v: (0., 1.),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Material {
pub alpha_cutoff: f32,
pub albedo: Handle<Texture>,
pub emission: Handle<Texture>,
pub normal: Handle<Texture>,
pub metallic_roughness: Handle<Texture>,
pub ambient_occlusion: Handle<Texture>,
pub cavity: Handle<Texture>,
pub uv_offset: TextureOffset,
}
impl Asset for Material {
const NAME: &'static str = "renderer::Material";
type Data = Self;
type HandleStorage = DenseVecStorage<Handle<Self>>;
}
#[derive(Debug, Clone)]
pub struct MaterialDefaults(pub Material);
pub trait StaticTextureSet<'a>:
Clone + Copy + std::fmt::Debug + PartialEq + Eq + std::hash::Hash + Send + Sync + 'static
{
type Iter: Iterator<Item = &'a Handle<Texture>>;
fn textures(mat: &'a Material) -> Self::Iter;
fn len() -> usize {
1
}
}
pub type FullTextureSet = (
TexAlbedo,
TexEmission,
TexNormal,
TexMetallicRoughness,
TexAmbientOcclusion,
TexCavity,
);
macro_rules! impl_texture {
($name:ident, $prop:ident) => {
#[doc = "Macro Generated Texture Type"]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct $name;
impl<'a> StaticTextureSet<'a> for $name {
type Iter = std::iter::Once<&'a Handle<Texture>>;
#[inline(always)]
fn textures(mat: &'a Material) -> Self::Iter {
std::iter::once(&mat.$prop)
}
}
};
}
impl_texture!(TexAlbedo, albedo);
impl_texture!(TexEmission, emission);
impl_texture!(TexNormal, normal);
impl_texture!(TexMetallicRoughness, metallic_roughness);
impl_texture!(TexAmbientOcclusion, ambient_occlusion);
impl_texture!(TexCavity, cavity);
macro_rules! recursive_iter {
(@value $first:expr, $($rest:expr),*) => { $first.chain(recursive_iter!(@value $($rest),*)) };
(@value $last:expr) => { $last };
(@type $first:ty, $($rest:ty),*) => { std::iter::Chain<$first, recursive_iter!(@type $($rest),*)> };
(@type $last:ty) => { $last };
}
macro_rules! impl_texture_set_tuple {
($($from:ident),*) => {
impl<'a, $($from,)*> StaticTextureSet<'a> for ($($from),*,)
where
$($from: StaticTextureSet<'a>),*,
{
type Iter = recursive_iter!(@type $($from::Iter),*);
#[inline(always)]
fn textures(mat: &'a Material) -> Self::Iter {
recursive_iter!(@value $($from::textures(mat)),*)
}
fn len() -> usize {
$($from::len() + )* 0
}
}
}
}
impl_texture_set_tuple!(A);
impl_texture_set_tuple!(A, B);
impl_texture_set_tuple!(A, B, C);
impl_texture_set_tuple!(A, B, C, D);
impl_texture_set_tuple!(A, B, C, D, E);
impl_texture_set_tuple!(A, B, C, D, E, F);