ranim_core/animation/
build.rs1use std::any::type_name;
13
14use crate::core_item::AnyExtractCoreItem;
15
16use super::{
17 eval::Eval,
18 node::{AnimNode, NodeContent},
19};
20
21pub trait IntoAnimNode: Sized {
23 fn into_anim_node(self) -> AnimNode;
25}
26
27pub trait Unplaced: IntoAnimNode {
34 fn at(self, offset_sec: f64) -> At<Self> {
36 At {
37 inner: self,
38 offset_sec,
39 }
40 }
41}
42
43pub trait PlaybackExt: Unplaced {
45 fn with_rate_func(self, rate_func: fn(f64) -> f64) -> Paramed<Self> {
47 Paramed::new(self).with_rate_func(rate_func)
48 }
49
50 fn with_duration(self, duration_secs: f64) -> Paramed<Self> {
52 Paramed::new(self).with_duration(duration_secs)
53 }
54
55 fn with_enabled(self, enabled: bool) -> Paramed<Self> {
57 Paramed::new(self).with_enabled(enabled)
58 }
59}
60
61impl<A: Unplaced> PlaybackExt for A {}
62
63impl<E> Unplaced for E
64where
65 E: Eval + 'static,
66 E::Output: AnyExtractCoreItem,
67{
68}
69
70impl<E> IntoAnimNode for E
71where
72 E: Eval + 'static,
73 E::Output: AnyExtractCoreItem,
74{
75 fn into_anim_node(self) -> AnimNode {
76 AnimNode {
77 content: NodeContent::Leaf(Box::new(self)),
78 internal_time_secs: 1.0,
79 anim_name: type_name::<E>(),
80 rate_func: None,
81 time_range: 0.0..1.0,
82 enabled: true,
83 }
84 }
85}
86
87#[derive(Debug, Clone)]
89pub(crate) struct AnimationParam {
90 pub rate_func: Option<fn(f64) -> f64>,
93 pub duration_secs: Option<f64>,
95 pub enabled: bool,
97}
98
99impl Default for AnimationParam {
100 fn default() -> Self {
101 Self {
102 rate_func: None,
103 duration_secs: None,
104 enabled: true,
105 }
106 }
107}
108
109pub struct Paramed<A> {
111 inner: A,
112 param: AnimationParam,
113}
114
115impl<A> Paramed<A> {
116 pub(crate) fn new(inner: A) -> Self {
118 Self {
119 inner,
120 param: AnimationParam::default(),
121 }
122 }
123
124 pub fn with_rate_func(mut self, rate_func: fn(f64) -> f64) -> Self {
126 self.param.rate_func = Some(rate_func);
127 self
128 }
129
130 pub fn with_duration(mut self, duration_secs: f64) -> Self {
136 assert_valid_duration(duration_secs);
137 self.param.duration_secs = Some(duration_secs);
138 self
139 }
140
141 pub fn with_enabled(mut self, enabled: bool) -> Self {
143 self.param.enabled = enabled;
144 self
145 }
146}
147
148impl<A: Unplaced + 'static> Unplaced for Paramed<A> {}
149impl<A: Unplaced + 'static> IntoAnimNode for Paramed<A> {
150 fn into_anim_node(self) -> AnimNode {
151 let mut cell = self.inner.into_anim_node();
152 if let Some(duration_secs) = self.param.duration_secs {
153 cell.time_range = 0.0..duration_secs;
154 }
155 cell.rate_func = self.param.rate_func;
156 cell.enabled = self.param.enabled;
157 cell.anim_name = type_name::<A>();
158 cell
159 }
160}
161
162pub struct At<A> {
168 inner: A,
169 offset_sec: f64,
170}
171
172impl<A: IntoAnimNode> IntoAnimNode for At<A> {
173 fn into_anim_node(self) -> AnimNode {
174 let mut animation = self.inner.into_anim_node();
175 animation.shift_by(self.offset_sec);
176 animation
177 }
178}
179
180fn assert_valid_duration(duration_secs: f64) {
181 assert!(
182 duration_secs.is_finite() && duration_secs >= 0.0,
183 "animation duration must be finite and non-negative"
184 );
185}