use crate::{Clock, Frame, core};
use core::{Animation, AnimationError, Target};
use gpui_kit::{App, Window};
use std::{
ops::{Deref, DerefMut},
time::Duration,
};
#[derive(Debug, Default)]
pub struct AnimationState {
inner: core::AnimationState,
clock: Clock,
}
impl AnimationState {
pub fn new(initial: Target) -> Self {
Self {
inner: core::AnimationState::new(initial),
clock: Clock::default(),
}
}
pub fn now(&self, cx: &App) -> Duration {
self.clock.now(cx)
}
pub fn frame(&mut self, animation: &Animation, window: &mut Window, cx: &App) -> Frame {
let now = self.clock.tick(cx);
let frame = self.sample(animation, now, cx.reduce_motion());
if frame.is_animating() {
window.request_animation_frame();
}
frame
}
pub fn sample(&mut self, animation: &Animation, now: Duration, reduced_motion: bool) -> Frame {
self.inner.sample(animation, now, reduced_motion).into()
}
}
impl Deref for AnimationState {
type Target = core::AnimationState;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl DerefMut for AnimationState {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
#[derive(Debug, Default)]
pub struct Timeline {
inner: core::Timeline,
frames: Vec<Frame>,
clock: Clock,
}
impl Timeline {
fn prepare_frame(&mut self, index: usize) -> usize {
debug_assert_eq!(self.frames.len(), index);
self.frames.push(core::Frame::at(Target::default()).into());
index
}
pub fn at(&mut self, at: Duration, animation: Animation) -> usize {
let index = self.inner.at(at, animation);
self.prepare_frame(index)
}
pub fn then(&mut self, animation: Animation) -> Result<usize, AnimationError> {
let index = self.inner.then(animation)?;
Ok(self.prepare_frame(index))
}
pub fn label(&mut self, name: impl Into<String>) -> Result<(), AnimationError> {
self.inner.label(name)
}
pub fn at_label(
&mut self,
name: &str,
offset: Duration,
animation: Animation,
) -> Result<usize, AnimationError> {
let index = self.inner.at_label(name, offset, animation)?;
Ok(self.prepare_frame(index))
}
pub fn now(&self, cx: &App) -> Duration {
self.clock.now(cx)
}
pub fn restart(&mut self, now: Duration) {
self.inner.restart(now);
}
pub fn pause(&mut self, now: Duration) {
self.inner.pause(now);
}
pub fn play(&mut self, now: Duration) {
self.inner.play(now);
}
pub fn seek(&mut self, playhead: Duration, now: Duration) {
self.inner.seek(playhead, now);
}
pub fn set_speed(&mut self, speed: f64, now: Duration) -> Result<(), AnimationError> {
self.inner.set_speed(speed, now)
}
pub fn sample(&mut self, now: Duration, reduced_motion: bool) -> &[Frame] {
for (output, input) in self
.frames
.iter_mut()
.zip(self.inner.sample(now, reduced_motion))
{
*output = (*input).into();
}
&self.frames
}
pub fn frame(&mut self, window: &mut Window, cx: &App) -> &[Frame] {
let now = self.clock.tick(cx);
self.sample(now, cx.reduce_motion());
if self.inner.is_animating() {
window.request_animation_frame();
}
&self.frames
}
pub fn is_animating(&self) -> bool {
self.inner.is_animating()
}
}