From e329a56c90a33aa82e7b5eecd8cb531803cbf7e3 Mon Sep 17 00:00:00 2001 From: Victoria Fischer Date: Sat, 16 Nov 2024 11:31:45 +0100 Subject: [PATCH] geometry: rewrite Coordinates trait into a concrete struct, pass coords by reference to shaders, and add a Rectangle type --- src/animations.rs | 12 ++-- src/geometry.rs | 105 +++++++++++++++++++++++++-------- src/platform/smart_leds_lib.rs | 2 +- src/render.rs | 2 +- 4 files changed, 89 insertions(+), 32 deletions(-) diff --git a/src/animations.rs b/src/animations.rs index 78c1f93..790366c 100644 --- a/src/animations.rs +++ b/src/animations.rs @@ -21,8 +21,8 @@ struct IdleShader { } impl Shader for IdleShader { - fn draw(&self, coords: VirtualCoordinates) -> RGB8 { - Hsv::new_srgb(self.frame.wrapping_add(coords.x()).wrapping_add(coords.y()), 255, 255).into_rgb8() + fn draw(&self, coords: &VirtualCoordinates) -> RGB8 { + Hsv::new_srgb(self.frame.wrapping_add(coords.x).wrapping_add(coords.y), 255, 255).into_rgb8() } } @@ -84,15 +84,15 @@ struct TestShader { } impl Shader for TestShader { - fn draw(&self, coords: VirtualCoordinates) -> RGB8 { + fn draw(&self, coords: &VirtualCoordinates) -> RGB8 { match self.pattern { Pattern::Red => RGB8::new(255, 0, 0), Pattern::Green => RGB8::new(0, 255, 0), Pattern::Blue => RGB8::new(0, 0, 255), Pattern::White => RGB8::new(255, 255, 255), - Pattern::RGB => RGB8::new(coords.x(), coords.y(), 255 - (coords.x() / 2 + coords.y() / 2)), - Pattern::HSV => Hsv::new_srgb(coords.x(), coords.y(), 255 - (coords.x() / 2 + coords.y() / 2)).into_rgb8(), - Pattern::Outline => match (coords.x(), coords.y()) { + Pattern::RGB => RGB8::new(coords.x, coords.y, 255 - (coords.x / 2 + coords.y / 2)), + Pattern::HSV => Hsv::new_srgb(coords.x, coords.y, 255 - (coords.x / 2 + coords.y / 2)).into_rgb8(), + Pattern::Outline => match (coords.x, coords.y) { (0, 0) => RGB8::new(255, 255, 255), (0, _) => RGB8::new(255, 0, 0), (_, 0) => RGB8::new(0, 255, 0), diff --git a/src/geometry.rs b/src/geometry.rs index 061b7f5..8583415 100644 --- a/src/geometry.rs +++ b/src/geometry.rs @@ -1,14 +1,72 @@ +use std::fmt::{Debug, Formatter}; use std::marker::PhantomData; pub trait CoordinateSpace {} -pub trait Coordinates { - fn x(&self) -> T; - fn y(&self) -> T; - fn new(x: T, y: T) -> Self; +#[derive(PartialEq, Eq, Clone, Copy)] +pub struct Coordinates, S: CoordinateSpace> { + pub x: T, + pub y: T, + space: PhantomData, +} - const MAX: T; - const MIN: T; +impl + Debug, S: CoordinateSpace> Debug for Coordinates { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.debug_tuple("@") + .field(&self.x) + .field(&self.y) + .finish() + } +} + +pub trait CoordLimits { + type Data: Sized; + const MIN: Self::Data; + const MAX: Self::Data; +} + +impl CoordLimits for u8 { + type Data = u8; + const MIN: u8 = 0; + const MAX: u8 = 255; +} + +impl CoordLimits for u16 { + type Data = u16; + const MIN: u16 = u16::MIN; + const MAX: u16 = u16::MAX; +} + +impl CoordLimits for usize { + type Data = usize; + const MIN: usize = usize::MIN; + const MAX: usize = usize::MAX; +} + +impl, S: CoordinateSpace> Coordinates { + pub const fn new(x: T, y: T) -> Self { + Self { + x, + y, + space: PhantomData, + } + } + + fn top_left() -> Self { + Self::new(T::MIN, T::MIN) + } + + fn top_right() -> Self { + Self::new(T::MAX, T::MIN) + } + + fn bottom_left() -> Self { + Self::new(T::MIN, T::MAX) + } + + fn bottom_right() -> Self { + Self::new(T::MAX, T::MAX) + } } #[derive(PartialEq, Debug, Copy, Clone)] @@ -26,28 +84,27 @@ pub struct Coord8 { space: PhantomData } -pub type VirtualCoordinates = Coord8; -pub type PhysicalCoordinates = Coord8; +pub type VirtualCoordinates = Coordinates; +pub type PhysicalCoordinates = Coordinates; -impl Coordinates for Coord8 -where -S: CoordinateSpace { - fn new(x: u8, y: u8) -> Self { +#[derive(PartialEq, Eq, Copy, Clone, Debug)] +pub struct Rectangle, Space: CoordinateSpace> { + pub top_left: Coordinates, + pub bottom_right: Coordinates +} + +impl, Space: CoordinateSpace> Rectangle { + pub fn new(top_left: Coordinates, bottom_right: Coordinates) -> Self { Self { - x: x, - y: y, - space: PhantomData + top_left, + bottom_right } } - fn x(&self) -> u8 { - self.x + pub fn everything() -> Self { + Self { + top_left: Coordinates::::top_left(), + bottom_right: Coordinates::::bottom_right() + } } - - fn y(&self) -> u8 { - self.y - } - - const MAX: u8 = 255; - const MIN: u8 = 255; } diff --git a/src/platform/smart_leds_lib.rs b/src/platform/smart_leds_lib.rs index f01e1e9..51573a6 100644 --- a/src/platform/smart_leds_lib.rs +++ b/src/platform/smart_leds_lib.rs @@ -72,7 +72,7 @@ impl>, S: Surface> Display for SmartLedDisp let mut pixel = Rgb::new(0, 0, 0); for surface in self.surfaces.iter() { surface.with_shader(|shader| { - pixel = pixel.saturating_add(shader.draw(virt_coords.clone())); + pixel = pixel.saturating_add(shader.draw(&virt_coords)); }) } self.total_mw += pixel.as_milliwatts(); diff --git a/src/render.rs b/src/render.rs index beb3f81..acc3ad4 100644 --- a/src/render.rs +++ b/src/render.rs @@ -14,7 +14,7 @@ use std::marker::PhantomData; use std::fmt::Debug; pub trait Shader: Send + Debug { - fn draw(&self, surface_coords: VirtualCoordinates) -> RGB8; + fn draw(&self, surface_coords: &VirtualCoordinates) -> RGB8; } pub trait Surface: Default + Clone + Debug {