2024-12-15 19:27:27 +01:00

128 lines
4.1 KiB
Rust

use crate::lib8::Hsv;
use rgb::RGB8;
use crate::{events::{Event, EventBus}, lib8::{interpolate::scale8, trig::{cos8, sin8}, IntoRgb8}, render::{Shader, Surface}, task::Task, time::Periodically};
use super::{Coordinates, Rectangle, VirtualCoordinates};
#[derive(Clone, Copy, Debug)]
enum TestShader {
Red,
Green,
Blue,
White,
RGB,
HSV,
Outline,
SweepX,
SweepY,
SinX,
SinY,
Metaballs
}
impl TestShader {
pub fn next(self) -> Self {
match self {
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::Red
}
}
}
impl Shader for TestShader {
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(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)
}
}
}
}
#[derive(Debug)]
pub struct TestPattern<T: Surface> {
surface: T,
updater: Periodically,
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), stepper: Periodically::new_every_n_ms(60), pattern: TestShader::HSV, frame: 0 }
}
}
//const Animations: Namespace = Namespace("animations");
impl<T: Surface> Task for TestPattern<T> {
fn name(&self) -> &'static str { "TestPattern" }
fn start(&mut self, _bus: &mut EventBus) {
self.surface.set_shader(self.pattern);
}
fn on_tick(&mut self, bus: &mut EventBus) {
self.updater.run(|| {
self.pattern = self.pattern.next();
log::info!("Test pattern: {:?}", self.pattern);
self.frame = 0;
self.surface.set_shader(self.pattern);
//bus.push(Animations.new_property_change( "test.pattern", format!("{:?}", self.pattern)));
});
self.stepper.run(|| {
self.frame = self.frame.wrapping_add(1);
self.surface.set_opacity(sin8(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, _bus: &mut EventBus) {
self.surface.clear_shader();
}
}