83 lines
2.5 KiB
Rust
83 lines
2.5 KiB
Rust
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()
|
|
}
|
|
}
|