1use glam::{Vec2, Vec3};
2use serde::{Deserialize, Serialize};
3use uuid::Uuid;
4
5use crate::anim_op::{AnimOP, IntoAnimOp};
6use crate::ease::Ease;
7use crate::seconds::Time;
8
9#[derive(Clone, Debug, Serialize, Deserialize)]
11pub struct Transform {
12 pub uuid: Uuid,
14 pub parent: Option<Uuid>,
16 pub position: Vec3,
18 pub rotation: f32,
20 pub scale: Vec2,
22}
23
24impl Transform {
25 #[must_use]
28 pub fn new(position: Vec3) -> Self {
29 Self {
30 uuid: Uuid::new_v4(),
31 parent: None,
32 position,
33 rotation: 0.0,
34 scale: Vec2::ONE,
35 }
36 }
37
38 #[must_use]
40 pub const fn with_parent(mut self, parent: Uuid) -> Self {
41 self.parent = Some(parent);
42 self
43 }
44
45 #[must_use]
53 pub const fn position(&self) -> PositionBuilder {
54 PositionBuilder {
55 uuid: self.uuid,
56 target: None,
57 object: None,
58 duration: 1.0,
59 ease: Ease::Linear,
60 }
61 }
62
63 #[must_use]
71 pub const fn scale(&self) -> ScaleBuilder {
72 ScaleBuilder {
73 uuid: self.uuid,
74 target: None,
75 object: None,
76 duration: 1.0,
77 ease: Ease::Linear,
78 }
79 }
80
81 #[must_use]
89 pub const fn rotation(&self) -> RotateBuilder {
90 RotateBuilder {
91 uuid: self.uuid,
92 target: None,
93 duration: 1.0,
94 ease: Ease::Linear,
95 }
96 }
97}
98
99pub struct PositionBuilder {
101 pub(crate) uuid: Uuid,
102 pub(crate) target: Option<Vec2>,
103 pub(crate) object: Option<Uuid>,
104 pub(crate) duration: Time,
105 pub(crate) ease: Ease,
106}
107
108#[allow(clippy::return_self_not_must_use)]
109impl PositionBuilder {
110 #[must_use]
111 pub fn object(mut self, target: impl Into<uuid::Uuid>) -> Self {
113 self.object = Some(target.into());
114 self
115 }
116
117 #[must_use]
118 pub const fn to(mut self, target: Vec2) -> Self {
120 self.target = Some(target);
121 self
122 }
123
124 #[must_use]
125 pub const fn over(mut self, duration: Time) -> Self {
127 self.duration = duration;
128 self
129 }
130
131 #[must_use]
132 pub fn ease(mut self, ease: Ease) -> AnimOP {
134 self.ease = ease;
135 self.into()
136 }
137}
138
139impl From<PositionBuilder> for AnimOP {
140 fn from(b: PositionBuilder) -> Self {
141 let target = b.target.unwrap_or(Vec2::ZERO);
142 b.object.map_or(
143 Self::TransformMovePos(b.uuid, target, b.duration, b.ease, None),
144 |obj| Self::TransformMoveToObj(b.uuid, obj, target, b.duration, b.ease, None),
145 )
146 }
147}
148
149impl IntoAnimOp for PositionBuilder {
150 fn into_anim_op(self) -> AnimOP {
151 self.into()
152 }
153}
154
155pub struct ScaleBuilder {
157 pub(crate) uuid: Uuid,
158 pub(crate) target: Option<Vec2>,
159 pub(crate) object: Option<Uuid>,
160 pub(crate) duration: Time,
161 pub(crate) ease: Ease,
162}
163
164#[allow(clippy::return_self_not_must_use)]
165impl ScaleBuilder {
166 #[must_use]
167 pub fn object(mut self, target: impl Into<uuid::Uuid>) -> Self {
169 self.object = Some(target.into());
170 self
171 }
172
173 #[must_use]
174 pub const fn to(mut self, target: Vec2) -> Self {
176 self.target = Some(target);
177 self
178 }
179
180 #[must_use]
181 pub const fn over(mut self, duration: Time) -> Self {
183 self.duration = duration;
184 self
185 }
186
187 #[must_use]
188 pub fn ease(mut self, ease: Ease) -> AnimOP {
190 self.ease = ease;
191 self.into()
192 }
193}
194
195impl From<ScaleBuilder> for AnimOP {
196 fn from(b: ScaleBuilder) -> Self {
197 Self::TransformScale(
198 b.uuid,
199 b.target.unwrap_or(Vec2::ONE),
200 b.duration,
201 b.ease,
202 None,
203 )
204 }
205}
206
207impl IntoAnimOp for ScaleBuilder {
208 fn into_anim_op(self) -> AnimOP {
209 self.into()
210 }
211}
212
213pub struct RotateBuilder {
215 pub(crate) uuid: Uuid,
216 pub(crate) target: Option<f32>,
217 pub(crate) duration: Time,
218 pub(crate) ease: Ease,
219}
220
221#[allow(clippy::return_self_not_must_use)]
222impl RotateBuilder {
223 #[must_use]
224 pub const fn to(mut self, target: f32) -> Self {
226 self.target = Some(target);
227 self
228 }
229
230 #[must_use]
231 pub const fn over(mut self, duration: Time) -> Self {
233 self.duration = duration;
234 self
235 }
236
237 #[must_use]
238 pub fn ease(mut self, ease: Ease) -> AnimOP {
240 self.ease = ease;
241 self.into()
242 }
243}
244
245impl From<RotateBuilder> for AnimOP {
246 fn from(b: RotateBuilder) -> Self {
247 Self::TransformRotate(b.uuid, b.target.unwrap_or(0.0), b.duration, b.ease, None)
248 }
249}
250
251impl IntoAnimOp for RotateBuilder {
252 fn into_anim_op(self) -> AnimOP {
253 self.into()
254 }
255}