ranim_core/animation/
build.rs1use std::any::type_name;
14
15use super::{
16 eval::Eval,
17 node::{AnimNode, LeafContent, NodeContent},
18};
19
20pub trait IntoAnimNode: Sized {
22 fn into_anim_node(self) -> AnimNode;
24}
25
26impl IntoAnimNode for AnimNode {
27 fn into_anim_node(self) -> AnimNode {
28 self
29 }
30}
31
32pub trait Unplaced: IntoAnimNode {
39 fn at(self, offset_sec: f64) -> At<Self> {
41 At {
42 inner: self,
43 offset_sec,
44 }
45 }
46}
47
48pub trait PlaybackExt: Unplaced {
50 fn with_rate_func(self, rate_func: fn(f64) -> f64) -> Paramed<Self> {
52 Paramed::new(self).with_rate_func(rate_func)
53 }
54
55 fn with_duration(self, duration_secs: f64) -> Paramed<Self> {
57 Paramed::new(self).with_duration(duration_secs)
58 }
59
60 fn with_enabled(self, enabled: bool) -> Paramed<Self> {
62 Paramed::new(self).with_enabled(enabled)
63 }
64}
65
66impl<A: Unplaced> PlaybackExt for A {}
67
68impl<E> Unplaced for E
69where
70 E: Eval + 'static,
71 E::Output: Clone + Send + Sync + 'static,
72{
73}
74
75impl<E> IntoAnimNode for E
76where
77 E: Eval + 'static,
78 E::Output: Clone + Send + Sync + 'static,
79{
80 fn into_anim_node(self) -> AnimNode {
81 AnimNode {
82 content: NodeContent::Leaf(LeafContent::Anim(Box::new(self))),
83 internal_time_secs: 1.0,
84 anim_name: type_name::<E>(),
85 rate_func: None,
86 time_range: 0.0..1.0,
87 end_inclusive: true,
88 enabled: true,
89 }
90 }
91}
92
93#[derive(Debug, Clone)]
95pub(crate) struct AnimationParam {
96 pub rate_func: Option<fn(f64) -> f64>,
99 pub duration_secs: Option<f64>,
101 pub enabled: bool,
103}
104
105impl Default for AnimationParam {
106 fn default() -> Self {
107 Self {
108 rate_func: None,
109 duration_secs: None,
110 enabled: true,
111 }
112 }
113}
114
115pub struct Paramed<A> {
117 inner: A,
118 param: AnimationParam,
119}
120
121impl<A> Paramed<A> {
122 pub(crate) fn new(inner: A) -> Self {
124 Self {
125 inner,
126 param: AnimationParam::default(),
127 }
128 }
129
130 pub fn with_rate_func(mut self, rate_func: fn(f64) -> f64) -> Self {
132 self.param.rate_func = Some(rate_func);
133 self
134 }
135
136 pub fn with_duration(mut self, duration_secs: f64) -> Self {
142 assert_valid_duration(duration_secs);
143 self.param.duration_secs = Some(duration_secs);
144 self
145 }
146
147 pub fn with_enabled(mut self, enabled: bool) -> Self {
149 self.param.enabled = enabled;
150 self
151 }
152}
153
154impl<A: Unplaced + 'static> Unplaced for Paramed<A> {}
155impl<A: Unplaced + 'static> IntoAnimNode for Paramed<A> {
156 fn into_anim_node(self) -> AnimNode {
157 let mut cell = self.inner.into_anim_node();
158 if let Some(duration_secs) = self.param.duration_secs {
159 cell.time_range = 0.0..duration_secs;
160 }
161 cell.rate_func = self.param.rate_func;
162 cell.enabled = self.param.enabled;
163 cell.anim_name = type_name::<A>();
164 cell
165 }
166}
167
168pub struct At<A> {
174 inner: A,
175 offset_sec: f64,
176}
177
178impl<A: IntoAnimNode> IntoAnimNode for At<A> {
179 fn into_anim_node(self) -> AnimNode {
180 let mut animation = self.inner.into_anim_node();
181 animation.shift_by(self.offset_sec);
182 animation
183 }
184}
185
186fn assert_valid_duration(duration_secs: f64) {
187 assert!(
188 duration_secs.is_finite() && duration_secs >= 0.0,
189 "animation duration must be finite and non-negative"
190 );
191}