rustyray_sys/
texture.rs

1use std::ffi::CString;
2use std::fmt::Debug;
3use std::fs;
4
5use libc::{c_int, c_uint, c_void};
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/// Image, pixel data stored in CPU memory (RAM)
28#[repr(C)]
29#[derive(Debug, Clone)]
30pub struct Image {
31    /// Image raw data
32    data: *mut c_void,
33    /// Image base width
34    width: c_int,
35    /// Image base height
36    height: c_int,
37    /// Mipmap levels, 1 by default
38    mipmaps: c_int,
39    /// Data format (PixelFormat type)
40    format: c_int,
41}
42
43/// RenderTexture, fbo for texture rendering
44#[repr(C)]
45#[derive(Debug, Clone)]
46pub struct RenderTexture {
47    /// OpenGL framebuffer object id
48    id: c_uint,
49    /// Color buffer attachment texture
50    pub texture: Texture,
51    /// Depth buffer attachment texture
52    pub depth: Texture,
53}
54pub type RenderTexture2D = RenderTexture;
55
56#[derive(Error)]
57pub enum TextureLoadError {
58    #[error("could not find file at path: {0}")]
59    FileNotFound(String),
60    #[error("you must first create a Window before loading textures")]
61    WindowNotReady(),
62}
63
64impl Debug for TextureLoadError {
65    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
66        write!(f, "{}", self)
67    }
68}
69
70impl Texture {
71    pub fn new(path: String) -> Result<Self, TextureLoadError> {
72        let window_ready = unsafe { is_window_ready() };
73        if !window_ready {
74            return Err(TextureLoadError::WindowNotReady());
75        }
76        let metadata = fs::metadata(&path);
77        if metadata.is_err() {
78            return Err(TextureLoadError::FileNotFound(path));
79        }
80        if !metadata.unwrap().is_file() {
81            return Err(TextureLoadError::FileNotFound(path));
82        }
83
84        unsafe { Ok(load_texture(CString::new(path).unwrap().as_ptr())) }
85    }
86
87    pub fn width(&self) -> i32 {
88        self.width
89    }
90
91    pub fn height(&self) -> i32 {
92        self.height
93    }
94
95    pub fn size(&self) -> Vector2i {
96        Vector2i {
97            x: self.width,
98            y: self.height,
99        }
100    }
101}
102
103impl RenderTexture {
104    pub fn new(width: i32, height: i32) -> Self {
105        unsafe { load_render_texture(width, height) }
106    }
107}