animation: implement an animation module
This commit is contained in:
160
src/animation.rs
Normal file
160
src/animation.rs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user