1use serde::{Deserialize, Serialize};
6use std::f32::consts::PI;
7
8#[derive(Default, Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
9#[serde(default)]
10pub struct Name(pub String);
11
12impl enum2schema::Schema for Name {
13 fn schema() -> enum2schema::serde_json::Value {
14 enum2schema::serde_json::json!({ "type": "string" })
15 }
16}
17
18#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, enum2schema::Schema)]
19#[serde(default)]
20pub struct Visibility {
21 pub visible: bool,
22}
23
24impl Default for Visibility {
25 fn default() -> Self {
26 Self { visible: true }
27 }
28}
29
30#[derive(Default, Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
31pub struct CastsShadow;
32
33impl enum2schema::Schema for CastsShadow {
34 fn schema() -> enum2schema::serde_json::Value {
35 enum2schema::serde_json::json!({ "type": "null" })
36 }
37}
38
39#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
46pub struct Guid(pub u64);
47
48#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
49pub struct RenderLayer(pub u32);
50
51impl enum2schema::Schema for RenderLayer {
52 fn schema() -> enum2schema::serde_json::Value {
53 enum2schema::serde_json::json!({ "type": "integer" })
54 }
55}
56
57impl Default for RenderLayer {
58 fn default() -> Self {
59 Self(Self::WORLD)
60 }
61}
62
63impl RenderLayer {
64 pub const WORLD: u32 = 0;
65 pub const OVERLAY: u32 = 1;
66
67 pub fn new(layer: u32) -> Self {
68 Self(layer)
69 }
70
71 pub fn is_in_layer(&self, layer: u32) -> bool {
72 self.0 == layer
73 }
74
75 pub fn is_overlay(&self) -> bool {
76 self.0 == Self::OVERLAY
77 }
78}
79
80#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
88pub struct CullingMask(pub u32);
89
90impl Default for CullingMask {
91 fn default() -> Self {
92 Self(1)
93 }
94}
95
96impl CullingMask {
97 pub const DEFAULT_LAYER: u32 = 1;
98
99 pub fn new(mask: u32) -> Self {
100 Self(mask)
101 }
102
103 pub fn add_layer(&mut self, layer_index: u32) {
104 self.0 |= 1u32 << layer_index;
105 }
106
107 pub fn remove_layer(&mut self, layer_index: u32) {
108 self.0 &= !(1u32 << layer_index);
109 }
110
111 pub fn intersects(self, other: CullingMask) -> bool {
112 (self.0 & other.0) != 0
113 }
114}
115
116impl enum2schema::Schema for CullingMask {
117 fn schema() -> enum2schema::serde_json::Value {
118 enum2schema::serde_json::json!({ "type": "integer" })
119 }
120}
121
122#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
128pub struct CameraCullingMask(pub u32);
129
130impl Default for CameraCullingMask {
131 fn default() -> Self {
132 Self(!0)
133 }
134}
135
136impl CameraCullingMask {
137 pub fn new(mask: u32) -> Self {
138 Self(mask)
139 }
140
141 pub fn intersects(self, layer: CullingMask) -> bool {
142 (self.0 & layer.0) != 0
143 }
144}
145
146impl enum2schema::Schema for CameraCullingMask {
147 fn schema() -> enum2schema::serde_json::Value {
148 enum2schema::serde_json::json!({ "type": "integer" })
149 }
150}
151
152#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, Serialize, Deserialize)]
153pub enum EasingFunction {
154 #[default]
155 Linear,
156 QuadIn,
157 QuadOut,
158 QuadInOut,
159 CubicIn,
160 CubicOut,
161 CubicInOut,
162 QuartIn,
163 QuartOut,
164 QuartInOut,
165 QuintIn,
166 QuintOut,
167 QuintInOut,
168 SineIn,
169 SineOut,
170 SineInOut,
171 ExpoIn,
172 ExpoOut,
173 ExpoInOut,
174 CircIn,
175 CircOut,
176 CircInOut,
177 BackIn,
178 BackOut,
179 BackInOut,
180 ElasticIn,
181 ElasticOut,
182 ElasticInOut,
183 BounceIn,
184 BounceOut,
185 BounceInOut,
186}
187
188impl EasingFunction {
189 pub fn evaluate(&self, t: f32) -> f32 {
190 let t = t.clamp(0.0, 1.0);
191 match self {
192 Self::Linear => t,
193 Self::QuadIn => t * t,
194 Self::QuadOut => 1.0 - (1.0 - t) * (1.0 - t),
195 Self::QuadInOut => {
196 if t < 0.5 {
197 2.0 * t * t
198 } else {
199 1.0 - (-2.0 * t + 2.0).powi(2) / 2.0
200 }
201 }
202 Self::CubicIn => t * t * t,
203 Self::CubicOut => 1.0 - (1.0 - t).powi(3),
204 Self::CubicInOut => {
205 if t < 0.5 {
206 4.0 * t * t * t
207 } else {
208 1.0 - (-2.0 * t + 2.0).powi(3) / 2.0
209 }
210 }
211 Self::QuartIn => t * t * t * t,
212 Self::QuartOut => 1.0 - (1.0 - t).powi(4),
213 Self::QuartInOut => {
214 if t < 0.5 {
215 8.0 * t * t * t * t
216 } else {
217 1.0 - (-2.0 * t + 2.0).powi(4) / 2.0
218 }
219 }
220 Self::QuintIn => t * t * t * t * t,
221 Self::QuintOut => 1.0 - (1.0 - t).powi(5),
222 Self::QuintInOut => {
223 if t < 0.5 {
224 16.0 * t * t * t * t * t
225 } else {
226 1.0 - (-2.0 * t + 2.0).powi(5) / 2.0
227 }
228 }
229 Self::SineIn => 1.0 - (t * PI / 2.0).cos(),
230 Self::SineOut => (t * PI / 2.0).sin(),
231 Self::SineInOut => -(PI * t).cos() / 2.0 + 0.5,
232 Self::ExpoIn => {
233 if t == 0.0 {
234 0.0
235 } else {
236 (2.0f32).powf(10.0 * t - 10.0)
237 }
238 }
239 Self::ExpoOut => {
240 if t == 1.0 {
241 1.0
242 } else {
243 1.0 - (2.0f32).powf(-10.0 * t)
244 }
245 }
246 Self::ExpoInOut => {
247 if t == 0.0 {
248 0.0
249 } else if t == 1.0 {
250 1.0
251 } else if t < 0.5 {
252 (2.0f32).powf(20.0 * t - 10.0) / 2.0
253 } else {
254 (2.0 - (2.0f32).powf(-20.0 * t + 10.0)) / 2.0
255 }
256 }
257 Self::CircIn => 1.0 - (1.0 - t * t).sqrt(),
258 Self::CircOut => (1.0 - (t - 1.0).powi(2)).sqrt(),
259 Self::CircInOut => {
260 if t < 0.5 {
261 (1.0 - (1.0 - (2.0 * t).powi(2)).sqrt()) / 2.0
262 } else {
263 ((1.0 - (-2.0 * t + 2.0).powi(2)).sqrt() + 1.0) / 2.0
264 }
265 }
266 Self::BackIn => {
267 let c1 = 1.70158;
268 let c3 = c1 + 1.0;
269 c3 * t * t * t - c1 * t * t
270 }
271 Self::BackOut => {
272 let c1 = 1.70158;
273 let c3 = c1 + 1.0;
274 1.0 + c3 * (t - 1.0).powi(3) + c1 * (t - 1.0).powi(2)
275 }
276 Self::BackInOut => {
277 let c1 = 1.70158;
278 let c2 = c1 * 1.525;
279 if t < 0.5 {
280 ((2.0 * t).powi(2) * ((c2 + 1.0) * 2.0 * t - c2)) / 2.0
281 } else {
282 ((2.0 * t - 2.0).powi(2) * ((c2 + 1.0) * (2.0 * t - 2.0) + c2) + 2.0) / 2.0
283 }
284 }
285 Self::ElasticIn => {
286 if t == 0.0 {
287 0.0
288 } else if t == 1.0 {
289 1.0
290 } else {
291 let c4 = 2.0 * PI / 3.0;
292 -(2.0f32).powf(10.0 * t - 10.0) * ((10.0 * t - 10.75) * c4).sin()
293 }
294 }
295 Self::ElasticOut => {
296 if t == 0.0 {
297 0.0
298 } else if t == 1.0 {
299 1.0
300 } else {
301 let c4 = 2.0 * PI / 3.0;
302 (2.0f32).powf(-10.0 * t) * ((10.0 * t - 0.75) * c4).sin() + 1.0
303 }
304 }
305 Self::ElasticInOut => {
306 if t == 0.0 {
307 0.0
308 } else if t == 1.0 {
309 1.0
310 } else {
311 let c5 = 2.0 * PI / 4.5;
312 if t < 0.5 {
313 -(2.0f32).powf(20.0 * t - 10.0) * ((20.0 * t - 11.125) * c5).sin() / 2.0
314 } else {
315 (2.0f32).powf(-20.0 * t + 10.0) * ((20.0 * t - 11.125) * c5).sin() / 2.0
316 + 1.0
317 }
318 }
319 }
320 Self::BounceIn => 1.0 - Self::BounceOut.evaluate(1.0 - t),
321 Self::BounceOut => bounce_out(t),
322 Self::BounceInOut => {
323 if t < 0.5 {
324 (1.0 - bounce_out(1.0 - 2.0 * t)) / 2.0
325 } else {
326 (1.0 + bounce_out(2.0 * t - 1.0)) / 2.0
327 }
328 }
329 }
330 }
331}
332
333fn bounce_out(t: f32) -> f32 {
334 let n1 = 7.5625;
335 let d1 = 2.75;
336 if t < 1.0 / d1 {
337 n1 * t * t
338 } else if t < 2.0 / d1 {
339 let t = t - 1.5 / d1;
340 n1 * t * t + 0.75
341 } else if t < 2.5 / d1 {
342 let t = t - 2.25 / d1;
343 n1 * t * t + 0.9375
344 } else {
345 let t = t - 2.625 / d1;
346 n1 * t * t + 0.984375
347 }
348}