animation: implement an animation module

This commit is contained in:
2025-10-11 16:32:21 +02:00
parent 019d134022
commit 9a8f0b31ab

160
src/animation.rs Normal file
View File

@@ -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<u8>,
to: Option<u8>,
duration: Duration
}
pub trait AnimationActor {
fn get_opacity(&self) -> u8;
fn set_opacity(&mut self, opacity: u8);
}
impl<S: Surface> 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<S: Surface> AnimationActor for AnimatedSurface<S> {
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<S: AnimationActor + Debug>(&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<S: Surface> {
surface: S,
is_on: bool,
opacity: u8
}
impl<S: Surface> Deref for AnimatedSurface<S> {
type Target = S;
fn deref(&self) -> &Self::Target {
&self.surface
}
}
impl<S: Surface> DerefMut for AnimatedSurface<S> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.surface
}
}
impl<S: Surface> From<S> for AnimatedSurface<S> {
fn from(surface: S) -> Self {
AnimatedSurface {
surface,
is_on: false,
opacity: 255
}
}
}
impl<S: Surface + Debug> AnimatedSurface<S> {
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);
}
}
}
}