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#[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 RenderTexture {
31 id: c_uint,
33 pub texture: Texture,
35 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}