use ecs::Component; use crate::color::Color; use crate::texture::Texture; use crate::builder; #[derive(Debug, Clone)] #[non_exhaustive] pub struct Material { pub ambient: Color, pub diffuse: Color, pub specular: Color, pub ambient_map: Option, pub diffuse_map: Option, pub specular_map: Option, pub shininess: f32, } impl Material { pub fn builder() -> Builder { Builder::default() } } impl Default for Material { fn default() -> Self { Self::builder().build() } } /// [`Material`] builder. #[derive(Debug, Clone)] pub struct Builder { ambient: Color, diffuse: Color, specular: Color, ambient_map: Option, diffuse_map: Option, specular_map: Option, shininess: f32, } impl Builder { #[must_use] pub fn new() -> Self { Self { ambient: Color::WHITE_F32, diffuse: Color::WHITE_F32, specular: Color::WHITE_F32, ambient_map: None, diffuse_map: None, specular_map: None, shininess: 32.0, } } #[must_use] pub fn ambient(mut self, ambient: Color) -> Self { self.ambient = ambient; self } #[must_use] pub fn diffuse(mut self, diffuse: Color) -> Self { self.diffuse = diffuse; self } #[must_use] pub fn specular(mut self, specular: Color) -> Self { self.specular = specular; self } #[must_use] pub fn ambient_map(mut self, ambient_map: Texture) -> Self { self.ambient_map = Some(ambient_map); self } #[must_use] pub fn diffuse_map(mut self, diffuse_map: Texture) -> Self { self.diffuse_map = Some(diffuse_map); self } #[must_use] pub fn specular_map(mut self, specular_map: Texture) -> Self { self.specular_map = Some(specular_map); self } #[must_use] pub fn shininess(mut self, shininess: f32) -> Self { self.shininess = shininess; self } /// Builds a new [`Material`]. /// /// # Panics /// Will panic if no ambient map, diffuse map or specular map is set. #[must_use] pub fn build(self) -> Material { Material { ambient: self.ambient, diffuse: self.diffuse, specular: self.specular, ambient_map: self.ambient_map, diffuse_map: self.diffuse_map, specular_map: self.specular_map, shininess: self.shininess, } } } impl Default for Builder { fn default() -> Self { Self::new() } } builder! { /// Material flags. #[builder(name = FlagsBuilder, derives = (Debug, Default, Clone))] #[derive(Debug, Default, Clone, Component)] #[non_exhaustive] pub struct Flags { /// Whether to use material's ambient color instead of the global ambient color. /// Default is `false` pub use_ambient_color: bool, } } impl Flags { #[must_use] pub fn builder() -> FlagsBuilder { FlagsBuilder::default() } }