Skip to main content

mittens_engine/engine/ecs/component/
transition.rs

1use crate::engine::ecs::component::Component;
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4pub enum TransitionEasing {
5    Step,
6    Linear,
7    EaseInQuad,
8    EaseOutQuad,
9    EaseInOutQuad,
10    EaseInCubic,
11    EaseOutCubic,
12    EaseInOutCubic,
13    EaseInOutSine,
14}
15
16impl TransitionEasing {
17    pub fn as_str(self) -> &'static str {
18        match self {
19            Self::Step => "step",
20            Self::Linear => "linear",
21            Self::EaseInQuad => "ease_in_quad",
22            Self::EaseOutQuad => "ease_out_quad",
23            Self::EaseInOutQuad => "ease_in_out_quad",
24            Self::EaseInCubic => "ease_in_cubic",
25            Self::EaseOutCubic => "ease_out_cubic",
26            Self::EaseInOutCubic => "ease_in_out_cubic",
27            Self::EaseInOutSine => "ease_in_out_sine",
28        }
29    }
30
31    pub fn parse(raw: &str) -> Result<Self, String> {
32        match raw {
33            "step" => Ok(Self::Step),
34            "linear" => Ok(Self::Linear),
35            "ease_in_quad" => Ok(Self::EaseInQuad),
36            "ease_out_quad" => Ok(Self::EaseOutQuad),
37            "ease_in_out_quad" => Ok(Self::EaseInOutQuad),
38            "ease_in_cubic" => Ok(Self::EaseInCubic),
39            "ease_out_cubic" => Ok(Self::EaseOutCubic),
40            "ease_in_out_cubic" => Ok(Self::EaseInOutCubic),
41            "ease_in_out_sine" => Ok(Self::EaseInOutSine),
42            other => Err(format!("Unknown transition easing: {}", other)),
43        }
44    }
45}
46
47#[derive(Debug, Clone, Copy, PartialEq, Eq)]
48pub enum TransitionReplacePolicy {
49    ReplaceSameTarget,
50    AllowParallel,
51}
52
53impl TransitionReplacePolicy {
54    pub fn as_str(self) -> &'static str {
55        match self {
56            Self::ReplaceSameTarget => "replace_same_target",
57            Self::AllowParallel => "allow_parallel",
58        }
59    }
60
61    pub fn parse(raw: &str) -> Result<Self, String> {
62        match raw {
63            "replace_same_target" => Ok(Self::ReplaceSameTarget),
64            "allow_parallel" => Ok(Self::AllowParallel),
65            other => Err(format!("Unknown transition replace policy: {}", other)),
66        }
67    }
68}
69
70#[derive(Debug, Clone, Copy, PartialEq)]
71pub struct TransitionComponent {
72    pub enabled: bool,
73    pub duration_beats: f64,
74    pub easing: TransitionEasing,
75    pub capture_from_current: bool,
76    pub replace: TransitionReplacePolicy,
77}
78
79impl TransitionComponent {
80    pub fn new() -> Self {
81        Self {
82            enabled: true,
83            duration_beats: 0.0,
84            easing: TransitionEasing::Linear,
85            capture_from_current: true,
86            replace: TransitionReplacePolicy::ReplaceSameTarget,
87        }
88    }
89
90    pub fn enabled(mut self, enabled: bool) -> Self {
91        self.enabled = enabled;
92        self
93    }
94
95    pub fn on(self) -> Self {
96        self.enabled(true)
97    }
98
99    pub fn off(self) -> Self {
100        self.enabled(false)
101    }
102
103    pub fn with_duration_beats(mut self, duration_beats: f64) -> Self {
104        self.duration_beats = if duration_beats.is_finite() {
105            duration_beats.max(0.0)
106        } else {
107            0.0
108        };
109        self
110    }
111
112    pub fn with_capture_from_current(mut self, capture_from_current: bool) -> Self {
113        self.capture_from_current = capture_from_current;
114        self
115    }
116
117    pub fn with_easing(mut self, easing: TransitionEasing) -> Self {
118        self.easing = easing;
119        self
120    }
121
122    pub fn with_replace(mut self, replace: TransitionReplacePolicy) -> Self {
123        self.replace = replace;
124        self
125    }
126}
127
128impl Default for TransitionComponent {
129    fn default() -> Self {
130        Self::new()
131    }
132}
133
134impl Component for TransitionComponent {
135    fn name(&self) -> &'static str {
136        "transition"
137    }
138
139    fn as_any(&self) -> &dyn std::any::Any {
140        self
141    }
142
143    fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
144        self
145    }
146
147    fn to_mms_ast(
148        &self,
149        _world: &crate::engine::ecs::World,
150    ) -> crate::scripting::ast::ComponentExpression {
151        use crate::engine::ecs::component::ce_helpers::*;
152        ce("Transition")
153            .with_call("enabled", vec![b(self.enabled)])
154            .with_call("duration_beats", vec![num(self.duration_beats)])
155            .with_call(self.easing.as_str(), vec![])
156            .with_call("capture_from_current", vec![b(self.capture_from_current)])
157            .with_call(self.replace.as_str(), vec![])
158    }
159}