1use crate::loop_mode::Loop;
4use crate::tween::Tween;
5use animato_core::{Animatable, Easing};
6
7pub struct TweenBuilder<T: Animatable> {
26 start: T,
27 end: T,
28 duration: f32,
29 easing: Easing,
30 delay: f32,
31 time_scale: f32,
32 looping: Loop,
33}
34
35impl<T: Animatable + core::fmt::Debug> core::fmt::Debug for TweenBuilder<T> {
36 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
37 f.debug_struct("TweenBuilder")
38 .field("start", &self.start)
39 .field("end", &self.end)
40 .field("duration", &self.duration)
41 .field("easing", &self.easing)
42 .field("delay", &self.delay)
43 .field("time_scale", &self.time_scale)
44 .field("looping", &self.looping)
45 .finish()
46 }
47}
48
49impl<T: Animatable> TweenBuilder<T> {
50 #[inline]
52 pub fn new(start: T, end: T) -> Self {
53 Self {
54 start,
55 end,
56 duration: 1.0,
57 easing: Easing::Linear,
58 delay: 0.0,
59 time_scale: 1.0,
60 looping: Loop::Once,
61 }
62 }
63
64 #[inline]
66 pub fn duration(mut self, secs: f32) -> Self {
67 self.duration = secs.max(0.0);
68 self
69 }
70
71 #[inline]
73 pub fn easing(mut self, e: Easing) -> Self {
74 self.easing = e;
75 self
76 }
77
78 #[inline]
80 pub fn delay(mut self, secs: f32) -> Self {
81 self.delay = secs.max(0.0);
82 self
83 }
84
85 #[inline]
87 pub fn time_scale(mut self, s: f32) -> Self {
88 self.time_scale = s.max(0.0);
89 self
90 }
91
92 #[inline]
94 pub fn looping(mut self, mode: Loop) -> Self {
95 self.looping = mode;
96 self
97 }
98
99 #[inline]
101 pub fn build(self) -> Tween<T> {
102 Tween::from_builder(
103 self.start,
104 self.end,
105 self.duration,
106 self.easing,
107 self.delay,
108 self.time_scale,
109 self.looping,
110 )
111 }
112}
113
114impl<T: Animatable> Tween<T> {
115 #[allow(clippy::new_ret_no_self)]
127 pub fn new(start: T, end: T) -> TweenBuilder<T> {
128 TweenBuilder::new(start, end)
129 }
130}
131
132#[cfg(test)]
133mod tests {
134 use super::*;
135 use animato_core::Update;
136
137 #[test]
138 fn builder_defaults() {
139 let t = Tween::new(0.0_f32, 1.0).build();
140 assert_eq!(t.duration, 1.0);
141 assert_eq!(t.delay, 0.0);
142 assert_eq!(t.time_scale, 1.0);
143 assert_eq!(t.looping, Loop::Once);
144 }
145
146 #[test]
147 fn builder_chains() {
148 let mut t = Tween::new(0.0_f32, 100.0)
149 .duration(2.0)
150 .delay(0.5)
151 .time_scale(2.0)
152 .looping(Loop::Forever)
153 .build();
154 assert_eq!(t.duration, 2.0);
155 t.update(0.5); t.update(0.5); assert!(t.value() > 0.0);
160 }
161
162 #[test]
163 fn negative_duration_clamped() {
164 let t = Tween::new(0.0_f32, 1.0).duration(-5.0).build();
165 assert_eq!(t.duration, 0.0);
166 }
167
168 #[test]
169 fn negative_delay_clamped() {
170 let t = Tween::new(0.0_f32, 1.0).delay(-1.0).build();
171 assert_eq!(t.delay, 0.0);
172 }
173}