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); } } } }