use serde::{Deserialize, Serialize};
use std::f32::consts::PI;
#[derive(Default, Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(default)]
pub struct Name(pub String);
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(default)]
pub struct Visibility {
pub visible: bool,
}
impl Default for Visibility {
fn default() -> Self {
Self { visible: true }
}
}
#[derive(Default, Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
pub struct CastsShadow;
#[derive(Default, Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct Guid(pub u64);
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct RenderLayer(pub u32);
impl Default for RenderLayer {
fn default() -> Self {
Self(Self::WORLD)
}
}
impl RenderLayer {
pub const WORLD: u32 = 0;
pub const OVERLAY: u32 = 1;
pub fn new(layer: u32) -> Self {
Self(layer)
}
pub fn is_in_layer(&self, layer: u32) -> bool {
self.0 == layer
}
pub fn is_overlay(&self) -> bool {
self.0 == Self::OVERLAY
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct CullingMask(pub u32);
impl Default for CullingMask {
fn default() -> Self {
Self(1)
}
}
impl CullingMask {
pub const DEFAULT_LAYER: u32 = 1;
pub fn new(mask: u32) -> Self {
Self(mask)
}
pub fn add_layer(&mut self, layer_index: u32) {
self.0 |= 1u32 << layer_index;
}
pub fn remove_layer(&mut self, layer_index: u32) {
self.0 &= !(1u32 << layer_index);
}
pub fn intersects(self, other: CullingMask) -> bool {
(self.0 & other.0) != 0
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct CameraCullingMask(pub u32);
impl Default for CameraCullingMask {
fn default() -> Self {
Self(!0)
}
}
impl CameraCullingMask {
pub fn new(mask: u32) -> Self {
Self(mask)
}
pub fn intersects(self, layer: CullingMask) -> bool {
(self.0 & layer.0) != 0
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, Serialize, Deserialize)]
pub enum EasingFunction {
#[default]
Linear,
QuadIn,
QuadOut,
QuadInOut,
CubicIn,
CubicOut,
CubicInOut,
QuartIn,
QuartOut,
QuartInOut,
QuintIn,
QuintOut,
QuintInOut,
SineIn,
SineOut,
SineInOut,
ExpoIn,
ExpoOut,
ExpoInOut,
CircIn,
CircOut,
CircInOut,
BackIn,
BackOut,
BackInOut,
ElasticIn,
ElasticOut,
ElasticInOut,
BounceIn,
BounceOut,
BounceInOut,
}
impl EasingFunction {
pub fn evaluate(&self, t: f32) -> f32 {
let t = t.clamp(0.0, 1.0);
match self {
Self::Linear => t,
Self::QuadIn => t * t,
Self::QuadOut => 1.0 - (1.0 - t) * (1.0 - t),
Self::QuadInOut => {
if t < 0.5 {
2.0 * t * t
} else {
1.0 - (-2.0 * t + 2.0).powi(2) / 2.0
}
}
Self::CubicIn => t * t * t,
Self::CubicOut => 1.0 - (1.0 - t).powi(3),
Self::CubicInOut => {
if t < 0.5 {
4.0 * t * t * t
} else {
1.0 - (-2.0 * t + 2.0).powi(3) / 2.0
}
}
Self::QuartIn => t * t * t * t,
Self::QuartOut => 1.0 - (1.0 - t).powi(4),
Self::QuartInOut => {
if t < 0.5 {
8.0 * t * t * t * t
} else {
1.0 - (-2.0 * t + 2.0).powi(4) / 2.0
}
}
Self::QuintIn => t * t * t * t * t,
Self::QuintOut => 1.0 - (1.0 - t).powi(5),
Self::QuintInOut => {
if t < 0.5 {
16.0 * t * t * t * t * t
} else {
1.0 - (-2.0 * t + 2.0).powi(5) / 2.0
}
}
Self::SineIn => 1.0 - (t * PI / 2.0).cos(),
Self::SineOut => (t * PI / 2.0).sin(),
Self::SineInOut => -(PI * t).cos() / 2.0 + 0.5,
Self::ExpoIn => {
if t == 0.0 {
0.0
} else {
(2.0f32).powf(10.0 * t - 10.0)
}
}
Self::ExpoOut => {
if t == 1.0 {
1.0
} else {
1.0 - (2.0f32).powf(-10.0 * t)
}
}
Self::ExpoInOut => {
if t == 0.0 {
0.0
} else if t == 1.0 {
1.0
} else if t < 0.5 {
(2.0f32).powf(20.0 * t - 10.0) / 2.0
} else {
(2.0 - (2.0f32).powf(-20.0 * t + 10.0)) / 2.0
}
}
Self::CircIn => 1.0 - (1.0 - t * t).sqrt(),
Self::CircOut => (1.0 - (t - 1.0).powi(2)).sqrt(),
Self::CircInOut => {
if t < 0.5 {
(1.0 - (1.0 - (2.0 * t).powi(2)).sqrt()) / 2.0
} else {
((1.0 - (-2.0 * t + 2.0).powi(2)).sqrt() + 1.0) / 2.0
}
}
Self::BackIn => {
let c1 = 1.70158;
let c3 = c1 + 1.0;
c3 * t * t * t - c1 * t * t
}
Self::BackOut => {
let c1 = 1.70158;
let c3 = c1 + 1.0;
1.0 + c3 * (t - 1.0).powi(3) + c1 * (t - 1.0).powi(2)
}
Self::BackInOut => {
let c1 = 1.70158;
let c2 = c1 * 1.525;
if t < 0.5 {
((2.0 * t).powi(2) * ((c2 + 1.0) * 2.0 * t - c2)) / 2.0
} else {
((2.0 * t - 2.0).powi(2) * ((c2 + 1.0) * (2.0 * t - 2.0) + c2) + 2.0) / 2.0
}
}
Self::ElasticIn => {
if t == 0.0 {
0.0
} else if t == 1.0 {
1.0
} else {
let c4 = 2.0 * PI / 3.0;
-(2.0f32).powf(10.0 * t - 10.0) * ((10.0 * t - 10.75) * c4).sin()
}
}
Self::ElasticOut => {
if t == 0.0 {
0.0
} else if t == 1.0 {
1.0
} else {
let c4 = 2.0 * PI / 3.0;
(2.0f32).powf(-10.0 * t) * ((10.0 * t - 0.75) * c4).sin() + 1.0
}
}
Self::ElasticInOut => {
if t == 0.0 {
0.0
} else if t == 1.0 {
1.0
} else {
let c5 = 2.0 * PI / 4.5;
if t < 0.5 {
-(2.0f32).powf(20.0 * t - 10.0) * ((20.0 * t - 11.125) * c5).sin() / 2.0
} else {
(2.0f32).powf(-20.0 * t + 10.0) * ((20.0 * t - 11.125) * c5).sin() / 2.0
+ 1.0
}
}
}
Self::BounceIn => 1.0 - Self::BounceOut.evaluate(1.0 - t),
Self::BounceOut => bounce_out(t),
Self::BounceInOut => {
if t < 0.5 {
(1.0 - bounce_out(1.0 - 2.0 * t)) / 2.0
} else {
(1.0 + bounce_out(2.0 * t - 1.0)) / 2.0
}
}
}
}
}
fn bounce_out(t: f32) -> f32 {
let n1 = 7.5625;
let d1 = 2.75;
if t < 1.0 / d1 {
n1 * t * t
} else if t < 2.0 / d1 {
let t = t - 1.5 / d1;
n1 * t * t + 0.75
} else if t < 2.5 / d1 {
let t = t - 2.25 / d1;
n1 * t * t + 0.9375
} else {
let t = t - 2.625 / d1;
n1 * t * t + 0.984375
}
}