rustyray_sys/
texture.rs

1use std::ffi::CString;
2use std::fmt::Debug;
3use std::fs;
4
5use libc::{c_int, c_uint};
6use thiserror::Error;
7
8use crate::ffi::{is_window_ready, load_render_texture, load_texture};
9use crate::vector::Vector2i;
10
11/// Texture, tex data stored in GPU memory (VRAM)
12#[repr(C)]
13#[derive(Debug, Clone)]
14pub struct Texture {
15    /// OpenGL texture id
16    id: c_uint,
17    /// Texture base width
18    width: c_int,
19    /// Texture base height
20    height: c_int,
21    /// Mipmap levels, 1 by default
22    mipmaps: c_int,
23    /// Data format (PixelFormat type)
24    format: c_int,
25}
26
27/// RenderTexture, fbo for texture rendering
28#[repr(C)]
29#[derive(Debug, Clone)]
30pub struct RenderTexture {
31    /// OpenGL framebuffer object id
32    id: c_uint,
33    /// Color buffer attachment texture
34    pub texture: Texture,
35    /// Depth buffer attachment texture
36    pub depth: Texture,
37}
38pub type RenderTexture2D = RenderTexture;
39
40#[derive(Error)]
41pub enum TextureLoadError {
42    #[error("could not find file at path: {0}")]
43    FileNotFound(String),
44    #[error("you must first create a Window before loading textures")]
45    WindowNotReady(),
46}
47
48impl Debug for TextureLoadError {
49    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50        write!(f, "{}", self)
51    }
52}
53
54impl Texture {
55    pub fn new(path: String) -> Result<Self, TextureLoadError> {
56        let window_ready = unsafe { is_window_ready() };
57        if !window_ready {
58            return Err(TextureLoadError::WindowNotReady());
59        }
60        let metadata = fs::metadata(&path);
61        if metadata.is_err() {
62            return Err(TextureLoadError::FileNotFound(path));
63        }
64        if !metadata.unwrap().is_file() {
65            return Err(TextureLoadError::FileNotFound(path));
66        }
67
68        unsafe { Ok(load_texture(CString::new(path).unwrap().as_ptr())) }
69    }
70
71    pub fn width(&self) -> i32 {
72        self.width
73    }
74
75    pub fn height(&self) -> i32 {
76        self.height
77    }
78
79    pub fn size(&self) -> Vector2i {
80        Vector2i {
81            x: self.width,
82            y: self.height,
83        }
84    }
85}
86
87impl RenderTexture {
88    pub fn new(width: i32, height: i32) -> Self {
89        unsafe { load_render_texture(width, height) }
90    }
91}