fennel_engine/
graphics.rs1use std::collections::HashMap;
9use std::path::Path;
10
11use image::ImageReader;
12use sdl3::Sdl;
13use sdl3::pixels::PixelFormat;
14use sdl3::render::{Canvas, FRect};
15use sdl3::video::Window;
16
17pub struct Graphics {
22 pub canvas: Canvas<Window>,
23 pub sdl_context: Sdl,
24 pub texture_creator: sdl3::render::TextureCreator<sdl3::video::WindowContext>,
25 texture_cache: HashMap<String, CachedTexture>,
26}
27
28#[derive(Clone)]
29struct CachedTexture {
30 buffer: Vec<u8>,
31 width: u32,
32 height: u32,
33}
34
35impl Graphics {
36 pub fn new(
52 name: String,
53 dimensions: (u32, u32),
54 ) -> Result<Graphics, Box<dyn std::error::Error>> {
55 let sdl_context = sdl3::init().unwrap();
59 let video_subsystem = sdl_context.video().unwrap(); let window = video_subsystem
64 .window(&name, dimensions.0, dimensions.1)
65 .position_centered()
66 .resizable()
67 .build()
68 .map_err(|e| e.to_string())?;
69
70 let canvas = window.into_canvas();
71 let texture_creator = canvas.texture_creator();
72 Ok(Graphics {
73 canvas,
74 sdl_context,
75 texture_creator,
76 texture_cache: HashMap::new(),
77 })
78 }
79
80 pub fn draw_image(&mut self, path: String, position: (f32, f32)) -> anyhow::Result<()> {
81 if !self.texture_cache.contains_key(&path) {
82 let path = Path::new(&path);
83 let img = ImageReader::open(path)?.decode()?;
84 let buffer = img.to_rgba8().into_raw();
85
86 self.texture_cache.insert(
87 path.display().to_string(),
88 CachedTexture {
89 buffer,
90 width: img.width(),
91 height: img.height(),
92 },
93 );
94 }
95 let buffer: &mut CachedTexture = &mut self.texture_cache.get(&path).unwrap().clone(); let surface = sdl3::surface::Surface::from_data(
101 buffer.buffer.as_mut_slice(),
102 buffer.width,
103 buffer.height,
104 buffer.width * 4,
105 PixelFormat::RGBA32,
106 )
107 .map_err(|e| e.to_string())
108 .unwrap();
109
110 let dst_rect = FRect::new(
111 position.0,
112 position.1,
113 surface.width() as f32,
114 surface.height() as f32,
115 );
116
117 let texture = self
118 .texture_creator
119 .create_texture_from_surface(surface)
120 .map_err(|e| e.to_string())
121 .unwrap();
122
123 self.canvas
124 .copy_ex(&texture, None, Some(dst_rect), 0.0, None, false, false)
125 .unwrap();
126
127 Ok(())
128 }
129}