1use crate::{range_iter, spline::*};
2use core::Scalar;
3use serde::{Deserialize, Serialize};
4use std::{convert::TryFrom, ops::Range};
5
6#[derive(Debug, Copy, Clone, Serialize, Deserialize)]
7pub enum Ease {
8 InSine,
9 OutSine,
10 InOutSine,
11 InQuad,
12 OutQuad,
13 InOutQuad,
14 InCubic,
15 OutCubic,
16 InOutCubic,
17 InQuart,
18 OutQuart,
19 InOutQuart,
20 InQuint,
21 OutQuint,
22 InOutQuint,
23 InExpo,
24 OutExpo,
25 InOutExpo,
26 InCirc,
27 OutCirc,
28 InOutCirc,
29 InBack,
30 OutBack,
31 InOutBack,
32}
33
34impl Ease {
35 pub fn bezier(self) -> (Scalar, Scalar, Scalar, Scalar) {
36 match self {
37 Self::InSine => (0.47, 0.0, 0.745, 0.715),
38 Self::OutSine => (0.39, 0.575, 0.565, 1.0),
39 Self::InOutSine => (0.445, 0.05, 0.55, 0.95),
40 Self::InQuad => (0.55, 0.085, 0.68, 0.53),
41 Self::OutQuad => (0.25, 0.46, 0.45, 0.94),
42 Self::InOutQuad => (0.455, 0.03, 0.515, 0.955),
43 Self::InCubic => (0.55, 0.055, 0.675, 0.19),
44 Self::OutCubic => (0.215, 0.61, 0.355, 1.0),
45 Self::InOutCubic => (0.645, 0.045, 0.355, 1.0),
46 Self::InQuart => (0.895, 0.03, 0.685, 0.22),
47 Self::OutQuart => (0.165, 0.84, 0.44, 1.0),
48 Self::InOutQuart => (0.77, 0.0, 0.175, 1.0),
49 Self::InQuint => (0.755, 0.05, 0.855, 0.06),
50 Self::OutQuint => (0.23, 1.0, 0.32, 1.0),
51 Self::InOutQuint => (0.86, 0.0, 0.07, 1.0),
52 Self::InExpo => (0.95, 0.05, 0.795, 0.035),
53 Self::OutExpo => (0.19, 1.0, 0.22, 1.0),
54 Self::InOutExpo => (1.0, 0.0, 0.0, 1.0),
55 Self::InCirc => (0.6, 0.04, 0.98, 0.335),
56 Self::OutCirc => (0.075, 0.82, 0.165, 1.0),
57 Self::InOutCirc => (0.785, 0.135, 0.15, 0.86),
58 Self::InBack => (0.6, -0.28, 0.735, 0.045),
59 Self::OutBack => (0.175, 0.885, 0.32, 1.275),
60 Self::InOutBack => (0.68, -0.55, 0.265, 1.55),
61 }
62 }
63}
64
65pub type PhaseDef = Vec<SplinePoint<(Scalar, Scalar)>>;
66
67#[derive(Debug, Clone, Serialize, Deserialize)]
68#[serde(try_from = "PhaseDef")]
69#[serde(into = "PhaseDef")]
70pub struct Phase {
71 spline: Spline<(Scalar, Scalar)>,
72 time_frame: Range<Scalar>,
73}
74
75impl Default for Phase {
76 fn default() -> Self {
77 Self::point(1.0).expect("Could not create default point phase")
78 }
79}
80
81impl Phase {
82 pub fn new(mut points: Vec<SplinePoint<(Scalar, Scalar)>>) -> Result<Self, SplineError> {
83 let mut time_frame = Scalar::INFINITY..Scalar::NEG_INFINITY;
84 for point in &mut points {
85 match &mut point.direction {
86 SplinePointDirection::Single(dir) => dir.0 = dir.0.max(0.0),
87 SplinePointDirection::InOut(from, to) => {
88 from.0 = from.0.min(0.0);
89 to.0 = to.0.max(0.0);
90 }
91 }
92 point.point.0 = point.point.0.max(time_frame.end);
93 time_frame.start = time_frame.start.min(point.point.0);
94 time_frame.end = time_frame.start.max(point.point.0);
95 }
96 Ok(Self {
97 spline: Spline::new(points)?,
98 time_frame,
99 })
100 }
101
102 pub fn linear(
103 value_frame: Range<Scalar>,
104 mut time_frame: Range<Scalar>,
105 ) -> Result<Self, SplineError> {
106 if time_frame.start > time_frame.end {
107 time_frame = time_frame.end..value_frame.start;
108 }
109 Self::new(vec![
110 SplinePoint::point((time_frame.start, value_frame.start)),
111 SplinePoint::point((time_frame.end, value_frame.end)),
112 ])
113 }
114
115 pub fn bezier(
116 (mut x1, mut y1, mut x2, mut y2): (Scalar, Scalar, Scalar, Scalar),
117 value_frame: Range<Scalar>,
118 mut time_frame: Range<Scalar>,
119 ) -> Result<Self, SplineError> {
120 if time_frame.start > time_frame.end {
121 time_frame = time_frame.end..value_frame.start;
122 }
123 let distance = (value_frame.end - value_frame.start).abs();
124 let duration = time_frame.end - time_frame.start;
125 x1 *= duration;
126 y1 *= distance;
127 x2 = (1.0 - x2) * -duration;
128 y2 = (1.0 - y2) * -distance;
129 Self::new(vec![
130 SplinePoint::new(
131 (time_frame.start, value_frame.start),
132 SplinePointDirection::Single((x1, y1)),
133 ),
134 SplinePoint::new(
135 (time_frame.end, value_frame.end),
136 SplinePointDirection::Single((x2, y2)),
137 ),
138 ])
139 }
140
141 pub fn ease(
142 ease: Ease,
143 value_frame: Range<Scalar>,
144 time_frame: Range<Scalar>,
145 ) -> Result<Self, SplineError> {
146 Self::bezier(ease.bezier(), value_frame, time_frame)
147 }
148
149 pub fn point(point: Scalar) -> Result<Self, SplineError> {
150 Self::linear(point..point, 0.0..0.0)
151 }
152
153 pub fn time_frame(&self) -> Range<Scalar> {
154 self.time_frame.to_owned()
155 }
156
157 pub fn duration(&self) -> Scalar {
158 self.time_frame.end - self.time_frame.start
159 }
160
161 pub fn points(&self) -> &[SplinePoint<(Scalar, Scalar)>] {
162 self.spline.points()
163 }
164
165 pub fn set_points(&mut self, points: Vec<SplinePoint<(Scalar, Scalar)>>) {
166 if let Ok(result) = Self::new(points) {
167 *self = result;
168 }
169 }
170
171 pub fn spline(&self) -> &Spline<(Scalar, Scalar)> {
172 &self.spline
173 }
174
175 pub fn time_iter(&self, steps: usize) -> impl Iterator<Item = Scalar> {
176 range_iter(steps, self.time_frame.start, self.time_frame.end)
177 }
178
179 pub fn sample(&self, mut time: Scalar) -> Scalar {
180 time = time.max(self.time_frame.start).min(self.time_frame.end);
181 self.spline.sample_along_axis(time, 0).unwrap().1
182 }
183}
184
185impl TryFrom<PhaseDef> for Phase {
186 type Error = SplineError;
187
188 fn try_from(value: PhaseDef) -> Result<Self, Self::Error> {
189 Self::new(value)
190 }
191}
192
193impl From<Phase> for PhaseDef {
194 fn from(v: Phase) -> Self {
195 v.spline.into()
196 }
197}