diff --git a/src/animations.rs b/src/animations.rs new file mode 100644 index 0000000..88d1062 --- /dev/null +++ b/src/animations.rs @@ -0,0 +1,126 @@ +use palette::Hsv; + +use rgb::RGB8; + +use crate::time::Periodically; +use crate::geometry::{Coordinates, VirtualCoordinates}; +use crate::render::{Shader, Surface}; +use crate::task::Task; +use crate::lib8::IntoRgb8; + +pub struct IdleTask { + frame: u8, + surface: T, + updater: Periodically +} + +struct IdleShader { + frame: u8 +} + +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() + } +} + +impl IdleTask { + pub fn new(surface: T) -> Self { + IdleTask { + frame: 0, + surface: surface, + updater: Periodically::new_every_n_ms(16) + } + } +} + +impl Task for IdleTask { + fn name(&self) -> &'static str { "Idle" } + + fn tick(&mut self) { + self.updater.run(|| { + self.frame = self.frame.wrapping_add(1); + self.surface.set_shader(Box::new(IdleShader { frame: self.frame })); + }) + } + + fn stop(&mut self) { + self.surface.clear_shader(); + } +} + +#[derive(Clone, Copy, Debug)] +enum Pattern { + Red, + Green, + Blue, + White, + RGB, + HSV, + Outline +} + +impl Pattern { + pub fn next(self) -> Pattern { + match self { + Pattern::Red => Pattern::Green, + Pattern::Green => Pattern::Blue, + Pattern::Blue => Pattern::White, + Pattern::White => Pattern::RGB, + Pattern::RGB => Pattern::HSV, + Pattern::HSV => Pattern::Outline, + Pattern::Outline => Pattern::Red + } + } +} + +struct TestShader { + pattern: Pattern +} + +impl Shader for TestShader { + 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()) { + (0, 0) => RGB8::new(255, 255, 255), + (0, _) => RGB8::new(255, 0, 0), + (_, 0) => RGB8::new(0, 255, 0), + _ => RGB8::new(0, 0, 0) + } + } + } +} + +pub struct TestPattern { + surface: T, + updater: Periodically, + pattern: Pattern +} + +impl TestPattern { + pub fn new(surface: T) -> Self { + TestPattern { surface, updater: Periodically::new_every_n_seconds(3), pattern: Pattern::Red } + } +} + +impl Task for TestPattern { + fn name(&self) -> &'static str { "Idle" } + + fn tick(&mut self) { + self.updater.run(|| { + self.pattern = self.pattern.next(); + log::info!("Test pattern: {:?}", self.pattern); + self.surface.set_shader(Box::new(TestShader { pattern: self.pattern })); + }) + } + + fn stop(&mut self) { + self.surface.clear_shader(); + } +} diff --git a/src/main.rs b/src/main.rs index 1b88412..282e2d7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,6 +9,7 @@ mod task; mod time; mod geometry; mod platform; +mod animations; use crate::time::Periodically; @@ -103,7 +104,8 @@ fn main() { log::info!("Creating runner"); let mut runner = task::Scheduler::new(vec![ - Box::new(IdleTask::new(display.new_surface().unwrap())), + Box::new(animations::IdleTask::new(display.new_surface().unwrap())), + Box::new(animations::TestPattern::new(display.new_surface().unwrap())), Box::new(display), ]);