animations: rewrite animations with improved surface capabilities
This commit is contained in:
parent
d17baa754f
commit
3783bc60b2
@ -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<T: Surface> {
|
||||
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<T: Surface> IdleTask<T> {
|
||||
pub fn new(surface: T) -> Self {
|
||||
pub fn new<S: Surfaces<T>>(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<T: Surface> Task for IdleTask<T> {
|
||||
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<T: Surface> {
|
||||
surface: T,
|
||||
updater: Periodically,
|
||||
pattern: Pattern
|
||||
stepper: Periodically,
|
||||
pattern: TestShader,
|
||||
frame: u8
|
||||
}
|
||||
|
||||
impl<T: Surface> TestPattern<T> {
|
||||
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<T: Surface> Task for TestPattern<T> {
|
||||
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) {
|
||||
|
@ -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)),
|
||||
]);
|
||||
|
Loading…
x
Reference in New Issue
Block a user