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)]
56pub struct CullingMask(pub u32);
57
58impl Default for CullingMask {
59 fn default() -> Self {
60 Self(1)
61 }
62}
63
64impl CullingMask {
65 pub const DEFAULT_LAYER: u32 = 1;
66
67 pub fn new(mask: u32) -> Self {
68 Self(mask)
69 }
70
71 pub fn add_layer(&mut self, layer_index: u32) {
72 self.0 |= 1u32 << layer_index;
73 }
74
75 pub fn remove_layer(&mut self, layer_index: u32) {
76 self.0 &= !(1u32 << layer_index);
77 }
78
79 pub fn intersects(self, other: CullingMask) -> bool {
80 (self.0 & other.0) != 0
81 }
82}
83
84impl enum2schema::Schema for CullingMask {
85 fn schema() -> enum2schema::serde_json::Value {
86 enum2schema::serde_json::json!({ "type": "integer" })
87 }
88}
89
90#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
96pub struct CameraCullingMask(pub u32);
97
98impl Default for CameraCullingMask {
99 fn default() -> Self {
100 Self(!0)
101 }
102}
103
104impl CameraCullingMask {
105 pub fn new(mask: u32) -> Self {
106 Self(mask)
107 }
108
109 pub fn intersects(self, layer: CullingMask) -> bool {
110 (self.0 & layer.0) != 0
111 }
112}
113
114impl enum2schema::Schema for CameraCullingMask {
115 fn schema() -> enum2schema::serde_json::Value {
116 enum2schema::serde_json::json!({ "type": "integer" })
117 }
118}
119
120#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, Serialize, Deserialize)]
121pub enum EasingFunction {
122 #[default]
123 Linear,
124 QuadIn,
125 QuadOut,
126 QuadInOut,
127 CubicIn,
128 CubicOut,
129 CubicInOut,
130 QuartIn,
131 QuartOut,
132 QuartInOut,
133 QuintIn,
134 QuintOut,
135 QuintInOut,
136 SineIn,
137 SineOut,
138 SineInOut,
139 ExpoIn,
140 ExpoOut,
141 ExpoInOut,
142 CircIn,
143 CircOut,
144 CircInOut,
145 BackIn,
146 BackOut,
147 BackInOut,
148 ElasticIn,
149 ElasticOut,
150 ElasticInOut,
151 BounceIn,
152 BounceOut,
153 BounceInOut,
154}
155
156impl EasingFunction {
157 pub fn evaluate(&self, t: f32) -> f32 {
158 let t = t.clamp(0.0, 1.0);
159 match self {
160 Self::Linear => t,
161 Self::QuadIn => t * t,
162 Self::QuadOut => 1.0 - (1.0 - t) * (1.0 - t),
163 Self::QuadInOut => {
164 if t < 0.5 {
165 2.0 * t * t
166 } else {
167 1.0 - (-2.0 * t + 2.0).powi(2) / 2.0
168 }
169 }
170 Self::CubicIn => t * t * t,
171 Self::CubicOut => 1.0 - (1.0 - t).powi(3),
172 Self::CubicInOut => {
173 if t < 0.5 {
174 4.0 * t * t * t
175 } else {
176 1.0 - (-2.0 * t + 2.0).powi(3) / 2.0
177 }
178 }
179 Self::QuartIn => t * t * t * t,
180 Self::QuartOut => 1.0 - (1.0 - t).powi(4),
181 Self::QuartInOut => {
182 if t < 0.5 {
183 8.0 * t * t * t * t
184 } else {
185 1.0 - (-2.0 * t + 2.0).powi(4) / 2.0
186 }
187 }
188 Self::QuintIn => t * t * t * t * t,
189 Self::QuintOut => 1.0 - (1.0 - t).powi(5),
190 Self::QuintInOut => {
191 if t < 0.5 {
192 16.0 * t * t * t * t * t
193 } else {
194 1.0 - (-2.0 * t + 2.0).powi(5) / 2.0
195 }
196 }
197 Self::SineIn => 1.0 - (t * PI / 2.0).cos(),
198 Self::SineOut => (t * PI / 2.0).sin(),
199 Self::SineInOut => -(PI * t).cos() / 2.0 + 0.5,
200 Self::ExpoIn => {
201 if t == 0.0 {
202 0.0
203 } else {
204 (2.0f32).powf(10.0 * t - 10.0)
205 }
206 }
207 Self::ExpoOut => {
208 if t == 1.0 {
209 1.0
210 } else {
211 1.0 - (2.0f32).powf(-10.0 * t)
212 }
213 }
214 Self::ExpoInOut => {
215 if t == 0.0 {
216 0.0
217 } else if t == 1.0 {
218 1.0
219 } else if t < 0.5 {
220 (2.0f32).powf(20.0 * t - 10.0) / 2.0
221 } else {
222 (2.0 - (2.0f32).powf(-20.0 * t + 10.0)) / 2.0
223 }
224 }
225 Self::CircIn => 1.0 - (1.0 - t * t).sqrt(),
226 Self::CircOut => (1.0 - (t - 1.0).powi(2)).sqrt(),
227 Self::CircInOut => {
228 if t < 0.5 {
229 (1.0 - (1.0 - (2.0 * t).powi(2)).sqrt()) / 2.0
230 } else {
231 ((1.0 - (-2.0 * t + 2.0).powi(2)).sqrt() + 1.0) / 2.0
232 }
233 }
234 Self::BackIn => {
235 let c1 = 1.70158;
236 let c3 = c1 + 1.0;
237 c3 * t * t * t - c1 * t * t
238 }
239 Self::BackOut => {
240 let c1 = 1.70158;
241 let c3 = c1 + 1.0;
242 1.0 + c3 * (t - 1.0).powi(3) + c1 * (t - 1.0).powi(2)
243 }
244 Self::BackInOut => {
245 let c1 = 1.70158;
246 let c2 = c1 * 1.525;
247 if t < 0.5 {
248 ((2.0 * t).powi(2) * ((c2 + 1.0) * 2.0 * t - c2)) / 2.0
249 } else {
250 ((2.0 * t - 2.0).powi(2) * ((c2 + 1.0) * (2.0 * t - 2.0) + c2) + 2.0) / 2.0
251 }
252 }
253 Self::ElasticIn => {
254 if t == 0.0 {
255 0.0
256 } else if t == 1.0 {
257 1.0
258 } else {
259 let c4 = 2.0 * PI / 3.0;
260 -(2.0f32).powf(10.0 * t - 10.0) * ((10.0 * t - 10.75) * c4).sin()
261 }
262 }
263 Self::ElasticOut => {
264 if t == 0.0 {
265 0.0
266 } else if t == 1.0 {
267 1.0
268 } else {
269 let c4 = 2.0 * PI / 3.0;
270 (2.0f32).powf(-10.0 * t) * ((10.0 * t - 0.75) * c4).sin() + 1.0
271 }
272 }
273 Self::ElasticInOut => {
274 if t == 0.0 {
275 0.0
276 } else if t == 1.0 {
277 1.0
278 } else {
279 let c5 = 2.0 * PI / 4.5;
280 if t < 0.5 {
281 -(2.0f32).powf(20.0 * t - 10.0) * ((20.0 * t - 11.125) * c5).sin() / 2.0
282 } else {
283 (2.0f32).powf(-20.0 * t + 10.0) * ((20.0 * t - 11.125) * c5).sin() / 2.0
284 + 1.0
285 }
286 }
287 }
288 Self::BounceIn => 1.0 - Self::BounceOut.evaluate(1.0 - t),
289 Self::BounceOut => bounce_out(t),
290 Self::BounceInOut => {
291 if t < 0.5 {
292 (1.0 - bounce_out(1.0 - 2.0 * t)) / 2.0
293 } else {
294 (1.0 + bounce_out(2.0 * t - 1.0)) / 2.0
295 }
296 }
297 }
298 }
299}
300
301fn bounce_out(t: f32) -> f32 {
302 let n1 = 7.5625;
303 let d1 = 2.75;
304 if t < 1.0 / d1 {
305 n1 * t * t
306 } else if t < 2.0 / d1 {
307 let t = t - 1.5 / d1;
308 n1 * t * t + 0.75
309 } else if t < 2.5 / d1 {
310 let t = t - 2.25 / d1;
311 n1 * t * t + 0.9375
312 } else {
313 let t = t - 2.625 / d1;
314 n1 * t * t + 0.984375
315 }
316}