// file: crates/engines/engine-v1-common/src/render.rs // version: 1 /// Maximum rectangle count carried by one engine V1 scene snapshot. pub const ENGINE_SCENE_RECT_CAPACITY: usize = 64; /// Platform-independent RGBA color. #[derive(Clone, Copy, Debug, Eq, PartialEq)] pub struct RenderColor { red: u8, green: u8, blue: u8, alpha: u8, } impl RenderColor { /// Creates an opaque RGB color. #[must_use] pub const fn rgb(red: u8, green: u8, blue: u8) -> Self { return Self { red, green, blue, alpha: 255 }; } /// Returns the red channel. #[must_use] pub const fn red(self) -> u8 { return self.red; } /// Returns the green channel. #[must_use] pub const fn green(self) -> u8 { return self.green; } /// Returns the blue channel. #[must_use] pub const fn blue(self) -> u8 { return self.blue; } /// Returns the alpha channel. #[must_use] pub const fn alpha(self) -> u8 { return self.alpha; } } /// Rectangle expressed in normalized viewport coordinates. #[derive(Clone, Copy, Debug, PartialEq)] pub struct NormalizedRect { x: f32, y: f32, width: f32, height: f32, } impl NormalizedRect { /// Creates a normalized rectangle while clamping all coordinates and dimensions. #[must_use] pub fn new(x: f32, y: f32, width: f32, height: f32) -> Self { let x = x.clamp(0.0, 1.0); let y = y.clamp(0.0, 1.0); let width = width.clamp(0.0, 1.0 - x); let height = height.clamp(0.0, 1.0 - y); return Self { x, y, width, height }; } /// Returns the normalized left coordinate. #[must_use] pub const fn x(self) -> f32 { return self.x; } /// Returns the normalized top coordinate. #[must_use] pub const fn y(self) -> f32 { return self.y; } /// Returns the normalized width. #[must_use] pub const fn width(self) -> f32 { return self.width; } /// Returns the normalized height. #[must_use] pub const fn height(self) -> f32 { return self.height; } /// Reports whether a normalized pointer coordinate lies inside this rectangle. #[must_use] pub fn contains(self, x: f32, y: f32) -> bool { return x >= self.x && y >= self.y && x <= self.x + self.width && y <= self.y + self.height; } } /// One colored rectangle in a platform-independent scene. #[derive(Clone, Copy, Debug, PartialEq)] pub struct RenderRect { rect: crate::NormalizedRect, color: crate::RenderColor, } impl RenderRect { /// Creates one colored scene rectangle. #[must_use] pub const fn new(rect: crate::NormalizedRect, color: crate::RenderColor) -> Self { return Self { rect, color }; } /// Returns the rectangle geometry. #[must_use] pub const fn rect(self) -> crate::NormalizedRect { return self.rect; } /// Returns the rectangle color. #[must_use] pub const fn color(self) -> crate::RenderColor { return self.color; } } /// Immutable platform-independent scene snapshot. #[derive(Clone, Copy, Debug, PartialEq)] pub struct EngineScene { background: crate::RenderColor, rectangles: [Option; crate::ENGINE_SCENE_RECT_CAPACITY], } impl EngineScene { /// Creates an empty scene with the supplied background. #[must_use] pub const fn empty(background: crate::RenderColor) -> Self { return Self { background, rectangles: [None; crate::ENGINE_SCENE_RECT_CAPACITY] }; } /// Returns the background color. #[must_use] pub const fn background(self) -> crate::RenderColor { return self.background; } /// Returns the rectangle slots. #[must_use] pub const fn rectangles(&self) -> &[Option; crate::ENGINE_SCENE_RECT_CAPACITY] { return &self.rectangles; } /// Returns a copy with one rectangle inserted into the first free slot. #[must_use] pub fn with_rect(mut self, rectangle: crate::RenderRect) -> Self { for slot in &mut self.rectangles { if slot.is_none() { *slot = Some(rectangle); return self; } } return self; } } #[cfg(test)] #[path = "../unit_tests/render.rs"] mod tests;