gpui_motion_kit/
playback.rs1use crate::{Clock, Frame, core};
3use core::{Animation, AnimationError, Target};
4use gpui_kit::{App, Window};
5
6use std::{
7 ops::{Deref, DerefMut},
8 time::Duration,
9};
10
11#[derive(Debug, Default)]
14pub struct AnimationState {
15 inner: core::AnimationState,
16 clock: Clock,
17}
18
19impl AnimationState {
20 pub fn new(initial: Target) -> Self {
22 Self {
23 inner: core::AnimationState::new(initial),
24 clock: Clock::default(),
25 }
26 }
27
28 pub fn now(&self, cx: &App) -> Duration {
31 self.clock.now(cx)
32 }
33
34 pub fn frame(&mut self, animation: &Animation, window: &mut Window, cx: &App) -> Frame {
36 let now = self.clock.tick(cx);
37
38 let frame = self.sample(animation, now, cx.reduce_motion());
39
40 if frame.is_animating() {
41 window.request_animation_frame();
42 }
43
44 frame
45 }
46
47 pub fn sample(&mut self, animation: &Animation, now: Duration, reduced_motion: bool) -> Frame {
50 self.inner.sample(animation, now, reduced_motion).into()
51 }
52}
53
54impl Deref for AnimationState {
55 type Target = core::AnimationState;
56
57 fn deref(&self) -> &Self::Target {
58 &self.inner
59 }
60}
61
62impl DerefMut for AnimationState {
63 fn deref_mut(&mut self) -> &mut Self::Target {
64 &mut self.inner
65 }
66}
67
68#[derive(Debug, Default)]
72pub struct Timeline {
73 inner: core::Timeline,
74 frames: Vec<Frame>,
75 clock: Clock,
76}
77
78impl Timeline {
79 fn prepare_frame(&mut self, index: usize) -> usize {
80 debug_assert_eq!(self.frames.len(), index);
81 self.frames.push(core::Frame::at(Target::default()).into());
82
83 index
84 }
85
86 pub fn at(&mut self, at: Duration, animation: Animation) -> usize {
88 let index = self.inner.at(at, animation);
89
90 self.prepare_frame(index)
91 }
92
93 pub fn then(&mut self, animation: Animation) -> Result<usize, AnimationError> {
95 let index = self.inner.then(animation)?;
96
97 Ok(self.prepare_frame(index))
98 }
99
100 pub fn label(&mut self, name: impl Into<String>) -> Result<(), AnimationError> {
102 self.inner.label(name)
103 }
104
105 pub fn at_label(
107 &mut self,
108 name: &str,
109 offset: Duration,
110 animation: Animation,
111 ) -> Result<usize, AnimationError> {
112 let index = self.inner.at_label(name, offset, animation)?;
113
114 Ok(self.prepare_frame(index))
115 }
116
117 pub fn now(&self, cx: &App) -> Duration {
119 self.clock.now(cx)
120 }
121
122 pub fn restart(&mut self, now: Duration) {
124 self.inner.restart(now);
125 }
126
127 pub fn pause(&mut self, now: Duration) {
129 self.inner.pause(now);
130 }
131
132 pub fn play(&mut self, now: Duration) {
134 self.inner.play(now);
135 }
136
137 pub fn seek(&mut self, playhead: Duration, now: Duration) {
139 self.inner.seek(playhead, now);
140 }
141
142 pub fn set_speed(&mut self, speed: f64, now: Duration) -> Result<(), AnimationError> {
144 self.inner.set_speed(speed, now)
145 }
146
147 pub fn sample(&mut self, now: Duration, reduced_motion: bool) -> &[Frame] {
149 for (output, input) in self
150 .frames
151 .iter_mut()
152 .zip(self.inner.sample(now, reduced_motion))
153 {
154 *output = (*input).into();
155 }
156
157 &self.frames
158 }
159
160 pub fn frame(&mut self, window: &mut Window, cx: &App) -> &[Frame] {
162 let now = self.clock.tick(cx);
163
164 self.sample(now, cx.reduce_motion());
165
166 if self.inner.is_animating() {
167 window.request_animation_frame();
168 }
169
170 &self.frames
171 }
172
173 pub fn is_animating(&self) -> bool {
175 self.inner.is_animating()
176 }
177}