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#[repr(C)]
13#[derive(Debug, Clone)]
14pub struct Texture {
15 id: c_uint,
17 width: c_int,
19 height: c_int,
21 mipmaps: c_int,
23 format: c_int,
25}
26
27#[repr(C)]
29#[derive(Debug, Clone)]
30pub struct Image {
31 data: *mut c_void,
33 width: c_int,
35 height: c_int,
37 mipmaps: c_int,
39 format: c_int,
41}
42
43#[repr(C)]
45#[derive(Debug, Clone)]
46pub struct RenderTexture {
47 id: c_uint,
49 pub texture: Texture,
51 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}