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