use std::num::NonZeroU32; use winit::raw_window_handle::WindowHandle; use winit::raw_window_handle::DisplayHandle; use softbuffer::Buffer; use super::objs::Object; // render context pub struct RenderCtx<'buf, 'win> { pub(crate) buffer: Buffer<'buf, DisplayHandle<'win>, WindowHandle<'win>>, pub(crate) win_size: (u32, u32), pub(crate) context_size: (u32, u32), pub(crate) context_pos: (u32, u32), } impl<'buf, 'win> RenderCtx<'buf, 'win> { // create new render context pub fn new( buffer: Buffer<'buf, DisplayHandle<'win>, WindowHandle<'win>>, win_size: (NonZeroU32, NonZeroU32), context_size: (u32, u32), ) -> Self { Self { buffer, win_size: (win_size.0.get(), win_size.1.get()), context_size, context_pos: ( (win_size.0.get() / 2).saturating_sub(context_size.0 / 2), (win_size.1.get() / 2).saturating_sub(context_size.1 / 2), ), } } pub fn clear(&mut self, color: u32) { self.rect(0, 0, self.context_size.0, self.context_size.1, color) } /// draw a rectangle in the context /// /// coordinates are relative to the context /// /// does not check against overflows pub fn rect_unchecked(&mut self, x: u32, y: u32, width: u32, height: u32, color: u32) { // position in buffer coordinates and not relative coordinates let x_buf_pos = self.context_pos.0 + x; let y_buf_pos = self.context_pos.1 + y; for y in y_buf_pos..(y_buf_pos + height) { for x in x_buf_pos..(x_buf_pos + width) { let index = y as usize * self.win_size.0 as usize + x as usize; if let Some(px) = self.buffer.get_mut(index) { *px = color } } } } pub fn rect(&mut self, x: u32, y: u32, width: u32, height: u32, color: u32) { if x >= self.context_size.0 || y >= self.context_size.1 || width == 0 || height == 0 { } else { let width = if (x + width) >= self.context_size.0 { width.saturating_sub((x + width) - self.context_size.0) } else { width }; let height = if (y + height) >= self.context_size.1 { height.saturating_sub((y + height) - self.context_size.1) } else { height }; self.rect_unchecked(x, y, width, height, color) } } pub fn force_present(self) { self.buffer.present().unwrap() } }