use core::fmt::Debug;
use core::time::Duration;
use crate::animation::{Motion, Progress};
use crate::mesh::Clip;
pub trait AnimationStates: Copy + Eq + Debug + Sized {
type Clip: Clip;
type Input: Default;
fn entry() -> Self;
fn motion(&self, input: &Self::Input) -> Motion<Self::Clip>;
fn next(&self, input: &Self::Input, at: Progress) -> Option<Transition<Self>>;
fn fade(self, over: Duration) -> Transition<Self> {
Transition::from(self).fade(over)
}
fn at_once(self) -> Transition<Self> {
Transition::from(self).at_once()
}
fn entering_at(self, fraction: f32) -> Transition<Self> {
Transition::from(self).entering_at(fraction)
}
fn restarted(self) -> Transition<Self> {
Transition::from(self).restarted()
}
}
#[must_use = "a transition only moves a machine once next returns it"]
#[derive(Clone, Debug)]
pub struct Transition<S> {
pub(crate) into: S,
pub(crate) fade: Duration,
pub(crate) entering_at: f32,
pub(crate) restarted: bool,
}
impl<S> Transition<S> {
pub const DEFAULT_FADE: Duration = Duration::from_millis(150);
pub fn fade(mut self, over: Duration) -> Self {
self.fade = over;
self
}
pub fn at_once(mut self) -> Self {
self.fade = Duration::ZERO;
self
}
pub fn entering_at(mut self, fraction: f32) -> Self {
self.entering_at = match fraction.is_nan() {
true => 0.0,
false => fraction.clamp(0.0, 1.0),
};
self
}
pub fn restarted(mut self) -> Self {
self.restarted = true;
self
}
}
impl<S> From<S> for Transition<S> {
fn from(into: S) -> Self {
Self {
into,
fade: Self::DEFAULT_FADE,
entering_at: 0.0,
restarted: false,
}
}
}