From f5b3b11ad449a60322bca096de010a35ba2b30c8 Mon Sep 17 00:00:00 2001 From: HampusM Date: Wed, 22 Jan 2025 18:00:03 +0100 Subject: feat(engine): add texture & texture properties builders --- engine/src/texture.rs | 152 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 107 insertions(+), 45 deletions(-) (limited to 'engine/src') diff --git a/engine/src/texture.rs b/engine/src/texture.rs index 16c1941..4a4fe86 100644 --- a/engine/src/texture.rs +++ b/engine/src/texture.rs @@ -8,6 +8,7 @@ use image::{DynamicImage, ImageError, Rgb, RgbImage}; use crate::color::Color; use crate::data_types::dimens::Dimens; use crate::opengl::texture::PixelDataFormat; +use crate::util::builder; static NEXT_ID: AtomicU32 = AtomicU32::new(0); @@ -30,62 +31,26 @@ pub struct Texture impl Texture { + pub fn builder() -> Builder + { + Builder::default() + } + /// Opens a texture image. /// /// # Errors /// Will return `Err` if: /// - Opening the image fails /// - The image data is not 8-bit/color RGB - #[allow(clippy::new_without_default)] pub fn open(path: &Path) -> Result { - let image = ImageReader::open(path) - .map_err(Error::OpenImageFailed)? - .decode() - .map_err(Error::DecodeImageFailed)?; - - let pixel_data_format = match &image { - DynamicImage::ImageRgb8(_) => PixelDataFormat::Rgb8, - DynamicImage::ImageRgba8(_) => PixelDataFormat::Rgba8, - _ => { - return Err(Error::UnsupportedImageDataKind); - } - }; - - let dimensions = Dimens { - width: image.width(), - height: image.height(), - }; - - let id = NEXT_ID.fetch_add(1, Ordering::Relaxed); - - Ok(Self { - id: Id::new(id), - image, - pixel_data_format, - dimensions, - properties: Properties::default(), - }) + Self::builder().open(path) } #[must_use] pub fn new_from_color(dimensions: &Dimens, color: &Color) -> Self { - let image = RgbImage::from_pixel( - dimensions.width, - dimensions.height, - Rgb([color.red, color.green, color.blue]), - ); - - let id = NEXT_ID.fetch_add(1, Ordering::Relaxed); - - Self { - id: Id::new(id), - image: image.into(), - pixel_data_format: PixelDataFormat::Rgb8, - dimensions: *dimensions, - properties: Properties::default(), - } + Self::builder().build_with_single_color(dimensions, color) } #[must_use] @@ -132,6 +97,84 @@ impl Drop for Texture } } +/// Texture builder. +#[derive(Debug, Default, Clone)] +pub struct Builder +{ + properties: Properties, +} + +impl Builder +{ + pub fn properties(mut self, properties: Properties) -> Self + { + self.properties = properties; + self + } + + /// Opens a image as a texture. + /// + /// # Errors + /// Will return `Err` if: + /// - Opening the image fails + /// - Decoding the image fails + /// - The image data is in a unsupported format + pub fn open(&self, path: &(impl AsRef + ?Sized)) -> Result + { + let image = ImageReader::open(path) + .map_err(Error::OpenImageFailed)? + .decode() + .map_err(Error::DecodeImageFailed)?; + + let pixel_data_format = match &image { + DynamicImage::ImageRgb8(_) => PixelDataFormat::Rgb8, + DynamicImage::ImageRgba8(_) => PixelDataFormat::Rgba8, + _ => { + return Err(Error::UnsupportedImageDataFormat); + } + }; + + let dimensions = Dimens { + width: image.width(), + height: image.height(), + }; + + let id = NEXT_ID.fetch_add(1, Ordering::Relaxed); + + Ok(Texture { + id: Id::new(id), + image, + pixel_data_format, + dimensions, + properties: self.properties.clone(), + }) + } + + #[must_use] + pub fn build_with_single_color( + &self, + dimensions: &Dimens, + color: &Color, + ) -> Texture + { + let image = RgbImage::from_pixel( + dimensions.width, + dimensions.height, + Rgb([color.red, color.green, color.blue]), + ); + + let id = NEXT_ID.fetch_add(1, Ordering::Relaxed); + + Texture { + id: Id::new(id), + image: image.into(), + pixel_data_format: PixelDataFormat::Rgb8, + dimensions: *dimensions, + properties: self.properties.clone(), + } + } +} + /// Texture error. #[derive(Debug, thiserror::Error)] pub enum Error @@ -142,11 +185,13 @@ pub enum Error #[error("Failed to decode texture image")] DecodeImageFailed(#[source] ImageError), - #[error("Unsupported image data kind")] - UnsupportedImageDataKind, + #[error("Unsupported image data format")] + UnsupportedImageDataFormat, } +builder! { /// Texture properties +#[builder(name = PropertiesBuilder, derives=(Debug, Clone))] #[derive(Debug, Clone)] #[non_exhaustive] pub struct Properties @@ -155,6 +200,15 @@ pub struct Properties pub magnifying_filter: Filtering, pub minifying_filter: Filtering, } +} + +impl Properties +{ + pub fn builder() -> PropertiesBuilder + { + PropertiesBuilder::default() + } +} impl Default for Properties { @@ -168,6 +222,14 @@ impl Default for Properties } } +impl Default for PropertiesBuilder +{ + fn default() -> Self + { + Properties::default().into() + } +} + /// Texture ID. #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct Id -- cgit v1.2.3-18-g5258