fennel_engine/resources/
loadable.rs

1use image::ImageReader;
2use std::{
3    cell::{Ref, RefCell},
4    path::PathBuf,
5    rc::Rc,
6};
7
8use crate::resources::LoadableResource;
9
10/// Simple image asset that stores its file location.
11#[derive(Clone)]
12pub struct Image {
13    /// Filesystem path to the image.
14    pub path: PathBuf,
15    pub buffer: Rc<RefCell<Vec<u8>>>,
16    pub width: u32,
17    pub height: u32,
18}
19
20impl LoadableResource for Image {
21    /// Construct an `Image` from `path` and return it as a boxed trait object.
22    ///
23    /// # Errors
24    /// This implementation never fails, but the signature matches the trait.
25    fn load(path: PathBuf) -> anyhow::Result<Box<dyn LoadableResource>> {
26        let img = ImageReader::open(&path)?.decode()?;
27        let buffer = img.to_rgba8().into_raw();
28        Ok(Box::new(Self {
29            path,
30            buffer: Rc::new(RefCell::new(buffer)),
31            width: img.width(),
32            height: img.height(),
33        }))
34    }
35
36    /// Identifier for the asset is the the string representation of its path.
37    fn name(&self) -> String {
38        self.path.to_string_lossy().to_string()
39    }
40
41    fn as_mut_slice(&self) -> &mut [u8] {
42        let mut mut_ref = self.buffer.borrow_mut();
43        // even more evil shit that PROBABLY :) should be safe because as we know in normal conditions only
44        // one thread should access (graphics, audio, ..) its respecting resources
45        // otherwise have a SEGFAULT >:3
46        //
47        // i have no fucking idea how this worked and didn't crash
48        unsafe { &mut *(mut_ref.as_mut_slice() as *mut [u8]) }
49    }
50
51    fn as_slice(&self) -> Ref<'_, [u8]> {
52        Ref::map(self.buffer.borrow(), |v| v.as_slice())
53    }
54}