Skip to main content

gpui_motion_kit/
typed.rs

1//! Native clocks for the shared typed clip and timeline engines.
2use crate::core::{AnimationError, MotionData, TypedAnimation, TypedFrame};
3use gpui_kit::{App, Window};
4
5use std::{
6    ops::{Deref, DerefMut},
7    time::Duration,
8};
9
10/// Kit executor clock around a shared, independently sampled typed state.
11#[derive(Debug)]
12pub struct TypedState<T, const N: usize> {
13    inner: crate::core::TypedState<T, N>,
14    clock: crate::Clock,
15}
16
17impl<T, const N: usize> Deref for TypedState<T, N> {
18    type Target = crate::core::TypedState<T, N>;
19
20    fn deref(&self) -> &Self::Target {
21        &self.inner
22    }
23}
24
25impl<T, const N: usize> DerefMut for TypedState<T, N> {
26    fn deref_mut(&mut self) -> &mut Self::Target {
27        &mut self.inner
28    }
29}
30
31impl<T: MotionData<N>, const N: usize> TypedState<T, N> {
32    /// Seeds the native presentation; use matching property masks in its clips.
33    pub fn new(value: T) -> Self {
34        Self {
35            inner: crate::core::TypedState::new(value),
36            clock: Default::default(),
37        }
38    }
39
40    /// Native control timestamp. Do not mix this clock with manual samples.
41    pub fn now(&self, cx: &App) -> Duration {
42        self.clock.now(cx)
43    }
44
45    /// Samples the shared clip and schedules only while active.
46    pub fn frame(
47        &mut self,
48        clip: &TypedAnimation<T, N>,
49        window: &mut Window,
50        cx: &App,
51    ) -> TypedFrame<T> {
52        let now = self.clock.tick(cx);
53        let frame = self.inner.sample(clip, now, cx.reduce_motion());
54
55        if frame.is_animating() {
56            window.request_animation_frame();
57        }
58
59        frame
60    }
61}
62
63/// Kit executor clock around a shared heterogeneous timeline.
64#[derive(Debug, Default)]
65pub struct TypedTimeline {
66    inner: crate::core::TypedTimeline,
67    clock: crate::Clock,
68}
69
70impl Deref for TypedTimeline {
71    type Target = crate::core::TypedTimeline;
72
73    fn deref(&self) -> &Self::Target {
74        &self.inner
75    }
76}
77
78impl DerefMut for TypedTimeline {
79    fn deref_mut(&mut self) -> &mut Self::Target {
80        &mut self.inner
81    }
82}
83
84impl TypedTimeline {
85    /// Native timestamp for playback controls.
86    pub fn now(&self, cx: &App) -> Duration {
87        self.clock.now(cx)
88    }
89
90    /// Samples all typed tracks using Kit's reduced-motion preference.
91    pub fn frame(&mut self, window: &mut Window, cx: &App) {
92        self.inner.sample(self.clock.tick(cx), cx.reduce_motion());
93
94        if self.inner.is_animating() {
95            window.request_animation_frame();
96        }
97    }
98
99    /// Changes playback speed using this adapter's clock.
100    pub fn speed(&mut self, speed: f64, cx: &App) -> Result<(), AnimationError> {
101        self.inner.set_speed(speed, self.now(cx))
102    }
103}