From 3783bc60b24fad59ce9f96dc2ba0f02ac3b72d6d Mon Sep 17 00:00:00 2001 From: Victoria Fischer Date: Sun, 24 Nov 2024 21:55:24 +0100 Subject: [PATCH] animations: rewrite animations with improved surface capabilities --- src/animations.rs | 178 +++++++++++++++++++++++++++++++++------------- src/main.rs | 2 +- 2 files changed, 128 insertions(+), 52 deletions(-) diff --git a/src/animations.rs b/src/animations.rs index 54a7d4e..1410c72 100644 --- a/src/animations.rs +++ b/src/animations.rs @@ -3,102 +3,159 @@ use palette::Hsv; use rgb::RGB8; use crate::time::Periodically; -use crate::geometry::{Coordinates, VirtualCoordinates}; -use crate::render::{Shader, Surface}; +use crate::geometry::*; +use crate::render::{Shader, Surface, Surfaces}; use crate::task::Task; -use crate::lib8::IntoRgb8; +use crate::lib8::{trig::{sin8, cos8}, interpolate::scale8, noise::inoise8, IntoRgb8}; #[derive(Debug)] pub struct IdleTask { - frame: u8, + solid: T, surface: T, - updater: Periodically + shimmer: T, } #[derive(Debug)] -struct IdleShader { - frame: u8 +struct SolidShader {} + +impl Shader for SolidShader { + fn draw(&self, _coords: &VirtualCoordinates, frame: usize) -> RGB8 { + Hsv::new_srgb((frame / 4 % 255) as u8, 255, sin8((frame % 64) as u8)).into_rgb8() + } } -impl Shader for IdleShader { - fn draw(&self, coords: &VirtualCoordinates, frame: u8) -> RGB8 { - Hsv::new_srgb(frame.wrapping_add(coords.x).wrapping_add(coords.y), 255, 255).into_rgb8() +#[derive(Debug)] +struct ShimmerShader {} + +impl Shader for ShimmerShader { + fn draw(&self, coords: &VirtualCoordinates, frame: usize) -> RGB8 { + Hsv::new_srgb(coords.x.wrapping_add((frame / 3) as u8), coords.y, sin8(frame as u8 % 255).max(75).min(64)).into_rgb8() + } +} + +#[derive(Debug)] +struct ThinkingShader {} + +impl Shader for ThinkingShader { + fn draw(&self, coords: &VirtualCoordinates, frame: usize) -> RGB8 { + //let noise_x = sin8(sin8((frame % 255) as u8).wrapping_add(coords.x)); + //let noise_y = cos8(cos8((frame % 255) as u8).wrapping_add(coords.y)); + let offset_x = sin8(((frame % 255) as u8).wrapping_add(coords.x)); + let offset_y = cos8(((frame % 255) as u8).wrapping_add(coords.y)); + let noise_x = offset_x / 2; + let noise_y = offset_y / 2; + //let noise_x = coords.x.wrapping_add(offset_x); + //let noise_y = coords.y.wrapping_add(offset_y); + Hsv::new_srgb( + inoise8(noise_x as i16, noise_y as i16), + 128_u8.saturating_add(inoise8(noise_y as i16, noise_x as i16)), + 255 + ).into_rgb8() + } +} + +#[derive(Debug)] +struct GayBarberShader {} + +impl Shader for GayBarberShader { + fn draw(&self, coords: &VirtualCoordinates, frame: usize) -> RGB8 { + Hsv::new_srgb((frame as u8).wrapping_add(coords.x).wrapping_add(coords.y), 255, sin8((frame % 128) as u8)).into_rgb8() } } impl IdleTask { - pub fn new(surface: T) -> Self { + pub fn new>(surfaces: &mut S) -> Self { IdleTask { - frame: 0, - surface: surface, - updater: Periodically::new_every_n_ms(16) + solid: surfaces.new_surface(&Rectangle::everything()).unwrap(), + surface: surfaces.new_surface(&Rectangle::everything()).unwrap(), + shimmer: surfaces.new_surface(&Rectangle::everything()).unwrap(), } } } impl Task for IdleTask { fn start(&mut self) { - self.surface.set_shader(Box::new(IdleShader { frame: self.frame })); + self.solid.set_shader(Box::new(SolidShader { })); + self.surface.set_shader(Box::new(ThinkingShader { })); + self.shimmer.set_shader(Box::new(ShimmerShader { })); + + self.solid.set_opacity(64); + self.surface.set_opacity(128); + self.shimmer.set_opacity(64); } - 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 tick(&mut self) {} fn stop(&mut self) { + self.solid.clear_shader(); self.surface.clear_shader(); + self.shimmer.clear_shader(); } } #[derive(Clone, Copy, Debug)] -enum Pattern { +enum TestShader { Red, Green, Blue, White, RGB, HSV, - Outline + Outline, + SweepX, + SweepY, + SinX, + SinY, + Metaballs } -impl Pattern { - pub fn next(self) -> Pattern { +impl TestShader { + pub fn next(self) -> Self { 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 + Self::Red => Self::Green, + Self::Green => Self::Blue, + Self::Blue => Self::White, + Self::White => Self::RGB, + Self::RGB => Self::HSV, + Self::HSV => Self::Outline, + Self::Outline => Self::SweepX, + Self::SweepX => Self::SweepY, + Self::SweepY => Self::SinX, + Self::SinX => Self::SinY, + Self::SinY => Self::Metaballs, + Self::Metaballs => Self::RGB } } } -#[derive(Debug)] -struct TestShader { - pattern: Pattern -} - impl Shader for TestShader { - fn draw(&self, coords: &VirtualCoordinates, _frame: usize) -> 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) { + fn draw(&self, coords: &VirtualCoordinates, frame: usize) -> RGB8 { + match self { + Self::Red => RGB8::new(255, 0, 0), + Self::Green => RGB8::new(0, 255, 0), + Self::Blue => RGB8::new(0, 0, 255), + Self::White => RGB8::new(255, 255, 255), + Self::RGB => RGB8::new(coords.x, coords.y, 255 - (coords.x / 2 + coords.y / 2)), + Self::HSV => Hsv::new_srgb(coords.x, coords.y, 255).into_rgb8(), + Self::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), (255, _) => RGB8::new(0, 0, 255), (_, 255) => RGB8::new(0, 0, 255), _ => RGB8::new(0, 0, 0) + }, + Self::SweepX => RGB8::new(255, 0, 0), + Self::SweepY => RGB8::new(255, 0, 0), + Self::SinX => RGB8::new(sin8(coords.x.wrapping_add((frame % 255) as u8)), 0, 0), + Self::SinY => RGB8::new(sin8(coords.y.wrapping_add((frame % 255) as u8)), 0, 0), + Self::Metaballs => { + let ball_center = Coordinates::new( + scale8(64, sin8(frame)) + 128, + scale8(64, cos8(frame)) + 128 + ); + let dist = 255 - coords.distance_to(&ball_center); + RGB8::new(dist, 0, 0) } } } @@ -108,26 +165,45 @@ impl Shader for TestShader { pub struct TestPattern { surface: T, updater: Periodically, - pattern: Pattern + stepper: Periodically, + pattern: TestShader, + frame: u8 } impl TestPattern { pub fn new(surface: T) -> Self { - TestPattern { surface, updater: Periodically::new_every_n_seconds(10), pattern: Pattern::Red } + TestPattern { surface, updater: Periodically::new_every_n_seconds(10), stepper: Periodically::new_every_n_ms(60), pattern: TestShader::HSV, frame: 0 } } } impl Task for TestPattern { fn start(&mut self) { - self.surface.set_shader(Box::new(TestShader { pattern: self.pattern })); + self.surface.set_shader(Box::new(self.pattern.clone())); } 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 })); - }) + self.frame = 0; + self.surface.set_shader(Box::new(self.pattern.clone())); + }); + self.stepper.run(|| { + self.frame = self.frame.wrapping_add(1); + self.surface.set_opacity(sin8(self.frame)); + //log::info!("Step {}", self.frame); + self.surface.set_rect( &match self.pattern { + TestShader::SweepX => Rectangle::new( + Coordinates::new(self.frame, 0), + Coordinates::new(self.frame, 255) + ), + TestShader::SweepY => Rectangle::new( + Coordinates::new(0, self.frame), + Coordinates::new(255, self.frame) + ), + _ => Rectangle::everything() + }); + }); } fn stop(&mut self) { diff --git a/src/main.rs b/src/main.rs index aac5a4a..482e6f7 100644 --- a/src/main.rs +++ b/src/main.rs @@ -49,7 +49,7 @@ fn main() { log::info!("Creating runner"); let mut runner = task::Scheduler::new(vec![ - Box::new(animations::IdleTask::new(display.new_surface(&Rectangle::everything()).unwrap())), + Box::new(animations::IdleTask::new(&mut display)), Box::new(animations::TestPattern::new(display.new_surface(&Rectangle::everything()).unwrap())), Box::new(Renderer::new(display)), ]);