pronto_graphics/texture.rs
1use sfml::graphics::Texture as SfmlTexture;
2use sfml::SfBox;
3
4/// A global static array containing all textures that have been loaded during the runtime of the program.
5/// Should not be accesses directly outside this module.
6/// # Excuses
7/// So, this isn't a pretty look, I know.
8/// The problem is, as far as I can tell, there is no way to tell Rust's lifetime rules that I just want to give
9/// an existing [`RectangleShape`] a reference to a texture for just the scope of one [`Window::texture`] call.
10/// Neither can I create a bundle of the Shape and it's Texture in one object to align their lifetimes.
11/// Therefore, to ensure than all Textures always outlive the Shape that potentially is referencing them,
12/// I have to make the textures `static`. Hence, this ungodly bunch of code.
13/// If there is a prettier solution that I have overlooked, this should be changed.
14static mut TEXTURE_STORE: Option<Vec<SfBox<SfmlTexture>>> = None;
15pub fn init_texture_store() {
16 unsafe {
17 if let None = TEXTURE_STORE {
18 TEXTURE_STORE = Some(Vec::new());
19 }
20 }
21}
22
23pub fn texture_store(texture: Texture) -> Option<&'static SfBox<SfmlTexture>> {
24 unsafe {
25 if let Some(textures) = &TEXTURE_STORE {
26 Some(&textures[texture.index])
27 } else {
28 None
29 }
30 }
31}
32
33pub fn texture_store_add(texture: SfBox<SfmlTexture>) -> Option<Texture> {
34 unsafe {
35 if let Some(textures) = &mut TEXTURE_STORE {
36 textures.push(texture);
37 Some(Texture {
38 index: textures.len() - 1,
39 })
40 } else {
41 None
42 }
43 }
44}
45
46/// A texture object returned by [`Window::load_texture`], that can be passed to [`Window::texture`] to draw the texture to the screen.
47/// # Examples
48/// ```
49/// let mut pg = Window::new_fullscreen();
50/// let my_texture = pg.load_texture("my_texture.png").unwrap();
51/// loop {
52/// pg.texture_((100., 250.), my_texture, 100.);
53///
54/// pg.update();
55/// }
56/// ```
57///
58/// [`Window::texture`]: crate::window::Window::texture
59/// [`Window::load_texture`]: crate::window::Window::load_texture
60#[derive(Clone, Copy)]
61pub struct Texture {
62 pub index: usize,
63}
64
65impl Texture {
66 /// The width of the texture in pixels.
67 pub fn width(&self) -> u32 {
68 texture_store(*self)
69 .and_then(|t| Some(t.size().x))
70 .unwrap_or(0)
71 }
72
73 /// The height of the texture in pixels.
74 pub fn height(&self) -> u32 {
75 texture_store(*self)
76 .and_then(|t| Some(t.size().y))
77 .unwrap_or(0)
78 }
79
80 /// The aspect ratio of the texture.
81 /// (`.width()/.height()`)
82 pub fn aspect(&self) -> f32 {
83 let h = self.height();
84 if h > 0 {
85 (self.width() as f32) / (h as f32)
86 } else {
87 0.
88 }
89 }
90}