summaryrefslogtreecommitdiff
path: root/engine/src/texture.rs
diff options
context:
space:
mode:
Diffstat (limited to 'engine/src/texture.rs')
-rw-r--r--engine/src/texture.rs100
1 files changed, 100 insertions, 0 deletions
diff --git a/engine/src/texture.rs b/engine/src/texture.rs
new file mode 100644
index 0000000..7874df4
--- /dev/null
+++ b/engine/src/texture.rs
@@ -0,0 +1,100 @@
+use std::path::Path;
+
+use image::io::Reader as ImageReader;
+use image::{DynamicImage, ImageError};
+
+use crate::opengl::texture::Texture as InnerTexture;
+use crate::vector::Vec2;
+
+mod reexports
+{
+ pub use crate::opengl::texture::{Filtering, Wrapping};
+}
+
+pub use reexports::*;
+
+#[derive(Debug)]
+pub struct Texture
+{
+ inner: InnerTexture,
+}
+
+impl Texture
+{
+ /// 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<Self, Error>
+ {
+ let image = ImageReader::open(path)
+ .map_err(Error::OpenImageFailed)?
+ .decode()
+ .map_err(Error::DecodeImageFailed)?;
+
+ if !matches!(image, DynamicImage::ImageRgb8(_)) {
+ return Err(Error::UnsupportedImageDataKind);
+ }
+
+ let inner = InnerTexture::new();
+
+ inner.bind(|texture_curr_bound| {
+ InnerTexture::generate(
+ &texture_curr_bound,
+ &Vec2 { x: image.width(), y: image.height() },
+ image.as_bytes(),
+ );
+ });
+
+ let me = Self { inner };
+
+ me.set_wrap(Wrapping::Repeat);
+ me.set_magnifying_filter(Filtering::Linear);
+ me.set_minifying_filter(Filtering::Nearest);
+
+ Ok(me)
+ }
+
+ pub fn set_wrap(&self, wrapping: Wrapping)
+ {
+ self.inner.bind(|texture_curr_bound| {
+ InnerTexture::set_wrap(texture_curr_bound, wrapping);
+ });
+ }
+
+ pub fn set_magnifying_filter(&self, filtering: Filtering)
+ {
+ self.inner.bind(|texture_curr_bound| {
+ InnerTexture::set_magnifying_filter(texture_curr_bound, filtering);
+ });
+ }
+
+ pub fn set_minifying_filter(&self, filtering: Filtering)
+ {
+ self.inner.bind(|texture_curr_bound| {
+ InnerTexture::set_minifying_filter(texture_curr_bound, filtering);
+ });
+ }
+
+ pub(crate) fn inner(&self) -> &InnerTexture
+ {
+ &self.inner
+ }
+}
+
+/// Texture error.
+#[derive(Debug, thiserror::Error)]
+pub enum Error
+{
+ #[error("Failed to open texture image")]
+ OpenImageFailed(#[source] std::io::Error),
+
+ #[error("Failed to decode texture image")]
+ DecodeImageFailed(#[source] ImageError),
+
+ #[error("Unsupported image data kind")]
+ UnsupportedImageDataKind,
+}