diff --git a/src/animation.rs b/src/animation.rs new file mode 100644 index 0000000..faa45ee --- /dev/null +++ b/src/animation.rs @@ -0,0 +1,160 @@ +use embassy_time::{Duration, Timer}; +use figments::surface::Surface; +use core::{fmt::Debug, ops::{Deref, DerefMut}}; +use log::*; + +use crate::events::DisplayControls; + +#[derive(Default, Debug, Clone, Copy)] +pub struct Animation { + from: Option, + to: Option, + duration: Duration +} + +pub trait AnimationActor { + fn get_opacity(&self) -> u8; + fn set_opacity(&mut self, opacity: u8); +} + +impl AnimationActor for S { + fn get_opacity(&self) -> u8 { + 0 + } + + fn set_opacity(&mut self, opacity: u8) { + self.set_opacity(opacity); + } +} + +#[derive(Debug)] +pub struct AnimDisplay<'a>(pub &'a DisplayControls); + +impl<'a> AnimationActor for AnimDisplay<'a> { + fn get_opacity(&self) -> u8 { + self.0.brightness() + } + + fn set_opacity(&mut self, opacity: u8) { + self.0.set_brightness(opacity); + } +} + +impl AnimationActor for AnimatedSurface { + fn get_opacity(&self) -> u8 { + self.opacity + } + + fn set_opacity(&mut self, opacity: u8) { + self.surface.set_opacity(opacity); + self.opacity = opacity; + } +} + +impl Animation { + pub fn from(self, from: u8) -> Self { + Self { + from: Some(from), + to: self.to, + duration: self.duration + } + } + + pub fn to(self, to: u8) -> Self { + Self { + from: self.from, + to: Some(to), + duration: self.duration + } + } + + pub fn duration(self, duration: Duration) -> Self { + Self { + from: self.from, + to: self.to, + duration + } + } + + pub async fn apply(&self, sfc: &mut S) { + let from = if let Some(val) = self.from { + val + } else { + sfc.get_opacity() + }; + let to = if let Some(val) = self.to { + val + } else { + sfc.get_opacity() + }; + let steps = from.abs_diff(to); + if steps == 0 { + return; + } + let step_time = self.duration / steps.into(); + trace!("fade={self:?} steps={steps} time={step_time} sfc={sfc:?}"); + if from > to { + let range = (to..=from).rev(); + for opacity in range { + sfc.set_opacity(opacity); + Timer::after(step_time).await; + } + } else { + let range = from..=to; + + for opacity in range { + sfc.set_opacity(opacity); + Timer::after(step_time).await; + } + } + } +} + +#[derive(Debug)] +pub struct AnimatedSurface { + surface: S, + is_on: bool, + opacity: u8 +} + +impl Deref for AnimatedSurface { + type Target = S; + + fn deref(&self) -> &Self::Target { + &self.surface + } +} + +impl DerefMut for AnimatedSurface { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.surface + } +} + +impl From for AnimatedSurface { + fn from(surface: S) -> Self { + AnimatedSurface { + surface, + is_on: false, + opacity: 255 + } + } +} + +impl AnimatedSurface { + pub async fn set_on(&mut self, is_on: bool) { + if self.is_on != is_on { + let anim = if is_on { + self.surface.set_visible(true); + Animation::default().duration(Duration::from_secs(1)).from(0).to(255) + } else { + Animation::default().duration(Duration::from_secs(1)).from(255).to(0) + }; + anim.apply(&mut self.surface).await; + self.is_on = true; + if !is_on { + self.surface.set_visible(false); + } + } + } +} \ No newline at end of file