fennel_engine/resources/
loadable.rs1use image::ImageReader;
2use sdl3::{
3 pixels::PixelFormat,
4 render::{Texture, TextureCreator},
5 video::WindowContext,
6};
7use std::{
8 cell::{Ref, RefCell},
9 path::PathBuf,
10 rc::Rc,
11 sync::Arc,
12};
13
14use crate::resources::LoadableResource;
15
16pub struct Image {
18 pub path: PathBuf,
20 pub buffer: Rc<RefCell<Vec<u8>>>,
21 pub texture: Rc<Texture<'static>>,
22 pub width: u32,
23 pub height: u32,
24}
25
26impl LoadableResource for Image {
27 fn load(
32 path: PathBuf,
33 texture_creator: &Arc<TextureCreator<WindowContext>>,
34 ) -> anyhow::Result<Box<dyn LoadableResource>> {
35 let img = ImageReader::open(&path)?.decode()?;
36 let mut buffer = img.to_rgba8().into_raw();
37 let surface = sdl3::surface::Surface::from_data(
38 &mut buffer,
39 img.width(),
40 img.height(),
41 img.width() * 4,
42 PixelFormat::RGBA32,
43 )?;
44
45 let texture = unsafe {
46 std::mem::transmute::<sdl3::render::Texture<'_>, sdl3::render::Texture<'static>>(
47 texture_creator.create_texture_from_surface(surface)?,
48 )
49 };
50
51 Ok(Box::new(Self {
52 path,
53 buffer: Rc::new(RefCell::new(buffer)),
54 texture: Rc::new(texture),
55 width: img.width(),
56 height: img.height(),
57 }))
58 }
59
60 fn name(&self) -> String {
62 self.path.to_string_lossy().to_string()
63 }
64
65 fn as_mut_slice(&self) -> &mut [u8] {
66 let mut mut_ref = self.buffer.borrow_mut();
67 unsafe { &mut *(mut_ref.as_mut_slice() as *mut [u8]) }
71 }
72
73 fn as_slice(&self) -> Ref<'_, [u8]> {
74 Ref::map(self.buffer.borrow(), |v| v.as_slice())
75 }
76}