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
116#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
122pub struct CameraCullingMask(pub u32);
123
124impl Default for CameraCullingMask {
125 fn default() -> Self {
126 Self(!0)
127 }
128}
129
130impl CameraCullingMask {
131 pub fn new(mask: u32) -> Self {
132 Self(mask)
133 }
134
135 pub fn intersects(self, layer: CullingMask) -> bool {
136 (self.0 & layer.0) != 0
137 }
138}
139
140#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, Serialize, Deserialize)]
141pub enum EasingFunction {
142 #[default]
143 Linear,
144 QuadIn,
145 QuadOut,
146 QuadInOut,
147 CubicIn,
148 CubicOut,
149 CubicInOut,
150 QuartIn,
151 QuartOut,
152 QuartInOut,
153 QuintIn,
154 QuintOut,
155 QuintInOut,
156 SineIn,
157 SineOut,
158 SineInOut,
159 ExpoIn,
160 ExpoOut,
161 ExpoInOut,
162 CircIn,
163 CircOut,
164 CircInOut,
165 BackIn,
166 BackOut,
167 BackInOut,
168 ElasticIn,
169 ElasticOut,
170 ElasticInOut,
171 BounceIn,
172 BounceOut,
173 BounceInOut,
174}
175
176impl EasingFunction {
177 pub fn evaluate(&self, t: f32) -> f32 {
178 let t = t.clamp(0.0, 1.0);
179 match self {
180 Self::Linear => t,
181 Self::QuadIn => t * t,
182 Self::QuadOut => 1.0 - (1.0 - t) * (1.0 - t),
183 Self::QuadInOut => {
184 if t < 0.5 {
185 2.0 * t * t
186 } else {
187 1.0 - (-2.0 * t + 2.0).powi(2) / 2.0
188 }
189 }
190 Self::CubicIn => t * t * t,
191 Self::CubicOut => 1.0 - (1.0 - t).powi(3),
192 Self::CubicInOut => {
193 if t < 0.5 {
194 4.0 * t * t * t
195 } else {
196 1.0 - (-2.0 * t + 2.0).powi(3) / 2.0
197 }
198 }
199 Self::QuartIn => t * t * t * t,
200 Self::QuartOut => 1.0 - (1.0 - t).powi(4),
201 Self::QuartInOut => {
202 if t < 0.5 {
203 8.0 * t * t * t * t
204 } else {
205 1.0 - (-2.0 * t + 2.0).powi(4) / 2.0
206 }
207 }
208 Self::QuintIn => t * t * t * t * t,
209 Self::QuintOut => 1.0 - (1.0 - t).powi(5),
210 Self::QuintInOut => {
211 if t < 0.5 {
212 16.0 * t * t * t * t * t
213 } else {
214 1.0 - (-2.0 * t + 2.0).powi(5) / 2.0
215 }
216 }
217 Self::SineIn => 1.0 - (t * PI / 2.0).cos(),
218 Self::SineOut => (t * PI / 2.0).sin(),
219 Self::SineInOut => -(PI * t).cos() / 2.0 + 0.5,
220 Self::ExpoIn => {
221 if t == 0.0 {
222 0.0
223 } else {
224 (2.0f32).powf(10.0 * t - 10.0)
225 }
226 }
227 Self::ExpoOut => {
228 if t == 1.0 {
229 1.0
230 } else {
231 1.0 - (2.0f32).powf(-10.0 * t)
232 }
233 }
234 Self::ExpoInOut => {
235 if t == 0.0 {
236 0.0
237 } else if t == 1.0 {
238 1.0
239 } else if t < 0.5 {
240 (2.0f32).powf(20.0 * t - 10.0) / 2.0
241 } else {
242 (2.0 - (2.0f32).powf(-20.0 * t + 10.0)) / 2.0
243 }
244 }
245 Self::CircIn => 1.0 - (1.0 - t * t).sqrt(),
246 Self::CircOut => (1.0 - (t - 1.0).powi(2)).sqrt(),
247 Self::CircInOut => {
248 if t < 0.5 {
249 (1.0 - (1.0 - (2.0 * t).powi(2)).sqrt()) / 2.0
250 } else {
251 ((1.0 - (-2.0 * t + 2.0).powi(2)).sqrt() + 1.0) / 2.0
252 }
253 }
254 Self::BackIn => {
255 let c1 = 1.70158;
256 let c3 = c1 + 1.0;
257 c3 * t * t * t - c1 * t * t
258 }
259 Self::BackOut => {
260 let c1 = 1.70158;
261 let c3 = c1 + 1.0;
262 1.0 + c3 * (t - 1.0).powi(3) + c1 * (t - 1.0).powi(2)
263 }
264 Self::BackInOut => {
265 let c1 = 1.70158;
266 let c2 = c1 * 1.525;
267 if t < 0.5 {
268 ((2.0 * t).powi(2) * ((c2 + 1.0) * 2.0 * t - c2)) / 2.0
269 } else {
270 ((2.0 * t - 2.0).powi(2) * ((c2 + 1.0) * (2.0 * t - 2.0) + c2) + 2.0) / 2.0
271 }
272 }
273 Self::ElasticIn => {
274 if t == 0.0 {
275 0.0
276 } else if t == 1.0 {
277 1.0
278 } else {
279 let c4 = 2.0 * PI / 3.0;
280 -(2.0f32).powf(10.0 * t - 10.0) * ((10.0 * t - 10.75) * c4).sin()
281 }
282 }
283 Self::ElasticOut => {
284 if t == 0.0 {
285 0.0
286 } else if t == 1.0 {
287 1.0
288 } else {
289 let c4 = 2.0 * PI / 3.0;
290 (2.0f32).powf(-10.0 * t) * ((10.0 * t - 0.75) * c4).sin() + 1.0
291 }
292 }
293 Self::ElasticInOut => {
294 if t == 0.0 {
295 0.0
296 } else if t == 1.0 {
297 1.0
298 } else {
299 let c5 = 2.0 * PI / 4.5;
300 if t < 0.5 {
301 -(2.0f32).powf(20.0 * t - 10.0) * ((20.0 * t - 11.125) * c5).sin() / 2.0
302 } else {
303 (2.0f32).powf(-20.0 * t + 10.0) * ((20.0 * t - 11.125) * c5).sin() / 2.0
304 + 1.0
305 }
306 }
307 }
308 Self::BounceIn => 1.0 - Self::BounceOut.evaluate(1.0 - t),
309 Self::BounceOut => bounce_out(t),
310 Self::BounceInOut => {
311 if t < 0.5 {
312 (1.0 - bounce_out(1.0 - 2.0 * t)) / 2.0
313 } else {
314 (1.0 + bounce_out(2.0 * t - 1.0)) / 2.0
315 }
316 }
317 }
318 }
319}
320
321fn bounce_out(t: f32) -> f32 {
322 let n1 = 7.5625;
323 let d1 = 2.75;
324 if t < 1.0 / d1 {
325 n1 * t * t
326 } else if t < 2.0 / d1 {
327 let t = t - 1.5 / d1;
328 n1 * t * t + 0.75
329 } else if t < 2.5 / d1 {
330 let t = t - 2.25 / d1;
331 n1 * t * t + 0.9375
332 } else {
333 let t = t - 2.625 / d1;
334 n1 * t * t + 0.984375
335 }
336}