use tiny_led_matrix::Render;
pub trait Animate {
fn is_finished(&self) -> bool;
fn reset(&mut self);
fn tick(&mut self);
}
#[derive(Default)]
#[derive(Copy, Clone, Debug)]
pub struct ScrollingState {
index: usize,
pixel: usize,
}
impl ScrollingState {
pub fn reset(&mut self) {
self.index = 0;
self.pixel = 0;
}
pub fn tick(&mut self) {
self.pixel += 1;
if self.pixel == 5 {
self.pixel = 0;
self.index += 1;
}
}
}
pub trait Scrollable {
type Subimage: Render;
fn length(&self) -> usize;
fn state(&self) -> &ScrollingState;
fn state_mut(&mut self) -> &mut ScrollingState;
fn subimage(&self, index: usize) -> &Self::Subimage;
fn current_brightness_at(&self, x: usize, y: usize) -> u8 {
if self.state().index > self.length() {return 0}
let state = self.state();
let (index, x) = if x + state.pixel < 5 {
if state.index == 0 {return 0}
(state.index - 1, x + state.pixel)
} else {
if state.index == self.length() {return 0}
(state.index, x + state.pixel - 5)
};
self.subimage(index).brightness_at(x, y)
}
}
impl<T : Scrollable> Animate for T {
fn is_finished(&self) -> bool {
self.state().index > self.length()
}
fn reset(&mut self) {
self.state_mut().reset();
}
fn tick(&mut self) {
if !self.is_finished() {
self.state_mut().tick();
}
}
}
#[derive(Copy, Clone)]
pub struct ScrollingImages<T: Render + 'static> {
images: &'static [T],
state: ScrollingState,
}
impl<T: Render + 'static> ScrollingImages<T> {
pub fn set_images(&mut self, images: &'static [T]) {
self.images = images;
self.reset();
}
}
impl<T: Render + 'static> Default for ScrollingImages<T> {
fn default() -> ScrollingImages<T> {
ScrollingImages {
images: &[],
state: Default::default(),
}
}
}
impl<T: Render + 'static> Scrollable for ScrollingImages<T> {
type Subimage = T;
fn length(&self) -> usize {
self.images.len()
}
fn state(&self) -> &ScrollingState {
&self.state
}
fn state_mut(&mut self) -> &mut ScrollingState {
&mut self.state
}
fn subimage(&self, index: usize) -> &T {
&self.images[index]
}
}
impl<T: Render + 'static> Render for ScrollingImages<T> {
fn brightness_at(&self, x: usize, y: usize) -> u8 {
self.current_brightness_at(x, y)
}
}