mittens_engine/engine/ecs/component/
transition.rs1use 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}